本文记录一次在云服务器上部署安装K8S集群,安装的K8S集群版本是1.31。

首先说下为什么想在云服务器上部署安装K8S集群?

假设在自己笔记本电脑虚拟机上部署K8S,当你关机再开机笔记本电脑,打开虚拟机,如果没有部署高可用,你的K8S node节点会显示NotReady状态。

这时候需要你重启kubelet,或者重装网络插件,甚至都处理不好,重新部署安装node才能解决NotReady状态,这样就显得麻烦。

所以萌生了在云服务器上部署安装 K8S集群的想法。

部署安装K8S集群最少需要三台服务器,一台Master节点,两台Node节点。

我刚好有三台云服务器,是阿里云的服务器,配置均为CPU 2核、内存 2GB,满足K8S集群部署安装的最低配置要求。

部署安装k8s集群的方式有好几种,本文记录介绍通过kubeadm进行安装。下面开始部署安装:

一、部署安装K8S的前置工作

我的三台云服务器镜像统一使用CentOS 7.6 64位。

1、安装所使用到的基础软件包

三台云服务器均要安装这些用到的软件包,均执行如下命令安装:

yum install -y device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack telnet ipvsadm

2、关闭云服务器SElinux安全机制

在部署安装K8S旧版本时,需要关闭SElinux安全机制,不然会限制K8S访问系统资源。

来自DeepSeek讲解:SELinux(Security-Enhanced Linux) 是由美国国家安全局(NSA)设计并贡献给开源社区的一种**强制访问控制(MAC,Mandatory Access Control)**安全机制,集成在 Linux 内核中。它的核心目标是为系统提供更细粒度的权限控制,超越传统的 Linux 自主访问控制(DAC,Discretionary Access Control)(如用户/组权限),从而限制进程、用户和文件之间的交互,降低恶意程序或漏洞对系统的破坏风险。

三台云服务器均执行如下命令进行关闭SElinux安全机制:

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

之后重启云服务器使之生效,重启后输入如下命令进行验证:

getenforce

如显示Disabled说明SElinux已经关闭了。

据说随着K8S增强对SElinux安全机制的支持,在K8S新版本中SElinux安全机制可以启用了。

3、关闭交换分区

来自DeepSeek讲解:Swap交换分区(交换空间) 是操作系统在硬盘上预留的一块特殊存储区域,用于扩展系统的可用内存。当物理内存(RAM)不足时,系统会将暂时不活跃的内存数据(如长时间未使用的进程)转移到Swap空间中,从而释放RAM供其他急需的程序使用。Swap本质上是一种内存扩展机制,通过“以空间换时间”避免因内存耗尽导致的系统崩溃或进程被强制终止。

swap交换分区会导致K8S运行速度变慢。

使用如下命令查看是否有交换分区:

free -h

如果有使用如下命令进行临时关闭:

swapoff -a

若要永久关闭需要编辑文件/etc/fstab将swap这行进行注释:

vim /etc/fstab 
#
# /etc/fstab
# Created by anaconda on Mon Jan 13 02:47:33 2025
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=XXXXXXX-XXXX-XXX-XXXX-XXXXXXXX /                       xfs     defaults        0 0
UUID=XXXX-XXXX          /boot/efi               vfat    defaults,uid=0,gid=0,umask=077,shortname=winnt 0 2

#/dev/mapper/centos-swap swap      swap    defaults        0 0

我的三台云服务器均没有交换分区,就不用做如上操作。

4、修改云服务器主机名

我设定阿里云的这台云服务器为Master节点,执行以下命令修改:

hostnamectl set-hostname master && bash

设定另外两个腾讯云服务器和华为云服务器为Node节点,分别执行以下命令修改:

hostnamectl set-hostname node1 && bash
hostnamectl set-hostname node2 && bash

5、配置云服务器hosts文件

云服务器一般有两个地址:公网地址和私网地址,如下表所示:

