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 提供的二进制包进行安装,我们选择后者。
- 下载 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"
|
- 如果你想用 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
|
- 创建完 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 的认识也只是停留在这些基础上,我们只有在后期不断去使用和学习才能继续发现和挖掘出它其他的一些妙用。