Kubernetes v1.28.2 离线部署实战

本篇覆盖单机/多节点、IPv4/双栈/纯 IPv6 三种网络模式,所有步骤均经过实战验证,可直接复制执行。

目录

  1. 前置准备
  2. 系统初始化
  3. 安装 Containerd
  4. 安装 Kubernetes 组件
  5. 初始化集群
  6. 安装 Calico CNI
  7. 验证与测试
  8. 生产加固
  9. 常见问题

1. 前置准备

环境要求

项目 最低要求 推荐配置
OS CentOS 7.9 / Rocky 8+ Rocky 9
CPU 2 核 4 核+
内存 2 GB 8 GB+
磁盘 20 GB 50 GB+ SSD

节点规划

10.0.0.1   k8s-master    (Master)
10.0.0.2   k8s-worker-2   (Worker)
10.0.0.3   k8s-worker-3   (Worker)
10.0.0.4   k8s-worker-4   (Worker)
...

📌 Tips:如果你是学习或测试,单节点就够了。生产环境建议至少 3 个 Master 节点实现高可用。关于多 Master 部署,可以参考 K8s 官方文档 - Creating Highly Available Clusters


2. 系统初始化

注意:这一步每台机器都要执行。

2.1 关闭防火墙

systemctl stop firewalld && systemctl disable firewalld

K8s 自带安全策略(NetworkPolicy、RBAC),生产环境用这些替代防火墙,不要同时开两层互相打架。详见 K8s Network Policies

2.2 设置主机名 & Hosts

hostnamectl set-hostname os-57

cat >> /etc/hosts <<EOF
10.0.0.1 k8s-master
10.0.0.2 k8s-worker-2
10.0.0.3 k8s-worker-3
10.0.0.4 k8s-worker-4
EOF

2.3 关闭 SELinux

sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

SELinux 和 K8s 的 Pod 安全上下文容易冲突,官方 kubeadm 安装文档也建议临时关闭。参考

2.4 关闭 Swap

sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab

为什么必须关? K8s 设计假设 Pod 随时可能被驱逐和重建,Swap 会导致内存回收行为不可预测,影响调度决策。官方说明

2.5 内核参数 & 模块

# 内核参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

sudo sysctl --system

# 加载内核模块
modprobe br_netfilter
modprobe ipv6

验证一下:

sysctl net.ipv4.ip_forward
# 输出: net.ipv4.ip_forward = 1

lsmod | grep br_netfilter
# 应有输出

2.6 配置 IPVS

IPVS 比 iptables 性能好很多,尤其在大规模集群下。K8s 官方服务代理对比

yum install ipvsadm ipset sysstat conntrack libseccomp -y

cat >> /etc/modules-load.d/ipvs.conf <<EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
ip_tables
ip_set
xt_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip
EOF

systemctl restart systemd-modules-load.service
lsmod | grep -e ip_vs -e nf_conntrack

全部准备就绪后,重启一次

reboot now

3. 安装 Containerd

K8s 1.24+ 已经移除了 Docker-shim,Containerd 是当前主流选择。

3.1 安装

# 配置 Docker CE 源(用于安装 containerd)
wget -O /etc/yum.repos.d/docker-ce.repo \
  https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum install -y containerd.io

3.2 配置

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

必须修改两个关键配置

① 启用 SystemdCgroup(K8s 官方推荐)

sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

为什么要用 SystemdCgroup?因为 kubelet 默认使用 systemd 作为 cgroup driver,两者不一致会导致 Pod 创建失败。官方文档

② 替换 Pause 镜像为国内源

sed -i 's#sandbox_image = "registry.k8s.io/pause:3.6"#sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"#' /etc/containerd/config.toml

3.3 启动 & 验证

sudo systemctl enable --now containerd
sudo systemctl status containerd

#查看版本
ctr version
#输出如下表示成功:
Client:
  Version:  1.6.32
  Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
  Go version: go1.21.10

Server:
  Version:  1.6.32
  Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
  UUID: 1ea4e608-7776-477b-b718-81ffab8222cb