云服务器 主机名 公网地址 私网地址
阿里云1 master 8.137.13.XXX 172.23.170.XXX
阿里云2 node1 47.109.146.XXX 172.23.170.XXX
阿里云3 node2 8.137.156.XXX 172.23.170.XXX

上述表格中公网地址和私网地址为示例,IP为瞎编的,如有雷同纯属巧合。

我的三台云服务器均使用同一个交换机,私网地址在一个网段上。

编辑云服务器上/etc/hosts文件进行配置:

vim /etc/hosts

其中master节点这台编辑如下:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6


172.23.170.XXX	master
47.109.146.XXX	node1
8.137.156.XXX	node2

其中node1节点这台编辑如下:

127.0.0.1 localhost.localdomain localhost
127.0.0.1 localhost4.localdomain4 localhost4

::1 localhost.localdomain localhost
::1 localhost6.localdomain6 localhost6

8.137.13.XXX	master
172.23.170.XXX	node1
8.137.156.XXX	node2

其中node2节点这台编辑如下:

::1	localhost	localhost.localdomain	localhost6	localhost6.localdomain6
127.0.0.1	localhost	localhost.localdomain	localhost4	localhost4.localdomain4
127.0.0.1	hcss-ecs-7ebb	hcss-ecs-7ebb

8.137.13.XXX	master
47.109.146.XXX	node1
172.23.170.XXX	node2

6、设置IP映射打通内网(可选)

来自DeepSeek讲解:IP映射 是指将一个IP地址(或端口)映射到另一个IP地址(或端口)的网络技术,通常用于流量重定向、负载均衡或隐藏真实服务器地址。

常见的实现方式包括 DNAT(Destination Network Address Translation,目的地址转换),它修改数据包的目的地址,使流量被转发到指定目标。

这个步骤要根据你云服务器实际情况来定,是否需要做IP映射打通内网。

我在两个node节点上设置针对master节点的IP映射:

(1)node1节点设置IP映射

 在node1节点上输入如下命令进行设置:

iptables -t nat -A OUTPUT -d 172.23.170.XXX -j DNAT --to-destination 8.137.13.XXX

#iptables -t nat -A OUTPUT -d master内网IP -j DNAT --to-destination master外网IP

(2)node2节点设置IP映射

 在node2节点上输入如下命令进行设置:

iptables -t nat -A OUTPUT -d 172.23.170.XXX -j DNAT --to-destination 8.137.13.XXX

#iptables -t nat -A OUTPUT -d master内网IP -j DNAT --to-destination master外网IP

7、配置云服务器之间免密登录

来自DeepSeek讲解:配置云服务器之间免密登录,指的是在多台云服务器之间设置 SSH 密钥认证,使得服务器之间通过 SSH 协议互相访问时无需手动输入密码。

配置云服务器之间的免密登录主要是为了方便,不然每次传文件之类的都要输入密码登录。

对于免密登录如果感兴趣可参看我的另一篇文章 https://blog.csdn.net/qq_33765205/article/details/118336346,基于RSA算法进行的免密登录操作。

下面开始操作配置免密登录:

(1)master节点配置免密登录

在master节点上输入如下命令:

ssh-keygen

一直按回车确认,之后输入如下命令将私钥文件拷贝至node1节点上:

ssh-copy-id node1

输入如下命令将私钥文件拷贝至node2节点上:

ssh-copy-id node2

Master节点配置免密登录就操作完成。两个Node节点也如此操作。

(2)node1节点配置免密登录

 在node1节点上输入如下命令:

ssh-keygen

一直按回车确认,之后输入如下命令将私钥文件拷贝至master节点上:

ssh-copy-id master

输入如下命令将私钥文件拷贝至node2节点上:

ssh-copy-id node2

(3)node2节点配置免密登录

  在node2节点上输入如下命令:

ssh-keygen

一直按回车确认,之后输入如下命令将私钥文件拷贝至master节点上:

ssh-copy-id master

输入如下命令将私钥文件拷贝至node1节点上:

ssh-copy-id node1

8、修改主机模块加载配置网络插件

