Kubernetes 生产环境 Cri-Dockerd 二进制部署指南

部署全流程

本指南以 Linux (CentOS/Ubuntu) 环境为例,演示如何在 K8s 节点上配置 cri-dockerd。

1. 获取二进制文件

首先,我们需要从 Mirantis 官方仓库下载编译好的二进制文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 定义版本变量
VERSION="0.3.4"
ARCH="amd64"

# 下载压缩包
wget https://github.com/Mirantis/cri-dockerd/releases/download/v${VERSION}/cri-dockerd-${VERSION}.${ARCH}.tgz

# 解压
tar -xvf cri-dockerd-${VERSION}.${ARCH}.tgz

# 移动二进制文件到系统路径
sudo mv cri-dockerd/cri-dockerd /usr/local/bin/

# 验证安装
cri-dockerd --version

2. 配置 Systemd 服务

我们需要创建两个 systemd 文件:一个用于 socket 激活,一个用于服务本身。

2.1 创建 Socket 文件

创建 /etc/systemd/system/cri-dockerd.socket

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-dockerd.service

[Socket]
# 这里定义了生成的 socket 文件路径
ListenStream=/var/run/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target

2.2 创建 Service 文件

创建 /etc/systemd/system/cri-dockerd.service

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-dockerd.socket

[Service]
Type=notify
# 关键启动参数
ExecStart=/usr/local/bin/cri-dockerd --container-runtime-endpoint fd:// \
          --network-plugin=cni \
          --pod-infra-container-image=registry.k8s.io/pause:3.9
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always

# 生产环境建议添加如下资源限制(可选)
LimitNOFILE=65536
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity

[Install]
WantedBy=multi-user.target

注意

  • --pod-infra-container-image:请根据你的 K8s 版本和网络环境修改 pause 镜像地址(国内环境可能需要替换为阿里云等镜像源,如 registry.aliyuncs.com/google_containers/pause:3.9)。
  • --network-plugin=cni:明确指定使用 CNI 网络插件。

3. 启动服务

1
2
3
4
5
6
7
8
9
# 重载 systemd 配置
sudo systemctl daemon-reload

# 启用并启动服务
sudo systemctl enable --now cri-dockerd.socket
sudo systemctl enable --now cri-dockerd.service

# 检查状态
systemctl status cri-dockerd.socket cri-dockerd.service

确保 socket 状态是 Active: active (running)

4. 修改 Kubelet 配置

这是最后也是最关键的一步,我们需要告诉 Kubelet 不要直接找 Docker,而是去找 cri-dockerd

方式 A: 修改 kubeadm 配置文件 (推荐新集群)

如果你是用 kubeadm 初始化集群,可以在 InitConfigurationJoinConfiguration 中指定:

1
2
nodeRegistration:
  criSocket: unix:///var/run/cri-dockerd.sock

方式 B: 修改现有节点配置

编辑 /var/lib/kubelet/kubeadm-flags.env(适用于 kubeadm 安装的集群):

1
2
# 找到 KUBELET_KUBEADM_ARGS 变量,添加或修改 --container-runtime-endpoint
KUBELET_KUBEADM_ARGS="... --container-runtime-endpoint=unix:///var/run/cri-dockerd.sock"

或者直接编辑 /etc/default/kubelet (Debian/Ubuntu) 或 /etc/sysconfig/kubelet (CentOS/RHEL),具体取决于你的发行版规范。

5. 重启 Kubelet

1
sudo systemctl restart kubelet

6. 验证 (Verification)

部署完成后,可以通过以下几种方式快速验证是否配置成功:

6.1 使用 crictl 验证 (最直接的方法)

crictl 是 Kubernetes 社区提供的 CRI 客户端工具。这是验证 cri-dockerd 是否正常工作的金标准

第一步:安装 crictl

为了确保兼容性(同时支持旧的 v1alpha2 和新的 v1 协议),推荐使用 v1.24.0 版本。这个版本就像一个“万能钥匙”,既能连接旧版 Kubernetes 组件,也能完美适配新的 cri-dockerd

1
2
3
4
VERSION="v1.24.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-$VERSION-linux-amd64.tar.gz

第二步:配置 crictl 连接 cri-dockerd

我们需要告诉 crictl 去哪里找 cri-dockerd 的 socket。执行以下命令直接生成配置文件:

1
2
3
4
5
6
7
8
sudo tee /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///var/run/cri-dockerd.sock
image-endpoint: unix:///var/run/cri-dockerd.sock
timeout: 10
debug: false
pull-image-on-create: false
disable-pull-on-run: false
EOF

第三步:执行验证命令

  1. 检查运行时状态:

    1
    
    crictl info

    成功标志: 输出一大段 JSON,其中 status.runtimeReadystatus.networkReady 都必须是 true

  2. 列出 Pod/容器:

    1
    
    crictl ps

    成功标志: 能看到正在运行的容器列表。如果不报错且能列出(或者列表为空但没报错),说明连接成功。

  3. 拉取镜像测试:

    1
    
    crictl pull busybox

    成功标志: 成功拉取镜像,没有报认证或连接错误。

6.2 查看 K8s 节点状态

在 Master 节点上执行:

1
kubectl get nodes -o wide
  • CONTAINER-RUNTIME: 应该显示 docker://20.10.x
  • STATUS: 应该显示 Ready

6.3 检查日志排除 “dockershim” 报错

如果你在日志中看到类似 CRI v1 runtime API is not implemented for endpoint "unix:///var/run/dockershim.sock" 的错误,这说明你的组件(如 Kubelet 或某些监控 Agent)还在尝试寻找旧的内置 dockershim

修复方法: 确保你已经彻底更新了所有相关配置,将旧的 /var/run/dockershim.sock 替换为新的 /var/run/cri-dockerd.sock

  • 检查 Kubelet 启动参数。
  • 检查 CNI 插件配置。
  • 检查是否有像 node-exporter 或其他 DaemonSet 挂载了错误的路径。

常见故障排查

  1. 启动失败,提示 fd:// 错误: 确保你先启动了 socket (systemctl start cri-dockerd.socket),因为 fd:// 语法依赖于 systemd socket activation 机制。

  2. Pod 无法启动,Sandbox 创建失败: 通常是 pause 镜像拉取失败。检查 /etc/systemd/system/cri-dockerd.service 中的 --pod-infra-container-image 地址是否可以访问。

  3. CNI 网络报错: 检查 cri-dockerd 的 --cni-bin-dir (默认 /opt/cni/bin) 和 --cni-conf-dir (默认 /etc/cni/net.d) 是否与你实际安装 CNI 插件的路径一致。

  4. crictl 版本不匹配 (Unimplemented service runtime.v1alpha2): 如果 crictl info 报错 unknown service runtime.v1alpha2.RuntimeService,说明你的 crictl 版本太老(不支持自动协商 v1),或者版本太新(完全移除了 v1alpha2 支持)。

    • 解决方案:推荐安装 v1.24.0 版本,它同时兼容 v1 和 v1alpha2 协议,兼容性最好。
0%