在rockylinux 10上使用国内源部署Kubernetes1.34.0集群(1主2从),容器运行时使用Containerd2.x


✅ 部署目标

角色IP 地址操作系统组件
Master1192.168.153.143rockylinux 10kube-apiserver, etcd, kube-scheduler, kube-controller-manager, Containerd2.x
Worker1192.168.153.144rockylinux 10kubelet, Containerd2.x, kube-proxy
Worker2192.168.153.145rockylinux 10kubelet, Containerd2.x, kube-proxy

🚩 前置要求

  • 所有节点硬件满足:2核CPU、2GB+内存、30GB+硬盘
  • 所有节点之间网络互通(ping 通)
  • 可访问国内镜像源(阿里云、清华等)
  • 关闭 Swap
  • 时间同步
  • 禁用防火墙或开放必要端口

🧩 第一步:所有节点通用初始化(Master + Worker)

1.1 修改设置主机ip

sudo vi /etc/NetworkManager/system-connections/ens160.nmconnection
[connection]
id=ens160
uuid=82a1609d-9a7f-36cd-ae1c-2c2e5fe9fbbb
type=ethernet
autoconnect-priority=-999
interface-name=ens160
timestamp=1757254896

[ethernet]

[ipv4]
method=manual
address1=192.168.153.143/24,192.168.153.2
dns=119.29.29.29;8.8.8.8;114.114.114.114

[ipv6]
addr-gen-mode=eui64
method=auto

[proxy]
nmcli c reload
nmcli c up ens160

1.2 域名解析相关检查与设置

#sudo dnf install bind-utils
#dig -t a xxx域名 或nslookup xxx域名

1.3 设置主机名(分别在各节点执行)

# 在 192.168.153.143 执行
sudo hostnamectl set-hostname k8s-master1

# 在 192.168.153.144 执行
sudo hostnamectl set-hostname k8s-worker1

# 在 192.168.153.145 执行
sudo hostnamectl set-hostname k8s-worker2

1.4 配置 hosts(所有节点执行)

sudo tee /etc/hosts << 'EOF'
192.168.153.143 k8s-master1
192.168.153.144 k8s-worker1
192.168.153.145 k8s-worker2
EOF

验证:ping worker1 等是否通。

1.5 禁用 Swap

sudo swapoff -a
sudo sed -ri 's/.*swap.*/#&/' /etc/fstab

1.6 配置内核转发及网桥过滤

#配置内核转发及网桥过滤
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
overlay
EOF

#本次执行,手动加载此模块
# modprobe overlay
# modprobe br_netfilter

查看已加载的模块
#lsmod | egrep "overlay"
overlay               212992  0
#lsmod | egrep "br_netfilter"
br_netfilter           32768  0
bridge                421888  1 br_netfilter

#添加网桥过滤及内核转发配置文件
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
net.ipv4.ip_local_port_range = 1024 65535
EOF
#加载内核参数
sudo sysctl --system

1.7 安装ipset及ipvsadm

#安装ipset及ipvsadm
# sudo dnf install ipset ipvsadm
#配置ipvsadm模块加载添加需要加载的模块
cat << EOF | sudo tee /etc/modules-load.d/ipvs.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF
#创建加载模块脚本文件
cat << EOF | sudo tee ipvs.sh
#!/bin/sh
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack
EOF
# lsmod | egrep "ip_vs"
ip_vs_sh               12288  0
ip_vs_wrr              12288  0
ip_vs_rr               12288  0
ip_vs                 221184  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack          196608  1 ip_vs
nf_defrag_ipv6         24576  2 nf_conntrack,ip_vs
libcrc32c              12288  4 nf_conntrack,btrfs,raid456,ip_vs

1.8 关闭防火墙

[root@localhost ~]# firewall-cmd --state
running
[root@localhost ~]# systemctl disable --now firewalld
Removed '/etc/systemd/system/multi-user.target.wants/firewalld.service'.
Removed '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'.
[root@localhost ~]# firewall-cmd --state
not running

1.9 关闭selinux

[root@localhost ~]# sestatus
SELinux status:                 enabled
[root@localhost ~]# vi /etc/selinux/config
..SELINUX=disabled..
[root@localhost ~]# sestatus
SELinux status:                 disabled

1.10 时间同步

[root@localhost ~]# systemctl status chronyd
● chronyd.service - NTP client/server
     Loaded: loaded (/usr/lib/systemd/system/chronyd.service; enabled; preset: enabled)
     Active: active (running) since Sun 2025-09-07 16:29:37 CST; 4min 5s ago
 Invocation: ec7746d1047741e9b99b5ff798990e2e
       Docs: man:chronyd(8)
             man:chrony.conf(5)
    Process: 832 ExecStart=/usr/sbin/chronyd $OPTIONS (code=exited, status=0/SUCCESS)
   Main PID: 844 (chronyd)
      Tasks: 1 (limit: 22948)
     Memory: 3.5M (peak: 4.1M)
        CPU: 57ms
     CGroup: /system.slice/chronyd.service
             └─844 /usr/sbin/chronyd -F 2

