这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

从 dockershim 迁移

本节提供从 dockershim 迁移到其他容器运行时的必备知识。

自从 Kubernetes 1.20 宣布 弃用 dockershim, 各类疑问随之而来:这对各类工作负载和 Kubernetes 部署会产生什么影响。 我们的弃用 Dockershim 常见问题可以帮助你更好地理解这个问题。

建议从 dockershim 迁移到其他替代的容器运行时。 请参阅容器运行时 一节以了解可用的备选项。 当在迁移过程中遇到麻烦,请上报问题。 那么问题就可以及时修复,你的集群也可以进入移除 dockershim 前的就绪状态。

1 - 将节点上的容器运行时从 Docker Engine 改为 containerd

本任务给出将容器运行时从 Docker 改为 containerd 所需的步骤。 此任务适用于运行 1.23 或更早版本 Kubernetes 的集群操作人员。 同时,此任务也涉及从 dockershim 迁移到 containerd 的示例场景, 以及可以从此页面 获得的其他容器运行时列表。

Before you begin

安装 containerd。进一步的信息可参见 containerd 的安装文档。 关于一些特定的环境准备工作,请遵循 containerd 指南

腾空节点

kubectl drain <node-to-drain> --ignore-daemonsets

<node-to-drain> 替换为你所要腾空的节点的名称

停止 Docker 守护进程

systemctl stop kubelet
systemctl disable docker.service --now

安装 Containerd

遵循此指南 了解安装 containerd 的详细步骤。

  1. 从官方的 Docker 仓库安装 containerd.io 包。关于为你所使用的 Linux 发行版来设置 Docker 仓库,以及安装 containerd.io 包的详细说明,可参见 Install Docker Engine
  1. 配置 containerd:

    sudo mkdir -p /etc/containerd
    containerd config default | sudo tee /etc/containerd/config.toml
    
  1. 重启 containerd:

    sudo systemctl restart containerd
    

启动一个 Powershell 会话,将 $Version 设置为期望的版本(例如:$Version="1.4.3"), 之后运行下面的命令:

  1. 下载 containerd:

    curl.exe -L https://github.com/containerd/containerd/releases/download/v$Version/containerd-$Version-windows-amd64.tar.gz -o containerd-windows-amd64.tar.gz
    tar.exe xvf .\containerd-windows-amd64.tar.gz
    
  1. 解压缩并执行配置:

    Copy-Item -Path ".\bin\" -Destination "$Env:ProgramFiles\containerd" -Recurse -Force
    cd $Env:ProgramFiles\containerd\
    .\containerd.exe config default | Out-File config.toml -Encoding ascii
    
    # 请审查配置信息。取决于你的安装环境,你可能需要调整:
    # - the sandbox_image (Kubernetes pause 镜像)
    # - cni bin_dir 和 conf_dir 的位置
    Get-Content config.toml
    
    # (可选步骤,但强烈建议执行)将 containerd 排除在 Windows Defender 扫描之外
    Add-MpPreference -ExclusionProcess "$Env:ProgramFiles\containerd\containerd.exe"
    
  1. 启动 containerd:

    .\containerd.exe --register-service
    Start-Service containerd
    

配置 kubelet 使用 containerd 作为其容器运行时

编辑文件 /var/lib/kubelet/kubeadm-flags.env,将 containerd 运行时添加到标志中: --container-runtime=remote--container-runtime-endpoint=unix:///run/containerd/containerd.sock"

对于使用 kubeadm 的用户,可以考虑下面的问题:

kubeadm 工具将每个主机的 CRI 套接字保存在该主机对应的 Node 对象的注解中。 使用 kubeadm 的用户应该知道,kubeadm 工具将每个主机的 CRI 套接字保存在该主机对应的 Node 对象的注解中。 要更改这一注解信息,你可以在一台包含 kubeadm /etc/kubernetes/admin.conf 文件的机器上执行以下命令:

kubectl edit no <node-name>

