搭建Kubernetes集群(本地)


1 基础准备

1.1 集群环境介绍

操作系统 主机名 IP地址 角色 k8s版本 containerd版本 配置
Rocky Linux 9.6 k8s-master 192.168.8.4 master节点 1.33.5 v2.1.4 4核4G
Rocky Linux 9.6 k8s-node1 192.168.8.5 node1节点 1.33.5 v2.1.4 4核4G
Rocky Linux 9.6 k8s-node2 192.168.8.6 node2节点 1.33.5 v2.1.4 4核4G
Rocky Linux 9.6 k8s-node3 192.168.8.7 node3节点 1.33.5 v2.1.4 4核4G

1.2 关闭防火墙和SELinux

# 下列步骤需要在集群中所有机器上完成

# 关闭防火墙并设置为开机自动关闭
systemctl disable --now firewalld

# 关闭SELinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config 

# 临时关闭SELinux
setenforce 0

1.3 修改主机名

# master节点
  hostnamectl set-hostname k8s-master

# node1节点
  hostnamectl set-hostname k8s-node1

# node2节点
  hostnamectl set-hostname k8s-node2

# node3节点
  hostnamectl set-hostname k8s-node3

2 Containerd部署

2.1 安装Containerd

  下载包含 containerdnerdctl 的完整工具包。

  解压到 /usr/local 目录,安装所有组件。

  安装 nerdctl-full 版本集成了 containerd 。如主机已安装 containerd 请选择 nerdctl简易版(nerdctl-2.1.6-linux-amd64.tar.gz)

  下载地址:https://github.com/containerd/nerdctl/releases

# 下列步骤需要在集群中所有机器上完成

# 下载nerdctl工具,这个工具使用containerd作为底层运行时,命令行高度兼容docker,是首选方案,下载好之后,把压缩包解压到 /usr/local 目录下,这样就可以方便后面使用

wget https://github.com/containerd/nerdctl/releases/download/v2.1.6/nerdctl-full-2.1.6-linux-amd64.tar.gz
tar Cxzvvf /usr/local nerdctl-full-2.1.6-linux-amd64.tar.gz

# 查看containerd安装好的版本
[root@k8s-master ~]# containerd -v
containerd github.com/containerd/containerd/v2 v2.1.4 75cb2b7193e4e490e9fbdc236c0e811ccaba3376

[root@k8s-node1 ~]# containerd -v
containerd github.com/containerd/containerd/v2 v2.1.4 75cb2b7193e4e490e9fbdc236c0e811ccaba3376

[root@k8s-node2 ~]# containerd -v
containerd github.com/containerd/containerd/v2 v2.1.4 75cb2b7193e4e490e9fbdc236c0e811ccaba3376

[root@k8s-node3 ~]# containerd -v
containerd github.com/containerd/containerd/v2 v2.1.4 75cb2b7193e4e490e9fbdc236c0e811ccaba3376

2.2 生成配置文件

  创建配置目录并生成默认配置文件。

  替换 pause 镜像为国内源,这里的国内源可以是任何你能访问的源。

  配置镜像加速器路径。

# 下列步骤需要在集群中所有机器上完成

# 要给 containerd 做一些配置,让它能更好地工作。首先创建一个配置文件夹 /etc/containerd,然后生成默认的配置文件
mkdir /etc/containerd

# containerd生成配置文件
containerd config default > /etc/containerd/config.toml

# 配置crictl连接containerd
cat >> /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

# 修改镜像源
1.修改一下配置文件,把默认的 pause 镜像地址换成一个国内的镜像地址,这样在国内访问会更快
  sed -i "s|sandbox = 'registry.k8s.io/pause:3.10'|sandbox = 'registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.10'|" /etc/containerd/config.toml

2.将 sandbox_image 镜像源设置为阿里云google_containers镜像源
  sed -i "s#registry.k8s.io/pause:3.8#registry.aliyuncs.com/google_containers/pause:3.10#g" /etc/containerd/config.toml

# 设置镜像仓库的配置路径,让containerd知道去哪里找镜像之类的,如果有容器镜像加速器,就应该配置在这个路径下。
# containerd的1.X版本和containerd的2.X版本,这里的路径是不一样的
sed -i '/^\s*\[plugins.'"'"'io.containerd.cri.v1.images'"'"'.registry\]/{n;s|^\(\s*\)config_path = .*$|\1config_path = '"'"'/etc/containerd/certs.d'"'"'|}' /etc/containerd/config.toml

# 配置containerd cgroup 驱动程序为systemd
sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml

2.3 使用镜像加速器

 在中国需要设置国内镜像加速器,提升拉取镜像的速度

  为了能让 containerd 正常拉取镜像,还要配置一下镜像仓库的证书信息。首先,创建一个目录来存放证书,创建一个配置文件,告诉 containerd 我们要使用一个国内的镜像代理地址,这样拉取镜像会更快。

  Containerd容器可用的免费镜像加速器配置方法。Containerd的配置方式与Docker不同,主要分为旧版本(1.5之前)和新版本(1.5及以上)两种方法‌:

  1.旧版本配置方法(1.5之前)

   对于Containerd 1.5版本之前的配置,需要直接修改/etc/containerd/config.toml文件‌:

