目录

containerd基础-基础命令和使用

containerd 的一些基础使用和命令.

关注点

在 kubernetes 1.24 及以后的版本都推荐使用 containerd 做 runtime ,我们对比一下 containerd 和 docker 之间,目录结构都有哪些变化。

  • containerd pull 镜像时,镜像都存储在 /var/lib/containerd/io.containerd.content.v1.content/blob/sha256

  • containerd 为 runtime 时,标准输出(stdout)的日志文件存放在 node:/var/log/containers

  • containerd 为 runtime 时,运行的所有文件(merger层)存放在 node:/run/containerd/io.containerd.runtime.v2.task/k8s.io/

  • containerd 为 runtime 时, lower 层和 upper 层存在 node: /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/

  • containerd 为 runtime 时,empty 挂载容器后,存放在 node: /var/lib/kubelet/pods/****/volumes/kubernetes.io~empty-dir/

containerd 安装

安装方式有 2 种,一种是安装 Docker ,因为 Docker 本身也集成了 containerd 的安装,然后再稍微做一下配置即可;另一种就是直接使用官方 GitHub 提供的二进制包进行安装,我们选择后者。

  1. 下载 containerd tar 包,解压至 /usr/local 。
1
2
3
4
5
6
7
8
$ tar Cxzvf /usr/local containerd-1.6.2-linux-amd64.tar.gz
bin/
bin/containerd-shim-runc-v2
bin/containerd-shim
bin/ctr
bin/containerd-shim-runc-v1
bin/containerd
bin/containerd-stress

配置 containerd

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
containerd config default > /etc/containerd/config.toml

# 配置 containerd 使用 systemd 作为 cgroup
systemd_cgroup = true

# 按需修改目录
# root 是用来保存持久化数据,包括 Snapshots, Content, Metadata 以及各种插件的数据,每一个插件都有自己单独的目录,Containerd 本身不存储任何数据,它的所有功能都来自于已加载的插件
root = "/var/lib/containerd"
# state 是用来保存运行时的临时数据的,包括 sockets、pid、挂载点、运行时状态以及不需要持久化的插件数据
state = "/run/containerd"
  1. 如果你想用 systemd 去管理 containerd ,创建 /usr/lib/systemd/system/containerd.service 文件。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd

Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# 注意这里,下面 3 个官方是 infinity 会报错
LimitNPROC=655350
LimitCORE=655350
LimitNOFILE=655350
TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target
  1. 创建完 reload 一下,开启开机自启。
1
2
3
systemctl daemon-reload
systemctl enable --now containerd
systemctl restart containerd

安装 runc

containerd 依赖 runc ,我们还需要安装 runc ,到官方 GitHub 下载最新版本。

下载 runc tar 包

执行命令安装 install -m 755 runc.amd64 /usr/local/sbin/runc

安装 CNI

containerd 本身没有网络相关的特性,需要借助 cni 插件来实现,不然创建容器会报 cni 的错。

下载 CNI 插件 tar 包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ mkdir -p /opt/cni/bin
$ tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.2.0.tgz
./
./macvlan
./static
./vlan
./portmap
./host-local
./vrf
./bridge
./tuning
./firewall
./host-device
./sbr
./loopback
./dhcp
./ptp
./ipvlan
./bandwidth

# 重启 containerd
systemctl start containerd
systemctl status containerd

管理工具

管理工具有 ctr , nerdctl , crictl 每种根据不同场景,有不同的用处。

ctr 是作为 containerd 项目的一部分提供命令行的客户端。

nerdctl 对用户比较友好和 docker 命令兼容,对于单机节点来说,个人使用起来和docker类似,基本没学习成本,把docker换成nerdctl即可。

crictl 是一个命令行客户端,使用 Kubernetes cri 兼容的容器运行时接口来管理其节点上的容器和 Pod ,主要是用于 kubernetes 。

信息
虽然 3 种工具各有特色,不过用起来还是不是特别顺手,比如我感受了一下 nerdctl ,创建的容器 -p 主机端口映射后,主机上 netstat -tnlp 查不到端口号,但是实际是映射成功的。

工具概览对比。