3.4 配置 crictl

cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 5
debug: false
pull-image-on-create: false
EOF

crictl version

4. 安装 Kubernetes 组件

4.1 配置 yum 源

cat > /etc/yum.repos.d/kubernetes.repo <<EOF
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
EOF

4.2 安装指定版本

sudo yum install -y kubelet-1.28.2 kubeadm-1.28.2 kubectl-1.28.2
sudo systemctl enable --now kubelet
#查看运行状态
sudo systemctl status kubelet

💡 kubelet 启动后会不断重试连接 API Server,这是正常的,等 kubeadm init 完成后就好了。


5. 初始化集群

以下操作只在 Master 节点执行。

5.1 选择网络模式

根据你的环境选择一种:

模式 命令 适用场景
纯 IPv4 --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12 大多数内网环境
双栈 (IPv4+IPv6) --pod-network-cidr=10.244.0.0/16,2001:10:244::/64 需要兼容两种协议
纯 IPv6 --pod-network-cidr=2002:10:233::/64 --apiserver-advertise-address <你的IPv6> 纯 IPv6 环境

5.2 执行初始化

纯 IPv4 示例

sudo kubeadm init \
  --v=5 \
  --pod-network-cidr=10.244.0.0/16 \
  --service-cidr=10.96.0.0/12 \
  --image-repository registry.aliyuncs.com/google_containers

双栈示例

sudo kubeadm init \
  --v=5 \
  --pod-network-cidr=10.244.0.0/16,2001:10:244::/64 \
  --service-cidr=10.96.0.0/12,2001:10:244:1000::/112 \
  --image-repository registry.aliyuncs.com/google_containers

--image-repository 指向阿里云镜像,离线环境需要提前拉取所有镜像。详见官方离线安装说明

5.3 配置 kubectl

初始化成功后,复制最后输出的 join 命令保存好,然后执行:

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

5.4 Worker 加入集群

在每台 Worker 节点上执行 kubeadm init 输出的命,注意这里的token和ca都是上面master执行 kubeadm init成功以后屏幕打印的数据(下列只是例子,不要完全复制)。

kubeadm join 10.0.0.1:6443 \
  --token rijgg6.j4oq3rp1evjsg6z4 \
  --discovery-token-ca-cert-hash sha256:e15747ff3267a2db0ca861d906124d124cffe5a353002ed98460e13308570062

如果 token 过期了,在 Master 上执行 kubeadm token create --print-join-command 重新生成。


6. 安装 Calico CNI

集群初始化后节点会显示 NotReady,因为还没装网络插件。

6.1 离线安装(只需要在主上执行即可)

# 下载离线包(在有网络的机器上)
wget https://github.com/projectcalico/calico/releases/download/v3.27.3/release-v3.27.3.tgz
tar -xzvf release-v3.27.3.tgz

# 导入镜像到所有节点
ctr -n k8s.io images import release-v3.27.3/images/calico-cni.tar
ctr -n k8s.io images import release-v3.27.3/images/calico-kube-controllers.tar
ctr -n k8s.io images import release-v3.27.3/images/calico-node.tar

6.2 修改 calico.yaml

编辑 release-v3.27.3/manifests/calico.yaml,需要改两处:

① IPAM 配置 — 增加双栈支持(纯 IPv4 可跳过 assign_ipv6),注意:这里的格式是json,最后一个字段是没有逗号的,否则报错都知哪里出问题:

"ipam": {
  "type": "calico-ipam",
  "assign_ipv4": "true",
  "assign_ipv6": "true"
},

② 环境变量

- name: IP
  value: "autodetect"
- name: IP6
  value: "autodetect"
- name: CALICO_IPV4POOL_IPIP
  value: "Always"
- name: CALICO_IPV6POOL_NAT_OUTGOING
  value: "true"
- name: FELIX_IPV6SUPPORT
  value: "true"

IP 设为 autodetect 让 Calico 自动发现网卡。如果机器有多张网卡,需要指定具体网卡名或 IP,参考 Calico 官方文档 - IP Autodetection