tomlCopy Code[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://docker.m.daocloud.io", "https://hub-mirror.c.163.com"]

  修改后需要重启Containerd服务。

  2.新版本配置方法(1.5及以上)

   新版本推荐使用/etc/containerd/certs.d/目录进行配置,这种方式支持热加载,无需重启服务‌:

# 下列步骤需要在集群中所有机器上完成
mkdir /etc/containerd/certs.d/docker.io -p
cat > /etc/containerd/certs.d/docker.io/hosts.toml <<-'EOF'
server = "https://docker-0.unsee.tech"
[host."https://docker-0.unsee.tech"]
  capabilities = ["pull", "resolve", "push"]
EOF

  3.常用免费加速器地址

   以下是一些可用的免费镜像加速器地址,可以根据需要选择使用‌:

   阿里云镜像加速器:https://<your_id>.mirror.aliyuncs.com(需替换为您的ID)

    https://1016220537097033.mirror.aliyuncs.com

   DaoCloud镜像加速器:https://docker.m.daocloud.io

  优先推荐(就近+稳定):

   https://docker.1ms.run

   https://docker-0.unsee.tech

  其他备选(均正常):

   https://docker.m.daocloud.io

   https://ccr.ccs.tencentyun.com

   https://hub.xdark.top

   https://dhub.kubesre.xyz

   https://docker.kejilion.pro

   https://docker.xuanyuan.me

  4.测试拉取镜像

   配置完成后,可以使用以下命令测试加速器是否生效‌:

[root@k8s-master ~]# nerdctl pull calico/node:v3.30.4
docker.io/calico/node:v3.30.4:                                                    resolved       |++++++++++++++++++++++++++++++++++++++|
index-sha256:362f10b69142fcc654c0ab65a5f371923f9a1d8f7772eac0ff223b9dc67704de:    done           |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:b6c92e535b935575f48092edadcfaec716ebce53f1fbc56d312744e86ce0fb17: done           |++++++++++++++++++++++++++++++++++++++|
config-sha256:833e8e11d9dc187377eab6f31e275114a6b0f8f0afc3bf578a2a00507e85afc9:   done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:44c2028a3ff8d71676da71a6c671786584592f991e0eea338c6de86237383ff7:    done           |++++++++++++++++++++++++++++++++++++++|
elapsed: 10.1s                                                                  total:  149.6  (14.8 MiB/s)

2.4 启动Containerd服务

  启动并设置 containerd 和 buildkit 服务为开机自启。

   containerd 是一个高性能的容器运行时,负责管理容器的生命周期,包括镜像拉取、容器创建、运行、停止等,是 Kubernetes 支持的主流运行时之一。

   BuildKit 是 Docker 和 containerd 的构建引擎,用于高效地构建镜像,支持并行构建、缓存优化和安全隔离等高级功能。

# 下列步骤需要在集群中所有机器上完成

# 启动 containerd 和 buildkit 服务
systemctl daemon-reload

# 启动containerd并设置开机自启动
systemctl enable --now containerd
systemctl enable --now buildkit

# 查看containerd状态
systemctl status containerd

2.5 添加nerdctl命令自动补齐

  生成 bash 自动补齐脚本,立即生效,提高命令行操作效率。

# 下列步骤需要在集群中所有机器上完成
nerdctl completion bash > /etc/bash_completion.d/nerdctl
source /etc/bash_completion.d/nerdctl

3 准备DNS解析

  这一步需要在集群中所有机器上完成

cat >> /etc/hosts <<EOF
192.168.8.4 k8s-master
192.168.8.5 k8s-node1
192.168.8.6 k8s-node2
192.168.8.7 k8s-node3
EOF

4 操作Containerd容器

4.1 镜像操作

1.拉取镜像
[root@k8s-master ~]~# nerdctl pull registry.myk8s.cn/library/httpd
[root@k8s-master ~]~# nerdctl images
REPOSITORY                 TAG       IMAGE ID        CREATED           PLATFORM       SIZE       BLOB SIZE
registry.myk8s.cn/library/httpd    latest    4564ca760495    2 minutes ago  linux/amd64    162.2MB    58.5MB
registry.myk8s.cn/library/nginx    latest    5ed8fcc66f4e    22 minutes ago linux/amd64    207MB     72.39MB

2.删除镜像
[root@k8s-master ~]~# nerdctl rmi registry.myk8s.cn/library/httpd
[root@k8s-master ~]~# nerdctl images
REPOSITORY              TAG       IMAGE ID        CREATED           PLATFORM       SIZE     BLOB SIZE
registry.myk8s.cn/library/nginx    latest    5ed8fcc66f4e    23 minutes ago linux/amd64    207MB    72.39MB

[root@k8s-master ~]~# nerdctl rmi -f $(nerdctl images -aq)
[root@k8s-master ~]~# nerdctl images
REPOSITORY    TAG       IMAGE ID        CREATED          PLATFORM       SIZE     BLOB SIZE
<none>        <none>    5ed8fcc66f4e    6 seconds ago    linux/amd64    207MB    72.39MB

参数说明:
1.删除镜像    nerdctl rmi 镜像名
2.删除所有镜像 nerdctl rmi -f $(docker images -aq)
  说明:列出所有镜像的ID,并使用nerdctl rmi -f强制删除
  
3.使用nerdctl system prune命令  nerdctl system prune -a --volumes
  说明:删除所有停止的容器、未被使用的网络、卷、没有关联容器的镜像以及所有构建缓存
4.使用nerdctl image prune命令   nerdctl image prune -a -f
  说明:删除所有未被使用的镜像,-a参数表示删除所有未使用的镜像,而不仅仅是悬空镜像,-f参数表示不进行确认提示

4.2 创建持续运行的容器

[root@k8s-master ~]~# nerdctl run -d -p 9000:80 --name container1 registry.myk8s.cn/library/nginx
9a834031839a1dbe75a454f8e4dbab6717b9a4f921d8a8657785502b565f376b
[root@k8s-master ~]~# nerdctl ps
CONTAINER ID    IMAGE              COMMAND        CREATED           STATUS    PORTS          NAMES
9a834031839a    registry.myk8s.cn/library/nginx:latest    "/docker-entrypoint.…"    10 seconds ago    Up        0.0.0.0:9000->80/tcp    container1
[root@k8s-master ~]~# nerdctl images
REPOSITORY                         TAG       IMAGE ID        CREATED       PLATFORM       SIZE     BLOB SIZE
registry.myk8s.cn/library/nginx    latest    5ed8fcc66f4e    9 minutes ago    linux/amd64    207MB    72.39MB


# 参数说明:
   -d:后台运行
   -p:端口映射,此处是将宿主机的8000端口和容器内的80端口映射到一起
   –name:容器的名字
   nginx:本次使用的镜像名字
   nerdctl ps      查看正在运行的容器  
   nerdctl ps -a   查看所有容器

4.3 进入容器并访问

1.进入容器
[root@k8s-master ~]~# nerdctl exec -it container1 /bin/bash
root@9a834031839a:/# echo Hello Containerd > /usr/share/nginx/html/index.html
root@9a834031839a:/# exit
exit

2.访问容器
[root@k8s-master ~]~# curl http://127.0.0.1:900
curl: (7) Failed to connect to 127.0.0.1 port 900 after 0 ms: Couldn't connect to server
[root@k8s-master ~]~# curl http://127.0.0.1:9000
Hello Containerd

4.4 删除容器

[root@k8s-master ~]~# nerdctl ps
CONTAINER ID    IMAGE      COMMAND         CREATED           STATUS    PORTS                   NAMES
9a834031839a    registry.myk8s.cn/library/nginx:latest    "/docker-entrypoint.…"    22 minutes ago    Up        0.0.0.0:9000->80/tcp    container1

[root@k8s-master ~]~# nerdctl rm -f container1
container1

[root@k8s-master ~]~# nerdctl ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

# 参数说明:
1.删除已经停止的容器      nerdctl rm 容器名称、nerdctl rm 容器ID
2.强制删除正在运行的容器   nerdctl rm -f 容器名称
  说明:使用强制删除选项-f会立即停止并删除容器,可能会导致数据丢失或服务中断
3.删除多个容器 nerdctl rm container1 container2 ...
4.删除所有容器(包括正在运行的容器)   nerdctl rm -f $(nerdctl ps -aq)
  说明:通过nerdctl ps -aq列出所有容器的ID,然后通过nerdctl rm -f强制删除
  
[root@k8s-master ~]~# nerdctl run -d -p 9000:80 --name container1 registry.myk8s.cn/library/nginx
[root@k8s-master ~]~# nerdctl run -d -p 7000:80 --name container2 registry.myk8s.cn/library/httpd

[root@k8s-master ~]~# nerdctl ps
CONTAINER ID    IMAGE    COMMAND           CREATED               STATUS    PORTS                   NAMES
edd159eed7e1    registry.myk8s.cn/library/httpd:latest    "httpd-foreground"        43 seconds ago        Up        0.0.0.0:7000->80/tcp    container2
9f789c6447dc    registry.myk8s.cn/library/nginx:latest    "/docker-entrypoint.…"    About a minute ago    Up        0.0.0.0:9000->80/tcp    container1

[root@k8s-master ~]~# nerdctl ps -aq
[root@k8s-master ~]~# nerdctl rm -f $(nerdctl ps -aq)
[root@k8s-master ~]~# nerdctl ps -a

4.5 构建与使用镜像

4.5.1 nerdctl commit构建

  使用容器中发生更改的部分生成一个新的镜像,通常的使用场景为,基于普通镜像启动了容器,在容器内部署了所需的业务后,把当前的状态重新生成镜像,以便以当前状态快速部署业务所用

[root@k8s-master ~]~# nerdctl images
REPOSITORY              TAG       IMAGE ID        CREATED           PLATFORM       SIZE       BLOB SIZE
registry.myk8s.cn/library/httpd    latest    4564ca760495    7 minutes ago     linux/amd64    162.2MB    58.5MB
registry.myk8s.cn/library/nginx    latest    5ed8fcc66f4e    18 minutes ago    linux/amd64    207MB      72.39MB
<none>                             <none>    5ed8fcc66f4e    32 minutes ago    linux/amd64    207MB      72.39MB

[root@k8s-master ~]~# nerdctl tag registry.myk8s.cn/library/nginx:latest nginx:v0
[root@k8s-master ~]~# nerdctl images
REPOSITORY              TAG       IMAGE ID        CREATED           PLATFORM       SIZE       BLOB SIZE
nginx                              v0        5ed8fcc66f4e    5 seconds ago     linux/amd64    207MB      72.39MB
registry.myk8s.cn/library/httpd    latest    4564ca760495    9 minutes ago     linux/amd64    162.2MB    58.5MB
registry.myk8s.cn/library/nginx    latest    5ed8fcc66f4e    21 minutes ago    linux/amd64    207MB      72.39MB
<none>                             <none>    5ed8fcc66f4e    34 minutes ago    linux/amd64    207MB      72.39MB

[root@k8s-master ~]~# nerdctl run -d -p 9000:80 --name container1 nginx:v0
[root@k8s-master ~]~# nerdctl ps -a
CONTAINER ID    IMAGE      COMMAND              CREATED          STATUS    PORTS                   NAMES
6f8c50caccc3    docker.io/library/nginx:v0    "/docker-entrypoint.…"    8 seconds ago    Up        0.0.0.0:9000->80/tcp    container1

1.将上述的container1容器生成一个新的镜像:nginx:v1
[root@k8s-master ~]~# nerdctl commit container1 nginx:v1
sha256:75075d88243da88c3be2009c39bbed95d384c90383c9122d06dc40f3492d4f0e
[root@k8s-master ~]~# nerdctl images
REPOSITORY            TAG       IMAGE ID        CREATED           PLATFORM       SIZE       BLOB SIZE
nginx                              v1        ff3d36d56246    23 seconds ago    linux/amd64    207MB      72.39MB
nginx                              v0        5ed8fcc66f4e    2 minutes ago     linux/amd64    207MB      72.39MB
registry.myk8s.cn/library/httpd    latest    4564ca760495    12 minutes ago    linux/amd64    162.2MB    58.5MB
registry.myk8s.cn/library/nginx    latest    5ed8fcc66f4e    23 minutes ago    linux/amd64    207MB      72.39MB
<none>                             <none>    5ed8fcc66f4e    37 minutes ago    linux/amd64    207MB      72.39MB

2.使用Commit镜像:使用nginx:v1镜像在本机的3000端口提供一个名为container2的容器
[root@k8s-master ~]~# nerdctl run -d -p 3000:80 --name container2 nginx:v1
eb4c803b8104b6ae66dba79b3d0e9cea01a7e5950ee834dded8575432e25025f
[root@k8s-master ~]~# nerdctl ps -a
CONTAINER ID    IMAGE        COMMAND          CREATED          STATUS    PORTS                   NAMES
eb4c803b8104    docker.io/library/nginx:v1    "/docker-entrypoint.…"    5 seconds ago    Up        0.0.0.0:3000->80/tcp    container2
6f8c50caccc3    docker.io/library/nginx:v0    "/docker-entrypoint.…"    2 minutes ago    Up        0.0.0.0:9000->80/tcp    container1


[root@k8s-master ~]~# nerdctl exec -it container2 /bin/bash
root@eb4c803b8104:/# echo hello ChengDu! > /usr/share/nginx/html/index.html
root@eb4c803b8104:/# exit
exit
[root@k8s-master ~]~# curl http://127.0.01:3000
hello ChengDu!

4.5.2 Dockerfile构建

   从零开始构建自己所需的镜像,在创建镜像之初把所需的各种设置和所需要的各种应用程序包含进去,生成的镜像可直接用于业务部署

   Dockerfile高频指令集:

   设计Dockerfile时应考虑: 容器应该是暂时的、避免安装不必要的软件包、每个容器只应该有一个用途、避免容器有过多的层、多行排序、建立缓存

1.创建dockerfile文件并构建
[root@k8s-master ~]~# vim dockerfile
FROM registry.myk8s.cn/library/httpd
MAINTAINER 252414302@qq.com
RUN echo 你好,中国 > /usr/local/apache2/htdocs/index.html
EXPOSE 80
WORKDIR /usr/local/apache/htdocs/

[root@k8s-master ~]~# nerdctl build -t httpd:v2 -f dockerfile .
[root@k8s-master ~]~# nerdctl images
REPOSITORY             TAG       IMAGE ID        CREATED               PLATFORM       SIZE       BLOB SIZE
httpd                              v2        43243a4ac567    2 seconds ago         linux/amd64    162.2MB    58.5MB
httpd                              v1        43243a4ac567    About a minute ago    linux/amd64    162.2MB    58.5MB
nginx                              v1        ff3d36d56246    11 minutes ago        linux/amd64    207MB      72.39MB
nginx                              v0        5ed8fcc66f4e    13 minutes ago        linux/amd64    207MB      72.39MB
registry.myk8s.cn/library/httpd    latest    4564ca760495    23 minutes ago        linux/amd64    162.2MB    58.5MB
registry.myk8s.cn/library/nginx    latest    5ed8fcc66f4e    34 minutes ago        linux/amd64    207MB      72.39MB
<none>                             <none>    5ed8fcc66f4e    48 minutes ago        linux/amd64    207MB      72.39MB


注明:如果文件名是Dockerfile时可不指定
nerdctl build -t web:v1 .

#参数说明:
   1.t 或 -tag:此选项允许为构建的镜像分配标签,以便于引用和版本控制
     示例用法: nerdctl build -t sampleapp:latest .

   2.f 或 file:如果 Dockerfile 的名称不是 “Dockerfile”,则可以使用此选项指定不同的 Dockerfile 名称或位置
     示例用法: nerdctl build -f ProductionDockerfile .
  
  
2.使用Dockerfile镜像:用httpd:v1的镜像在本机4000端口上提供一个名为dockerfilecontainer的容器
[root@k8s-master ~]~# nerdctl run -d -p 4000:80 --name dockerfilecontainer httpd:v1
[root@k8s-master ~]~# nerdctl ps -a
CONTAINER ID    IMAGE               COMMAND      CREATED           STATUS    PORTS                   NAMES
8ade7ac2dd39    docker.io/library/httpd:v1    "httpd-foreground"        8 seconds ago     Up        0.0.0.0:4000->80/tcp    dockerfilecontainer
eb4c803b8104    docker.io/library/nginx:v1    "/docker-entrypoint.…"    11 minutes ago    Up        0.0.0.0:3000->80/tcp    container2
6f8c50caccc3    docker.io/library/nginx:v0    "/docker-entrypoint.…"    14 minutes ago    Up        0.0.0.0:9000->80/tcp    container1

5 部署kubernetes集群

5.1 时间同步

  可选步骤,主要是让三个节点的时间同步。

# 下列步骤需要在集群中所有机器上完成

yum install -y chrony
sed -i 's/^pool.*/#&/' /etc/chrony.conf

cat >> /etc/chrony.conf << EOF
pool ntp1.aliyun.com iburst
EOF

systemctl restart chronyd
chronyc sources
# 修改时区,如果之前是这个时区就不用修改
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo 'Asia/Shanghai' > /etc/timezone

[root@k8s-master ~]# date
Wed Oct 29 15:57:38 CST 2025
[root@k8s-master ~]# cat /etc/timezone
Asia/Shanghai

[root@k8s-node1 ~]# date
Wed Oct 29 15:58:19 CST 2025
[root@k8s-node1 ~]# cat /etc/timezone
Asia/Shanghai

[root@k8s-node2 ~]# date
Wed Oct 29 15:59:21 CST 2025
[root@k8s-node2 ~]# cat /etc/timezone
Asia/Shanghai

[root@k8s-node3 ~]# date
Wed Oct 29 03:55:43 PM CST 2025
[root@k8s-node3 ~]# cat /etc/timezone
Asia/Shanghai

5.2 关闭交换分区

  Kubernetes 在1.34版本之前要求禁用 swap 分区,否则 kubelet 会拒绝启动。第一条命令临时关闭 swap,第二条命令注释掉 /etc/fstab 中的 swap 配置,防止重启后自动启用

  1.34以上的版本还是推荐禁用swap分区以提升稳定性

# 下列步骤需要在集群中所有机器上完成

# 关闭当前交换分区
swapoff -a
# 禁止开机自动启动交换分区
sed -i 's/.*swap.*/#&/' /etc/fstab

5.3 允许 iptables 检查桥接流量

  这些配置确保 Kubernetes 网络插件(如 Calico)能正确处理容器之间的网络流量:

   加载 br_netfilter 模块,使 Linux 能够检查桥接网络流量,将桥接的IPv4流量传递到iptables的链

   设置内核参数,允许 iptables 处理 IPv4 和 IPv6 桥接数据包。

   启用 IP 转发,支持容器之间的通信。

# 下列步骤需要在集群中所有机器上完成

# 加载内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

# 加载
modprobe overlay
modprobe br_netfilter

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF

# 加载生效
sysctl -p /etc/sysctl.d/k8s.conf
sysctl --system

# 查看是否加载完成
lsmod | grep br_netfilter 

[root@k8s-master ~]# lsmod | grep br_netfilter
br_netfilter           36864  0
bridge                417792  1 br_netfilter

[root@k8s-node1 ~]# lsmod | grep br_netfilter
br_netfilter           36864  0
bridge                417792  1 br_netfilter

[root@k8s-node2 ~]# lsmod | grep br_netfilter
br_netfilter           36864  0
bridge                417792  1 br_netfilter

[root@k8s-node3 ~]# lsmod | grep br_netfilter
br_netfilter           36864  0
bridge                417792  1 br_netfilter

5.4 配置免密登录

  可选操作,主要便于批量管理

# 以下步骤仅在master节点完成即可

ssh-keygen  # 连续回车三次
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.8.4
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.8.5
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.8.6
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.8.7

# 测试登录
[root@k8s-master ~]# ssh root@192.168.8.5
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Wed Oct 22 15:05:58 2025 from 192.168.8.4
[root@k8s-node1 ~]#

[root@k8s-master ~]# ssh root@192.168.8.6
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Wed Oct 22 15:05:27 2025 from 192.168.8.4
[root@k8s-node2 ~]#

[root@k8s-master ~]# ssh root@192.168.8.7
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Wed Oct 29 14:44:48 2025 from 192.168.8.1
[root@k8s-node3 ~]#

5.5 安装ipvs转发支持

  在kubernetes中Service有两种代理模型,一种是基于iptables的,一种是基于ipvs,两者对比ipvs的性能要高。默认使用iptables,所以要手动加载ipvs。

# 下列步骤需要在集群中所有机器上完成

# 安装依赖包
yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp

mkdir /etc/sysconfig/modules

cat > /etc/sysconfig/modules/ipvs.modules <<EOF
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack  
EOF

chmod +x /etc/sysconfig/modules/ipvs.modules 

# 执行脚本
/etc/sysconfig/modules/ipvs.modules

# 验证ipvs模块
[root@k8s-master ~]# lsmod | grep -e ip_vs -e nf_conntrack_ipv4
ip_vs_sh               12288  0
ip_vs_wrr              12288  0
ip_vs_rr               12288  0
ip_vs                 237568  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          229376  3 nf_nat,nft_ct,ip_vs
nf_defrag_ipv6         24576  2 nf_conntrack,ip_vs
libcrc32c              12288  5 nf_conntrack,nf_nat,nf_tables,xfs,ip_vs

[root@k8s-node1 ~]# lsmod | grep -e ip_vs -e nf_conntrack_ipv4
ip_vs_sh               12288  0
ip_vs_wrr              12288  0
ip_vs_rr               12288  0
ip_vs                 237568  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          229376  3 nf_nat,nft_ct,ip_vs
nf_defrag_ipv6         24576  2 nf_conntrack,ip_vs
libcrc32c              12288  5 nf_conntrack,nf_nat,nf_tables,xfs,ip_vs

[root@k8s-node2 ~]# lsmod | grep -e ip_vs -e nf_conntrack_ipv4
ip_vs_sh               12288  0
ip_vs_wrr              12288  0
ip_vs_rr               12288  0
ip_vs                 237568  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          229376  3 nf_nat,nft_ct,ip_vs
nf_defrag_ipv6         24576  2 nf_conntrack,ip_vs
libcrc32c              12288  5 nf_conntrack,nf_nat,nf_tables,xfs,ip_vs

[root@k8s-node3 ~]# lsmod | grep -e ip_vs -e nf_conntrack_ipv4
ip_vs_sh               12288  0
ip_vs_wrr              12288  0
ip_vs_rr               12288  0
ip_vs                 237568  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          229376  3 nf_nat,nft_ct,ip_vs
nf_defrag_ipv6         24576  2 nf_conntrack,ip_vs
libcrc32c              12288  5 nf_conntrack,nf_nat,nf_tables,xfs,ip_vs

5.6 安装Docker、Containerd

  dockerd实际真实调用的还是containerd的api接口,containerd是dockerd和runC之间的一个中间交流组件。所以启动docker服务的时候,也会启动containerd服务的。

  kubernets自v1.24.0后,就不再使用docker.shim,替换采用containerd作为容器运行时端点。因此需要安装containerd(在docker的基础下安装),上面安装docker的时候就自动安装了containerd了。这里的docker只是作为客户端而已。容器引擎还是containerd。

  可以直接安装container.io,而不用安装docker

# 获取阿里云YUM源
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装yum-config-manager配置工具
yum -y install yum-utils

# 设置yum源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装docker-ce版本
yum install -y docker-ce
# 启动并设置开机自启动
systemctl enable --now docker

# 查看版本号
docker --version
# 查看版本具体信息
docker version

# Docker镜像源设置
# 修改文件 /etc/docker/daemon.json,没有这个文件就创建
# 添加以下内容后,重启docker服务:
cat >/etc/docker/daemon.json<<EOF
{
"registry-mirrors": [
"https://registry.cn-hangzhou.aliyuncs.com",
"https://docker.mirrors.ustc.edu.cn",
"http://hub-mirror.c.163.com",
"https://docker.1panel.live",
"https://hub.littlediary.cn",
"https://docker.kejilion.pro",
"https://docker.1ms.run",
"https://lispy.org",
"https://docker.xiaogenban1993.com",
"https://docker.xuanyuan.me",
"https://docker.mybacc.com",
"https://docker-0.unsee.tech",
"https://dockerpull.cn"
 ]
}
EOF

# 加载启动Docker
systemctl enable --now docker

# 查看
systemctl status docker containerd

5.7 配置k8s在国内的yum源

  配置南京大学软件仓库进行加速,本次安装的k8s版本是1.34

# 下列步骤需要在集群中所有机器上完成

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.nju.edu.cn/kubernetes/core%3A/stable%3A/v1.33/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.nju.edu.cn/kubernetes/core%3A/stable%3A/v1.33/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

yum clean all
yum makecache

# 查看所有的可用版本
yum list kubelet --showduplicates | sort -r |grep 1.34

[root@k8s-master ~]# yum list kubelet --showduplicates | sort -r |grep 1.34

5.8 安装kubectl、kubelet和kubeadm

  安装kubelet kubeadm kubectl这三个包,把kubelet服务启动一下

# 下列步骤需要在集群中所有机器上完成

# 安装指定版本
yum install -y kubectl-1.34.1 kubelet-1.34.1 kubeadm-1.34.1

# 若不指定版本默认安装最高版本
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

# 安装包解释
  1.kubectl是命令行工具
  2.kubeadm仅是一个集群搭建工具,不涉及启动
  3.kubelet是一个守护进程程序,由kubeadm在搭建过程中自动启动,这里仅设置开机启动即可
sudo systemctl enable --now kubelet

5.9 添加命令自动补齐功能

  启用 bash 自动补齐,提高命令行效率,避免拼写错误。

# 下列步骤需要在集群中所有机器上完成

kubectl completion bash > /etc/bash_completion.d/kubectl
kubeadm completion bash > /etc/bash_completion.d/kubeadm
source /etc/bash_completion.d/kubectl
source /etc/bash_completion.d/kubeadm

5.10 集成Containerd

  crictl 是一个用来管理容器运行时的命令行工具,它就像是一个“中间人”,帮助 Kubernetes 和容器运行时(比如 containerd)之间进行通信。

  Kubernetes 通过 CRI 与容器运行时通信。这里使用 crictl 工具配置运行时接口:

   如果使用 cri-dockerd,则指向 /run/cri-dockerd.sock

   如果使用 containerd,则指向 /run/containerd/containerd.sock

  1.runtime-endpoint

   这个字段告诉 crictl,容器运行时(containerd)的运行时接口地址在哪里。这里写的是 unix:///run/containerd/containerd.sock,意思就是通过 Unix 套接字(socket)的方式,连接到 /run/containerd/containerd.sock 这个地址。简单来说,就是告诉 crictl 怎么和 containerd 通信。

  2.image-endpoint

   这个字段和 runtime-endpoint 类似,不过它是用来指定镜像服务的接口地址。这里也是 unix:///run/containerd/containerd.sock,说明镜像服务和运行时服务是同一个地址,都是通过 containerd 来管理的。

# 下列步骤需要在集群中所有机器上完成

# crictl config --set runtime-endpoint=unix:///run/containerd/containerd.sock
# crictl config --set image-endpoint=unix:///run/containerd/containerd.sock
# crictl images

cat > /etc/crictl.yaml <<-'EOF'
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

# 集成是否成功,可以用下面的命令来简单检查一下,不报错就是成功了
[root@k8s-master ~]# crictl images
IMAGE               TAG                 IMAGE ID            SIZE

[root@k8s-node1 ~]# crictl images
IMAGE               TAG                 IMAGE ID            SIZE

[root@k8s-node2 ~]# crictl images
IMAGE               TAG                 IMAGE ID            SIZE

[root@k8s-node3 ~]# crictl images
IMAGE               TAG                 IMAGE ID            SIZE

# 顺便给crictl做一个命令补齐功能
crictl completion bash > /etc/bash_completion.d/crictl
source /etc/bash_completion.d/crictl

5.11 开通防火墙

# 下列步骤需要在集群中所有机器上完成

1.开启 IP 隧道协议(IP-in-IP)
  sudo firewall-cmd --zone=public --add-protocol=ipip --permanent

2.开启 BGP 所需的 TCP 179 端口
  sudo firewall-cmd --zone=public --add-port=179/tcp --permanent

3.开启 VXLAN 所需的 UDP 4789 端口
  sudo firewall-cmd --zone=public --add-port=4789/udp --permanent

4.开启 Wireguard 所需的 UDP 51820 端口
  sudo firewall-cmd --zone=public --add-port=51820/udp --permanent

5.开启 IPv6 Wireguard 所需的 UDP 51821 端口
  sudo firewall-cmd --zone=public --add-port=51821/udp --permanent

6.开启 Typha 代理所需的 TCP 5473 端口
  sudo firewall-cmd --zone=public --add-port=5473/tcp --permanent

7.开启 Kubernetes API (kube-apiserver) 所需的 TCP 4436443 端口
  sudo firewall-cmd --zone=public --add-port=443/tcp --permanent
  sudo firewall-cmd --zone=public --add-port=6443/tcp --permanent

8.开启 Calico Enterprise API 服务器所需的 TCP 80805443 端口
  sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
  sudo firewall-cmd --zone=public --add-port=5443/tcp --permanent

9.开启 calico-node (Felix, BIRD, confd) 所需的 TCP 9090 端口
  sudo firewall-cmd --zone=public --add-port=9090/tcp --permanent

10.开启 Prometheus 指标所需的 TCP 9081 端口
  sudo firewall-cmd --zone=public --add-port=9081/tcp --permanent

11.开启 Prometheus BGP 指标所需的 TCP 9900 端口
  sudo firewall-cmd --zone=public --add-port=9900/tcp --permanent

12.开启 Elasticsearch with fluentd 数据存储所需的 TCP 9200 端口
  sudo firewall-cmd --zone=public --add-port=9200/tcp --permanent

13.开启 Elasticsearch 云 (ECK) 所需的 TCP 9443 端口
  sudo firewall-cmd --zone=public --add-port=9443/tcp --permanent

14.开启 Elasticsearch 网关所需的 TCP 5444 端口
  sudo firewall-cmd --zone=public --add-port=5444/tcp --permanent

15.开启 Kibana 所需的 TCP 5601 端口
  sudo firewall-cmd --zone=public --add-port=5601/tcp --permanent

16.开启 数据包捕获 API 所需的 TCP 8444 端口
  sudo firewall-cmd --zone=public --add-port=8444/tcp --permanent

17.开启 Calico Enterprise Manager UI 所需的 TCP 9443 端口
  sudo firewall-cmd --zone=public --add-port=9443/tcp --permanent

18.开启 多集群管理所需的 TCP 9449 端口
  sudo firewall-cmd --zone=public --add-port=9449/tcp --permanent

19.开启 出口网关所需的 UDP 4790 端口
  sudo firewall-cmd --zone=public --add-port=4790/udp --permanent

20.重新加载防火墙配置,使更改生效
  sudo firewall-cmd --reload

5.12 集群部署

  下方kubeadm.yaml中name字段必须在网络中可被解析,也可以将解析记录添加到集群中所有机器的/etc/hosts中

  这个初始化集群部署的操作只能在k8s-master上执行

  这里生产了k8s安装所需要的配置文件,将配置文件中的API服务器地址改成本地的IP,然后集群名字我们用的k8s-master,容器镜像拉取选择了阿里云,为将来的pod网络预留了一个172.16.0.0/16

# 以下步骤仅在master节点完成即可

kubeadm config print init-defaults > kubeadm.yaml
sed -i 's/.*advert.*/  advertiseAddress: 192.168.8.4/g' kubeadm.yaml
sed -i 's/.*name.*/  name: k8s-master/g' kubeadm.yaml
sed -i 's|imageRepo.*|imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers|g' kubeadm.yaml
sed -i "/^\\s*networking:/a\\  podSubnet: 172.16.0.0/16" kubeadm.yaml

  生成默认配置文件并进行定制:

   设置主节点 IP 地址。

   设置集群名,这个名称要求集群之间能互相解析。

   使用阿里云镜像源加速拉取镜像。

   设置 Pod 网段(与 Calico 配置保持一致)。

   指定 CRI socket(仅当使用 cri-dockerd 时需要)。

  使用 kubeadm init 初始化集群,成功后会输出 kubeadm join 命令,用于添加node节点。

# 以下步骤仅在master节点完成即可

modprobe br_netfilter 
kubeadm init --config kubeadm.yaml

  出现下面的提示就是成功了,保存好join的命令

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.8.4:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:cdef263e1fe962f26a37ac949b28b78f83f2c84cbd43461006a0bb72cc63edfc

  授权管理权限,将集群配置文件复制到当前用户目录,使 kubectl 能正常访问和管理集群。

# 以下步骤仅在master节点完成即可

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

5.13 部署Calico网络插件

  Calico网络插件部署的操作只能在k8s-master上执行

在开始之前,请打开以下calico官方网址,将所有镜像都下载到机器上,不然无法成功

https://docs.tigera.io/calico/3.30/operations/image-options/alternate-registry#push-calico-images-to-your-registry

1.Use the following commands to pull the required Calico images.

nerdctl pull quay.io/tigera/operator:v1.38.7
nerdctl pull calico/node:v3.30.4
nerdctl pull calico/cni:v3.30.4
nerdctl pull calico/apiserver:v3.30.4
nerdctl pull calico/kube-controllers:v3.30.4
nerdctl pull calico/envoy-gateway:v3.30.4 
nerdctl pull calico/envoy-proxy:v3.30.4
nerdctl pull calico/envoy-ratelimit:v3.30.4
nerdctl pull calico/dikastes:v3.30.4
nerdctl pull calico/pod2daemon-flexvol:v3.30.4
nerdctl pull calico/key-cert-provisioner:v3.30.4
nerdctl pull calico/goldmane:v3.30.4
nerdctl pull calico/whisker:v3.30.4
nerdctl pull calico/whisker-backend:v3.30.4

2.Retag the images with the name of your registry $REGISTRY.

nerdctl tag quay.io/tigera/operator:v1.38.7 harbor.cncf.net:447/library/quay.io/tigera/operator:v1.38.7
nerdctl tag calico/node:v3.30.4 harbor.cncf.net:447/library/calico/node:v3.30.4
nerdctl tag calico/cni:v3.30.4 harbor.cncf.net:447/library/calico/cni:v3.30.4
nerdctl tag calico/apiserver:v3.30.4 harbor.cncf.net:447/library/calico/apiserver:v3.30.4
nerdctl tag calico/kube-controllers:v3.30.4 harbor.cncf.net:447/library/calico/kube-controllers:v3.30.4
nerdctl tag calico/envoy-gateway:v3.30.4 harbor.cncf.net:447/library/calico/envoy-gateway:v3.30.4
nerdctl tag calico/envoy-proxy:v3.30.4 harbor.cncf.net:447/library/calico/envoy-proxy:v3.30.4
nerdctl tag calico/envoy-ratelimit:v3.30.4 harbor.cncf.net:447/library/calico/envoy-ratelimit:v3.30.4
nerdctl tag calico/dikastes:v3.30.4 harbor.cncf.net:447/library/calico/dikastes:v3.30.4
nerdctl tag calico/pod2daemon-flexvol:v3.30.4 harbor.cncf.net:447/library/calico/pod2daemon-flexvol:v3.30.4
nerdctl tag calico/key-cert-provisioner:v3.30.4 harbor.cncf.net:447/library/calico/key-cert-provisioner:v3.30.4
nerdctl tag calico/goldmane:v3.30.4 harbor.cncf.net:447/library/calico/goldmane:v3.30.4
nerdctl tag calico/whisker:v3.30.4 harbor.cncf.net:447/library/calico/whisker:v3.30.4
nerdctl tag calico/whisker-backend:v3.30.4 harbor.cncf.net:447/library/calico/whisker-backend:v3.30.4

镜像下载后,用下面这个operator把calico组件给安装上:

kubectl create -f https://raw.gitmirror.com/projectcalico/calico/v3.31.0/manifests/operator-crds.yaml
kubectl create -f https://raw.gitmirror.com/projectcalico/calico/v3.31.0/manifests/tigera-operator.yaml

[root@k8s-master ~]# kubectl create -f https://raw.gitmirror.com/projectcalico/calico/v3.31.0/manifests/tigera-operator.yaml
namespace/tigera-operator created
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator-secrets created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
rolebinding.rbac.authorization.k8s.io/tigera-operator-secrets created
deployment.apps/tigera-operator created

  1.operator-crds.yaml 的作用

   这个文件用于部署 Calico Operator 的 CRDs(Custom Resource Definitions,自定义资源定义)

   CRDs 是 Kubernetes 中的一种扩展机制,允许你定义新的资源类型。

   operator-crds.yaml 中定义了 Calico Operator 所需的资源类型,比如 InstallationIPPoolFelixConfiguration 等。

   这些资源类型是 Calico Operator 管理网络组件的基础,必须先创建它们,Operator 才能识别和处理后续的配置。

   简单来说:这是为 Calico Operator 打好“地基”,让 Kubernetes 能识别 Calico 的专属资源类型。

  2.custom-resources.yaml 的作用

   这个文件是一个 Calico 的自定义资源配置文件,用于告诉 Calico Operator 如何部署和配置网络插件。

   它定义了一个 Installation 资源,指定 Calico 的网络模式、IP 地址池等关键参数。

   其中的 ipPools 字段设置了 Pod 网络的地址范围(例如 172.16.0.0/16),必须与 kubeadm.yaml 中的 podSubnet 保持一致。

   应用该文件后,Calico Operator 会根据这些配置自动部署 Calico 的核心组件(如 calico-nodetypha 等)。

   简单来说:这是告诉 Calico Operator“怎么部署”,包括网络范围、组件行为等。

用下面的自定义资源设置一下calico在集群中的网段:

wget https://raw.gitmirror.com/projectcalico/calico/v3.31.0/manifests/custom-resources.yaml

[root@k8s-master ~]# wget https://raw.gitmirror.com/projectcalico/calico/v3.31.0/manifests/custom-resources.yaml

# 修改 custom-resources.yaml 中的 cidr 字段,确保与 kubeadm.yaml 中的 podSubnet 保持一致
[root@k8s-master ~]# vim custom-resources.yaml
......
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  # Configures Calico networking.
  calicoNetwork:
    ipPools:
    - name: default-ipv4-ippool
      blockSize: 26
      cidr: 172.16.0.0/16   #这里换成上面规定好的172.16.0.0/16
      encapsulation: VXLANCrossSubnet
      natOutgoing: Enabled
      nodeSelector: all()
......

将自定义资源发布到集群中:

  应用配置后,Calico 会自动部署网络组件,确保 Pod 间通信正常。

[root@k8s-master ~]# kubectl apply -f custom-resources.yaml
installation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created
goldmane.operator.tigera.io/default created
whisker.operator.tigera.io/default created

查询集群组件是否工作正常,正常应该都处于running:

[root@k8s-master ~]# kubectl get nodes
NAME         STATUS   ROLES           AGE   VERSION
k8s-master   Ready    control-plane   21m   v1.33.5

[root@k8s-master ~]# kubectl get pod -A
NAMESPACE         NAME                                       READY   STATUS    RESTARTS   AGE
calico-system     calico-apiserver-69cbdcdcf5-gbgts          1/1     Running   0          110s
calico-system     calico-apiserver-69cbdcdcf5-rnd5r          1/1     Running   0          110s
calico-system     calico-kube-controllers-85d75d757c-j2mq4   1/1     Running   0          109s
calico-system     calico-node-6zmpq                          1/1     Running   0          109s
calico-system     calico-typha-9bfd898b7-t85vm               1/1     Running   0          109s
calico-system     csi-node-driver-dwxk9                      2/2     Running   0          109s
calico-system     goldmane-5cfbfbffd6-8lmkw                  1/1     Running   0          110s
calico-system     whisker-84c887fc48-d8vqm                   2/2     Running   0          64s
kube-system       coredns-746c97786-h8mnt                    1/1     Running   0          20m
kube-system       coredns-746c97786-ndcwk                    1/1     Running   0          20m
kube-system       etcd-k8s-master                            1/1     Running   0          20m
kube-system       kube-apiserver-k8s-master                  1/1     Running   0          20m
kube-system       kube-controller-manager-k8s-master         1/1     Running   0          20m
kube-system       kube-proxy-rhxls                           1/1     Running   0          20m
kube-system       kube-scheduler-k8s-master                  1/1     Running   0          20m
tigera-operator   tigera-operator-75f6548d76-j4qzq           1/1     Running   0          8m23s

6 加入node节点

  加入节点操作需在所有的worker节点完成,这里要注意,Worker节点需要完成以下先决条件才能执行kubeadm join:

   1.Containerd部署

   2.Swap 分区关闭

   3.iptables 桥接流量的允许

   4.安装kubeadm等软件

   5.集成Containerd

   6.所有节点的/etc/hosts中互相添加对方的解析

  如果时间长忘记了join参数,可以在master节点上用以下方法重新生成

[root@k8s-master ~]# kubeadm token create --print-join-command
kubeadm join 192.168.8.4:6443 --token kquj54.8tqxdkslnhiq75pt --discovery-token-ca-cert-hash sha256:cdef263e1fe962f26a37ac949b28b78f83f2c84cbd43461006a0bb72cc63edfc

  如果有多个CRI对象,在worker节点上执行以下命令加入节点时,指定CRI对象,案例如下:

kubeadm join 192.168.8.4:6443 --token kquj54.8tqxdkslnhiq75pt --discovery-token-ca-cert-hash sha256:cdef263e1fe962f26a37ac949b28b78f83f2c84cbd43461006a0bb72cc63edfc --cri-socket=unix:///run/containerd/containerd.sock

[root@k8s-node1 ~]# kubeadm join 192.168.8.4:6443 --token kquj54.8tqxdkslnhiq75pt --discovery-token-ca-cert-hash sha256:cdef263e1fe962f26a37ac949b28b78f83f2c84cbd43461006a0bb72cc63edfc --cri-socket=unix:///run/containerd/containerd.sock
......
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

[root@k8s-node2 ~]# kubeadm join 192.168.8.4:6443 --token kquj54.8tqxdkslnhiq75pt --discovery-token-ca-cert-hash sha256:cdef263e1fe962f26a37ac949b28b78f83f2c84cbd43461006a0bb72cc63edfc --cri-socket=unix:///run/containerd/containerd.sock
......
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

[root@k8s-node3 ~]# kubeadm join 192.168.8.4:6443 --token kquj54.8tqxdkslnhiq75pt --discovery-token-ca-cert-hash sha256:cdef263e1fe962f26a37ac949b28b78f83f2c84cbd43461006a0bb72cc63edfc --cri-socket=unix:///run/containerd/containerd.sock
......
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

  注意上描述命令最后的–cri-socket参数,在系统中部署了docker和cri-docker时,必须明确指明此参数,并将此参数指向我们的cri-docker,不然命令会报告有两个重复的CRI的错误,而我们部署的是containerd,就没这个问题

  在master机器上执行以下内容给节点打上node角色标签,便于资源调度和管理。

kubectl label nodes k8s-node1 node-role.kubernetes.io/node=
kubectl label nodes k8s-node2 node-role.kubernetes.io/node=
kubectl label nodes k8s-node3 node-role.kubernetes.io/node=
kubectl get nodes

[root@k8s-master ~]# kubectl label nodes k8s-node1 node-role.kubernetes.io/node=
node/k8s-node1 labeled

[root@k8s-master ~]# kubectl label nodes k8s-node2 node-role.kubernetes.io/node=
node/k8s-node2 labeled

[root@k8s-master ~]# kubectl label nodes k8s-node3 node-role.kubernetes.io/node=
node/k8s-node3 labeled

[root@k8s-master ~]# kubectl get nodes -o wide
NAME  STATUS   ROLES  AGE VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE KERNEL-VERSION   CONTAINER-RUNTIME
k8s-master   Ready    control-plane   25m    v1.33.5   192.168.8.4   <none>        Rocky Linux 9.6 (Blue Onyx)   5.14.0-570.42.2.el9_6.x86_64   containerd://2.1.4
k8s-node1    Ready    node            2m3s   v1.33.5   192.168.8.5   <none>        Rocky Linux 9.6 (Blue Onyx)   5.14.0-570.17.1.el9_6.x86_64   containerd://2.1.4
k8s-node2    Ready    node            119s   v1.33.5   192.168.8.6   <none>        Rocky Linux 9.6 (Blue Onyx)   5.14.0-570.17.1.el9_6.x86_64   containerd://2.1.4
k8s-node3    Ready    node            116s   v1.33.5   192.168.8.7   <none>        Rocky Linux 9.6 (Blue Onyx)   5.14.0-570.17.1.el9_6.x86_64   containerd://2.1.4

  开放node节点的防火墙:

# 开启 IP 隧道协议(IP-in-IP)
sudo firewall-cmd --zone=public --add-protocol=ipip --permanent

# 开启 BGP 所需的 TCP 179 端口
sudo firewall-cmd --zone=public --add-port=179/tcp --permanent

# 开启 VXLAN 所需的 UDP 4789 端口
sudo firewall-cmd --zone=public --add-port=4789/udp --permanent

# 开启 Wireguard 所需的 UDP 51820 端口
sudo firewall-cmd --zone=public --add-port=51820/udp --permanent

# 开启 IPv6 Wireguard 所需的 UDP 51821 端口
sudo firewall-cmd --zone=public --add-port=51821/udp --permanent

# 开启 Typha 代理所需的 TCP 5473 端口
sudo firewall-cmd --zone=public --add-port=5473/tcp --permanent

# 开启 Kubernetes API (kube-apiserver) 所需的 TCP 443 和 6443 端口
sudo firewall-cmd --zone=public --add-port=443/tcp --permanent
sudo firewall-cmd --zone=public --add-port=6443/tcp --permanent

# 开启 Calico Enterprise API 服务器所需的 TCP 8080 和 5443 端口
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --zone=public --add-port=5443/tcp --permanent

# 开启 calico-node (Felix, BIRD, confd) 所需的 TCP 9090 端口
sudo firewall-cmd --zone=public --add-port=9090/tcp --permanent

# 开启 Prometheus 指标所需的 TCP 9081 端口
sudo firewall-cmd --zone=public --add-port=9081/tcp --permanent

# 开启 Prometheus BGP 指标所需的 TCP 9900 端口
sudo firewall-cmd --zone=public --add-port=9900/tcp --permanent

# 开启 Elasticsearch with fluentd 数据存储所需的 TCP 9200 端口
sudo firewall-cmd --zone=public --add-port=9200/tcp --permanent

# 开启 Elasticsearch 云 (ECK) 所需的 TCP 9443 端口
sudo firewall-cmd --zone=public --add-port=9443/tcp --permanent

# 开启 Elasticsearch 网关所需的 TCP 5444 端口
sudo firewall-cmd --zone=public --add-port=5444/tcp --permanent

# 开启 Kibana 所需的 TCP 5601 端口
sudo firewall-cmd --zone=public --add-port=5601/tcp --permanent

# 开启 数据包捕获 API 所需的 TCP 8444 端口
sudo firewall-cmd --zone=public --add-port=8444/tcp --permanent

# 开启 Calico Enterprise Manager UI 所需的 TCP 9443 端口
sudo firewall-cmd --zone=public --add-port=9443/tcp --permanent

# 开启 多集群管理所需的 TCP 9449 端口
sudo firewall-cmd --zone=public --add-port=9449/tcp --permanent

# 开启 出口网关所需的 UDP 4790 端口
sudo firewall-cmd --zone=public --add-port=4790/udp --permanent

# 重新加载防火墙配置,使更改生效
sudo firewall-cmd --reload

  一定要开通端口,不然calico的node pod会报告这些日志

2025-05-23 09:26:26.390 [INFO][4264] tunnel-ip-allocator/discovery.go 188: (Re)discovering Typha endpoints using the Kubernetes API...
W0523 09:26:26.393216    4264 warnings.go:70] v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice
2025-05-23 09:26:26.393 [INFO][4264] tunnel-ip-allocator/discovery.go 243: Found ready Typha addresses. addresses=[]discovery.Typha{discovery.Typha{Addr:"192.168.8.4:5473", IP:"192.168.8.4", NodeName:(*string)(0xc000b31790)}}
2025-05-23 09:26:26.393 [FATAL][4264] tunnel-ip-allocator/startsyncerclient.go 86: Failed to connect to Typha error=failed to load next Typha address to try: tried all available discovered addresses

