Proxmox + CentOS 9 Stream 部署 K8s 1.28 集群实战指南 (避坑版)
环境信息:
-
Master: 192.168.80.225 (k8s-master)
-
Node1: 192.168.80.226 (k8s-node1)
-
Node2: 192.168.80.227 (k8s-nobe2)
-
软件版本: Kubernetes v1.28.2 | Containerd v1.7.x (锁定版本) | Calico v3.26.1
第一阶段:基础环境准备 (所有节点执行)
所有机器以 root 身份执行。
1. 初始化系统配置
# 1. 设置主机名 (仅示例,请在对应机器执行)
# hostnamectl set-hostname k8s-master
# 2. 配置 Hosts
cat >> /etc/hosts <<EOF
192.168.80.225 k8s-master
192.168.80.226 k8s-node1
192.168.80.227 k8s-nobe2
EOF
# 3. 关闭防火墙、Swap、SELinux (必须)
systemctl stop firewalld && systemctl disable firewalld
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
2. 加载内核模块与网络参数
cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
cat <<EOF | 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
EOF
sysctl --system
第二阶段:安装与配置 Containerd (避坑核心)
核心策略:强制安装 1.7.x 版本,避开 v2.x 与 K8s 1.28 工具链的兼容性问题;直接写入正确配置,不依赖默认生成。
在所有节点执行:
1. 安装 Containerd 1.7.x
dnf install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 避坑点1:不要直接 install containerd.io,这会装上 v2.x
dnf install -y containerd.io-1.7.11
# 如果报错提示没有找到匹配可通过dnf list containerd.io --showduplicates | sort -r查看可用下载版本根据版本选择1.7的最新版本即可如不放心那就选择最新版本的上一版本
dnf install -y containerd.io-1.7.29
2. 写入“黄金配置” (SystemdCgroup + 阿里云镜像)
mkdir -p /etc/containerd
# 避坑点2:直接覆盖配置,防止 sed 改错或默认配置缺失 sandbox_image
cat <<EOF > /etc/containerd/config.toml
version = 2
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
# 核心:将 registry.k8s.io 替换为阿里云,解决初始化超时
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
# 核心:必须开启 SystemdCgroup,否则 kubelet 启动失败
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://docker.m.daocloud.io"]
EOF
# 启动服务
systemctl enable --now containerd
3. 配置 crictl 客户端
# 避坑点3:crictl 默认连 docker,必须指定连 containerd
cat <<EOF > /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
第三阶段:安装 Kubernetes (所有节点)
1. 添加阿里云 YUM 源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
2. 安装组件
dnf install -y kubelet-1.28.2 kubeadm-1.28.2 kubectl-1.28.2 --disableexcludes=kubernetes
systemctl enable --now kubelet
第四阶段:初始化 Master (仅 Master 节点)
1. 执行初始化
# 避坑点4:指定 image-repository 解决核心组件拉取问题
kubeadm init \
--apiserver-advertise-address=192.168.80.225 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.28.2 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
2. 配置 Kubectl 权限
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
第五阶段:部署网络插件 Calico (手动同步版)
背景:Worker 节点通常拉不动 docker.io 镜像,导致 Calico 卡在 Init:0/3。
策略:Master 下载 -> 导出 -> 传输 -> Worker 导入。
1. 准备清单文件 (Master)
curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O
# 替换为代理源,方便 Master 拉取
sed -i 's|docker.io/calico|docker.m.daocloud.io/calico|g' calico.yaml
kubectl apply -f calico.yaml
2. “手动搬运”镜像 (解决 ImagePullBackOff)
在 Master 上检查镜像是否已拉取 (crictl images | grep calico),然后执行:
# 1. 在 Master 导出
ctr -n k8s.io images export calico-cni.tar docker.m.daocloud.io/calico/cni:v3.26.1
ctr -n k8s.io images export calico-node.tar docker.m.daocloud.io/calico/node:v3.26.1
ctr -n k8s.io images export calico-ctl.tar docker.m.daocloud.io/calico/kube-controllers:v3.26.1
# 2. 发送给 Worker (Node1, Node2)
scp calico-*.tar root@192.168.80.226:/root/
scp calico-*.tar root@192.168.80.227:/root/
在 Worker 节点上执行导入:
# 避坑点5:必须指定 -n k8s.io,否则 kubelet 看不到
ctr -n k8s.io images import calico-cni.tar
ctr -n k8s.io images import calico-node.tar
ctr -n k8s.io images import calico-ctl.tar
第六阶段:Worker 加入与最终验证
1. Worker 加入集群
在 Node1 和 Node2 执行 kubeadm join ... (初始化时生成的命令)。
2. 解决 CNI 配置文件丢失问题 (避坑点6)
如果节点加入后长期 NotReady,报错 cni plugin not initialized:
-
原因:可能为了排错删除了 /etc/cni/net.d。
-
修复:在 Master 上执行 kubectl delete pod -l k8s-app=calico-node -n kube-system。重启的 Pod 会重新写入配置文件。
3. 部署测试应用 (Nginx)
# Master 操作
kubectl create deployment nginx-demo --image=docker.m.daocloud.io/library/nginx:alpine --replicas=2
kubectl expose deployment nginx-demo --port=80 --target-port=80 --type=NodePort
如果 Worker 上的 Pod 卡在 ContainerCreating,使用同样的“打包-SCP-导入”大法手动分发 Nginx 镜像。
附录:踩坑报错与解决方案总结
| 现象/报错信息 | 根本原因 | 解决方案 |
| Timeout waiting for the condition (kubeadm init) | 1. 无法拉取 pause 镜像<br>2. Cgroup 驱动不一致 (systemd vs cgroupfs) | 1. config.toml 中修改 sandbox_image 为阿里云地址。<br>2. config.toml 中设置 SystemdCgroup = true。 |
| crictl: context deadline exceeded / connection refused | crictl 默认去连 Docker,但我们装的是 Containerd。 | 创建 /etc/crictl.yaml 指定 runtime-endpoint 为 containerd.sock。 |
| CRI v1 runtime API is not implemented | 安装了 Containerd v2.x,与 K8s 1.28 的工具链不兼容。 | 降级:卸载 v2,强制安装 containerd.io-1.7.11。 |
| NetworkPluginNotReady: cni plugin not initialized | /etc/cni/net.d/ 目录为空或不存在。通常因为排错时误删。 | 1. 确保目录存在 mkdir -p /etc/cni/net.d<br>2. 删除 Calico Pod 让其重建并重写配置。<br>3. 重启 kubelet。 |
| Pod 一直 ContainerCreating / Init:0/3 | Worker 节点网络差,无法从公网拉取镜像。 | 手动搬运:Master 导出 (ctr export) -> SCP -> Worker 导入 (ctr -n k8s.io import)。 |
| ImagePullBackOff (尽管手动导入了镜像) | 导入时忘记加 -n k8s.io 参数,镜像进了 default 命名空间,K8s 看不到。 | 在 Worker 上重新执行导入命令,务必加上 -n k8s.io。 |
更多推荐



所有评论(0)