跳到主要内容

CentOS 7 手动安装 Kubernetes v1.31.x + containerd

KubeKey v4.x 在 CentOS 7(kernel 3.10)上有多个已知 bug。本文档记录经过验证的手动安装方案,作为 KubeKey 不可用时的备选。


1. 环境概览​

项目值
OSCentOS 7.9 (kernel 3.10.0-1160)
K8sv1.31.x
CRIcontainerd 1.7.13
CNIWeave Net 2.8.1
kube-proxyiptables 模式

节点规划​

角色内网 IP公网 IP主机名
control-plane172.26.16.1543.130.14.242k8s-master01
worker172.26.0.14-vm-0-14-centos

2. KubeKey 已知问题速查​

如果坚持使用 KubeKey v4.x 自动安装,CentOS 7 上会遇到以下问题。以下解决方案已在本环境实测通过。

问题 1:systemctl --value 报错​

Error: task [Defaults | Get kubelet.service LoadState] run failed:
systemctl: unrecognized option '--value'

根因:CentOS 7 的 systemd 219 不支持 systemctl show --value,KubeKey 的 playbook 在 pre-check 阶段使用了此参数。

解决:替换 /usr/bin/systemctl 为 wrapper:

cp /usr/bin/systemctl /usr/bin/systemctl.real
cat > /usr/bin/systemctl <<'WRAP'
#!/bin/bash
if [[ "$@" == *"--value"* ]]; then
/usr/bin/systemctl.real $(echo "$@" | sed 's/--value //g') | awk -F= '{print $2}'
else
/usr/bin/systemctl.real "$@"
fi
WRAP
chmod +x /usr/bin/systemctl

问题 2:内核版本检查不通过​

The kernel version "3.10.0-1160" is too old. Minimum required version: 4.9.17.

根因:KubeKey v4.x 对所有 K8s 版本统一要求内核 >= 4.9.17。

解决:替换 /usr/bin/uname 为 wrapper,让 pre-check 看到假内核版本:

cp /usr/bin/uname /usr/bin/uname.real
cat > /usr/bin/uname <<'WRAP'
#!/bin/bash
for arg in "$@"; do
if [ "$arg" = "-r" ]; then
echo "5.4.278-1.el7.elrepo.x86_64"
exit 0
fi
done
exec /usr/bin/uname.real "$@"
WRAP
chmod +x /usr/bin/uname

问题 3:init_kubernetes_node nil pointer​

error calling index: index of nil pointer

根因:KubeKey v4.x 的 Go 模板在部分场景下无法正确设置 init_kubernetes_node 变量。

解决:放弃 KubeKey,改用手动 kubeadm init。

问题 4:Docker 二进制缺失​

stat /root/kubekey/kubekey/docker/25.0.5/amd64/docker-25.0.5.tgz: no such file

根因:即使配置了 container_manager: containerd,KubeKey 仍尝试部署 Docker。

解决:手动下载 Docker 二进制放到缓存路径,或使用空文件占位。

mkdir -p ~/kubekey/kubekey/docker/25.0.5/amd64/
curl -Lo ~/kubekey/kubekey/docker/25.0.5/amd64/docker-25.0.5.tgz \
https://download.docker.com/linux/static/stable/x86_64/docker-25.0.5.tgz

3. Master 节点安装​

3.1 通用初始化​

# 关 swap
swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab

# 内核参数
cat > /etc/sysctl.d/99-kubernetes.conf <<EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
modprobe br_netfilter && sysctl --system

# conntrack
yum install -y conntrack

3.2 安装 containerd 1.7.13​

# 下载二进制
cd /tmp
curl -LO https://github.com/containerd/containerd/releases/download/v1.7.13/containerd-1.7.13-linux-amd64.tar.gz
tar xzf containerd-1.7.13-linux-amd64.tar.gz -C /usr/local/

# 创建 containerd service
cat > /etc/systemd/system/containerd.service <<'SVC'
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target
SVC

# 配置
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's|sandbox_image = "registry.k8s.io/pause:3.9"|sandbox_image = "hub.kubesphere.com.cn/kubernetes/pause:3.10"|' /etc/containerd/config.toml

systemctl daemon-reload && systemctl enable containerd --now

3.3 安装 kubelet / kubeadm / kubectl​

# 方式 A:官方 yum 源(CN 节点可能 403)
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.31/rpm/
enabled=1
gpgcheck=0
EOF

yum makecache && yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

# 方式 B:下载二进制(yum 源 403 时的备选)
# curl -LO https://dl.k8s.io/v1.31.0/kubernetes-node-linux-amd64.tar.gz
# tar xzf kubernetes-node-linux-amd64.tar.gz
# cp kubernetes/node/bin/{kubelet,kubeadm,kubectl} /usr/local/bin/