7 确认集群状态

#这里的pod必须是全部running   到此已经成功部署了k8s集群
[root@k8s-master ~]# kubectl get nodes
NAME         STATUS   ROLES           AGE     VERSION
k8s-master   Ready    control-plane   26m     v1.33.5
k8s-node1    Ready    node            3m15s   v1.33.5
k8s-node2    Ready    node            3m11s   v1.33.5
k8s-node3    Ready    node            3m8s    v1.33.5
[root@k8s-master ~]# kubectl get pod -A
NAMESPACE         NAME                                       READY   STATUS    RESTARTS   AGE
calico-system     calico-apiserver-69cbdcdcf5-gbgts          1/1     Running   0          8m45s
calico-system     calico-apiserver-69cbdcdcf5-rnd5r          1/1     Running   0          8m45s
calico-system     calico-kube-controllers-85d75d757c-j2mq4   1/1     Running   0          8m44s
calico-system     calico-node-6zmpq                          1/1     Running   0          8m44s
calico-system     calico-node-95brq                          1/1     Running   0          3m15s
calico-system     calico-node-lvljl                          1/1     Running   0          3m18s
calico-system     calico-node-q7ptn                          1/1     Running   0          3m22s
calico-system     calico-typha-9bfd898b7-7q9st               1/1     Running   0          3m15s
calico-system     calico-typha-9bfd898b7-t85vm               1/1     Running   0          8m44s
calico-system     csi-node-driver-4fwxj                      2/2     Running   0          3m15s
calico-system     csi-node-driver-d7x5w                      2/2     Running   0          3m18s
calico-system     csi-node-driver-dwxk9                      2/2     Running   0          8m44s
calico-system     csi-node-driver-kqxq6                      2/2     Running   0          3m22s
calico-system     goldmane-5cfbfbffd6-8lmkw                  1/1     Running   0          8m45s
calico-system     whisker-84c887fc48-d8vqm                   2/2     Running   0          7m59s
kube-system       coredns-746c97786-h8mnt                    1/1     Running   0          26m
kube-system       coredns-746c97786-ndcwk                    1/1     Running   0          26m
kube-system       etcd-k8s-master                            1/1     Running   0          27m
kube-system       kube-apiserver-k8s-master                  1/1     Running   0          27m
kube-system       kube-controller-manager-k8s-master         1/1     Running   0          27m
kube-system       kube-proxy-fwx7d                           1/1     Running   0          3m15s
kube-system       kube-proxy-qp87t                           1/1     Running   0          3m18s
kube-system       kube-proxy-rhxls                           1/1     Running   0          26m
kube-system       kube-proxy-sjrxc                           1/1     Running   0          3m22s
kube-system       kube-scheduler-k8s-master                  1/1     Running   0          27m
tigera-operator   tigera-operator-75f6548d76-j4qzq           1/1     Running   0          15m

8 重置集群

  如果在安装好集群的情况下,想重复练习初始化集群,或者包括初始化集群报错在内的任何原因,想重新初始化集群时,可以用下面的方法重置集群,重置后,集群就会被删除,可以用于重新部署,一般来说,这个命令仅用于k8s-master这个节点

1.kubeadm reset 清除集群配置。
2.手动清理 CNI 网络配置、iptables 规则和 kubeconfig 文件。
3.清理后可重新部署集群

[root@k8s-master ~]# kubeadm reset --cri-socket=unix:///run/containerd/containerd.sock
...
[reset] Are you sure you want to proceed? [y/N]: y
...
The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d

The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.

If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.

The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.

# 根据提示,手工完成文件和规则的清理
[root@k8s-master ~]# rm -rf /etc/cni/net.d
[root@k8s-master ~]# iptables -F
[root@k8s-master ~]# rm -rf $HOME/.kube/config

# 清理后就可以重新部署集群了

文章作者: 罗宇
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗宇 !
  目录