Kubernetes切换Docker容器引擎为Containerd

文章目录

  • 前言
  • 一、准备一套使用Docker引擎的kubernetes集群
  • 二、配置先决条件
    • 1.启用Containerd依赖的overlay、br_netfilter内核模块
    • 2.设置必要的sysctl参数,这些参数在重新启动后仍然存在
  • 三、安装Containerd
  • 四、修改Containerd配置文件
  • 五、配置Kubelet使用Containerd
  • 六、使用Containerd管理容器
    • crictl查看本地镜像
    • crictl查看本地容器
    • crictl进入容器
    • crictl查看pod
  • crictl常用命令
  • 七、切换回Docker容器引擎
  • 总结


前言

 在未来的kubernetes版本会计划彻底放弃Docker支持,会弃用kubelet中的docker-shim组件;也就是k8s不能默认直接使用docker引擎了,所以在以后可能containerd可能会成为主流,很多大企业现在都已经换成containerd了,包括我之前在阿里云上创建ACK的时候,会出现让选择容器运行时的一个选项,上面就涵盖了containerd和docker两项;

docker-shim组件是k8s为了专门与docker适配的,能够与Docker Engine进行通信

 这篇文章我们来一起学习下将k8s集群下的容器引擎切换为Containerd以及Containerd如何去使用的;



一、准备一套使用Docker引擎的kubernetes集群

我直接用之前kubeadm部署的单master集群来进行操作;有需要k8s单集群部署的可以看下:kubeadm部署k8s集群手册

软件环境:

软件 版本
操作系统 Centos 7.9_x64
docker 20-ce
kubernetes v1.20.0
containerd v1.6.4

服务器规划:

角色 IP
k8s-master 192.168.1.1
k8s-node1 192.168.1.2
k8s-node2 192.168.1.3

我们用于测试修改容器引擎,只需要在其中一个节点测试下就可以了,我在node2节点上进行修改;



二、配置先决条件

1.启用Containerd依赖的overlay、br_netfilter内核模块

[root@k8s-node2 ~]# lsmod | grep overlay
overlay                91659  6 
[root@k8s-node2 ~]# lsmod | grep netfilter
br_netfilter           22256  0 
bridge                151336  1 br_netfilter

这两个内核模块在操作系统中是默认加载的,可以使用lsmod来进行查看

提示:如果这两个内核模块没有加载的话可以执行下面的命令进行加载:

[root@k8s-node2 ~]# sudo modprobe overlay
[root@k8s-node2 ~]# sudo modprobe br_netfilter

2.设置必要的sysctl参数,这些参数在重新启动后仍然存在

[root@k8s-node2 ~]# cat <
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1 #启动路由转发功能
EOF
[root@k8s-node2 ~]# sysctl --system #进行加载配置


三、安装Containerd

我们前面说过,containerd之前是docker的一部分,所以我们切换docker容器引擎为containerd的话则不需要安装containerd了
此时使用containerd容器引擎的流程图是这样的
如图:
Kubernetes切换Docker容器引擎为Containerd_第1张图片

提示:下面这些安装containerd的命令是针对之前容器引擎不是docker的或者没有安装过docker的亲们:

[root@k8s-node2 ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
[root@k8s-node2 ~]# yum install -y containerd.io
[root@k8s-node2 ~]# mkdir -p /etc/containerd
[root@k8s-node2 ~]# containerd config default > /etc/containerd/config.toml
[root@k8s-node2 ~]# ps -ef |grep containerd  #查看containerd的守护进程
root       1051      1  0 19:00 ?        00:00:08 /usr/bin/containerd
root       1237      1  0 19:00 ?        00:00:15 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root       3425      1  0 19:03 ?        00:00:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 0f2011ed7771da01d3077e0286076a77b4376195028e6d5845b6069af5d7786f -address /run/containerd/containerd.sock
...


四、修改Containerd配置文件

  • pause镜像设置为阿里云镜像仓库地址(默认是k8s国外的仓库,可能会拉去超时);
  • cgroups驱动设置为systemd;

提示:默认的containerd配置文件(/etc/containerd/config.toml)里的内容只有一行,是默认禁用cri的,如下图

Kubernetes切换Docker容器引擎为Containerd_第2张图片
所以我们需要重新获取下配置文件

[root@k8s-node2 ~]# containerd config default > /etc/containerd/config.toml
[root@k8s-node2 ~]# vim /etc/containerd/config.toml
disabled_plugins = []#可以看到此时生成的配置文件已经没有禁用cri了
[plugins."io.containerd.grpc.v1.cri"]
   sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2"
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]
            SystemdCgroup = true
            ...

