Containerd ctr、crictl、nerdctl 客戶端命令介紹與實戰(zhàn)操作
一、概述
在V1.24起的版本的 kubelet 就徹底移除了dockershim,改為默認使用Containerd了,當然也使用 cri-dockerd 適配器來將 Docker Engine 與 Kubernetes 集成。可以參考官方文檔:
- https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#docker
二、Containerd 常見命令操作
- 更換 Containerd 后,以往我們常用的 docker 命令也不再使用,取而代之的分別是 crictl 和 ctr 兩個命令客戶端。
- crictl 是遵循 CRI 接口規(guī)范的一個命令行工具,通常用它來檢查和管理kubelet節(jié)點上的容器運行時和鏡像。
- ctr 是 containerd 的一個客戶端工具。
- ctr -v 輸出的是 containerd 的版本,crictl -v 輸出的是當前 k8s 的版本,從結果顯而易見你可以認為 crictl 是用于 k8s 的。
- 一般來說你某個主機安裝了 k8s 后,命令行才會有 crictl 命令。而 ctr 是跟 k8s 無關的,你主機安裝了 containerd 服務后就可以操作 ctr 命令。
使用crictl命令之前,需要先配置/etc/crictl.yaml如下:
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
也可以通過命令進行設置:
crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl config image-endpoint unix:///run/containerd/containerd.sock
命令 | docker | ctr(containerd) | crictl(kubernetes) |
查看運行的容器 | 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 |
啟動/關閉已有的容器 | docker start/stop | ctr task start/kill | crictl start/stop |
運行一個新的容器 | docker run | ctr run | 無(最小單元為 pod) |
打標簽 | docker tag | ctr image tag | 無 |
創(chuàng)建一個新的容器 | docker create | ctr container create | crictl create |
導入鏡像 | docker load | ctr image import | 無 |
導出鏡像 | 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 的概念,對于上層編排系統(tǒng)的支持,ctr 客戶端 主要區(qū)分了 3 個命名空間分別是k8s.io、moby和default,以上我們用crictl操作的均在k8s.io命名空間,使用ctr 看鏡像列表就需要加上-n 參數(shù)。crictl 是只有一個k8s.io命名空間,但是沒有-n 參數(shù)。
- 【溫馨提示】ctr images pull 拉取的鏡像默認放在default,而 crictl pull 和 kubelet 默認拉取的鏡像都在 k8s.io 命名空間下。所以通過ctr導入鏡像的時候特別注意一點,最好指定命名空間。
# 注意-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命令指定命名空間導入鏡像
ctr -n=k8s.io image import dashboard.tar
#查看鏡像,可以看到可以查詢到了
crictl images
三、containerd 客戶端工具 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 的目標并不是單純地復制 docker 的功能,它還實現(xiàn)了很多 docker 不具備的功能,例如延遲拉取鏡像(lazy-pulling)、鏡像加密(imgcrypt)等。具體看 nerdctl。
延遲拉取鏡像功能可以參考這篇文章:Containerd 使用 Stargz Snapshotter 延遲拉取鏡像
- https://icloudnative.io/posts/startup-containers-in-lightning-speed-with-lazy-image-distribution-on-containerd/
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/
啟動服務 buildkit
systemctl enable buildkit containerd --now
systemctl status buildkit containerd
3)安裝 buildkit 支持構建鏡像
buildkit GitHub 地址:
- https://github.com/moby/buildkit
- 使用精簡版 nerdctl 無法直接通過 containerd 構建鏡像,需要與 buildkit 組全使用以實現(xiàn)鏡像構建。當然你也可以安裝上面的完整 nerdctl;buildkit 項目是 Docker 公司開源出來的一個構建工具包,支持 OCI 標準的鏡像構建。它主要包含以下部分:
- 服務端 buildkitd,當前支持 runc 和 containerd 作為 worker,默認是 runc;
- 客戶端 buildctl,負責解析 Dockerfile,并向服務端 buildkitd 發(fā)出構建請求。
buildkit 是典型的C/S 架構,client 和 server 可以不在一臺服務器上。而 nerdctl 在構建鏡像方面也可以作為 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 的啟動文件,可以從這里下載:
- https://github.com/moby/buildkit/tree/master/examples/systemd
buildkit 需要配置兩個文件
- /usr/lib/systemd/system/buildkit.socket
cat > /usr/lib/systemd/system/buildkit.socket <<EOF
[Unit]
Description=BuildKit
Documentation=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]
Description=BuildKit
Requires=buildkit.socket
After=buildkit.socket
Documentation=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
啟動 buildkit
systemctl daemon-reload
systemctl enable buildkit --now
四、實戰(zhàn)操作
1)修改 containerd 配置文件
可以參考我之前的文章:
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 #跳過認證
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
- 注意:這個配置文件是給crictl和kubelet使用,ctr是不可以用這個配置文件的,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 跳過認證
# --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)鏡像構建
cat > Dockerfile <<EOF
FROM nginx:alpine
RUN echo 'Hello Nerdctl From Containerd' > /usr/share/nginx/html/index.html
EOF
然后在文件所在目錄執(zhí)行鏡像構建命令:
# 不加-n指定命名空間,crictl看不到,kubelet也不能使用它,默認在default命名空間下
nerdctl -n k8s.io build -t nginx:nerctl -f ./Dockerfile .
### 參數(shù)解釋
# -t:指定鏡像名稱
# . :當前目錄Dockerfile
# -f:指定Dockerfile路徑
# --no-cache:不緩存
4)打標簽 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方式,配置如下:
# 以下兩個哪個都可以
# 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" #相對路徑
#ca = "/opt/auth/ca.crt" #絕對路徑
#ca = ["/opt/auth/ca.crt"]
#ca = ["ca.crt"]
#client = [["/opt/auth/nginx.cclinux.cn.crt", "/opt/auth/nginx.cclinux.cn.key"]]
EOF
第一種情況:https方式,配置如下:
# 以下兩個哪個都可以
# 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" #相對路徑
#ca = "/opt/auth/ca.crt" #絕對路徑
#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 跳過認證
# --user 指定harbor用戶名及密碼
Containerd ctr,crictl,nerdctl 客戶端命令介紹與實戰(zhàn)操作就到這里了。