工具 社区 API 目标 帮助信息
ctr containerd Native For debugging only ctr --help 查看
nerdctl containerd (non-core) Native General-purpose nerdctl官方GitHub
crictl Kubernetes SIG-node CRI For debugging only crictl官方GitHub

工具命令对比,如果是 kubernetes 场景下 crictl 更推荐。

命令 docker crictl(推荐) ctr
查看容器列表 docker ps crictl ps ctr -n k8s.io c ls
查看容器详情 docker inspect crictl inspect ctr -n k8s.io c info
查看容器日志 docker logs crictl logs
容器内执行命令 docker exec crictl exec
挂载容器 docker attach crictl attach
容器资源使用 docker stats crictl stats
创建容器 docker create crictl create ctr -n k8s.io c create
启动容器 docker start crictl start ctr -n k8s.io run
停止容器 docker stop crictl stop
删除容器 docker rm crictl rm ctr -n k8s.io c del
查看镜像列表 docker images crictl images ctr -n k8s.io i ls
查看镜像详情 docker inspect crictl inspecti
拉取镜像 docker pull crictl pull ctr -n k8s.io i pull
推送镜像 docker push ctr -n k8s.io i push
删除镜像 docker rmi crictl rmi ctr -n k8s.io i rm
查看Pod列表 crictl pods
查看Pod详情 crictl inspectp
启动Pod crictl runp
停止Pod crictl stopp

安装单节点 kubernetes 集群测试一下。

先配置 yum 源

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
 http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

安装 kubelet kubectl kubeadm 三件套

yum install -y kubelet-1.24.11 kubeadm-1.24.11 kubectl-1.24.11 --disableexcludes=kubernetes

拉起单节点 1.24 版本的 Kubernetes

kubeadm init --apiserver-advertise-address=192.168.22.226 --image-repository registry.aliyuncs.com/google_containers --control-plane-endpoint=192.168.22.226 --kubernetes-version v1.24.11 --service-cidr=10.1.0.0/16 --pod-network-cidr=10.244.0.0/16 --v=5

nerdctl 查看所有 pod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ nerdctl -n k8s.io ps

CONTAINER ID    IMAGE                                                                       COMMAND                   CREATED           STATUS    PORTS    NAMES
01228b6dd482    registry.aliyuncs.com/google_containers/pause:3.6                           "/pause"                  13 minutes ago    Up                 k8s://kube-system/coredns-74586cf9b6-p42vf
2bdd9d045757    registry.aliyuncs.com/google_containers/pause:3.6                           "/pause"                  13 minutes ago    Up                 k8s://kube-system/kube-scheduler-dev01
37cbd0677e1a    registry.aliyuncs.com/google_containers/pause:3.6                           "/pause"                  13 minutes ago    Up                 k8s://kube-system/etcd-dev01
40ca90ad1c4f    registry.aliyuncs.com/google_containers/pause:3.6                           "/pause"                  13 minutes ago    Up                 k8s://kube-system/kube-controller-manager-dev01
451f34d736f1    registry.aliyuncs.com/google_containers/coredns:v1.8.6                      "/coredns -conf /etc…"    13 minutes ago    Up                 k8s://kube-system/coredns-74586cf9b6-jwt87/coredns
5152d7631cb2    registry.aliyuncs.com/google_containers/coredns:v1.8.6                      "/coredns -conf /etc…"    13 minutes ago    Up                 k8s://kube-system/coredns-74586cf9b6-p42vf/coredns
6040f26266b9    registry.aliyuncs.com/google_containers/kube-controller-manager:v1.24.11    "kube-controller-man…"    13 minutes ago    Up                 k8s://kube-system/kube-controller-manager-dev01/kube-controller-manager
73f778808fab    registry.aliyuncs.com/google_containers/pause:3.6                           "/pause"                  13 minutes ago    Up                 k8s://kube-system/kube-apiserver-dev01
9fa31ae29788    registry.aliyuncs.com/google_containers/etcd:3.5.6-0                        "etcd --advertise-cl…"    13 minutes ago    Up                 k8s://kube-system/etcd-dev01/etcd
a06a11848bfd    registry.aliyuncs.com/google_containers/pause:3.6                           "/pause"                  13 minutes ago    Up                 k8s://kube-system/coredns-74586cf9b6-jwt87
b30c34841895    registry.aliyuncs.com/google_containers/kube-apiserver:v1.24.11             "kube-apiserver --ad…"    13 minutes ago    Up                 k8s://kube-system/kube-apiserver-dev01/kube-apiserver
b82098336ac6    registry.aliyuncs.com/google_containers/kube-proxy:v1.24.11                 "/usr/local/bin/kube…"    13 minutes ago    Up                 k8s://kube-system/kube-proxy-j264w/kube-proxy
ba0cfb9ec381    registry.aliyuncs.com/google_containers/pause:3.6                           "/pause"                  13 minutes ago    Up                 k8s://kube-system/kube-proxy-j264w
df4c61aabb97    registry.aliyuncs.com/google_containers/kube-scheduler:v1.24.11             "kube-scheduler --au…"    13 minutes ago    Up                 k8s://kube-system/kube-scheduler-dev01/kube-scheduler