9月 07 16:29:36 localhost systemd[1]: Starting chronyd.service - NTP client/server...
9月 07 16:29:37 localhost chronyd[844]: chronyd version 4.6.1 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS +SECHASH +IPV6 +DEBUG)
9月 07 16:29:37 localhost chronyd[844]: Frequency 9.979 +/- 0.216 ppm read from /var/lib/chrony/drift
9月 07 16:29:37 localhost chronyd[844]: Loaded seccomp filter (level 2)
9月 07 16:29:37 localhost systemd[1]: Started chronyd.service - NTP client/server.
9月 07 16:29:48 localhost.localdomain chronyd[844]: Selected source 139.199.215.251 (2.rocky.pool.ntp.org)
[root@localhost ~]# timedatectl
               Local time: 日 2025-09-07 16:34:19 CST
           Universal time: 日 2025-09-07 08:34:19 UTC
                 RTC time: 日 2025-09-07 08:34:20
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

🐳 第二步:安装 Containerd2.x(所有节点)

使用二进制源安装 Containerd 2.1.4

2.1 替换Rocky Linux 10的yum源

# 备份原有源
cp -r /etc/yum.repos.d /etc/yum.repos.d.backup

# 替换为阿里云源(Rocky Linux 10)
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
    -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://mirrors.aliyun.com/rockylinux|g' \
    -i.bak /etc/yum.repos.d/rocky-*.repo

# 清理并生成缓存
dnf clean all && dnf makecache

2.2 cri-containerd2.x 安装

containerd2.x 官方存储库适用于 Red Hat 系发行版(如 Rocky Linux)

-rw-r--r-- 1 root root 55350615  9月10日 21:57 cni-plugins-linux-amd64-v1.8.0.tgz
-rw-r--r-- 1 root root 33205327  9月10日 21:57 containerd-2.1.4-linux-amd64.tar.gz
-rw-r--r-- 1 root root 13059800  9月10日 21:57 runc.amd64
#tar Cxzvf /usr/local containerd-2.1.4-linux-amd64.tar.gz
bin/
bin/containerd-stress
bin/ctr
bin/containerd
bin/containerd-shim-runc-v2
#install -m 755 runc.amd64 /usr/local/sbin/runc
#mkdir -p /opt/cni/bin
#tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.8.0.tgz
./
./README.md
./static
./host-device
./ipvlan
./dhcp
./LICENSE
./portmap
./tap
./host-local
./vlan
./loopback
./sbr
./firewall
./bandwidth
./bridge
./vrf
./macvlan
./tuning
./dummy
./ptp
# vi /etc/systemd/system/containerd.service

# Copyright The containerd Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target dbus.service

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd

Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5

# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity

# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now containerd

2.3 验证

[root@localhost ~]# systemctl status containerd
● containerd.service - containerd container runtime
     Loaded: loaded (/etc/systemd/system/containerd.service; enabled; preset: disabled)
     Active: active (running) since Wed 2025-09-10 22:08:09 CST; 14s ago
 Invocation: 048bdd51ee7742d0aaf6c6fd4684267f
       Docs: https://containerd.io
    Process: 4999 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
   Main PID: 5000 (containerd)
      Tasks: 8
     Memory: 26.1M (peak: 32.6M)
        CPU: 161ms
     CGroup: /system.slice/containerd.service
             └─5000 /usr/local/bin/containerd

9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.473584207+08:00" level=info msg="Start cni network conf syncer for default"
9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.473644677+08:00" level=info msg="Start streaming server"
9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.473669499+08:00" level=info msg="Registered namespace \"k8s.io\" with NRI"
9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.473684952+08:00" level=info msg="runtime interface starting up..."
9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.473702573+08:00" level=info msg="starting plugins..."
9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.473735546+08:00" level=info msg="Synchronizing NRI (plugin) with current runtime state"
9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.474294308+08:00" level=info msg=serving... address=/run/containerd/containerd.sock.ttrpc
9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.474362694+08:00" level=info msg=serving... address=/run/containerd/containerd.sock
9月 10 22:08:09 localhost.localdomain systemd[1]: Started containerd.service - containerd container runtime.
9月 10 22:08:09 localhost.localdomain containerd[5000]: time="2025-09-10T22:08:09.476286188+08:00" level=info msg="containerd successfully booted in 0.090654s"

2.4 配置 containerd2.x 使用国内镜像源并从国内源拉取镜像

2.4.1. 定位配置文件

containerd 的配置文件通常位于 /etc/containerd/config.toml。 如果文件不存在,可通过以下命令生成默认配置:

sudo mkdir -p /etc/containerd
sudo containerd config default > /etc/containerd/config.toml

2.4.2. 修改配置文件

