K8s集群Containerd运行时离线标准化部署实操
K8s集群Containerd运行时离线标准化部署实操
|
项目 |
内容 |
|
适用版本 |
Kubernetes v1.28.15 + containerd 1.7.x + Rocky Linux 8.6 / RHEL 8.x |
|
部署模式 |
单Master + 多Worker(可扩展高可用) |
|
编写日期 |
2026-08-17 |
|
文档版本 |
v1.0 |
1. 操作环境与前置准备
1.1 硬件要求
|
角色 |
CPU |
内存 |
硬盘 |
网卡 |
|
Worker |
4核+ |
8GB+ |
200GB SSD |
千兆×1 |
|
Harbor仓库(可选) |
4核+ |
8GB+ |
500GB+ |
千兆×1 |
1.2 软件版本矩阵
|
组件 |
版本 |
说明 |
|
内核 |
4.18.0-372+ |
系统自带 |
|
Kubernetes |
v1.28.15 |
稳定版 |
|
containerd |
1.7.11+ |
CRI运行时 |
|
runc |
1.1.10+ |
OCI运行时 |
|
CNI插件 |
1.3.0+ |
容器网络接口 |
|
Calico |
v3.26.x |
网络策略引擎 |
|
crictl |
v1.28.0 |
CRI调试工具 |
|
Docker CLI(可选) |
24.0.x |
仅用于镜像打包导出 |
1.3 节点规划示例
|
主机名 |
IP地址 |
角色 |
|
k8s-worker01 |
192.168.10.21 |
Worker |
|
k8s-worker02 |
192.168.10.22 |
Worker |
|
harbor.local |
192.168.10.30 |
私有镜像仓库 |
1.4 离线环境网络要求
- 所有节点之间网络互通(同VLAN或路由可达)
- Master节点6443端口对Worker开放
- 节点间10250(kubelet)、2379-2380(etcd)端口互通
- Calico BGP模式开放179端口;VXLAN模式开放4789/UDP
2. 对接原理:Containerd与K8s CRI架构
2.1 整体架构
┌─────────────────────────────────────────────────────┐
│ Kubernetes Node │
│ │
│ ┌──────────┐ CRI gRPC ┌──────────────────┐ │
│ │ kubelet │◄──────────────►│ containerd │ │
│ │ │ (unix socket) │ ┌────────────┐ │ │
│ └──────────┘ │ │ CRI Plugin│ │ │
│ │ └────────────┘ │ │
│ │ ┌────────────┐ │ │
│ │ │ core API │ │ │
│ │ └────────────┘ │ │
│ │ ┌────────────┐ │ │
│ │ │ shim API │ │ │
│ │ └─────┬──────┘ │ │
│ └─────────┼────────┘ │
│ │ │
│ ┌─────────▼────────┐ │
│ │ containerd-shim │ │
│ │ (runc v2) │ │
│ └─────────┬────────┘ │
│ │ │
│ ┌─────────▼────────┐ │
│ │ runc │ │
│ │ (OCI runtime) │ │
│ └─────────┬────────┘ │
│ │ │
│ ┌─────────▼────────┐ │
│ │ Linux Namespace│ │
│ │ + Cgroups │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────┘
2.2 核心对接点
CRI(Container Runtime Interface) 是Kubernetes定义的容器运行时gRPC接口规范,kubelet通过以下两个核心服务与containerd通信:
|
服务 |
职责 |
|
ImageService |
镜像管理(拉取/推送/列出/删除镜像) |
通信方式:Unix Domain Socket,默认路径 /run/containerd/containerd.sock
2.3 离线部署核心思路
公网环境(有网) 离线环境(无网)
┌──────────────┐ ┌──────────────┐
│ 1. 下载RPM包 │ ──── U盘/光盘 ──►│ 1. 本地YUM源 │
│ 2. 拉取镜像 │ ──── tar包 ─────►│ 2. ctr导入镜像│
│ 3. 下载二进制 │ ──── 压缩包 ────►│ 3. 解压部署 │
└──────────────┘ └──────────────┘
离线部署三大介质:
- RPM软件包 — 通过 yumdownloader 或 reposync 下载全量依赖
- 容器镜像 — 通过 docker save / ctr images export 导出为tar包
- 二进制文件 — 从GitHub官方Release下载预编译二进制
3. 离线介质包制作
以下操作在**有公网的跳板机**上执行,制作完成后拷贝至离线环境。
3.1 创建工作目录
mkdir -p /opt/k8s-offline/{rpms,images,binaries,cni,configs}
cd /opt/k8s-offline
3.2 下载RPM包(含完整依赖)
3.2.1 配置Kubernetes YUM源
cat > /etc/yum.repos.d/kubernetes.repo << 'EOF'
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
3.2.2 下载K8s组件及依赖
# 安装下载工具
yum install -y yum-utils
# 下载kubelet kubeadm kubectl及全部依赖
yumdownloader --resolve --destdir=/opt/k8s-offline/rpms \
kubelet-1.28.15 \
kubeadm-1.28.15 \
kubectl-1.28.15 \
cri-tools-1.28.0 \
kubernetes-cni-1.3.0
# 下载containerd及依赖
yumdownloader --resolve --destdir=/opt/k8s-offline/rpms \
containerd-1.7.11
# 下载系统依赖(离线环境通常缺失)
yumdownloader --resolve --destdir=/opt/k8s-offline/rpms \
conntrack-tools socat ipvsadm ipset nfs-utils \
bash-completion libnetfilter_cthelper \
libnetfilter_cttimeout libnetfilter_queue
3.2.3 制作本地YUM仓库
yum install -y createrepo_c
createrepo_c /opt/k8s-offline/rpms/
cd /opt/k8s-offline && tar czf k8s-rpms-1.28.15.tar.gz rpms/
3.3 导出容器镜像
3.3.1 拉取K8s所需镜像
# 查看kubeadm所需镜像列表
kubeadm config images list --kubernetes-version=v1.28.15
# 拉取镜像
images=(
registry.k8s.io/kube-apiserver:v1.28.15
registry.k8s.io/kube-controller-manager:v1.28.15
registry.k8s.io/kube-scheduler:v1.28.15
registry.k8s.io/kube-proxy:v1.28.15
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.9-0
registry.k8s.io/coredns/coredns:v1.10.1
docker.io/calico/cni:v3.26.1
docker.io/calico/node:v3.26.1
docker.io/calico/kube-controllers:v3.26.1
docker.io/calico/typha:v3.26.1
)
for img in "${images[@]}"; do
docker pull "$img"
done
3.3.2 导出镜像tar包
# K8s核心镜像
docker save \
registry.k8s.io/kube-apiserver:v1.28.15 \
registry.k8s.io/kube-controller-manager:v1.28.15 \
registry.k8s.io/kube-scheduler:v1.28.15 \
registry.k8s.io/kube-proxy:v1.28.15 \
registry.k8s.io/pause:3.9 \
registry.k8s.io/etcd:3.5.9-0 \
registry.k8s.io/coredns/coredns:v1.10.1 \
-o /opt/k8s-offline/images/k8s-core-images-v1.28.15.tar
# Calico镜像
docker save \
calico/cni:v3.26.1 \
calico/node:v3.26.1 \
calico/kube-controllers:v3.26.1 \
calico/typha:v3.26.1 \
-o /opt/k8s-offline/images/calico-images-v3.26.1.tar
3.4 下载二进制工具
cd /opt/k8s-offline/binaries
# containerd官方二进制包(含runc)
wget https://github.com/containerd/containerd/releases/download/v1.7.11/containerd-1.7.11-linux-amd64.tar.gz
# runc独立二进制
wget https://github.com/opencontainers/runc/releases/download/v1.1.10/runc.amd64
# CNI插件
wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
# crictl
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.28.0/crictl-v1.28.0-linux-amd64.tar.gz
# etcdctl(可选)
wget https://github.com/etcd-io/etcd/releases/download/v3.5.9/etcd-v3.5.9-linux-amd64.tar.gz
3.5 介质包校验
cd /opt/k8s-offline
# 生成校验和
sha256sum rpms/*.rpm > rpms/SHA256SUMS
sha256sum images/*.tar > images/SHA256SUMS
sha256sum binaries/* > binaries/SHA256SUMS
# 最终打包
tar czf k8s-offline-full-v1.28.15.tar.gz rpms/ images/ binaries/ configs/
4. 系统初始化标准化配置
以下操作在**所有节点**(Master + Worker)上执行。
4.1 配置主机名与hosts
# Master节点
hostnamectl set-hostname k8s-master01
# Worker节点分别执行
hostnamectl set-hostname k8s-worker01
hostnamectl set-hostname k8s-worker02
# 所有节点配置hosts
cat >> /etc/hosts << 'EOF'
192.168.10.10 k8s-master01
192.168.10.21 k8s-worker01
192.168.10.22 k8s-worker02
192.168.10.30 harbor.local
EOF
4.2 关闭防火墙与SELinux
# 关闭firewalld
systemctl stop firewalld
systemctl disable firewalld
# 关闭SELinux
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
sed -i 's/^SELINUX=permissive$/SELINUX=disabled/' /etc/selinux/config
# 验证
getenforce # 应输出 Disabled
4.3 关闭Swap
swapoff -a
sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab
free -h # Swap行应全为0
4.4 内核参数优化
cat > /etc/sysctl.d/99-kubernetes-cri.conf << 'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
fs.inotify.max_user_instances = 8192
fs.inotify.max_user_watches = 524288
fs.file-max = 52706963
fs.nr_open = 52706963
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 16384
vm.swappiness = 0
vm.overcommit_memory = 1
EOF
# 加载内核模块
modprobe overlay
modprobe br_netfilter
cat > /etc/modules-load.d/k8s.conf << 'EOF'
overlay
br_netfilter
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF
sysctl --system
4.5 配置时间同步
yum install -y chrony
systemctl enable --now chronyd
# 配置内网NTP服务器(如有)
sed -i 's/^pool .*/server 192.168.10.1 iburst/' /etc/chrony.conf
systemctl restart chronyd
chronyc sources -v
timedatectl
4.6 配置本地YUM源
# 上传介质包并解压
mkdir -p /opt/k8s-offline
tar xzf k8s-rpms-1.28.15.tar.gz -C /opt/k8s-offline/
# 备份原有repo
mkdir -p /etc/yum.repos.d/backup
mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/
# 配置本地源
cat > /etc/yum.repos.d/k8s-local.repo << 'EOF'
[k8s-local]
name=K8s Local Repo
baseurl=file:///opt/k8s-offline/rpms
enabled=1
gpgcheck=0
EOF
yum clean all && yum makecache
5. Containerd运行时离线部署
5.1 RPM包方式安装(推荐)
yum install -y containerd-1.7.11
# 验证
rpm -qa | grep containerd
containerd --version
runc --version
5.2 二进制方式安装
cd /opt/k8s-offline/binaries
# 解压containerd
tar Cxzf /usr/local containerd-1.7.11-linux-amd64.tar.gz
# 安装runc
install -m 755 runc.amd64 /usr/local/sbin/runc
# 安装CNI插件
mkdir -p /opt/cni/bin
tar Cxzf /opt/cni/bin cni-plugins-linux-amd64-v1.3.0.tgz
# 安装crictl
tar xzf crictl-v1.28.0-linux-amd64.tar.gz -C /usr/local/bin/
5.3 生成配置文件
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
5.4 关键配置项修改
编辑 /etc/containerd/config.toml,重点修改以下内容:
# 数据目录(建议单独挂载数据盘)
root = "/data/containerd"
state = "/run/containerd"
# 1. systemd cgroup驱动(K8s推荐,必须与kubelet一致)
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
# 2. pause镜像(离线环境使用私有仓库地址)
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "harbor.local/k8s/pause:3.9"
# 3. 私有镜像仓库(HTTP内网,跳过TLS验证)
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.local"]
endpoint = ["http://harbor.local"]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.local".tls]
insecure_skip_verify = true
5.5 配置systemd服务
cat > /etc/systemd/system/containerd.service << 'EOF'
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/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
EOF
systemctl daemon-reload
systemctl enable --now containerd
systemctl status containerd
5.6 配置crictl
cat > /etc/crictl.yaml << 'EOF'
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
crictl version
crictl info
5.7 导入离线镜像
# 导入K8s核心镜像
ctr -n k8s.io images import /opt/k8s-offline/images/k8s-core-images-v1.28.15.tar
# 导入Calico镜像
ctr -n k8s.io images import /opt/k8s-offline/images/calico-images-v3.26.1.tar
# 验证
ctr -n k8s.io images ls
crictl images
**注意**:K8s使用的镜像必须导入到 `k8s.io` 命名空间,否则kubelet找不到镜像。
6. Kubernetes组件离线部署
6.1 安装K8s RPM包
# 所有节点执行
yum install -y kubelet-1.28.15 kubeadm-1.28.15 kubectl-1.28.15
# 启动kubelet(此时会反复重启,属正常现象,kubeadm init后恢复正常)
systemctl enable --now kubelet
6.2 配置kubelet cgroup驱动
cat > /etc/sysconfig/kubelet << 'EOF'
KUBELET_EXTRA_ARGS=--cgroup-driver=systemd --container-runtime-endpoint=unix:///run/containerd/containerd.sock
EOF
systemctl daemon-reload
systemctl restart kubelet
6.3 配置kubectl命令补全
yum install -y bash-completion
source /usr/share/bash-completion/bash_completion
echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -F __start_kubectl k' >> ~/.bashrc
source ~/.bashrc
7. 集群初始化与节点加入
7.1 准备kubeadm配置文件
在Master节点创建 /root/kubeadm-config.yaml:
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.10.10
bindPort: 6443
nodeRegistration:
criSocket: unix:///run/containerd/containerd.sock
name: k8s-master01
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.28.15
controlPlaneEndpoint: "192.168.10.10:6443"
imageRepository: registry.k8s.io
networking:
podSubnet: "10.244.0.0/16"
serviceSubnet: "10.96.0.0/12"
dnsDomain: "cluster.local"
etcd:
local:
dataDir: /var/lib/etcd
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
clusterDomain: cluster.local
clusterDNS:
- 10.96.0.10
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs
ipvs:
scheduler: rr
7.2 预拉取镜像验证
# 查看所需镜像列表
kubeadm config images list --config=/root/kubeadm-config.yaml
# 对比已导入镜像
crictl images | grep -E 'kube-apiserver|kube-controller|kube-scheduler|kube-proxy|pause|etcd|coredns'
7.3 初始化Master节点
kubeadm init --config=/root/kubeadm-config.yaml --upload-certs
成功后输出示例:
Your Kubernetes control-plane has initialized successfully!
kubeadm join 192.168.10.10:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxx
7.4 配置kubectl访问
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
kubectl get nodes
kubectl cluster-info
7.5 Worker节点加入集群
# 在Worker节点执行(token和hash从Master init输出获取)
kubeadm join 192.168.10.10:6443 \
--token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
--cri-socket unix:///run/containerd/containerd.sock
# 如token过期,在Master重新生成
kubeadm token create --print-join-command
7.6 移除Master污点(可选)
# 单节点集群或需在Master运行业务Pod时执行
kubectl taint nodes k8s-master01 node-role.kubernetes.io/control-plane:NoSchedule-
8. 容器网络插件部署(Calico)
8.1 下载并修改Calico YAML
# 有网环境下载
wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O calico.yaml
# 修改镜像地址为私有仓库
sed -i 's|docker.io/calico|harbor.local/k8s|g' calico.yaml
# 修改CIDR与kubeadm podSubnet一致
sed -i 's|# - name: CALICO_IPV4POOL_CIDR|- name: CALICO_IPV4POOL_CIDR|' calico.yaml
sed -i 's|# value: "192.168.0.0/16"| value: "10.244.0.0/16"|' calico.yaml
8.2 部署Calico
# 所有节点导入Calico镜像
ctr -n k8s.io images import /opt/k8s-offline/images/calico-images-v3.26.1.tar
# Master节点部署
kubectl apply -f calico.yaml
# 等待Pod就绪
kubectl get pods -n kube-system -w
8.3 验证网络
kubectl get nodes -o wide # 节点应为Ready
kubectl get pods -n kube-system -l k8s-app=calico-node
kubectl get ippools
9. 离线镜像仓库配置(Harbor对接)
9.1 Containerd配置Harbor认证
mkdir -p /etc/containerd/certs.d/harbor.local
# HTTP内网方式
cat > /etc/containerd/certs.d/harbor.local/hosts.toml << 'EOF'
server = "http://harbor.local"
[host."http://harbor.local"]
capabilities = ["pull", "resolve", "push"]
skip_verify = true
EOF
# HTTPS自签名证书方式(需拷贝CA证书)
# cp harbor-ca.crt /etc/containerd/certs.d/harbor.local/ca.crt
systemctl restart containerd
9.2 config.toml仓库配置
在 /etc/containerd/config.toml 中确认:
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
9.3 推送镜像到Harbor
# 登录Harbor
ctr -n k8s.io images login harbor.local -u admin -p Harbor12345
# 重新打标签
ctr -n k8s.io images tag \
registry.k8s.io/pause:3.9 \
harbor.local/k8s/pause:3.9
# 推送
ctr -n k8s.io images push harbor.local/k8s/pause:3.9
10. 验证流程
10.1 节点状态验证
kubectl get nodes -o wide
预期输出:
NAME STATUS ROLES AGE VERSION INTERNAL-IP
k8s-master01 Ready control-plane 10m v1.28.15 192.168.10.10
k8s-worker01 Ready <none> 5m v1.28.15 192.168.10.21
k8s-worker02 Ready <none> 5m v1.28.15 192.168.10.22
10.2 系统Pod验证
kubectl get pods -n kube-system -o wide
核心组件必须全部Running:
- kube-apiserver-master01
- kube-controller-manager-master01
- kube-scheduler-master01
- etcd-master01
- kube-proxy-xxx(每节点一个)
- calico-node-xxx(每节点一个)
- calico-kube-controllers-xxx
- coredns-xxx(2副本)
10.3 容器运行时验证
systemctl is-active containerd # 应为 active
containerd --version
crictl info | jq '.status'
crictl ps
crictl images
10.4 网络连通性验证
# 创建测试Pod
kubectl run net-test --image=harbor.local/k8s/pause:3.9 --restart=Never
kubectl get pod net-test -o wide
# 跨节点Ping
kubectl run ping-test --image=busybox:1.36 --rm -it --restart=Never -- ping -c 4 <对端PodIP>
# Service连通性
kubectl create deployment nginx --image=harbor.local/k8s/nginx:1.25 --replicas=2
kubectl expose deployment nginx --port=80 --type=ClusterIP
kubectl run curl-test --image=curlimages/curl --rm -it --restart=Never -- curl -s http://nginx
10.5 DNS验证
kubectl run dns-test --image=busybox:1.36 --rm -it --restart=Never -- nslookup kubernetes.default
预期输出包含:
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: kubernetes.default
Address 1: 10.96.0.1
10.6 IPVS模式验证
ipvsadm -Ln
# 应看到ClusterIP对应的虚拟服务和后端Pod
更多推荐

所有评论(0)