辞旧迎新,新手使用Containerd时的几点须知

2021-01-05 10:27:55 浏览数 (1)

相信大家在2020年岁末都被Kubernetes即将抛弃Docker的消息刷屏了。事实上作为接替Docker运行时的Containerd在早在Kubernetes1.7时就能直接与Kubelet集成使用,只是大部分时候我们因熟悉Docker,在部署集群时采用了默认的dockershim。不过社区也说了,在1.20之后的版本的kubelet会放弃对dockershim部分的支持。

作为普通小白,我们在更换Containerd后,以往的一些习惯和配置也不得不改变和适配。那么本篇也是最近小白逐渐替换Containerd后的一些总结。

1. Containerd安装与Kubelet集成

  • 安装前的准备
代码语言:txt复制
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 设置必需的 sysctl 参数,这些参数在重新启动后仍然存在。
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

sudo sysctl --system
  • 安装containerd
代码语言:txt复制
# 安装 Docker 的官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key --keyring /etc/apt/trusted.gpg.d/docker.gpg add -

# 新增 Docker apt 仓库。
sudo add-apt-repository 
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu 
    $(lsb_release -cs) 
    stable"
    
# 安装containerd包
sudo apt-get update && sudo apt-get install -y containerd.io
  • 生成containerd默认配置
代码语言:txt复制
sudo mkdir -p /etc/containerd
sudo containerd config default > /etc/containerd/config.toml
  • 修改kubelet配置

在配置文件/var/lib/kubelet/kubeadm-flags.env的KUBELET_KUBEADM_ARGS追加以下部分

代码语言:txt复制
KUBELET_KUBEADM_ARGS="--container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock --image-service-endpoint=unix:///run/containerd/containerd.sock"
  • 重启containerd和kubelet服务
代码语言:txt复制
systemctl restart containerd kubelet

2. Containerd常见操作

更换Containerd后,以往我们常用的docker命令也不再使用,取而代之的分别是crictl和ctr两个命令客户端。

  • crictl是遵循CRI接口规范的一个命令行工具,通常用它来检查和管理kubelet节点上的容器运行时和镜像
  • ctr是containerd的一个客户端工具,

使用crictl命令之前,需要先配置/etc/crictl.yaml如下:

代码语言:txt复制
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false

接下来就是crictl的的常见命令,其中能完全替代docker命令的参照下列表格

操作

crictl

docker

查看运行容器

crictl ps

docker ps

查看镜像

crictl images

docker images

查看容器日志

crictl logs

docker logs

登陆容器控制台

crictl exec

docker exec

pull镜像

crictl pull

docker pull

容器启动/停止

crictl start/stop

docker start/stop

容器资源情况

crictl stats

docker stats

可以看到crictl对容器生命周期的管理基本已经覆盖,不过在crictl我们不能完成操作也比较多,比如对镜像的管理就不属于它的管理范围。这部分还得依靠ctr来实现,操作方式同样可以参照下表

操作

ctr

docker

查看镜像

ctr images ls

docker images

镜像导入/导出

ctr images import/exporter

docker load/save

镜像拉取/推送

ctr images pull/push

docker pull/push

镜像tag

ctr images tag

docker tag

这里需注意的是,由于Containerd也有namespaces的概念,对于上层编排系统的支持,主要区分了3个命名空间分别是k8s.iomobydefault,以上我们用crictl操作的均在k8s.io命名空间完成如查看镜像列表就需要加上-n参数

代码语言:txt复制
ctr -n k8s.io images list

3. Containerd与(虚拟)显卡设备

在Docker中,通常用nvidia-docker来调用nvidia-container-runtime来实现容器的GPU设备挂载。在更换成Containerd后,我们就不再需要nvidia-docker这个客户端,而是直接在containerd运行时的plugin中直接调用nvidia-container-runtime

除了需要正常安装containerd和nvidia、cuda驱动外,还需要安装nvidia-container-runtime

代码语言:txt复制
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | 
  sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | 
  sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list
sudo apt update
sudo apt install nvidia-container-runtime -y

最后在containerd添加nvidia运行时配置

/etc/containerd/config.toml

代码语言:txt复制
    [plugins."io.containerd.grpc.v1.cri".containerd]
      snapshotter = "overlayfs"
-     default_runtime_name = "runc"
      default_runtime_name = "nvidia"
      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
        # This section is added by system, we can just ignore it.
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
          runtime_type = "io.containerd.runc.v2"
          runtime_engine = ""
          runtime_root = ""
          privileged_without_host_devices = false
          base_runtime_spec = ""
        [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
          runtime_type = "io.containerd.runc.v2"
          runtime_engine = ""
          runtime_root = ""
          privileged_without_host_devices = false
          base_runtime_spec = ""
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
            BinaryName = "nvidia-container-runtime"

此外如果你和小白一样用了腾讯的tke-gpu-manager来虚拟化GPU设备的话,还需要将gpu-manager升级到1.1.0版本以上。然后修改启动参数即可解决

代码语言:txt复制
containers:
- env:
  - name: EXTRA_FLAGS
    value: --container-runtime-endpoint=/var/run/containerd/containerd.sock

最后我们用一个pod来验证GPU是否能正常识别到即可

代码语言:txt复制
apiVersion: v1
kind: Pod
metadata:
  name: vcuda
spec:
  restartPolicy: Never
  containers:
  - image: nvidia/cuda:10.1-runtime-ubuntu16.04
    name: nvidia
    command:
    - "/usr/local/nvidia/bin/nvidia-smi"
    - "pmon"
    - "-d"
    - "10"
    resources:
      requests:
        tencent.com/vcuda-core: 50
        tencent.com/vcuda-memory: 4
      limits:
        tencent.com/vcuda-core: 50
        tencent.com/vcuda-memory: 4

4. Containerd控制台日志

在Docker时代,kubernetes的容器控制日志默认格式为json,在更换为Containerd后,容器的控制台输出变为text格式,如下

代码语言:txt复制
# docker的json格式日志
{"log":"[INFO] plugin/reload: Running configuration MD5 = 4665410bf21c8b272fcfd562c482cb82n","stream":"stdout","time":"2020-01-10T17:22:50.838559221Z"}

#contaienrd的text格式日志
2020-01-10T18:10:40.01576219Z stdout F [INFO] plugin/reload: Running configuration MD5 = 4665410bf21c8b272fcfd562c482cb82

大多情况情况下这会导致我们默认的日志采集客户端以前用json格式解析器报错而无法继续采集日志,所以当我们把Containerd上线后还需要修改日志采集端的配置。

以fluentd为样例,我们需要引入multi_format来解析两种格式的容器日志

代码语言:txt复制
<source>
  @id fluentd-containers.log
  @type tail
  path /var/log/containers/*.log
  pos_file /var/log/es-containers.log.pos
  tag raw.kubernetes.*
  read_from_head true
  <parse>
    @type multi_format
    <pattern>
      format json
      time_key time
      time_format %Y-%m-%dT%H:%M:%S.%NZ
    </pattern>
    #这部分用来正则匹配CRI容器日志格式
    <pattern>
      format /^(?<time>. ) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/
      time_format %Y-%m-%dT%H:%M:%S.%N%:z
    </pattern>
  </parse>
</source>

总结

K8S的Worker节点逐渐的往轻量化转移,除了Containerd之外还有k8s的亲儿子cri-o,不过相比Containerd已经过大规模生产环境验证的产品来讲,当下Containerd仍然是最佳的容器运行时管理工具。


扫描二维码关注「云原生小白」,回复【入群】进入Loki学习群

0 人点赞