ctr images pull 拉取的鏡像默認(rèn)放在default,而crictl pull 和 kubelet 默認(rèn)拉取的鏡像都在k8s.io命名空間下。所以通過ctr導(dǎo)入鏡像的時(shí)候特別注意一點(diǎn),最好指定命名空間。
一、概述
作為接替Docker運(yùn)行時(shí)的Containerd在早在Kubernetes1.7時(shí)就能直接與Kubelet集成使用,只是大部分時(shí)候我們因熟悉Docker,在部署集群時(shí)采用了默認(rèn)的dockershim。在V1.24?起的版本的kubelet就徹底移除了dockershim?,改為默認(rèn)使用Containerd?了,當(dāng)然也可以使用 cri-dockerd? 適配器來將 Docker Engine 與 Kubernetes 集成??梢詤⒖脊俜轿臋n。

二、Containerd 常見命令操作
更換Containerd后,以往我們常用的docker命令也不再使用,取而代之的分別是 crictl? 和 ctr 兩個(gè)命令客戶端。
- crictl? 是遵循CRI接口規(guī)范的一個(gè)命令行工具,通常用它來檢查和管理kubelet節(jié)點(diǎn)上的容器運(yùn)行時(shí)和鏡像。
- ctr? 是 containerd 的一個(gè)客戶端工具。
- ctr -v? 輸出的是 containerd 的版本,crictl -v 輸出的是當(dāng)前 k8s 的版本,從結(jié)果顯而易見你可以認(rèn)為 crictl 是用于 k8s 的。
- 一般來說你某個(gè)主機(jī)安裝了 k8s 后,命令行才會(huì)有 crictl 命令。而 ctr 是跟 k8s 無關(guān)的,你主機(jī)安裝了 containerd 服務(wù)后就可以操作 ctr 命令。
使用crictl?命令之前,需要先配置/etc/crictl.yaml如下:
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
也可以通過命令進(jìn)行設(shè)置:
crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl config image-endpoint unix:///run/containerd/containerd.sock
命令
| docker
| ctr(containerd)
| crictl(kubernetes)
|
查看運(yùn)行的容器
| docker ps
| ctr task ls/ctr container ls
| crictl ps
|
查看鏡像
| docker images
| ctr image ls
| crictl images
|
查看容器日志
| docker logs
| 無
| crictl logs
|
查看容器數(shù)據(jù)信息
| docker inspect
| ctr container info
| crictl inspect
|
查看容器資源
| docker stats
| 無
| crictl stats
|
啟動(dòng)/關(guān)閉已有的容器
| docker start/stop
| ctr task start/kill
| crictl start/stop
|
運(yùn)行一個(gè)新的容器
| docker run
| ctr run
| 無(最小單元為pod)
|
打標(biāo)簽
| docker tag
| ctr image tag
| 無
|
創(chuàng)建一個(gè)新的容器
| docker create
| ctr container create
| crictl create
|
導(dǎo)入鏡像
| docker load
| ctr image import
| 無
|
導(dǎo)出鏡像
| docker save
| ctr image export
| 無
|
刪除容器
| docker rm
| ctr container rm
| crictl rm
|
刪除鏡像
| docker rmi
| ctr image rm
| crictl rmi
|
拉取鏡像
| docker pull
| ctr image pull
| ctictl pull
|
推送鏡像
| docker push
| ctr image push
| 無
|
登錄或在容器內(nèi)部執(zhí)行命令
| docker exec
| 無
| crictl exec
|
清空不用的容器
| docker image prune
| 無
| crictl rmi --prune
|
更多命令操作,可以直接在命令行輸入命令查看幫助。
docker --help
ctr --help
crictl --help
由于Containerd也有namespaces的概念,對(duì)于上層編排系統(tǒng)的支持,ctr? 客戶端 主要區(qū)分了3個(gè)命名空間分別是k8s.io、moby和default?,以上我們用crictl?操作的均在k8s.io?命名空間,使用ctr? 看鏡像列表就需要加上-n參數(shù)。crictl是只有一個(gè)k8s.io命名空間,但是沒有-n參數(shù)。
【溫馨提示】ctr images pull 拉取的鏡像默認(rèn)放在default?,而crictl pull 和 kubelet 默認(rèn)拉取的鏡像都在k8s.io命名空間下。所以通過ctr導(dǎo)入鏡像的時(shí)候特別注意一點(diǎn),最好指定命名空間。
# 注意-n不能放在命令最后面,下面幾行查看的鏡像是一樣的
ctr -n=k8s.io image ls
ctr -n k8s.io image ls
# crictl 沒有-n參數(shù),操作都在`k8s.io`命名空間下。
crictl image ls
crictl images
# crictl image list = ctr -n=k8s.io image list
# crictl image ls = ctr -n=k8s.io image ls
# crictl images = ctr -n=k8s.io image list
# crictl images = ctr -n=k8s.io image ls
# 使用ctr命令指定命名空間導(dǎo)入鏡像
ctr -n=k8s.io image import dashboard.tar
#查看鏡像,可以看到可以查詢到了
crictl images

