基础
需要注意的是,替换runtime,需要重新下载镜像。这会严重的加大Pod的恢复时间。
特别是在国内,一些镜像因为某些不可描述的原因,可能会无法下载成功。
另外,虽然镜像一样,但是containerd无法去找到docker本地的镜像缓存。至少我还没找到解决方式。。。
配置必要系统环境
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# Setup required sysctl params, these persist across reboots.
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# Apply sysctl params without reboot
sudo sysctl --system
安装
containerd可以从docker源中获取
# add repo
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# install
yum install containerd.io
# modify containerd config
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
修正配置/etc/containerd/config.toml,更改存储根路径
root=""
修正配置/etc/containerd/config.toml,使用 systemd cgroup driver
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
修正配置/etc/containerd/config.toml,使用国内163镜像源
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["http://hub-mirror.c.163.com","https://registry-1.docker.io"]
更改runtime
当使用kubeadm安装集群的时候:
- kubeadm 会将kubelet的配置写入 /var/lib/kubelet/config.yaml和cm对象
- kubeadm 会将启动参数以环境变量的方式写入/var/lib/kubelet/kubeadm-flags.env
配置选项可以参考https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration
启动参数可以参考 https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
我们需要将kubelet的runtime变更为containerd
# 手动追加runtime参数到kubelet配置:/var/lib/kubelet/kubeadm-flags.env
--cgroup-driver=systemd --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock
安装客户端工具crictl
https://kubernetes.io/zh/docs/tasks/debug-application-cluster/crictl/
wget 'https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.22.0/crictl-v1.22.0-linux-amd64.tar.gz'
tar xf crictl-*.tar.gz
cp crictl /usr/local/bin/
配置客户端工具
vim /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: true
endpoint的地址根据选用的runtime指定,不出意外应该是下面三个:
- unix:///var/run/dockershim.sock
- unix:///run/containerd/containerd.sock
- unix:///run/crio/crio.sock
查看当前k8s所用的镜像版本
docker images | grep k8s.gcr.io
k8s.gcr.io/kube-apiserver:v1.22.4
k8s.gcr.io/kube-controller-manager:v1.22.4
k8s.gcr.io/kube-scheduler:v1.22.4
k8s.gcr.io/kube-proxy:v1.22.4
k8s.gcr.io/pause:3.5
k8s.gcr.io/etcd:3.5.0-0
k8s.gcr.io/coredns/coredns:v1.8.4
✨当然,不仅仅有k8s自身镜像,还有其它部署的镜像。
拉取镜像到containerd本地库
根据上面的指令填充
full_version=1.22.4
cat>crictl-pull-images.sh<<EOF
#!/bin/bash
# kubeadm config images list
images=(
kube-apiserver:v${full_version}
kube-controller-manager:v${full_version}
kube-scheduler:v${full_version}
kube-proxy:v${full_version}
pause:3.5
etcd:3.5.0-0
coredns:1.8.4
)
for imageName in \${images[@]};
do
crictl pull registry.aliyuncs.com/google_containers/\${imageName}
ctr --namespace k8s.io images tag registry.aliyuncs.com/google_containers/\${imageName} k8s.gcr.io/\${imageName}
done
EOF
保存先不执行脚本。
ctr -n k8s.io 指定位于k8s.io命名空间的镜像
逐个更新
💥千万不能docker和containerd同时启动
# nodeName
nodeName=k8s01
# 驱逐node
kubectl drain ${nodeName} --ignore-daemonsets
# 校验是否只有 daemonsets pod
kubectl get all --all-namespaces -o wide| grep ${nodeName}
# 关闭kubelet
systemctl stop kubelet
# 关闭runtime
systemctl stop docker && systemctl disable docker
确保节点上异常的信息,在本文档实施过程中,出现 docker 和 kubelet 关闭的情况下,容器进行依然运行占用端口,导致containerd启动的时候无法正常运行Pod.
# 检查是否有异常端口
ss -tnalp
# 启动 containerd
systemctl start containerd && systemctl enable containerd && systemctl stop kubelet
# 执行拉取容器镜像的脚本
bash crictl-pull-images.sh
# 启动 kubelet
systemctl restart kubelet
# 恢复 node
kubectl uncordon ${nodeName}