背景
随着Kubernetes的兴起,Docker在K8s中的地位逐渐受到挑战。一方面,Docker作为一个完整的容器平台,包含了许多K8s并不需要的功能,导致资源浪费。另一方面,K8s本身提供了容器编排和调度的功能,与Docker重叠,造成了一定程度上的冲突。Kubernetes早在1.20版本中变更日志描述如下: "Docker support in the kubelet is now deprecated and will be removed in a future release. "。Kubernetes弃用Docker,其实也不用过分紧张,在文章: 别慌: Kubernetes 和 Docker中 , 作者简介清晰的表达了观点:弃用 Docker 这个底层运行时,转而支持符合为 Kubernetes 创建的容器运行接口 Container Runtime Interface (CRI) 的运行时(常见的选择 containerd 和 CRI-O)。 但使用 Docker 构建的镜像,仍然可以在你的集群的所有运行时中继续工作。因为docker构建的镜像是符合OCI(Open Container Initiative)标准的。
那么Kubernetes为什么要移除Docker?主要原因还是Docker长期以来不支持Kubernetes主推的CRI容器运行时标准,Kubernetes需要长期维护着dockershim组件来专门适配Docker。dockershim是出现在Kubernetes发展初期、Docker如日中天阶段的产物,但是随着containerd等容器运行时的发展,Kubernetes也有了足够的理由不再维护dockershim了。
kubernetes Docker完整调用链

kubernetes Containerd完整调用链

docker
Docker作为一种早期的容器技术,它的出现颠覆了传统虚拟化方式,通过轻量级容器化的方式实现了应用的打包、交付和运行。Docker在容器技术的普及过程中发挥了关键作用,其用户友好的命令行工具和图形化界面让容器技术对广大开发者变得更加友好和易用。一度,Docker几乎成为容器化的代名词。为了防止docker一家独大,docker当年的实现被拆分出了几个标准化的模块,标准化的目的是模块是可被其他实现替换的,不由任何一个厂商控制。 Docker 由
- docker-client
- dockerd
- containerd
- docker-shim
- runc
组成,所以containerd是docker的基础组件之一,docker 对容器的管理和操作基本都是通过 containerd 完成的。 那么,containerd 是什么呢?
docker完整调用链