Master节点和两个Node节点均执行如下命令,将 br_netfilter 模块添加到主机内核中:

modprobe br_netfilter

之后新建k8s.conf文件编辑如下:

vim /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1

之后执行如下命令:

sysctl -p /etc/sysctl.d/k8s.conf

9、防火墙放行相关端口

K8S集群所使用到的端口如下表所示:

K8S服务 端口类型 所使用到的端口号
Kube-apiserver TCP 6443
etcd datastore TCP 2379、2380
Kube-controller-manager TCP 10257
Kube-scheduler TCP 10259
Kubelet TCP 10250
Kube-proxy TCP 在1024到65535之间
Calico Networking(BGP) TCP 179、5743
Calico Networking(VXLAN) UDP 4789
HTTPS TCP 443

归纳上述端口为:

TCP:6443,2379,2380,10257,10259,10250,1024-65535,179,5743,443

UPD:4789

打开云服务器控制台页面中的安全组进行配置,在入方向放行K8S所使用的相关端口,如下图所示:

需要注意的是,如果你不是用的云服务器,是自己本地的虚拟机练习部署搭建,建议你可以直接把防火墙关闭。

输入如下命令关闭Firewalld防火墙:

systemctl stop firewalld && systemctl disable firewalld

如果你在本地生产环境,不能关闭Firewalld防火墙,可以配置防火墙将上述K8S集群所使用到的端口放开。

例如放开TCP端口6643,输入如下命令:

firewall-cmd --zone=public --add-port=6443/tcp --permanent

例如放开UCP端口6643,输入如下命令:

firewall-cmd --zone=public --add-port=4789/udp --permanent

配置完之后执行如下命令进行防火墙规则加载:

firewall-cmd --reload

对于Firewalld防火墙更多的使用配置,可参看我的公众号推文 https://mp.weixin.qq.com/s/vWfR10N4mMlOHma7l4BE2g

10、配置阿里云的repo源

使用如下命令配置docker的阿里云源,输入如下命令配置:

yum install yum-utils -y

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

11、云服务器时间同步配置(可选)

进行时间同步配置,使得K8S集群节点时间保持一致。

云服务器上通常时间一致,但也可以配置时间同步。

首先在master、node1和node2三个节点中安装chrony软件服务,执行如下命令:

yum -y install chrony

设置开机自启动,执行如下命令:

 systemctl enable chronyd --now

编辑/etc/chrony.conf文件设置时间服务器:

vim /etc/chrony.conf
# Enable kernel RTC synchronization.
rtcsync

# In first three updates step the system clock instead of slew
# if the adjustment is larger than 10 seconds.
makestep 10 3

# Allow NTP client access from local network.
#allow 192.168/16

# Listen for commands only on localhost.
bindcmdaddress 127.0.0.1
bindcmdaddress ::1

# Serve time even if not synchronized to any NTP server.
#local stratum 10

# Disable logging of client accesses.
noclientlog

# Send a message to syslog if a clock adjustment is larger than 0.5 seconds.
logchange 0.5

logdir /var/log/chrony
#log measurements statistics tracking


server ntp1.aliyun.com iburst
server ntp2.aliyun.com iburst
server ntp1.tencent.com iburst
server ntp2.tencent.com iburst

可以写个计划任务定时同步下时间,执行以下命令:

crontab -e
* * * * * /usr/bin/systemctl restart chronyd

配置好之后还可以查看下master、node1和node2三个节点时间是否一致:

以上就是所有前置工作,不仅是部署安装K8S集群,部署其他集群的前置工作如部署Hadoop集群也类似之处,也可以参看。


二、安装容器运行时containerd和docker

1、安装containerd

来自DeepSeek讲解:containerd 是一个开源的容器运行时(Container Runtime),专注于管理容器生命周期(如创建、启动、停止、删除容器)和镜像管理(如下载、存储镜像)。它是 Docker 生态系统的一部分,但设计为更轻量级、模块化的核心组件。

