弃用 Docker

Kubernetes 最新版本 Kubernetes v1.20.0-rc.0 现已正式发布。Kubernetes 计划弃用 kubelet 中 Docker Engine 支持,对于 dockershim 的支持也将在下个版本中放弃。[1]不过不必担心,在目前 Kubernetes v1.20 中,Kubernetes 管理员可以继续使用 Docker 命令与 kubectl 命令管理 Kubernetes 集群,而且镜像使用不会受到任何影响。在未来发布的 Kubernetes 版本中,包括接下来陆续推出的次要版本,对于 dockershim 的支持将最终被移除(最早会在 v1.23 把 Dockershim 从 Kubelet 中移除),届时将无法使用 Docker 命令检查集群。

Kubernetes 本次弃用的是 dockershim[2],即 Kubernetes kubelet 实现中的组件之一,它能够与 Docker Engine 进行通信。

其实 Docker 中已经包含 containerd,Kubernetes 为什么还需要 Dockershim?这是因为 Docker 与 CRI(即容器运行时接口)并不相容。简而言之,Docker 并不支持 CRI(容器运行时接口)这一 Kubernetes 运行时 API,而 Kubernetes 用户一直以来所使用的其实是名为“dockershim”的桥接服务。Dockershim 能够转换 Docker API 与 CRI,但以后,Kubernetes 将不再提供这项桥接服务。

为什么弃用

Kubernetes 是一款基础设施工具,可对多种不同计算资源(例如虚拟、物理机)进行分组,使其呈现为统一的巨量计算资源,从而供应用程序使用或与其他人共享。在这样的架构中,Docker(或者容器运行时)仅用于通过 Kubernetes 控制平面进行调度,从而在实际主机内运行应用程序。

通过以上架构图,可以看到每个 Kubernetes 节点都与控制平面彼此通信。各个节点上的 kubelet 获取元数据,并执行 CRI 在该节点上进行容器的创建、删除。Kubernetes 只能与 CRI 通信,因此要与 Docker 通信,就必须使用桥接服务“dockershim”,这就是第一点原因。

这里再看一下 Docker 架构示意图:

Kubernetes 实际上只需要红框内的内容,Docker 网络与存储卷都在外部,而这些用不到的功能可能会带来安全隐患。众所周知,拥有的功能越少,攻击面也就越小,这是第二点原因。因此,我们需要考虑使用替代方案,即 CRI 运行时,例如 containerd 与 CRI-O,以下是选用二者的区别:

  • containerd 与 Docker 相兼容,二者共享相同的核心组件。
  • 如果主要使用 Kubernetes 的最小功能选项,CRI-O可能更为适合。[4]

如何应对

对于 Kubernetes 最终用户,此次调整不会有太大影响。Docker 不会就此消亡,仍然可以继续将 Docker 作为开发工具使用。Docker 可以继续构建容器,运行 docker build 命令所生成的镜像也能在 Kubernetes 集群内正常运行。

如果使用的是 Kubernetes 托管服务,需要确保在未来的 Kubernetes 版本彻底放弃 Docker 支持之前,为工作节点引入受支持的容器运行时。如果节点中包含自定义项,那可能需要根据当前环境及运行时要求做出更新,确保正确完成升级测试及规划。

如果集群一直在滚动扩展,则是需要配合变量以避免服务中断。在 v1.20 中,我们会收到 Docker 弃用警告,在未来的 Kubernets 版本(计划在 2021 年下半年发布的 v1.23)中,Docker 运行时将被彻底移除,并不再受到支持,届时必须切换至其他兼容的容器运行时,例如 containerd 或者 CRI-O。只需要保证我们所使用的运行时,能够支持当前正在使用的 Docker 守护程序配置即可(例如日志记录)。[3]

弃用常见问题

为什么不赞成使用 dockershim?

维护 dockershim 已成为 Kubernetes 维护人员的沉重负担。创建 CRI 标准是为了减轻这种负担,并允许不同容器运行时的流畅互用性。Docker 本身目前尚未实现 CRI,因此出现了问题。此外,这些较新的 CRI 运行时中正在实现与 dockershim 基本上不兼容的功能,例如 cgroups v2 和用户命名空间。放弃对 dockershim 的支持能有更多精力在这些领域中进行进一步的开发。

可以在 Kubernetes v1.20 使用 Docker 吗?

可以,在 v1.20 中唯一改变的是,如果使用 Docker 作为运行时,在 kubelet 启动时会打印一个警告日志。

dockershim 什么时候会被移除?

不会在 Kubernetes v1.22 之前被移除,这意味着最早不使用 dockershim 的版本会是 2021 年底的 v1.23。

现有的 Docker 镜像还能工作吗?

可以,从 docker build 产生的镜像将与所有 CRI 实现一起工作,所有的现有镜像将继续仍然完全相同的工作。

私有镜像能否继续工作?

可以,所有 CRI 运行时都支持 Kubernetes 中使用的相同的 pull secret 配置,无论是通过 PodSpec 还是 ServiceAccount。[5]

参考资料:

[1]https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#deprecation

[2]https://github.com/kubernetes/kubernetes/tree/master/pkg/kubelet/dockershim

[3]https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/

[4]https://dev.to/inductor/wait-docker-is-deprecated-in-kubernetes-now-what-do-i-do-e4m

[5]https://kubernetes.io/blog/2020/12/02/dockershim-faq/

本周 K8s 开源项目推荐

audit2rbac

  • 它可以将 Kubernetes 审核日志和用户名作为输入,生成 RBAC 角色和绑定对象,以覆盖该用户提出的所有 API 请求。
  • github.com/liggitt/audit2rbac

craft

  • 它以健壮和通用的方式为任何资源声明了 Kubernetes Operator,使开发人员可以专注于 Dockerfile 中资源管理的 CRUD 操作。
  • github.com/salesforce/craft

pluto

  • 它能帮助用户在其代码存储库和 Helm 版本中找到已弃用的 Kubernetes apiVersion。
  • github.com/FairwindsOps/pluto

ThreatMapper

  • 它能识别正在运行的容器、镜像、主机和存储库中的漏洞。
  • github.com/deepfence/ThreatMapper

stale-feature-branch-operator

  • 它可以删除 Kubernetes 集群中的陈旧功能分支。
  • github.com/dmytrostriletskyi/stale-feature-branch-operator

polaris

  • 它会进行各种检查以确保使用最佳实践来配置 Kubernetes Pod 和控制器,从而避免将来出现问题。
  • github.com/FairwindsOps/polaris