containerd
Containerd是由Docker团队开源的容器运行时,它专注于提供轻量级、高性能的容器运行环境。作为一个纯粹的容器运行时,Containerd被设计为更加符合K8s的架构和需求。它具有更小的资源占用,更快的启动时间,以及更好的性能表现。 K8s社区认可了Containerd的优势,并将其作为K8s生态系统的标配容器运行时。 Containerd 可以在宿主机中管理完整的容器生命周期:容器镜像的传输和存储、容器的执行和管理、存储和网络等。详细点说,Containerd 负责干下面这些事情:
- 管理容器的生命周期(从创建容器到销毁容器)
- 拉取/推送容器镜像
- 存储管理(管理镜像及容器数据的存储)
- 调用 runC 运行容器(与 runC 等容器运行时交互)
- 管理容器网络接口及网络
Containerd 和 Docker 组件常用命令是什么
Containerd 不支持 docker API 和 docker CLI,但是可以通过 cri-tool 命令实现类似的功能。
镜像相关
| 镜像相关功能 | Docker | Containerd |
|---|---|---|
| 显示本地镜像列表 | docker images | crictl images |
| 下载镜像 | docker pull | crictl pull |
| 上传镜像 | docker push | 无 |
| 删除本地镜像 | docker rmi | crictl rmi |
| 查看镜像详情 | docker inspect IMAGE-ID | crictl inspect IMAGE-ID |
容器相关
| 容器相关功能 | Docker | Containerd |
|---|---|---|
| 显示容器列表 | docker ps | crictl ps |
| 创建容器 | docker create | crictl create |
| 启动容器 | docker start | crictl start |
| 停止容器 | docker stop | crictl stop |
| 删除容器 | docker rm | crictl rm |
| 查看容器详情 | docker inspect | crictl inspect |
| attach | docker attach | crictl attach |
| exec | docker exec | crictl exec |
| logs | docker logs | crictl logs |
| stats | docker stats | crictl stats |
容器相关
| POD 相关功能 | Docker | Containerd |
|---|---|---|
| 显示 POD 列表 | 无 | crictl pods |
| 查看 POD 详情 | 无 | crictl inspectp |
| 运行 POD | 无 | crictl runp |
| 停止 POD | 无 | crictl stopp |
安装crictl工具
下载crictl需和kubernetes版本对应
| Kubernetes Version | cri-tools Version | cri-tools branch |
|---|---|---|
| ≥ 1.27.x | ≥ 1.27.x | master |
| ≥ 1.16.x ≤ 1.26.x | ≥ 1.16.x ≤ 1.26.x | master |
| 1.15.X | v1.15.0 | release-1.15 |
| 1.14.X | v1.14.0 | release-1.14 |
| 1.13.X | v1.13.0 | release-1.13 |
| 1.12.X | v1.12.0 | release-1.12 |
| 1.11.X | v1.11.1 | release-1.11 |
| 1.10.X | v1.0.0-beta.2 | release-1.10 |
| 1.9.X | v1.0.0-alpha.1 | release-1.9 |
| 1.8.X | v0.2 | release-1.8 |
| 1.7.X | v0.1 | release-1.7 |
VERSION="v1.22.0" #下载与你的 kubernetes 版本相对应的版本
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
# 解压crictl
tar zxvf crictl-$VERSION-linux-amd64.tar.gz
chown root.root crictl
mv crictl /usr/bin/
创建crictl 配置
cat <<EOF | tee /etc/crictl.yaml
runtime-endpoint: "unix:///var/run/containerd/containerd.sock"
image-endpoint: "unix:///var/run/containerd/containerd.sock"
timeout: 10
debug: false
pull-image-on-create: true
disable-pull-on-run: false
EOF
安装containerd
yum -y install containerd.io
# 创建containerd配置目录
mkdir -p /etc/containerd
# 生成containerd默认配置文件
containerd config default | sudo tee /etc/containerd/config.toml
启用 IPv4 数据包转发
手动启用 IPv4 数据包转发:
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
使用以下命令验证 net.ipv4.ip_forward 是否设置为 1:
sysctl net.ipv4.ip_forward
需要修改 /etc/containerd/config.toml 为如下内容
# 修改 pause 容器的下载地址,改成国内地址
sandbox_image = "registry.aliyuncs.com/k8sxio/pause:3.6"
# 结合 runc 使用 systemd cgroup 驱动
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
如果你使用 cgroup v2,则推荐 systemd cgroup 驱动。
Kubernetes集群容器引擎切换
环境
- OS: CentOS 7.6(当前最新版kernel)
- Container runtime: Docker CE 20.10.11
- Kubernetes: v1.22.4
[root@k8s-master-01 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master-01 Ready control-plane,master 11m v1.22.4 172.16.50.200 <none> CentOS Linux 7 (Core) 5.4.163-1.el7.elrepo.x86_64 docker://20.10.11
k8s-node-01 Ready <none> 10m v1.22.4 172.16.50.203 <none> CentOS Linux 7 (Core) 5.4.163-1.el7.elrepo.x86_64 docker://20.10.11
k8s-node-02 Ready <none> 10m v1.22.4 172.16.50.204 <none> CentOS Linux 7 (Core) 5.4.163-1.el7.elrepo.x86_64 docker://20.10.11
将该node标记为不可被调度,并且驱逐该node上的pod资源
[root@k8s-master-01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 14m 10.244.1.2 k8s-node-01 <none> <none>
nginx-7fb7fd49b4-pzqm6 1/1 Running 0 14m 10.244.2.2 k8s-node-02 <none> <none>
驱逐该node节点上的pod资源到集群中的其它节点上去
kubectl drain k8s-node-02 --delete-local-data --force --ignore-daemonsets
查看之前运行在该node上的pod被调度到了集群中的哪个节点
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
busybox 1/1 Running 0 23m 10.244.1.2 k8s-node-01 <none> <none>
nginx-7fb7fd49b4-bg5pn 1/1 Running 0 3m18s 10.244.1.3 k8s-node-01 <none> <none>
查看Kubernetes集群中的node资源信息
[root@k8s-master-01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master-01 Ready control-plane,master 33m v1.22.4
k8s-node-01 Ready <none> 32m v1.22.4
k8s-node-02 Ready,SchedulingDisabled <none> 32m v1.22.4
# 如上信息,k8s-node-02节点已经不可被调度了,接下来开始切换容器引擎
卸载原有docker
rpm -qa | grep docker
rpm -e docker-ce-20.10.11-3.el7.x86_64 docker-ce-cli-20.10.11-3.el7.x86_64 docker-ce-rootless-extras-20.10.11-3.el7.x86_64 docker-scan-plugin-0.9.0-3.el7.x86_64
安装containerd部分请参考本文章上面部分,这里我就不在写一遍了,安装方法都是一样的。
配置kubelet使用containerd
vim /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
重启kubelet
systemctl daemon-reload
systemctl restart kubelet
验证容器引擎是否成功切换为containerd
[root@k8s-master-01 ~]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-master-01 Ready control-plane,master 51m v1.22.4 172.16.50.200 <none> CentOS Linux 7 (Core) 5.4.163-1.el7.elrepo.x86_64 docker://20.10.11
k8s-node-01 Ready <none> 51m v1.22.4 172.16.50.203 <none> CentOS Linux 7 (Core) 5.4.163-1.el7.elrepo.x86_64 docker://20.10.11
k8s-node-02 Ready,SchedulingDisabled <none> 51m v1.22.4 172.16.50.204 <none> CentOS Linux 7 (Core) 5.4.163-1.el7.elrepo.x86_64 containerd://1.4.12
通过将节点标记为可调度,让节点重新上线
# 将 <node-to-drain> 替换为当前节点的名称
kubectl uncordon <node-to-drain>

2536

被折叠的 条评论
为什么被折叠?