这里装的是1.6.22这个版本,安装执行如下命令:

yum install containerd.io-1.6.22* -y

之后修改配置文件,输入如下命令进入/etc/containerd目录下:

cd /etc/containerd

修改目录下的config.toml这个文件,修改之后如下所示:

disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
temp = ""
version = 2

[cgroup]
  path = ""

[debug]
  address = ""
  format = ""
  gid = 0
  level = ""
  uid = 0

[grpc]
  address = "/run/containerd/containerd.sock"
  gid = 0
  max_recv_message_size = 16777216
  max_send_message_size = 16777216
  tcp_address = ""
  tcp_tls_ca = ""
  tcp_tls_cert = ""
  tcp_tls_key = ""
  uid = 0

[metrics]
  address = ""
  grpc_histogram = false

[plugins]

  [plugins."io.containerd.gc.v1.scheduler"]
    deletion_threshold = 0
    mutation_threshold = 100
    pause_threshold = 0.02
    schedule_delay = "0s"
    startup_delay = "100ms"

  [plugins."io.containerd.grpc.v1.cri"]
    device_ownership_from_security_context = false
    disable_apparmor = false
    disable_cgroup = false
    disable_hugetlb_controller = true
    disable_proc_mount = false
    disable_tcp_service = true
    enable_selinux = false
    enable_tls_streaming = false
    enable_unprivileged_icmp = false
    enable_unprivileged_ports = false
    ignore_image_defined_volumes = false
    max_concurrent_downloads = 3
    max_container_log_line_size = 16384
    netns_mounts_under_state_dir = false
    restrict_oom_score_adj = false
    sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7"
    selinux_category_range = 1024
    stats_collect_period = 10
    stream_idle_timeout = "4h0m0s"
    stream_server_address = "127.0.0.1"
    stream_server_port = "0"
    systemd_cgroup = false
    tolerate_missing_hugetlb_controller = true
    unset_seccomp_profile = ""

    [plugins."io.containerd.grpc.v1.cri".cni]
      bin_dir = "/opt/cni/bin"
      conf_dir = "/etc/cni/net.d"
      conf_template = ""
      ip_pref = ""
      max_conf_num = 1

    [plugins."io.containerd.grpc.v1.cri".containerd]
      default_runtime_name = "runc"
      disable_snapshot_annotations = true
      discard_unpacked_layers = false
      ignore_rdt_not_enabled_errors = false
      no_pivot = false
      snapshotter = "overlayfs"

      [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
        base_runtime_spec = ""
        cni_conf_dir = ""
        cni_max_conf_num = 0
        container_annotations = []
        pod_annotations = []
        privileged_without_host_devices = false
        runtime_engine = ""
        runtime_path = ""
        runtime_root = ""
        runtime_type = ""

        [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]

      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]

        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
          base_runtime_spec = ""
          cni_conf_dir = ""
          cni_max_conf_num = 0
          container_annotations = []
          pod_annotations = []
          privileged_without_host_devices = false
          runtime_engine = ""
          runtime_path = ""
          runtime_root = ""
          runtime_type = "io.containerd.runc.v2"

          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
            BinaryName = ""
            CriuImagePath = ""
            CriuPath = ""
            CriuWorkPath = ""
            IoGid = 0
            IoUid = 0
            NoNewKeyring = false
            NoPivotRoot = false
            Root = ""
            ShimCgroup = ""
            SystemdCgroup = true

      [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
        base_runtime_spec = ""
        cni_conf_dir = ""
        cni_max_conf_num = 0
        container_annotations = []
        pod_annotations = []
        privileged_without_host_devices = false
        runtime_engine = ""
        runtime_path = ""
        runtime_root = ""
        runtime_type = ""

        [plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]

    [plugins."io.containerd.grpc.v1.cri".image_decryption]
      key_model = "node"

    [plugins."io.containerd.grpc.v1.cri".registry]
      config_path = ""

      [plugins."io.containerd.grpc.v1.cri".registry.auths]

      [plugins."io.containerd.grpc.v1.cri".registry.configs]
        [plugins."io.containerd.grpc.v1.cri".registry.configs."你的Harbor的IP地址".tls]
            insecure_skip_verify = true
        [plugins."io.containerd.grpc.v1.cri".registry.configs."你的Harbor的IP地址".auth]
            username = "你的Harbor的账号名"
            password = "你的Harbor的密码"

      [plugins."io.containerd.grpc.v1.cri".registry.headers]

      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
         [plugins."io.containerd.grpc.v1.cri".registry.mirrors."你的Harbor的IP地址"]
            endpoint = ["https://你的Harbor的IP地址:443"]
          [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
             endpoint = ["https://docker-0.unsee.tech","https://docker-cf.registry.cyou","https://docker.1panel.live","https://registry.docker-cn.com"]

    [plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
      tls_cert_file = ""
      tls_key_file = ""

  [plugins."io.containerd.internal.v1.opt"]
    path = "/opt/containerd"

  [plugins."io.containerd.internal.v1.restart"]
    interval = "10s"

  [plugins."io.containerd.internal.v1.tracing"]
    sampling_ratio = 1.0
    service_name = "containerd"

  [plugins."io.containerd.metadata.v1.bolt"]
    content_sharing_policy = "shared"

  [plugins."io.containerd.monitor.v1.cgroups"]
    no_prometheus = false

  [plugins."io.containerd.runtime.v1.linux"]
    no_shim = false
    runtime = "runc"
    runtime_root = ""
    shim = "containerd-shim"
    shim_debug = false

  [plugins."io.containerd.runtime.v2.task"]
    platforms = ["linux/amd64"]
    sched_core = false

  [plugins."io.containerd.service.v1.diff-service"]
    default = ["walking"]

  [plugins."io.containerd.service.v1.tasks-service"]
    rdt_config_file = ""

  [plugins."io.containerd.snapshotter.v1.aufs"]
    root_path = ""

  [plugins."io.containerd.snapshotter.v1.btrfs"]
    root_path = ""

  [plugins."io.containerd.snapshotter.v1.devmapper"]
    async_remove = false
    base_image_size = ""
    discard_blocks = false
    fs_options = ""
    fs_type = ""
    pool_name = ""
    root_path = ""

  [plugins."io.containerd.snapshotter.v1.native"]
    root_path = ""

  [plugins."io.containerd.snapshotter.v1.overlayfs"]
    root_path = ""
    upperdir_label = false

  [plugins."io.containerd.snapshotter.v1.zfs"]
    root_path = ""

  [plugins."io.containerd.tracing.processor.v1.otlp"]
    endpoint = ""
    insecure = false
    protocol = ""

[proxy_plugins]

[stream_processors]

  [stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
    accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
    args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
    env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
    path = "ctd-decoder"
    returns = "application/vnd.oci.image.layer.v1.tar"

  [stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
    accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
    args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
    env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
    path = "ctd-decoder"
    returns = "application/vnd.oci.image.layer.v1.tar+gzip"

[timeouts]
  "io.containerd.timeout.bolt.open" = "0s"
  "io.containerd.timeout.shim.cleanup" = "5s"
  "io.containerd.timeout.shim.load" = "5s"
  "io.containerd.timeout.shim.shutdown" = "3s"
  "io.containerd.timeout.task.state" = "2s"

[ttrpc]
  address = ""
  gid = 0
  uid = 0

修改的内容为:

(1)将SystemdCgroup = false改为SystemdCgroup = true。

(2)将sandbox_image的源改为sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7"。

(3)加入Harbor仓库地址,注意缩进:

      [plugins."io.containerd.grpc.v1.cri".registry.auths]

      [plugins."io.containerd.grpc.v1.cri".registry.configs]
        [plugins."io.containerd.grpc.v1.cri".registry.configs."你的Harbor的IP地址".tls]
            insecure_skip_verify = true
        [plugins."io.containerd.grpc.v1.cri".registry.configs."你的Harbor的IP地址".auth]
            username = "你的Harbor的账号名"
            password = "你的Harbor的密码"

      [plugins."io.containerd.grpc.v1.cri".registry.headers]

      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
         [plugins."io.containerd.grpc.v1.cri".registry.mirrors."你的Harbor的IP地址"]
            endpoint = ["https://你的Harbor的IP地址:443"]
          [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
             endpoint = ["https://vh3bm52y.mirror.aliyuncs.com","https://registry.docker-cn.com"]

之后输入如下命令启动containerd:

systemctl start containerd && systemctl enable containerd

查看的版本使用如下命令:

ctr version

2、安装docker

来自DeepSeek讲解:Docker 是一个开源的容器化平台,用于开发、部署和运行应用程序。它通过将应用程序及其依赖项打包到一个轻量级、可移植的“容器”中,实现了应用在不同环境(如开发、测试、生产)中的一致性运行。

安装与适配的docker,这里安装的是24.0.6版本,执行如下命令进行安装:

yum install docker-ce-24.0.6 -y

执行如下命令启动docker并设置开机自启动:

systemctl start docker && systemctl enable docker

之后配置docker镜像加速器,输入如下命令进行编辑:

 tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker-0.unsee.tech",
"https://docker-cf.registry.cyou",
"https://docker.1panel.live"
 ]
}
EOF

三、安装K8S

1、安装kubelet

在master和node节点上都要安装kubelet。

首先进行配置安装K8S组件用到的源,输入如下命令:

cat >  /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.31/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.31/rpm/repodata/repomd.xml.key
EOF

之后运行如下命令:

yum clean all && yum makecache

接下来安装kubelet,这次安装的版本为1.31.3,执行如下命令:

yum install -y kubelet-1.31.3 kubeadm-1.31.3 kubectl-1.31.3

将kubelet设置为开机自启动,执行如下命令:

systemctl enable kubelet

2、在master节点里安装K8S

在master节点上执行如下命令:

kubeadm config print init-defaults > kubeadm.yaml

之后输入如下命令修改文件:

vim kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1beta4
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 172.23.170.XXX  #你的master节点的IP
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  imagePullSerial: true
  name: master
  taints: null
timeouts:
  controlPlaneComponentHealthCheck: 4m0s
  discovery: 5m0s
  etcdAPICall: 2m0s
  kubeletHealthCheck: 4m0s
  kubernetesAPICall: 1m0s
  tlsBootstrap: 5m0s
  upgradeManifests: 5m0s
---
apiServer: {}
apiVersion: kubeadm.k8s.io/v1beta4
caCertificateValidityPeriod: 87600h0m0s
certificateValidityPeriod: 8760h0m0s
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
encryptionAlgorithm: RSA-2048
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.31.0
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
  podSubnet: 10.244.0.0/16
proxy: {}
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd

需要修改的地方有:

(1)将advertiseAddress这项后面的IP修改为你的控制节点的IP,注意是云服务器内网IP。

(2)在name这里要填写自己的主机名,我这里的主机名是master。

(3)criSocket项后面的位置,需要查看本机的文件所在地址进行填写,例如我的这个文件在/run/containerd/containerd.sock这。

(4)需要指定pod网段,增加podSubnet: 10.244.0.0/16这个内容。

(5)将imageRepository改成国内的镜像仓库,例如改成registry.cn-hangzhou.aliyuncs.com/google_containers。

(6)在最后追加如下行内容:

---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd

特别注意:上述的6个修改的内容一定要认真仔细修改,不可以漏项,不然后面会出错。其次,这里的kubeadm.yaml一定是前面命令生成的,然后根据生成的进行修改。而不是新建一个把我上面的复制或覆盖进去。

之后在master节点里执行如下命令安装K8S:

kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=SystemVerification

如果报错提示云服务器使用内存不足,例如:

[init] Using Kubernetes version: v1.31.0
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
	[ERROR Mem]: the system RAM (1675 MB) is less than the minimum 1700 MB
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`

可以通过加上 --ignore-preflight-errors=Mem 参数忽略内存检查错误:

kubeadm init --config=kubeadm.yaml --ignore-preflight-errors=Mem

之后根据输出内容提示执行命令:

mkdir -p $HOME/.kube

cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

chown $(id -u):$(id -g) $HOME/.kube/config

之后运行如下命令验证:

kubectl get nodes

4、添加node节点

首先在master节点上运行如下命令:

kubeadm token create --print-join-command

之后在node1节点上执行上述命令的反馈结果,例如:

kubeadm join XXX.XXX.XXX.XX:6443 --token vulvta.XXXXXXXXX  --discovery-token-ca-cert-hash sha256:XXXXXXXXX --ignore-preflight-errors=SystemVerification

这样就将node1节点加入进来了。

node2节点也是一样的操作。

在node2节点上执行上述命令的反馈结果,例如:

kubeadm join XXX.XXX.XXX.XX:6443 --token vulvta.XXXXXXXXX  --discovery-token-ca-cert-hash sha256:XXXXXXXXX  --ignore-preflight-errors=SystemVerification

需要在反馈结果后面加上--ignore-preflight-errors=SystemVerification,这样node2节点也加入进来了。

如果报错,可在反馈结果后面加上--ignore-preflight-errors=SystemVerification。

然后,可以使用如下命令将node节点打标签为work。

kubectl label nodes node1 node-role.kubernetes.io/work=work

四、安装Calico网络插件

来自DeepSeek讲解:Calico 是一个开源的容器网络解决方案,专为 Kubernetes、OpenShift、OpenStack 等云原生平台设计。它提供了高性能、高可扩展性和灵活的网络策略管理能力,支持容器间的安全通信和网络隔离。

如何安装Calico可参看官网说明 Installing on on-premises deployments | Calico Documentation

在官网安装Calico那选择Manifest,如下图所示,根据官网上描述的进行安装:

首先运行官网上的这个命令:

curl https://raw.githubusercontent.com/projectcalico/calico/v3.29.3/manifests/calico.yaml -O

之后修改calico.yaml这个文件。

vim calico.yaml

文件内容太多了,通过vim编辑器定位修改的地方。

输入 / 进入查找模式,然后输入要查找的文本,这里是查找value:这个,如下图所示:

在图中位置加入修改的内容:

- name: IP_AUTODETECTION_METHOD
  value: "interface=eth0"

其中,interface= 后面的值为你的云服务的网卡名称。

例如我的云服务的网卡名称是eth0,所以写成 value: "interface=eth0"。

之后在master节点运行如下命令:

kubectl apply -f calico.yaml

然后执行如下命令验证,如果状态都为Ready,Calico网络插件安装就成功了:

kubectl get nodes


五、安装Dashboard监控集群资源状态和性能(可选)

Dashboard是网页端图形可视化监控集群资源状态和性能,可装可不装。

首先下载官方提供的YAML文件,用于部署Dashboard,执行如下命令:

wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

之后修改recommended.yaml这个文件,执行如下命令:

vim recommended.yaml

在spec里加上type: NodePort,如下图所示:

之后执行如下命令进行部署安装Dashboard:

kubectl apply -f recommended.yaml

之后通过执行如下命令查看端口:

kubectl get svc -n kubernetes-dashboard

比如我的端口是32032,要打开云服务器控制台页面中的安全组进行配置,将端口32032放开。

之后在网页输入 https:// 8.137.13.XXX:32032,其中8.137.13.XXX是master节点地址,32032是端口。

如果网页打不开,在网页的任意位置,直接键盘敲入这11个字符:thisisunsafe,可以直接跳过安全报错进入页面。

之后创建相应的Token登入即可使用。


至此,云服务器上部署安装 K8S集群基本完成了。大家如果觉得K8S复杂,还可以参看我另一篇文章K3S的安装 https://blog.csdn.net/qq_33765205/article/details/139699106 。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