sandbox_image = “registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2” #设置管理容器(负责网络)的镜像为阿里云的镜像;
SystemdCgroup = true #需要在[plugins.“io.containerd.grpc.v1.cri”.containerd.default_runtime.options]下添加 ;设置cgroup的驱动为systemd



五、配置Kubelet使用Containerd

编辑kubelet配置文件/etc/sysconfig/kubelet
提示:这个配置文件是kubelet可以向对外提供参数的地方,我们想加参数的时候可以在这里加;

[root@k8s-node2 ~]# vim /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=/run/containerd/containerd.sock --cgroup-driver=systemd

–container-runtime=remote #表示我们使用的不是docker引擎(只要不是docker引擎的话都是remote这个值);
–container-runtime-endpoint=/run/containerd/containerd.sock #指定containerd的容器引擎地址,这个sock文件就相当于是个api;
–cgroup-driver=systemd #设置cgroup的驱动为systemd;

加的kubelet这些启动参数可以通以下命令查看

[root@k8s-node2 ~]# kubelet --help | grep runtime
--container-runtime string                                 The container runtime to use. Possible values: 'docker', 'remote'. (default "docker")
#可以看到kubelet使用的容器引擎由两个只,一个是docker,还有一个值是只要使用的不是docker引擎 那么值为remote;
--container-runtime-endpoint string                        [Experimental] The endpoint of remote runtime service. Currently unix socket endpoint is supported on Linux, while npipe and tcp endpoints are supported on windows.  Examples:'unix:///var/run/dockershim.sock', 'npipe:./pipe/dockershim' (default "unix:///var/run/dockershim.sock")
#指定容器引擎的api的地址,sock文件的地址,可以看到默认使用的是docker-shim的sock;

最后再重启下Containerd的进程
提示:Containerd是可以独立的去管理的,例如做start,stop操作;