containerd 2.x 中,配置国内镜像源可以通过修改 /etc/containerd/config.toml 文件实现。


1. 编辑配置文件

打开 /etc/containerd/config.toml 文件,找到或添加以下配置段落:

[plugins."io.containerd.cri.v1.images".registry]
  config_path = "/etc/containerd/certs.d"

此配置表示将镜像仓库的配置文件统一放在 /etc/containerd/certs.d 目录下。


2. 创建镜像源配置目录

为每个需要配置的镜像仓库(如 docker.ioregistry.k8s.io 等)创建对应的目录和配置文件:

mkdir -p /etc/containerd/certs.d/docker.io
mkdir -p /etc/containerd/certs.d/registry.k8s.io

3. 配置镜像加速规则
(1) 配置 docker.io 的镜像加速

编辑文件 /etc/containerd/certs.d/docker.io/hosts.toml,添加以下内容:

server = "https://docker.io"

[host."https://docker.m.daocloud.io"]
  capabilities = ["pull", "resolve"]

[host."https://docker.1ms.run"]
  capabilities = ["pull", "resolve"]

[host."https://docker.xuanyuan.me"]
  capabilities = ["pull", "resolve"]

[host."https://docker.1panel.live"]
  capabilities = ["pull", "resolve"]

[host."https://hub.uuuadc.top"]
  capabilities = ["pull", "resolve"]

[host."https://docker.anyhub.us.kg"]
  capabilities = ["pull", "resolve"]

[host."https://dockerhub.jobcher.com"]
  capabilities = ["pull", "resolve"]

[host."https://dockerhub.icu"]
  capabilities = ["pull", "resolve"]

[host."https://docker.ckyl.me"]
  capabilities = ["pull", "resolve"]

[host."https://docker.awsl9527.cn"]
  capabilities = ["pull", "resolve"]

[host."https://b9pmyelo.mirror.aliyuncs.com"]
  capabilities = ["pull", "resolve"]

[host."https://docker.mirrors.ustc.edu.cn"]
  capabilities = ["pull", "resolve"]

[host."https://registry.docker-cn.com"]
  capabilities = ["pull", "resolve"]