这一命令会打开一个文本编辑器,供你在其中编辑 Node 对象。 要选择不同的文本编辑器,你可以设置 KUBE_EDITOR 环境变量。

  • 更改 kubeadm.alpha.kubernetes.io/cri-socket 值,将其从 /var/run/dockershim.sock 改为你所选择的 CRI 套接字路径 (例如:unix:///run/containerd/containerd.sock)。

    注意新的 CRI 套接字路径必须带有 unix:// 前缀。

  • 保存文本编辑器中所作的修改,这会更新 Node 对象。

重启 kubelet

systemctl start kubelet

验证节点处于健康状态

运行 kubectl get nodes -o wide,containerd 会显示为我们所更改的节点上的运行时。

最后,在一切顺利时删除 Docker。

sudo yum remove docker-ce docker-ce-cli

sudo apt-get purge docker-ce docker-ce-cli

sudo dnf remove docker-ce docker-ce-cli

sudo apt-get purge docker-ce docker-ce-cli

2 - 查明节点上所使用的容器运行时

本页面描述查明集群中节点所使用的容器运行时 的步骤。

取决于你运行集群的方式,节点所使用的容器运行时可能是事先配置好的, 也可能需要你来配置。如果你在使用托管的 Kubernetes 服务, 可能存在特定于厂商的方法来检查节点上配置的容器运行时。 本页描述的方法应该在能够执行 kubectl 的场合下都可以工作。

Before you begin

安装并配置 kubectl。参见安装工具 节了解详情。

查明节点所使用的容器运行时

使用 kubectl 来读取并显示节点信息:

kubectl get nodes -o wide

输出如下面所示。CONTAINER-RUNTIME 列给出容器运行时及其版本。

# For dockershim
NAME         STATUS   VERSION    CONTAINER-RUNTIME
node-1       Ready    v1.16.15   docker://19.3.1
node-2       Ready    v1.16.15   docker://19.3.1
node-3       Ready    v1.16.15   docker://19.3.1
# For containerd
NAME         STATUS   VERSION   CONTAINER-RUNTIME
node-1       Ready    v1.19.6   containerd://1.4.1
node-2       Ready    v1.19.6   containerd://1.4.1
node-3       Ready    v1.19.6   containerd://1.4.1

你可以在容器运行时 页面找到与容器运行时相关的更多信息。

3 - 检查弃用 Dockershim 对你的影响

Kubernetes 的 dockershim 组件使得你可以把 Docker 用作 Kubernetes 的 容器运行时。 在 Kubernetes v1.20 版本中,内建组件 dockershim弃用

本页讲解你的集群把 Docker 用作容器运行时的运作机制, 并提供使用 dockershim 时,它所扮演角色的详细信息, 继而展示了一组操作,可用来检查弃用 dockershim 对你的工作负载是否有影响。

检查你的应用是否依赖于 Docker

即使你是通过 Docker 创建的应用容器,也不妨碍你在其他任何容器运行时上运行这些容器。 这种使用 Docker 的方式并不构成对 Docker 作为一个容器运行时的依赖。

当用了别的容器运行时之后,Docker 命令可能不工作,或者产生意外的输出。 下面是判定你是否依赖于 Docker 的方法。

  1. 确认没有特权 Pod 执行 Docker 命令(如 docker ps)、重新启动 Docker 服务(如 systemctl restart docker.service)或修改 Docker 配置文件 /etc/docker/daemon.json
  2. 检查 Docker 配置文件(如 /etc/docker/daemon.json)中容器镜像仓库的镜像(mirror)站点设置。 这些配置通常需要针对不同容器运行时来重新设置。
  3. 检查确保在 Kubernetes 基础设施之外的节点上运行的脚本和应用程序没有执行 Docker 命令。 可能的情况如:
    • SSH 到节点排查故障;
    • 节点启动脚本;
    • 直接安装在节点上的监控和安全代理。
  4. 检查执行上述特权操作的第三方工具。详细操作请参考 从 dockershim 迁移遥测和安全代理
  5. 确认没有对 dockershim 行为的间接依赖。这是一种极端情况,不太可能影响你的应用。 一些工具很可能被配置为使用了 Docker 特性,比如,基于特定指标发警报, 或者在故障排查指令的一个环节中搜索特定的日志信息。 如果你有此类配置的工具,需要在迁移之前,在测试集群上测试这类行为。

Docker 依赖详解

容器运行时是一个软件,用来运行组成 Kubernetes Pod 的容器。 Kubernetes 负责编排和调度 Pod;在每一个节点上,kubelet 使用抽象的容器运行时接口,所以你可以任意选用兼容的容器运行时。

在早期版本中,Kubernetes 提供的兼容性支持一个容器运行时:Docker。 在 Kubernetes 发展历史中,集群运营人员希望采用更多的容器运行时。 于是 CRI 被设计出来满足这类灵活性需要 - 而 kubelet 亦开始支持 CRI。 然而,因为 Docker 在 CRI 规范创建之前就已经存在,Kubernetes 就创建了一个适配器组件 dockershim。 dockershim 适配器允许 kubelet 与 Docker 交互,就好像 Docker 是一个 CRI 兼容的运行时一样。

你可以阅读博文 Kubernetes 正式支持集成 Containerd

Dockershim 和 Containerd CRI 的实现对比图

切换到容器运行时 Containerd 可以消除掉中间环节。 所有相同的容器都可由 Containerd 这类容器运行时来运行。 但是现在,由于直接用容器运行时调度容器,它们对 Docker 是不可见的。 因此,你以前用来检查这些容器的 Docker 工具或漂亮的 UI 都不再可用。

你不能再使用 docker psdocker inspect 命令来获取容器信息。 由于你不能列出容器,因此你不能获取日志、停止容器,甚至不能通过 docker exec 在容器中执行命令。

你仍然可以下载镜像,或者用 docker build 命令创建它们。 但用 Docker 创建、下载的镜像,对于容器运行时和 Kubernetes,均不可见。 为了在 Kubernetes 中使用,需要把镜像推送(push)到某镜像仓库。

What's next

4 - 从 dockershim 迁移遥测和安全代理

在 Kubernetes 1.20 版本中,dockershim 被弃用。 在博文弃用 Dockershim 常见问题中, 你大概已经了解到,大多数应用并没有直接通过运行时来托管容器。 但是,仍然有大量的遥测和安全代理依赖 docker 来收集容器元数据、日志和指标。 本文汇总了一些信息和链接:信息用于阐述如何探查这些依赖,链接用于解释如何迁移这些代理去使用通用的工具或其他容器运行。

遥测和安全代理

为了让代理运行在 Kubernetes 集群中,我们有几种办法。 代理既可以直接在节点上运行,也可以作为守护进程运行。

为什么遥测代理依赖于 Docker?

因为历史原因,Kubernetes 建立在 Docker 之上。 Kubernetes 管理网络和调度,Docker 则在具体的节点上定位并操作容器。 所以,你可以从 Kubernetes 取得调度相关的元数据,比如 Pod 名称;从 Docker 取得容器状态信息。 后来,人们开发了更多的运行时来管理容器。 同时一些项目和 Kubernetes 特性也不断涌现,支持跨多个运行时收集容器状态信息。

一些代理和 Docker 工具紧密绑定。此类代理可以这样运行命令,比如用 docker psdocker top 这类命令来列出容器和进程,用 docker logs 订阅 Docker 的日志。 但随着 Docker 作为容器运行时被弃用,这些命令将不再工作。

识别依赖于 Docker 的 DaemonSet

如果某 Pod 想调用运行在节点上的 dockerd,该 Pod 必须满足以下两个条件之一:

  • 将包含 Docker 守护进程特权套接字的文件系统挂载为一个;或
  • 直接以卷的形式挂载 Docker 守护进程特权套接字的特定路径。

举例来说:在 COS 镜像中,Docker 通过 /var/run/docker.sock 开放其 Unix 域套接字。 这意味着 Pod 的规约中需要包含 hostPath 卷以挂载 /var/run/docker.sock

下面是一个 shell 示例脚本,用于查找包含直接映射 Docker 套接字的挂载点的 Pod。 你也可以删掉 grep /var/run/docker.sock 这一代码片段以查看其它挂载信息。

kubectl get pods --all-namespaces \
-o=jsonpath='{range .items[*]}{"\n"}{.metadata.namespace}{":\t"}{.metadata.name}{":\t"}{range .spec.volumes[*]}{.hostPath.path}{", "}{end}{end}' \
| sort \
| grep '/var/run/docker.sock'

检测节点代理对 Docker 的依赖性

在你的集群节点被定制、且在各个节点上均安装了额外的安全和遥测代理的场景下, 一定要和代理的供应商确认:该代理是否依赖于 Docker。

遥测和安全代理的供应商

我们通过 谷歌文档 提供了为各类遥测和安全代理供应商准备的持续更新的迁移指导。 请与供应商联系,获取从 dockershim 迁移的最新说明。