[root@k8s-node2 ~]# systemctl restart containerd
[root@k8s-node2 ~]# systemctl status containerd
● containerd.service - containerd container runtime
   Loaded: loaded (/usr/lib/systemd/system/containerd.service; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2022-06-15 22:40:30 CST; 16s ago
     Docs: https://containerd.io
  Process: 21876 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
 Main PID: 21878 (containerd)
    Tasks: 71
   Memory: 133.4M
   CGroup: /system.slice/containerd.service
   ...

这时我们去master节点查看下node2这个节点使用的容器引擎是什么
提示:现在应该还是默认的docker,因为需要重启一下node2节点上的kubelet才会变成containerd引擎

[root@k8s-master ~]# kubectl get node -o wide 
NAME         STATUS   ROLES                  AGE   VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
k8s-master   Ready    control-plane,master   8d    v1.20.11   192.168.1.1   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   docker://20.10.16
k8s-node1    Ready    <none>                 8d    v1.20.11   192.168.1.2   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   docker://20.10.16
k8s-node2    Ready    <none>                 8d    v1.20.11   192.168.1.3   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   docker://20.10.16

注意看最后CONTAINER-RUNTIME这一列,这一列表示的就是节点使用的容器引擎,可以看到现在还是使用的默认的引擎docker 20.10版本;


重启**kubelet**,使容器引擎使用containerd
[root@k8s-node2 ~]# systemctl restart kubelet 
[root@k8s-node2 ~]# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/kubelet.service.d
           └─10-kubeadm.conf
   Active: active (running) since Wed 2022-06-15 22:51:00 CST; 9min ago
     Docs: https://kubernetes.io/docs/
 Main PID: 29912 (kubelet)
    Tasks: 14
   Memory: 40.2M
   CGroup: /system.slice/kubelet.service
           └─29912 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --...
...

再次查看node2节点使用的容器引擎

[root@k8s-master ~]# kubectl get node -o wide 
NAME         STATUS   ROLES                  AGE   VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
k8s-master   Ready    control-plane,master   8d    v1.20.11   192.168.1.1   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   docker://20.10.16
k8s-node1    Ready    <none>                 8d    v1.20.11   192.168.1.2   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   docker://20.10.16
k8s-node2    Ready    <none>                 8d    v1.20.11   192.168.1.3   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   containerd://1.6.4

可以看到node2的容器引擎已经变成了containerd 1.6.4版本;
这就已经顺利的将docker切换成了containerd,现在如果创建个容器分配到这个节点上的话,就是containerd负责创建这个容器,包括销毁这样的动作,就不会再调用docker了;
提示:与此同时,docker还是会运行在此节点上的,但是有关容器的动作不会去调用docker,而是直接使用containerd,所以完全可以把docker这个进程干掉;



六、使用Containerd管理容器

 containerd提供了ctr命令行工具管理容器,但功能比较简单,所以一般会用crictl工具检查和调试容器。
提示:crictl这个工具,不只是给containerd提供的,而是所有适配CRI的容器引擎都可以用这个工具进行调试;
项目地址:https://github.com/kubernetes-sigs/cri-tools/


crictl这个工具默认是已经装了的

crictl这个工具最大的好处就是它与docker命令的使用风格是一毛一样的;
例如:

crictl查看本地镜像

[root@k8s-node2 ~]# crictl images
WARN[0000] image connect using default endpoints: [unix:///var/run/dockershim.sock unix:///run/containerd/containerd.sock unix:///run/crio/crio.sock uni As the default settings are now deprecated, you should set the endpoint instead. 
ERRO[0000] unable to determine image API version: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial uninect: connection refused" 
IMAGE                                                TAG                 IMAGE ID            SIZE
docker.io/calico/cni                                 v3.23.1             90d97aa939bbf       111MB
docker.io/calico/node                                v3.23.1             fbfd04bbb7f47       76.6MB
docker.io/library/busybox                            latest              62aedd01bd852       778kB
docker.io/library/nginx                              latest              0e901e68141fd       56.7MB
registry.aliyuncs.com/google_containers/coredns      1.7.0               bfe3a36ebd252       14MB
registry.aliyuncs.com/google_containers/kube-proxy   v1.23.0             e03484a90585e       39.3MB
registry.aliyuncs.com/google_containers/pause        3.2                 80d28bedfe5de       300kB

噶,我们可以看到报错了,
  这个Warnning是因为默认的引擎是一个列表,会一个一个的去连接尝试一下;这个列表里面包含了dockershim.sockcontainerd.sockcri-dockerd.sock(红帽的容器引擎);但是现在已经弃用了,所以报Warnning;
 这个ERROR报的是连接不上docker导致的;但是结果最终还是给我们输出了镜像信息,还是因为那个默认引擎是个列表,docker连不上,就给我们连上了containerd这个引擎 列出了镜像;
提示:我们在上面的引擎列表里可以看到有个dockershim.sock,这可能是docker已经做出了向k8s CRI适配的一个动作喔;


下面写下这个错误的解决办法,否则他会一直尝试连接这个列表的

[root@k8s-node2 ~]# vim /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10 #超时时间
debug: false #debug是否输出debug信息

/etc/crictl.yaml是crictl这个工具默认的配置文件,需要创建;
然后需要指定下endpoint的为containerd的sock地址;

再次查看镜像就没有warnning和error信息了;

[root@k8s-node2 ~]# crictl images
IMAGE                       TAG                 IMAGE ID            SIZE
docker.io/library/busybox   latest              62aedd01bd852       778kB

crictl查看本地容器

[root@k8s-node2 ~]# crictl ps 
CONTAINER           IMAGE               CREATED             STATE               NAME                ATTEMPT             POD ID              POD
ff073f3b0c45b       bfe3a36ebd252       3 minutes ago       Running             coredns             0                   220dcdcae5aff       coredns-5879556fbc-ghxfx
b16aa39b0554a       e03484a90585e       3 minutes ago       Running             kube-proxy          0                   64bccc538f5b4       kube-proxy-jhh5p
435bd9ba245eb       fbfd04bbb7f47       4 minutes ago       Running             calico-node         0                   4b01fffd2aea7       calico-node-gk86n
bd9d6caa5a8f9       0e901e68141fd       5 minutes ago       Running             my-nginx            0                   69f53f8f4e577       my-nginx-64cc7f8db7-b64gb
198c13cf5d94f       0e901e68141fd       5 minutes ago       Running             my-nginx            0                   cc4506ed4c87a       my-nginx-64cc7f8db7-2hcvb

crictl进入容器

[root@k8s-node2 ~]# crictl exec -it bd9d6caa5a8f9 bash 
root@my-nginx-64cc7f8db7-b64gb:/# ls  
bin  boot  dev	docker-entrypoint.d  docker-entrypoint.sh  etc	home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@my-nginx-64cc7f8db7-b64gb:/# 

crictl查看pod

[root@k8s-node2 ~]# crictl pods 
POD ID              CREATED             STATE               NAME                        NAMESPACE           ATTEMPT             RUNTIME
220dcdcae5aff       9 minutes ago       Ready               coredns-5879556fbc-ghxfx    kube-system         0                   (default)
69f53f8f4e577       9 minutes ago       Ready               my-nginx-64cc7f8db7-b64gb   default             0                   (default)
cc4506ed4c87a       9 minutes ago       Ready               my-nginx-64cc7f8db7-2hcvb   default             0                   (default)
64bccc538f5b4       9 minutes ago       Ready               kube-proxy-jhh5p            kube-system         0                   (default)
4b01fffd2aea7       9 minutes ago       Ready               calico-node-gk86n           kube-system         0                   (default)

这里就先演示这几个crictl命令;更多的命令我会在下面列出来



crictl常用命令

镜像:

镜像相关功能 Docker Containerd
显示本地镜像列表 docker images crictl images
下载镜像 docker pull crictl pull
上传镜像 docker push 无,需要使用buildkit等工具构建并上传镜像
删除本地镜像 docker rmi crictl rmi
查看镜像详情 docker inspect crictl inspecti 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
附加容器 docker attach crictl attach
进入容器/执行命令 docker exec crictl exec
查看日志 docker logs crictl logs
查看容器资源 docker stats crictl stats

Pod:

Pod相关功能 Docker Containerd
显示Pod列表 crictl pods
查看Pod详情 crictl inspectp
运行Pod crictl runp
停止Pod crictl stopp


七、切换回Docker容器引擎

提示:containerd只是作为测试练习,建议练习后还切回Docker引擎,就是把kubelet配置参数去掉并重启kubelet即可;

[root@k8s-node2 ~]# vim /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS=
[root@k8s-node2 ~]# systemctl restart kubelet
然后去master节点上查看node2节点是否切换回了docker容器引擎
[root@k8s-master ~]# kubectl get nodes -o wide 
NAME         STATUS   ROLES                  AGE   VERSION    INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION                CONTAINER-RUNTIME
k8s-master   Ready    control-plane,master   8d    v1.20.11   192.168.1.1   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   docker://20.10.16
k8s-node1    Ready    <none>                 8d    v1.20.11   192.168.1.2   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   docker://20.10.16
k8s-node2    Ready    <none>                 8d    v1.20.11   192.168.1.3   <none>        CentOS Linux 7 (Core)   3.10.0-1160.66.1.el7.x86_64   docker://20.10.16

总结

到这里,切换contained容器引擎就结束了;
 通过学习,总结了以下几个切换contianerd的相关问题:

  1. 正常情况下是所有节点都完成切换,前期测试建议docker与containerd共存;
  2. containerd完全兼容之前的容器镜像,应该说是只要是与CRI适配了的容器引擎它们之间的镜像都是兼容的,因为CRI也有一套容器镜像的标准;
  3. 学习containerd是先做技术储备,并不是立马就要用,还是用docker就行;

你可能感兴趣的:(Kubernetes学习分享;,docker,kubernetes,容器)