6.3 部署

kubectl apply -f calico.yaml

# 观察部署进度
kubectl get pod -n kube-system -w

#如果报错了,修改calico.yaml文件以后需要删除以后再安装
kubectl delete -f calico.yaml
kubectl apply -f calico.yaml

等所有 Pod 变成 Running 后检查节点状态:

kubectl get nodes
# 应该显示 Ready

💡 关于 CNI 插件的选择:Calico 适合通用场景,支持 NetworkPolicy;如果需要高并发短连接可以看看 Cilium,它基于 eBPF 性能更好。CNI 插件对比


7. 验证与测试

7.1 Pod 连通性测试

# 导入测试镜像(需要先找一个有docker环境pull镜像然后save生成tar.gz镜像文件)
ctr -n k8s.io images import busybox-v1.36.tar.gz

# 启动两个测试 Pod
kubectl run pod01 --image=busybox:1.36 --command -- sleep 10000
kubectl run pod02 --image=busybox:1.36 --command -- sleep 10000

# 进入 Pod 互 ping
kubectl exec -it pod01 -- ping <pod02的IP>

7.2 Service 测试

kubectl create deployment nginx --image=nginx:1.19
kubectl expose deployment nginx --port=80 --target-port=80 --name=nginx --type=NodePort

kubectl get svc
curl <nginx CLUSTER-IP>

8. 生产加固

8.1 单节点也跑工作负载(选配)

默认 Master 不调度 Pod(只跑控制面),单节点部署需要移除污点:

# k8s 1.24以后
kubectl taint nodes --all node-role.kubernetes.io/control-plane-

# k8s 1.24以前
kubectl taint nodes --all node-role.kubernetes.io/master-

生产多节点环境不要这样做,Master 节点应该专注于控制面。参考

8.2 开启 IPVS

kubectl edit configmap kube-proxy -n kube-system
# 找到 mode,改为:
mode: "ipvs"
iptables.masqueradeAll: true

# 重启 kube-proxy Pod 使配置生效
kubectl delete pod --all -n kube-system -l k8s-app=kube-proxy

验证:

kubectl logs -n kube-system <kube-proxy-pod> | grep "Using ipvs Proxier"

9. 常见问题

Q: kubeadm init 失败怎么办?

kubeadm reset        # 清理状态
# 修正问题后重新 init

Q: Calico Pod 一直 CrashLoopBackOff?

# 查看日志定位
kubectl logs -n kube-system <calico-node-pod-name>

# 常见原因:
# 1. 双栈参数没配对 → 检查 calico.yaml 中的 IPAM 和环境变量
# 2. 镜像版本不匹配 → crictl images 确认镜像已导入
# 3. 网卡自动检测选错了 → 手动指定 IP_AUTODETECTION_METHOD

Q: 节点 NotReady?

# 检查 kubelet 状态
systemctl status kubelet
journalctl -u kubelet -f

# 常见原因:
# 1. CNI 未安装或安装失败
# 2. 容器运行时异常 → systemctl status containerd
# 3. 内核模块未加载 → lsmod | grep br_netfilter

Q: Token 过期了怎么加节点?

kubeadm token create --print-join-command

🔗 官方文档延伸阅读

主题 链接
kubeadm 安装指南 https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
容器运行时配置 https://kubernetes.io/docs/setup/production-environment/container-runtimes/
创建高可用集群 https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/high-availability/
CNI 网络插件列表 https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/
Network Policy https://kubernetes.io/docs/concepts/services-networking/network-policies/
RBAC 最佳实践 https://kubernetes.io/docs/concepts/security/rbac-good-practices/
kube-proxy IPVS 模式 https://kubernetes.io/docs/reference/networking/virtual-ips/

总结:整个流程就是 系统初始化 → 装运行时 → 装 K8s → 初始化集群 → 装 CNI → 验证。离线环境的关键在于提前准备好所有镜像(containerd + kubeadm 所需 + Calico),然后按步骤执行即可。遇到问题别慌,journalctl -u kubelet -fkubectl logs 是你的好朋友。