crictl 查看所有 pod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ crictl ps

CONTAINER           IMAGE               CREATED             STATE               NAME                      ATTEMPT             POD ID              POD
5152d7631cb25       a4ca41631cc7a       11 minutes ago      Running             coredns                   0                   01228b6dd4828       coredns-74586cf9b6-p42vf
451f34d736f13       a4ca41631cc7a       11 minutes ago      Running             coredns                   0                   a06a11848bfd8       coredns-74586cf9b6-jwt87
b82098336ac6c       d6ccf30c8566e       11 minutes ago      Running             kube-proxy                0                   ba0cfb9ec381a       kube-proxy-j264w
b30c348418959       0849bf5f3ef4e       11 minutes ago      Running             kube-apiserver            0                   73f778808fab6       kube-apiserver-dev01
9fa31ae29788a       fce326961ae2d       11 minutes ago      Running             etcd                      0                   37cbd0677e1a1       etcd-dev01
df4c61aabb976       b1ef1dbb09ca5       11 minutes ago      Running             kube-scheduler            0                   2bdd9d045757a       kube-scheduler-dev01
6040f26266b93       4b0f3887b66e7       11 minutes ago      Running             kube-controller-manager   0                   40ca90ad1c4f8       kube-controller-manager-dev01

目录验证

创建一个 deployment ,验证一下 containerd 数据在宿主机上的存放路径。

挂载 emptyDir{} ,验证下数据存放再宿主机什么路径下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "2"
  labels:
    app: sample
  name: sample
  namespace: default
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: sample
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: sample
    spec:
      containers:
      - image: nginx:alpine
        imagePullPolicy: IfNotPresent
        name: nginx
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /var/log/app
          name: tmp-vol
      volumes:
      - emptyDir: {}
        name: tmp-vol
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      terminationGracePeriodSeconds: 30

查看 pod uid .

uid: baf1e1a6-cf0e-474c-912d-e32a0d424c25

随后我们进入 pod 容器内,创建一个文件。

1
2
$ cd /var/log/app/ 
$ echo hello >> app.log

进入宿主机 kubelet pods 目录下对应 uid 的目录下。

1
2
3
$ cd /var/lib/kubelet/pods/baf1e1a6-cf0e-474c-912d-e32a0d424c25/volumes/kubernetes.io~empty-dir/tmp-vol/
$ cat app.log 
hello

输出结果符合我们的预期。我们再在容器的 /var/log/nginx 目录下 touch test.txt

接下来我们 crictl ps 查看一下 pod 的容器 id ,进入到

/run/containerd/io.containerd.runtime.v2.task/k8s.io/20220e35cc63208ac772bffed478d34a5bb54b0ffbb9a447d169f5b7415b3063/rootfs

相当于是进入到了容器的 / 目录,再进入 var/log/nginx

可以看到 test.txt 也出现在宿主机上面。验证了我们上面的关注点的内容。

结束

本次也只是单纯记录一下 containerd 的一些简单使用情况,毕竟本篇我们只是基础的安装和体验,对 containerd 的认识也只是停留在这些基础上,我们只有在后期不断去使用和学习才能继续发现和挖掘出它其他的一些妙用。