替换 <你的阿里云加速器> 为你的阿里云账号专属加速器地址(例如 https://45hrqeao.mirror.aliyuncs.com)。

(2) 配置 registry.k8s.io 的镜像加速

编辑文件 /etc/containerd/certs.d/registry.k8s.io/hosts.toml,添加以下内容:

server = "https://registry.k8s.io"

[host."https://docker.m.daocloud.io"]
  capabilities = ["pull", "resolve"]

[host."https://docker.1ms.run"]
  capabilities = ["pull", "resolve"]

[host."https://docker.xuanyuan.me"]
  capabilities = ["pull", "resolve"]

[host."https://docker.1panel.live"]
  capabilities = ["pull", "resolve"]

[host."https://hub.uuuadc.top"]
  capabilities = ["pull", "resolve"]

[host."https://docker.anyhub.us.kg"]
  capabilities = ["pull", "resolve"]

[host."https://dockerhub.jobcher.com"]
  capabilities = ["pull", "resolve"]

[host."https://dockerhub.icu"]
  capabilities = ["pull", "resolve"]

[host."https://docker.ckyl.me"]
  capabilities = ["pull", "resolve"]

[host."https://docker.awsl9527.cn"]
  capabilities = ["pull", "resolve"]

[host."https://b9pmyelo.mirror.aliyuncs.com"]
  capabilities = ["pull", "resolve"]

[host."https://docker.mirrors.ustc.edu.cn"]
  capabilities = ["pull", "resolve"]

[host."https://registry.docker-cn.com"]
  capabilities = ["pull", "resolve"]

4. 验证配置

重启 containerd 服务(可选,因为 certs.d 目录的配置支持热加载):

systemctl restart containerd
[root@k8s-master1 certs.d]# systemctl status containerd
● containerd.service - containerd container runtime
     Loaded: loaded (/etc/systemd/system/containerd.service; enabled; preset: disabled)
     Active: active (running) since Thu 2025-09-11 21:56:25 CST; 9s ago
 Invocation: 34db6f7ae8b44e9aafa150003051ef32
       Docs: https://containerd.io
    Process: 5134 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
   Main PID: 5135 (containerd)
      Tasks: 72
     Memory: 118.2M (peak: 138.4M)
        CPU: 497ms
     CGroup: /system.slice/containerd.service
             ├─3943 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 9900306183a436bf6ca6e0fae23ba3f831bd921a4669a57896161684f55bea23 -address /run/containerd/containerd.sock
             ├─3947 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id a3aa2789144cfaa1bac9cbce92e075bc034c8efc3488d771fa5f139c1cee6f52 -address /run/containerd/containerd.sock
             ├─3964 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 869c8469e4f4bf74fa1a53d78d457710716dd552dfac5c74ba165f48380e5716 -address /run/containerd/containerd.sock
             ├─4035 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 9e5e158e9df0edccb4b4f2fdad47aa6fd6a19f9c7eb5d338857f8c98241e04c3 -address /run/containerd/containerd.sock
             ├─4683 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 1bc38b638cd8daf55a9defa90cbcd9d45b0979cd6d77d4494c316423ea826579 -address /run/containerd/containerd.sock
             └─5135 /usr/local/bin/containerd

9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.477462585+08:00" level=info msg=serving... address=/run/containerd/containerd.sock
9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.561877439+08:00" level=info msg="Start event monitor"
9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.561954224+08:00" level=info msg="Start cni network conf syncer for default"
9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.561968988+08:00" level=info msg="Start streaming server"
9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.561978830+08:00" level=info msg="Registered namespace \"k8s.io\" with NRI"
9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.561989094+08:00" level=info msg="runtime interface starting up..."
9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.561996532+08:00" level=info msg="starting plugins..."
9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.562010035+08:00" level=info msg="Synchronizing NRI (plugin) with current runtime state"
9月 11 21:56:25 k8s-master1 containerd[5135]: time="2025-09-11T21:56:25.570303515+08:00" level=info msg="containerd successfully booted in 0.366820s"
9月 11 21:56:25 k8s-master1 systemd[1]: Started containerd.service - containerd container runtime.

1、创建 crictl.yaml 配置文件

crictl 的配置文件 /etc/crictl.yaml 不存在,需手动创建并指定运行时端点。

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

2、验证 Containerd 服务状态

确保 containerd 服务已启动且正常运行,并检查套接字文件是否存在:

# 检查 Containerd 状态
sudo systemctl status containerd

# 检查套接字文件是否存在
ls -l /run/containerd/containerd.sock

如果套接字文件不存在,重启 Containerd 服务:

sudo systemctl restart containerd

3、重新运行 crictl info 验证配置

配置完成后,再次运行命令:

crictl info
  • 不再出现 Config does not existdefault endpoints 警告。
  • 显示 Containerd 的详细运行时信息(包括镜像源配置)。

4、验证镜像源配置是否生效

检查镜像源配置是否已正确加载:

crictl info | grep -A 10 "registry"

输出应包含你配置的镜像源列表(如 docker.io 的镜像地址)。


5、测试镜像拉取

尝试拉取一个镜像以验证镜像源是否生效:

crictl pull docker.io/library/nginx:latest
crictl pull registry.k8s.io/pause:3.10.1

如果拉取成功,说明镜像源配置正确。


常见问题排查

问题 1:/run/containerd/containerd.sock 不存在

  • 原因containerd 服务未启动或配置错误。

  • 解决

    1. 检查服务状态:systemctl status containerd

    2. 查看日志:journalctl -u containerd -n 100

    3. 重新生成配置文件并重启服务:

      sudo containerd config default > /etc/containerd/config.toml
      sudo systemctl restart containerd
      

问题 2:权限不足

  • 现象:提示 connect: permission denied

  • 解决:使用 sudo 运行命令,或确保当前用户在 containerd 用户组中:

    sudo usermod -aG containerd $USER
    newgrp containerd
    

问题 3:镜像源配置未生效

  • 检查点

    1. 确保 /etc/containerd/certs.d/docker.io/hosts.toml 文件格式正确(无语法错误)。

    2. 确保 config.toml 中启用了 certs.d 配置路径:

      [plugins."io.containerd.cri.v1.images".registry]
        config_path = "/etc/containerd/certs.d"
      
    3. 重启 Containerd 服务:sudo systemctl restart containerd

通过创建 crictl.yaml 配置文件并指定 containerd 的运行时端点,可以消除警告并正确验证镜像源配置。如果仍存在问题,需检查 Containerd 服务状态和配置文件语法。配置成功后,镜像拉取速度将显著提升。

5. 其他注意事项
  1. 镜像源优先级

    • containerd 会按顺序尝试 hosts.toml 中列出的镜像源,直到拉取成功为止。建议将延迟较低的镜像源放在前面。
    • 如果某个镜像源失效,可以删除或注释掉对应的配置。
  2. 私有仓库配置 如果需要配置私有仓库(如 Harbor),可以参考以下示例:

    [host."http://192.168.0.39:5000"]
      capabilities = ["pull", "resolve"]
      skip_verify = true  # 跳过 TLS 验证
    

配置 Pause 镜像(Kubernetes 环境)

如果使用 Kubernetes,建议修改 sandbox_image 为国内源:

[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.10.1"

确保 containerd 使用与 Kubernetes 一致的 Cgroup 驱动(推荐 systemd):

# 编辑 /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true
[root@localhost ~]# sudo cat /etc/containerd/config.toml | grep "SystemdCgroup"
            SystemdCgroup = true

2.4.3. 保存并重启服务

保存配置文件后,重启 containerd 服务以使配置生效:

sudo systemctl restart containerd

2.4.4. 验证配置

测试拉取镜像

尝试拉取镜像以验证是否从国内源获取:

crictl pull registry.aliyuncs.com/google_containers/pause:3.10.1
[root@localhost ~]# crictl pull registry.aliyuncs.com/google_containers/pause:3.10.1
Image is up to date for sha256:cd073f4c5f6a8e9dc6f3125ba00cf60819cae95c1ec84a1f146ee4a9cf9e803f

2.4.5. 推荐镜像源

原始仓库国内镜像源(示例)
docker.iohttps://45hrqeao.mirror.aliyuncs.com
registry.k8s.iohttps://registry.aliyuncs.com/google_containers
k8s.gcr.iohttps://registry.aliyuncs.com/google_containers

🧱 第三步:安装 kubeadm、kubelet、kubectl(所有节点)

3.1 添加Kubernetes 源

# 添加 Kubernetes 官方源
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.34/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.34/rpm/repodata/repomd.xml.key
EOF

# 导入 GPG 密钥
sudo rpm --import https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.34/rpm/repodata/repomd.xml.key
# 列出所有可用的 Kubernetes 包版本
sudo dnf list --showduplicates kubelet kubeadm kubectl
sudo dnf list --showduplicates kubelet kubeadm kubectl
上次元数据过期检查:0:01:17 前,执行于 2025年09月07日 星期日 19时07分39秒。
可安装的软件包
kubeadm.aarch64                               1.34.0-150500.1.1                               kubernetes
kubeadm.ppc64le                               1.34.0-150500.1.1                               kubernetes
kubeadm.s390x                                 1.34.0-150500.1.1                               kubernetes
kubeadm.src                                   1.34.0-150500.1.1                               kubernetes
kubeadm.x86_64                                1.34.0-150500.1.1                               kubernetes
kubectl.aarch64                               1.34.0-150500.1.1                               kubernetes
kubectl.ppc64le                               1.34.0-150500.1.1                               kubernetes
kubectl.s390x                                 1.34.0-150500.1.1                               kubernetes
kubectl.src                                   1.34.0-150500.1.1                               kubernetes
kubectl.x86_64                                1.34.0-150500.1.1                               kubernetes
kubelet.aarch64                               1.34.0-150500.1.1                               kubernetes
kubelet.ppc64le                               1.34.0-150500.1.1                               kubernetes
kubelet.s390x                                 1.34.0-150500.1.1                               kubernetes
kubelet.src                                   1.34.0-150500.1.1                               kubernetes
kubelet.x86_64                                1.34.0-150500.1.1                               kubernetes

3.2 安装指定版本组件

sudo dnf update
# 安装指定版本的组件
sudo dnf install -y kubeadm-1.34.0 kubelet-1.34.0 kubectl-1.34.0

锁定版本防止升级:

sudo dnf install -y dnf-plugin-versionlock
sudo dnf versionlock add kubelet-1.34.0 kubeadm-1.34.0 kubectl-1.34.0
sudo dnf versionlock list
#如果未来需要升级 Kubernetes,需先解除锁定
sudo dnf versionlock delete kubelet-1.34.0 kubeadm-1.34.0 kubectl-1.34.0

3.3 配置kubectl

  • Red Hat/CentOS/RockyLinux/etc/sysconfig/kubelet
  • Debian/Ubuntu/etc/default/kubelet
# vi /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

3.4 启用 kubelet(先不启动)

sudo systemctl enable kubelet

🌐 第四步:初始化 Master 节点(仅在 master 执行)

4.0 查看镜像、拉取镜像

root@k8s-master1:~# kubeadm config images list --kubernetes-version=v1.34.0 --image-repository registry.aliyuncs.com/google_containers
registry.aliyuncs.com/google_containers/kube-apiserver:v1.34.0
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.34.0
registry.aliyuncs.com/google_containers/kube-scheduler:v1.34.0
registry.aliyuncs.com/google_containers/kube-proxy:v1.34.0
registry.aliyuncs.com/google_containers/coredns:v1.12.1
registry.aliyuncs.com/google_containers/pause:3.10.1
registry.aliyuncs.com/google_containers/etcd:3.6.4-0
root@k8s-master1:~# kubeadm config images pull --kubernetes-version=v1.34.0 --image-repository registry.aliyuncs.com/google_containers
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.34.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.34.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.34.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.34.0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:v1.12.1
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.10.1
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.6.4-0
root@k8s-master1:~#

4.1 编写 kubeadm 配置文件

kubeadm config print init-defaults> kubeadm-config-v1.34.0.yaml
root@k8s-master1:~/k8s# cat kubeadm-config-v1.34.0.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: 1.2.3.4
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///var/run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  imagePullSerial: true
  name: node
  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.k8s.io
kind: ClusterConfiguration
kubernetesVersion: 1.34.0
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12
proxy: {}
scheduler: {}
root@k8s-master1:~/k8s# vi kubeadm-config-v1.34.0.yaml 
root@k8s-master1:~/k8s# cat kubeadm-config-v1.34.0.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: 192.168.153.143
  bindPort: 6443
nodeRegistration:
  criSocket: unix:///var/run/containerd/containerd.sock
  imagePullPolicy: IfNotPresent
  imagePullSerial: true
  name: k8s-master1
  taints: null
timeouts:
  controlPlaneComponentHealthCheck: 4m0s
  discovery: 5m0s
  etcdAPICall: 2m0s
  kubeletHealthCheck: 4m0s
  kubernetesAPICall: 1m0s
  tlsBootstrap: 5m0s
  upgradeManifests: 5m0s
---
apiServer: {}
apiVersion: kubeadm.k8s.io/v1beta4
caCertificateValidityPeriod: 876000h0m0s
certificateValidityPeriod: 876000h0m0s
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
encryptionAlgorithm: RSA-2048
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.34.0
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/12
proxy: {}
scheduler: {}

4.2 拉取镜像(使用阿里云镜像仓库)

#也可以这样预先拉取镜像
sudo kubeadm config images pull --config kubeadm-config-v1.34.0.yaml --image-repository registry.aliyuncs.com/google_containers

4.3 初始化集群

kubeadm init --config kubeadm-config-v1.34.0.yaml --upload-certs --v=9

✅ 成功后会输出类似:

kubeadm join 192.168.153.143:6443 --token ... --discovery-token-ca-cert-hash sha256:...

请务必保存这个 kubeadm join 命令!

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

验证:

[root@k8s-master1 ~]# kubectl get nodes
NAME          STATUS     ROLES           AGE   VERSION
k8s-master1   NotReady   control-plane   46s   v1.34.0

🧩 第五步:Worker 节点加入集群(在 worker1 和 worker2 执行)

使用 master 初始化输出的 kubeadm join 命令,例如:

kubeadm join 192.168.153.143:6443 --token abcdef.0123456789abcdef \
	--discovery-token-ca-cert-hash sha256:e610bf71ba05390b3a0194061c1f8d56726c9d54be17b6d58b46a631646e9ed0
[root@k8s-master1 ~]# kubectl get nodes
NAME          STATUS     ROLES           AGE   VERSION
k8s-master1   NotReady   control-plane   92s   v1.34.0
k8s-worker1   NotReady   <none>          16s   v1.34.0
k8s-worker2   NotReady   <none>          10s   v1.34.0

注意:token 有效期 24 小时,过期可使用以下命令重新生成:

# 在 master 上执行
kubeadm token create --print-join-command

🌐 第六步:安装 CNI 插件(Calico)

6.1 查看当前k8s状态

[root@k8s-master1 ~]# kubectl get pods -n kube-system
NAME                                  READY   STATUS    RESTARTS   AGE
coredns-7cc97dffdd-569wk              0/1     Pending   0          103s
coredns-7cc97dffdd-rb4hx              0/1     Pending   0          103s
etcd-k8s-master1                      1/1     Running   0          108s
kube-apiserver-k8s-master1            1/1     Running   0          108s
kube-controller-manager-k8s-master1   1/1     Running   0          110s
kube-proxy-cglmq                      1/1     Running   0          72s
kube-proxy-nvbrb                      1/1     Running   0          103s
kube-proxy-x2jvs                      1/1     Running   0          77s
kube-scheduler-k8s-master1            1/1     Running   0          108s
[root@k8s-master1 ~]# kubectl get pods -n kube-system -o wide
NAME                                  READY   STATUS    RESTARTS   AGE   IP                NODE          NOMINATED NODE   READINESS GATES
coredns-7cc97dffdd-569wk              0/1     Pending   0          66s   <none>            <none>        <none>           <none>
coredns-7cc97dffdd-rb4hx              0/1     Pending   0          66s   <none>            <none>        <none>           <none>
etcd-k8s-master1                      1/1     Running   0          71s   192.168.153.143   k8s-master1   <none>           <none>
kube-apiserver-k8s-master1            1/1     Running   0          71s   192.168.153.143   k8s-master1   <none>           <none>
kube-controller-manager-k8s-master1   1/1     Running   0          73s   192.168.153.143   k8s-master1   <none>           <none>
kube-proxy-cglmq                      1/1     Running   0          35s   192.168.153.145   k8s-worker2   <none>           <none>
kube-proxy-nvbrb                      1/1     Running   0          66s   192.168.153.143   k8s-master1   <none>           <none>
kube-proxy-x2jvs                      1/1     Running   0          40s   192.168.153.144   k8s-worker1   <none>           <none>
kube-scheduler-k8s-master1            1/1     Running   0          71s   192.168.153.143   k8s-master1   <none>           <none>

6.2 安装calico网络组件

https://docs.tigera.io/calico/latest/about

使用 Calico 提供 Pod 网络,支持 10.244.0.0/16

wget https://raw.githubusercontent.com/projectcalico/calico/v3.30.1/manifests/tigera-operator.yaml
kubectl create -f tigera-operator.yaml
[root@k8s-master1 k8s]# kubectl get ns
NAME              STATUS   AGE
default           Active   4m49s
kube-node-lease   Active   4m49s
kube-public       Active   4m49s
kube-system       Active   4m49s
tigera-operator   Active   18s
[root@k8s-master1 k8s]# kubectl get pods -n tigera-operator
NAME                               READY   STATUS    RESTARTS   AGE
tigera-operator-697957d976-clc7x   1/1     Running   0          49s
wget https://raw.githubusercontent.com/projectcalico/calico/v3.30.1/manifests/custom-resources.yaml
vi custom-resources.yaml
将192.168.0.0 改为 10.244.0.0

kubectl create -f custom-resources.yaml
root@k8s-master1:~/k8s# kubectl get pods -n calico-system -w
NAME                                      READY   STATUS    RESTARTS   AGE
calico-kube-controllers-89ff8967c-gf9sq   1/1     Running   0          6m25s
calico-node-f6527                         1/1     Running   0          6m25s
calico-node-kbxkc                         1/1     Running   0          6m26s
calico-node-nw22s                         1/1     Running   0          6m25s
calico-typha-866888995d-26sxq             1/1     Running   0          6m26s
calico-typha-866888995d-qxt9p             1/1     Running   0          6m19s
csi-node-driver-2s8fg                     2/2     Running   0          6m25s
csi-node-driver-486qr                     2/2     Running   0          6m25s
csi-node-driver-nc8cc                     2/2     Running   0          6m25s
goldmane-58849b4d85-64pd8                 1/1     Running   0          6m26s
whisker-dcffbfb5d-w8rvj                   2/2     Running   0          4m29s
[root@k8s-master1 k8s]# kubectl describe pod calico-kube-controllers-59f5dc97d8-7z4qb -n calico-system
Name:                 calico-kube-controllers-59f5dc97d8-7z4qb
Namespace:            calico-system
Priority:             2000000000
Priority Class Name:  system-cluster-critical
Service Account:      calico-kube-controllers
Node:                 k8s-master1/192.168.153.137
Start Time:           Sun, 07 Sep 2025 19:44:13 +0800
Labels:               app.kubernetes.io/name=calico-kube-controllers
                      k8s-app=calico-kube-controllers
                      pod-template-hash=59f5dc97d8
Annotations:          cni.projectcalico.org/containerID: 23c2f07184382ed1876a49fe4e87b69980af9c6026dd5ea6080bb0b7de43d257
                      cni.projectcalico.org/podIP: 10.244.159.136/32
                      cni.projectcalico.org/podIPs: 10.244.159.136/32
                      hash.operator.tigera.io/system: afea2595203eb027afcee25a2f11a6666a8de557
                      tigera-operator.hash.operator.tigera.io/tigera-ca-private: 41f16f4176b60c81618849d17cb7afe75b281bfc
Status:               Running
IP:                   10.244.159.136

✅ 第七步:验证集群状态

[root@k8s-master1 k8s]# kubectl get nodes
NAME          STATUS   ROLES           AGE   VERSION
k8s-master1   Ready    control-plane   16m   v1.34.0
k8s-worker1   Ready    <none>          14m   v1.34.0
k8s-worker2   Ready    <none>          14m   v1.34.0
[root@k8s-master1 k8s]# kubectl get pods -n kube-system
NAME                                  READY   STATUS    RESTARTS   AGE
coredns-7cc97dffdd-h7r44              1/1     Running   0          16m
coredns-7cc97dffdd-szlm2              1/1     Running   0          16m
etcd-k8s-master1                      1/1     Running   0          16m
kube-apiserver-k8s-master1            1/1     Running   0          16m
kube-controller-manager-k8s-master1   1/1     Running   0          16m
kube-proxy-j25tc                      1/1     Running   0          14m
kube-proxy-j9txz                      1/1     Running   0          16m
kube-proxy-zjgxq                      1/1     Running   0          14m
kube-scheduler-k8s-master1            1/1     Running   0          16m
[root@k8s-master1 k8s]# kubectl get pods -n kube-system -o wide
NAME                                  READY   STATUS    RESTARTS   AGE   IP                NODE          NOMINATED NODE   READINESS GATES
coredns-7cc97dffdd-h7r44              1/1     Running   0          17m   10.244.159.134    k8s-master1   <none>           <none>
coredns-7cc97dffdd-szlm2              1/1     Running   0          17m   10.244.159.130    k8s-master1   <none>           <none>
etcd-k8s-master1                      1/1     Running   0          17m   192.168.153.137   k8s-master1   <none>           <none>
kube-apiserver-k8s-master1            1/1     Running   0          17m   192.168.153.137   k8s-master1   <none>           <none>
kube-controller-manager-k8s-master1   1/1     Running   0          17m   192.168.153.137   k8s-master1   <none>           <none>
kube-proxy-j25tc                      1/1     Running   0          15m   192.168.153.139   k8s-worker2   <none>           <none>
kube-proxy-j9txz                      1/1     Running   0          17m   192.168.153.137   k8s-master1   <none>           <none>
kube-proxy-zjgxq                      1/1     Running   0          15m   192.168.153.138   k8s-worker1   <none>           <none>
kube-scheduler-k8s-master1            1/1     Running   0          17m   192.168.153.137   k8s-master1   <none>           <none>
root@k8s-master1:~/k8s# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS    MESSAGE   ERROR
scheduler            Healthy   ok        
controller-manager   Healthy   ok        
etcd-0               Healthy   ok
[root@k8s-master1 k8s]# kubectl get service -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   18m
[root@k8s-master1 k8s]# kubectl get service -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   18m
[root@k8s-master1 k8s]# dig -t a blog.nn3n.com @10.96.0.10

; <<>> DiG 9.18.33 <<>> -t a blog.nn3n.com @10.96.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60711
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 95265f509d92bfb4 (echoed)
;; QUESTION SECTION:
;blog.nn3n.com.			IN	A

;; ANSWER SECTION:
blog.nn3n.com.		30	IN	A	120.55.48.153

;; Query time: 158 msec
;; SERVER: 10.96.0.10#53(10.96.0.10) (UDP)
;; WHEN: Sun Sep 07 19:55:13 CST 2025
;; MSG SIZE  rcvd: 83

✅ 第八步:部署一个测试 Pod

在 Kubernetes 集群中部署一个 Nginx Pod 和 Service,并将其暴露到集群外部,部署在名为 dev-demo 的命名空间下


8.1 创建命名空间 dev-demo

root@k8s-master1:~/k8s# kubectl create namespace dev-demo
namespace/dev-demo created

您也可以使用 YAML 文件创建,但命令更简洁。


8.2 部署 Nginx Pod 和 Service 的 YAML 文件

创建一个名为 nginx-dev-demo.yaml 的文件,内容如下:

apiVersion: v1
kind: Namespace
metadata:
  name: dev-demo
  annotations: {}
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: dev-demo
  labels:
    app: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx:1.25  # 使用稳定版 Nginx 镜像
    ports:
    - containerPort: 80
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: dev-demo
spec:
  type: NodePort  # 使用 NodePort 类型,允许从集群外部访问
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080  # 可选:指定端口,范围 30000-32767

🔍 说明:

  • Namespace 单独定义,确保命名空间存在。
  • Pod 使用 nginx:1.25 镜像,标签 app: nginx 用于 Service 选择。
  • Service 类型为 NodePort,将 Pod 暴露到每个节点的 IP 上。
  • nodePort: 30080 是可选的,如果不指定,Kubernetes 会自动分配(30000–32767)。

8.3 应用部署文件

kubectl apply -f nginx-dev-demo.yaml
root@k8s-master1:~/k8s# kubectl apply -f nginx-dev-demo.yaml
namespace/dev-demo created
pod/nginx-pod created
service/nginx-service created

8.4 验证部署状态

  1. 检查命名空间:
kubectl get namespaces | grep dev-demo
  1. 检查 Pod 状态:
kubectl get pods -n dev-demo
root@k8s-master1:~/k8s# kubectl get pods -n dev-demo
NAME        READY   STATUS    RESTARTS   AGE
nginx-pod   1/1     Running   0          3m23s
  1. 检查 Service:
kubectl get svc -n dev-demo
[root@k8s-master1 k8s]# kubectl get svc -n dev-demo
NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx-service   NodePort   10.96.211.66   <none>        80:30080/TCP   118s

8.5 从集群外部访问 Nginx

由于使用了 NodePort,您可以通过 任意 Kubernetes 节点的公网 IP + NodePort 端口 访问 Nginx。

例如:

http://<Node-IP>:30080

<Node-IP> 替换为任意一个 Worker 节点的公网 IP 地址。

✅ 浏览器打开 http://<Node-IP>:30080,应看到 Nginx 欢迎页。


❓ 常见问题与说明

Q:如何升级 k8s 版本?

A:使用 kubeadm upgrade 流程,先升级 control-plane,再升级 node。


📌 总结

步骤操作
1所有节点初始化(主机名、hosts、关闭 swap 等)
2安装 containerd2.x(使用阿里云源 + 镜像加速)
4安装 kubeadm/kubelet/kubectl(使用阿里云源)
5Master 初始化
6安装 Calico 网络插件
7Worker 节点 join 集群
8验证集群状态

至此,Kubernetes v1.34.0 集群已成功部署,使用 Containerd2.x 作为容器运行时,全部使用国内源加速。

后续会出持续部署 Dashboard、Ingress、Metrics Server 等组件,可不定期继续扩展。