# kubelet drop-in 配置
mkdir -p /var/lib/kubelet /usr/lib/systemd/system/kubelet.service.d
cat > /var/lib/kubelet/kubeadm-flags.env <<'EOF'
KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///run/containerd/containerd.sock"
EOF

cat > /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf <<'EOF'
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
EOF

systemctl daemon-reload && systemctl enable kubelet

3.4 初始化集群​

# /tmp/kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 172.26.16.15 # 替换为你的内网 IP
bindPort: 6443
nodeRegistration:
criSocket: unix:///run/containerd/containerd.sock
name: k8s-master01 # 替换为你的主机名
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.31.14
controlPlaneEndpoint: 172.26.16.15:6443
apiServer:
certSANs:
- 127.0.0.1
- 172.26.16.15 # 内网 IP
- 43.130.14.242 # 公网 IP
- lb.kubernetes.local
networking:
podSubnet: 10.233.64.0/18
serviceSubnet: 10.233.0.0/18
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
kubeadm init --config=/tmp/kubeadm-config.yaml --ignore-preflight-errors=SystemVerification

注意:--ignore-preflight-errors=SystemVerification 用于绕过 kernel 3.10 的 kernel config 模块缺失检查。

3.5 部署后置组件​

# 配置 kubectl
mkdir -p ~/.kube && cp /etc/kubernetes/super-admin.conf ~/.kube/config

# 补 kube-proxy(kubeadm init 超时中断时可能漏掉)
kubeadm init phase addon kube-proxy --config=/tmp/kubeadm-config.yaml

# 补 bootstrap-token + cluster-info ConfigMap
kubeadm init phase bootstrap-token --config=/tmp/kubeadm-config.yaml

# 安装 CNI
kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml

# 检查 CNI 配置残留(重要!)
rm -f /etc/cni/net.d/10-flannel.conflist

3.6 验证​

kubectl get nodes -o wide
NAME STATUS ROLES VERSION INTERNAL-IP CONTAINER-RUNTIME
k8s-master01 Ready control-plane v1.31.14 172.26.16.15 containerd://1.7.13

4. Worker 节点安装​

4.1 初始化(同 master 3.1 节)​

swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab
cat > /etc/sysctl.d/99-kubernetes.conf <<EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
modprobe br_netfilter && sysctl --system
yum install -y conntrack

4.2 安装 containerd(版本与 master 一致)​

# 从 master 拷贝二进制(推荐,确保版本一致)
ssh root@k8s-master01 \
'tar czf - -C /usr/local/bin containerd containerd-shim containerd-shim-runc-v1 containerd-shim-runc-v2 ctr runc' \
| tar xzf - -C /usr/local/bin

# 创建 service + 配置(同 master 3.2 节)

systemctl daemon-reload && systemctl enable containerd --now

4.3 安装 kubelet / kubeadm​

# yum 源安装(同 master 3.3 节)
cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.31/rpm/
enabled=1
gpgcheck=0
EOF

yum makecache && yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable kubelet

4.4 加入集群​

在 master 上获取 join 命令:

kubeadm token create --print-join-command

在 worker 上执行:

kubeadm join 172.26.16.15:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<HASH> \
--ignore-preflight-errors=SystemVerification

5. 常见问题​

5.1 CoreDNS 一直 ContainerCreating​

原因:CNI 配置文件冲突(多个 .conflist 文件并存)。

解决:

ls /etc/cni/net.d/ # 确认有旧 conflist
rm -f /etc/cni/net.d/10-flannel.conflist # 删掉 flannel 残留
kubectl delete pod -n kube-system -l k8s-app=kube-dns

5.2 kubeadm join 卡在 preflight​

原因:cluster-info ConfigMap 缺失(kubeadm init 中断导致)。

解决:

# 在 master 上执行
kubeadm init phase bootstrap-token --config=/tmp/kubeadm-config.yaml

5.3 kube-apiserver 无法启动(containerd RuntimeConfig)​

RuntimeConfig from runtime service failed: unknown method RuntimeConfig

原因:containerd 1.6.x 不实现 RuntimeConfig RPC,kubelet 预期升级到 1.7.x。

解决:将 worker 的 containerd 升级到 1.7.x。

5.4 Flannel/Weave 报 "ID cannot be empty"​

原因:kube-proxy 未部署,Service IP 不可达,CNI 无法通过 API Server 注册节点。

解决:

kubeadm init phase addon kube-proxy --config=/tmp/kubeadm-config.yaml

6. 参考​