三、container 客戶端工具 nerdctl
推薦使用nerdctl,使用效果與docker命令的語法一致github下載鏈接:https://github.com/containerd/nerdctl/releases
- 精簡 (nerdctl--linux-amd64.tar.gz): 只包含nerdctl
- 完整 (nerdctl-full--linux-amd64.tar.gz): 包含 containerd, runc, and CNI等依賴
nerdctl 的目標(biāo)并不是單純地復(fù)制 docker 的功能,它還實(shí)現(xiàn)了很多 docker 不具備的功能,例如延遲拉取鏡像(lazy-pulling)、鏡像加密(imgcrypt)等。具體看nerdctl。

延遲拉取鏡像功能可以參考這篇文章:Containerd 使用 Stargz Snapshotter 延遲拉取鏡像
1)安裝 nerdctl(精簡版)
wget https://github.com/containerd/nerdctl/releases/download/v0.22.2/nerdctl-0.22.2-linux-amd64.tar.gz
# 解壓
tar -xf nerdctl-0.22.2-linux-amd64.tar.gz
ln -s /opt/k8s/nerdctl/nerdctl /usr/local/bin/nerdctl
2)安裝 nerdctl(完整版,這里不裝)
wget https://github.com/containerd/nerdctl/releases/download/v0.22.2/nerdctl-full-0.22.2-linux-amd64.tar.gz
tar -xf nerdctl-full-0.16.0-linux-amd64.tar.gz -C /usr/local/
cp /usr/local/lib/systemd/system/*.service /etc/systemd/system/
啟動(dòng)服務(wù)buildkit
systemctl enable buildkit containerd --now
systemctl status buildkit containerd
3)安裝 buildkit 支持構(gòu)建鏡像
buildkit GitHub地址:https://github.com/moby/buildkit
使用精簡版 nerdctl無法直接通過containerd構(gòu)建鏡像,需要與buildkit組全使用以實(shí)現(xiàn)鏡像構(gòu)建。當(dāng)然你也可以安裝上面的完整nerdctl;buildkit項(xiàng)目是Docker公司開源出來的一個(gè)構(gòu)建工具包,支持OCI標(biāo)準(zhǔn)的鏡像構(gòu)建。它主要包含以下部分:
- 服務(wù)端buildkitd,當(dāng)前支持runc和containerd作為worker,默認(rèn)是runc;
- 客戶端buildctl,負(fù)責(zé)解析Dockerfile,并向服務(wù)端buildkitd發(fā)出構(gòu)建請(qǐng)求。
buildkit是典型的C/S架構(gòu),client和server可以不在一臺(tái)服務(wù)器上。而nerdctl在構(gòu)建鏡像方面也可以作為buildkitd的客戶端。
# https://github.com/moby/buildkit/releases
wget https://github.com/moby/buildkit/releases/download/v0.10.4/buildkit-v0.10.4.linux-amd64.tar.gz
tar -xf buildkit-v0.10.4.linux-amd64.tar.gz -C /usr/local/
配置buildkit的啟動(dòng)文件,可以從這里下載:https://github.com/moby/buildkit/tree/master/examples/systemdbuildkit需要配置兩個(gè)文件
- /usr/lib/systemd/system/buildkit.socket
cat > /usr/lib/systemd/system/buildkit.socket <<EOF
[Unit]
Descriptinotallow=BuildKit
Documentatinotallow=https://github.com/moby/buildkit
[Socket]
ListenStream=%t/buildkit/buildkitd.sock
SocketMode=0660
[Install]
WantedBy=sockets.target
EOF
- /usr/lib/systemd/system/buildkit.service
cat > /usr/lib/systemd/system/buildkit.service << EOF
[Unit]
Descriptinotallow=BuildKit
Requires=buildkit.socket
After=buildkit.socket
Documentatinotallow=https://github.com/moby/buildkit
[Service]
# Replace runc builds with containerd builds
ExecStart=/usr/local/bin/buildkitd --addr fd://
[Install]
WantedBy=multi-user.target
EOF
啟動(dòng)buildkit
systemctl daemon-reload
systemctl enable buildkit --now

四、實(shí)戰(zhàn)操作
1)修改containerd配置文件
可以參考我之前的文章:【云原生.大數(shù)據(jù)】鏡像倉庫Harbor對(duì)接MinIO對(duì)象存儲(chǔ)
containerd config default > /etc/containerd/config.toml
配置如下:
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = ""
[plugins."io.containerd.grpc.v1.cri".registry.auths]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."myharbor-minio.com".tls]
insecure_skip_verify = true #跳過認(rèn)證
ca_file = "/etc/containerd/myharbor-minio.com/ca.crt"
[plugins."io.containerd.grpc.v1.cri".registry.configs."myharbor-minio.com".auth]
username = "admin"
password = "Harbor12345"
[plugins."io.containerd.grpc.v1.cri".registry.headers]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."myharbor-minio.com"]
endpoint = ["https://myharbor-minio.com"]

重啟containerd
#重新加載配置
systemctl daemon-reload
#重啟containerd
systemctl restart containerd
注意:這個(gè)配置文件是給crictl和kubelet?使用,ctr是不可以用這個(gè)配置文件的,ctr 不使用 CRI,因此它不讀取plugins."io.containerd.grpc.v1.cri"配置。
2)ctr 拉取推送鏡像
# 推送鏡像到harbor
ctr --namespace=k8s.io images push myharbor-minio.com/bigdata/minio:2022.8.22-debian-11-r0 --skip-verify --user admin:Harbor12345
# --namespace=k8s.io 指定命名空間,不是必須,根據(jù)環(huán)境而定
# --skip-verify 跳過認(rèn)證
# --user 指定harbor用戶名及密碼
ctr images pull --user admin:Harbor12345 --tlscacert=/etc/containerd/myharbor-minio.com/ca.crt myharbor-minio.com/bigdata/minio:2022.8.22-debian-11-r0
不想-u user:password每次必須使用 ctr pull/ctr push, 可以使用nerdctl 。
3)鏡像構(gòu)建
cat > Dockerfile <<EOF
FROM nginx:alpine
RUN echo 'Hello Nerdctl From Containerd' > /usr/share/nginx/html/index.html
EOF
然后在文件所在目錄執(zhí)行鏡像構(gòu)建命令:
# 不加-n指定命名空間,crictl看不到,kubelet也不能使用它,默認(rèn)在default命名空間下
nerdctl -n k8s.io build -t nginx:nerctl -f ./Dockerfile .
### 參數(shù)解釋
# -t:指定鏡像名稱
# . :當(dāng)前目錄Dockerfile
# -f:指定Dockerfile路徑
# --no-cache:不緩存

4)打標(biāo)簽 tag
# crictl沒有tag命令,只能使用nerdctl和ctr,必須指定命名空間,要不然kubelet無法使用。
ctr -n k8s.io i tag
nerdctl -n k8s.io tag nginx:nerctl myharbor-minio.com/bigdata/nginx:nerctl
# ctr -n k8s.io tag nginx:nerctl myharbor-minio.com/bigdata/nginx:nerctl
# 查看鏡像
nerdctl -n k8s.io images myharbor-minio.com/bigdata/nginx:nerctl
5)將鏡像推送到 Harbor
第一種情況:http方式,配置如下:
# 以下兩個(gè)哪個(gè)都可以
# mkdir -p /etc/docker/certs.d/myharbor-minio.com:443
mkdir -p /etc/containerd/certs.d/myharbor-minio.com:443
cat > /etc/containerd/certs.d/myharbor-minio.com\:443/hosts.toml <<EOF
server = "https://docker.io"
[host."http://myharbor-minio.com:80"]
capabilities = ["pull", "resolve","push"]
#skip_verify = true
#ca = "ca.crt" #相對(duì)路徑
#ca = "/opt/auth/ca.crt" #絕對(duì)路徑
#ca = ["/opt/auth/ca.crt"]
#ca = ["ca.crt"]
#client = [["/opt/auth/nginx.cclinux.cn.crt", "/opt/auth/nginx.cclinux.cn.key"]]
EOF
第一種情況:https方式,配置如下:
# 以下兩個(gè)哪個(gè)都可以
# mkdir -p /etc/docker/certs.d/myharbor-minio.com:443
mkdir -p /etc/containerd/certs.d/myharbor-minio.com:443
cat > /etc/containerd/certs.d/myharbor-minio.com\:443/hosts.toml <<EOF
server = "https://docker.io"
[host."https://myharbor-minio.com:443"]
capabilities = ["pull", "resolve","push"]
skip_verify = true
#ca = "ca.crt" #相對(duì)路徑
#ca = "/opt/auth/ca.crt" #絕對(duì)路徑
#ca = ["/opt/auth/ca.crt"]
ca = ["/etc/containerd/myharbor-minio.com/ca.crt"]
#client = [["/opt/auth/nginx.cclinux.cn.crt", "/opt/auth/nginx.cclinux.cn.key"]]
EOF
通過 nerdctl 登錄 harbor
echo Harbor12345 | nerdctl login --username "admin" --password-stdin myharbor-minio.com:443
# nerdctl login --username "admin" --password Harbor12345 myharbor-minio.com:443
# 登出
# nerdctl logout

開始將鏡像推送到harbor
### 推送到Harbor
# --insecure-registry skips verifying HTTPS certs, and allows falling back to plain HTTP
nerdctl --insecure-registry --namespace=k8s.io push myharbor-minio.com/bigdata/nginx:nerctl
# ctr --namespace=k8s.io images push myharbor-minio.com/bigdata/nginx:nerctl --skip-verify --user admin:Harbor12345
# --namespace=k8s.io 指定命名空間,跟-n一樣,不是必須,根據(jù)環(huán)境而定
# --skip-verify 跳過認(rèn)證
# --user 指定harbor用戶名及密碼
?
?