K8S组件与容器引擎

一、服务管理

如果是kubeadm安装,相关服务管理如下:

# 1、系统服务
systemctl enable containerd   # 老版本是docker
systemctl enable kubelet
systemctl restart containerd  # 老版本是docker
systemctl restart kubelet

# 2、静态pod
# 注意:kube-proxy是daemonset,而不是静态pod(静态pod由kubelet单独管理)。
[root@k8s-master-01 ~]# kubectl get pod -n kube-system
NAME                           READY   STATUS    RESTARTS   AGE
coredns-6d58d46f65-2bm7z       1/1     Running   0          37h
coredns-6d58d46f65-f492h       1/1     Running   0          37h
etcd-node                      1/1     Running   452        37h
kube-apiserver-node            1/1     Running   443        37h
kube-controller-manager-node   1/1     Running   5          37h
kube-proxy-kztlj               1/1     Running   0          37h
kube-proxy-tlwtt               1/1     Running   0          37h
kube-proxy-wrtjn               1/1     Running   0          37h
kube-scheduler-node            1/1     Running   5          37h
[root@k8s-master-01 ~]# 

### 1.3 总结与归纳
系统服务(所有节点上都有):
- 容器引擎:负责容器创建,镜像加速
- kubelet:kubelet汇报自己的节点的状态,负责调度容器引擎管理容器。

master节点:(两个系统服务,4个静态pod)
- apiserver
- scheduler
- controller-mananger
- etcd

worker节点:(两个系统服务,一个kube-proxy,kube-proxy不是静态pod,而是由daemonset控制器启动的pod)
- kube-proxy ---> 用于管理svc
- 业务pod
- coredns
- 网络组件如 flannel

静态pod的yaml配置

# 静态pod由kubelet管理,kubelet会定期扫描这些文件并加载配置,所以修改后不需要重启kubelet
[root@k8s-master-01 ~]# ll /etc/kubernetes/manifests/
total 16
-rw------- 1 root root 2432 Jun 23 04:05 etcd.yaml
-rw------- 1 root root 3407 Jun 23 04:05 kube-apiserver.yaml
-rw------- 1 root root 2913 Jun 23 04:05 kube-controller-manager.yaml
-rw------- 1 root root 1499 Jun 23 04:05 kube-scheduler.yaml

kubectl 怎么连接apiserver

[root@k8s-master-01 ~]# ll ~/.kube/ 
total 8
drwxr-x--- 4 root root   35 Jun 23 04:07 cache
-rw------- 1 root root 5657 Jun 23 04:06 config # 就靠这个配置文件

(了解即可)如果你采用的是二进制部署,那相关服务管理如下:

# worker node
systemctl enable containerd  # 老版本是docker
systemctl enable kubelet
systemctl enable flannel
systemctl enable kube-proxy
systemctl restart containerd  # 老版本是docker
systemctl restart kubelet
systemctl restart flannel
systemctl restart kube-proxy

# master node
systemctl enable etcd
systemctl enable kube-controller-manager
systemctl enable kube-scheduler
systemctl restart etcd
systemctl restart kube-controller-manager
systemctl restart kube-scheduler

注意: 删除docker0网桥,如果cni0隧道网卡与docker0网桥ip地址冲突,会导致网络问题,此时我们应该删掉docker0,因为我们用的是cni0,删除命令如下:

yum -y install bridge-utils
ifconfig docker0 down
brctl delbr docker0

二、容器引擎客户端命令

2.1 containerd介绍

对比着来看,作为k8s容器运行时,containerd跟docker的对比

2.1.1 调用链路的区别

在V1.24起的版本的 kubelet 就彻底移除了dockershim,改为默认使用Containerd了,当然也使用 cri-dockerd 适配器来将 Docker Engine 与 Kubernetes 集成。可以参考官方文档:https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#docker

image-20260625052022434

kubelet --> dockershim(k8s功能) --> docker --> containerd --> container
kubelet --> cri-containerd(containerd功能) --> containerd --> container

2.1.2 标准输出日志路径的区别

容器有两种日志:业务日志和标准输出日志

  • 业务日志直接丢到程序自定义的日志文件中
  • 标准输出日志则会被保存到宿主机的一个json文件中(跟容器不同,宿主机自己的标准输出是直接丢掉的)

针对容器内的标准输出日志, 即容器应用直接打印到终端的内容,有/dev/stdout与/dev/stderr两种,默认情况下会将二者统一存入宿主机上的一个json文件中。

  • docker引擎用docker logs可以直接查看该json日志里的内容
  • containerd引擎可以用crictl查看。

容器日志及相关参数如下:

对比项 docker containerd
存储路径 如果 Kubernetes 使用 Docker 作为容器运行时,容器日志的落盘由docker来完成,日志通常存储在 /var/lib/docker/containers/<container-id>/<container-id>-json.log 如果 Kubernetes 使用 containerd 作为容器运行时,容器日志的落盘由kubelet来完成,路径 /var/log/pods/<namespace>_<pod-name>_<pod-uid>/<container-name>/<container-id>.log,同时在/var/log/containers目录下创建软链接,指向日志文件
配置参数 在docker配置文件中指定:
"log-driver": "json-file",
"log-opts": {"max-size": "100m","max-file": "5"}
方法一:在kubelet参数中指定: --container-log-max-files=5 --container-log-max-size=100Mi
方法二:在KubeletConfiguration中指定: "containerLogMaxSize": "100Mi", "containerLogMaxFiles": 5
把容器日志保存到数据盘 把数据盘挂载到"data-root"(缺省是/var/lib/docker)即可 创建一个软链接/var/log/pods指向数据盘挂载点下的某个目录。在TKE中选择"将容器日志保存到数据盘",会自动创建软链接/var/log/pods

示例:k8s采用containerd作为容器运行时查看标准输出日志

[root@k8s-master-01 study]# cat test.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: registry.cn-shanghai.aliyuncs.com/egon-k8s-test/busybox:v1.0
        name: nginx
        command: ["sh","-c","while true;do echo 111 ;sleep 1;done"]
status: {}


[root@k8s-master-01 study]# kubectl apply -f test.yaml 
deployment.apps/web created

[root@k8s-node-01 ~]# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
web-587b6775f8-jhfqh      1/1     Running   0          38m

[root@k8s-node-01 ~]# ll /var/log/containers/web-587b6775f8-jhfqh_default_nginx-309b96044a4dbcdbdef7dce0ac72eb09aabb2ad449a8738a9dad07d123c8e99e.log
lrwxrwxrwx 1 root root 91 8月  6 19:54 /var/log/containers/web-587b6775f8-jhfqh_default_nginx-309b96044a4dbcdbdef7dce0ac72eb09aabb2ad449a8738a9dad07d123c8e99e.log -> /var/log/pods/default_web-587b6775f8-jhfqh_3dc50a3d-fdcf-4fc2-bc51-fb0e29050072/nginx/0.log

日志切割实验:

1、了解kubelet的配置(前面我们了解到以containerd为runc时,容器的标准输出日志是由kubelet控制的)

先登录到需要做日志切割的那台机器上,然后执行systemctl status kubelet查看kubelet当前系统服务配置路径,发现为/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.confimage-20260625052730358

可以看到,k8s启动参数解读

# 用于集群初建立时kubelet与apiserver临时通信凭证,完成集群搭建后已经自动删掉了。
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf
# kubelet 与 apiserver 通信用的正式身份认证凭证(kubeconfig)
--kubeconfig=/etc/kubernetes/kubelet.conf
# kubelet 的核心配置文件
--config=/var/lib/kubelet/config.yaml
# 使用 containerd 作为容器运行时,通过本地 Unix Socket 通信
--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock
# 指定 Pod 基础容器(pause 容器 / sandbox 容器)镜像
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9

10-kubeadm.conf 由kubeadm安装时生成,用于告诉systemd怎么启动kubelet。

image-20260625052753097

2、配置日志轮转参数

配置文件:vim /var/lib/kubelet/kubeadm-flags.env

新增参数:--container-log-max-files=5 --container-log-max-size='5Ki'

KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9 --container-log-max-files=5 --container-log-max-size='5Ki'"

3、测试日志轮转

在default名称空间下创建一个测试pod

[root@k8s-master-01 study]# cat test.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: registry.cn-shanghai.aliyuncs.com/egon-k8s-test/busybox:v1.0
        name: nginx
        command: ["sh","-c","while true;do echo 111 ;sleep 1;done"]
status: {}


[root@k8s-master-01 study]# kubectl apply -f test.yaml 
deployment.apps/web created
[root@k8s-master-01 study]# kubectl get pod -n default
NAME                   READY   STATUS    RESTARTS   AGE
web-587b6775f8-nf92f   1/1     Running   0          7s
[root@k8s-master-01 study]# 

image-20260625065539956

2.1.3 配置文件路径

containerd配置文件/etc/containerd/config.toml

# 默认配置中还有两个关于存储的配置路径:
# 1、保存持久化数据,包括 Snapshots, Content, Metadata 以及各种插件的数据
root = "/var/lib/containerd"

# 2、保存运行时的临时数据的,包括 sockets、pid、挂载点、运行时状态以及不需要持久化的插件数据。
state = "/run/containerd"

2.1.4 stream server

kubectl exec/logs等命令需要在apiserver跟容器运行时之间建立流转发通道。

docker API本身提供stream服务,kubelet内部的docker-shim会通过docker API做流转发。

containerd的stream服务需要单独配置:

image-20260625065737409

在k8s 1.11之前,kubelet并不会做stream proxy, 只会做redirect。也就是把containerd暴露的stream server地址告诉apiserver, 让apiserver直接来访问containerd的stream server。这种情况下,需要给stream server使能tls认证来做安全防护。

从k8s1.11引入了kubelet stream proxy (https://github.com/kubernetes/kubernetes/pull/64006),从而使得containerd stream server只需要监听本地地址即可。

2.1.5 CNI网络

对比项 docker containerd
谁负责调用CNI kubelet内部的docker-shim containerd内置的cri-plugin(containerd 1.1以后)
如何配置CNI kubelet参数 --cni-bin-dir 和 --cni-conf-dir containerd配置文件(toml): plugins."io.containerd.grpc.v1.cri".cni
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"

2.2 containerd客户端命令介绍

2.2.1 crictl、ctr命令

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

# 1、crictl 命令(k8s提供)
crictl 是遵循 CRI 接口规范的一个命令行工具,通常用它来检查和管理kubelet节点上的容器运行时和镜像。

# 2、ctr 命令(containerd提供)
ctr 是 containerd 的一个客户端工具。

crictl与ctr二者的区别总结:

`ctr -v` 输出的是 containerd 的版本
`crictl -v` 输出的是当前 k8s 的版本,从结果显而易见你可以认为 crictl 是用于 k8s 的。

使用crictl命令之前,需要先配置/etc/crictl.yaml如下(不配置的话,你用该命令会一直报warn警告):

cat > /etc/crictl.yaml << 'EOF'
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

也可以通过命令进行设置(会自动生成/etc/crictl.yaml):

crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl config image-endpoint unix:///run/containerd/containerd.sock

简单操作:

# 1、
[root@k8s-node-01 ~]# ctr ns ls
NAME    LABELS
default
k8s.io
moby

[root@k8s-node-01 ~]# ctr -n k8s.io image ls

# 2、crictl 没有-n参数,操作都在`k8s.io`命名空间下。
crictl images
crictl pods

2.2.2 nerdctl命令

前面我们介绍了可以使用 ctr 操作管理 containerd 镜像容器,但是大家都习惯了使用 docker cli,ctr 使用起来可能还是不太顺手,为了能够让大家更好的转到 containerd 上面来,社区提供了一个新的命令行工具:nerdctl。nerdctl 是一个与 docker cli 风格兼容的 containerd 客户端工具,而且直接兼容 docker compose 的语法的,这就大大提高了直接将 containerd 作为本地开发、测试或者单机容器部署使用的效率。

安装:

# 如果没有安装 containerd,则可以下载 nerdctl-full-<VERSION>-linux-amd64.tar.gz 包进行安装
wget https://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-1.7.6-linux-amd64.tar.gz
mkdir -p /usr/local/containerd/bin/ && tar -zxvf nerdctl-1.7.6-linux-amd64.tar.gz nerdctl && mv nerdctl /usr/local/containerd/bin/
ln -s /usr/local/containerd/bin/nerdctl /usr/local/bin/nerdctl

[root@k8s-node-01 ~]# nerdctl version  # 报错warn,提示buildkit未安装
WARN[0000] unable to determine buildctl version: exec: "buildctl": executable file not found in $PATH
Client:
 Version: v1.7.6

安装buildkit(参考: https://zhuanlan.zhihu.com/p/366671300 ):

wget https://github.com/moby/buildkit/releases/download/v0.13.2/buildkit-v0.13.2.linux-amd64.tar.gz
# 解压后得到一个bin目录,把这个bin目录放到 $PATH 里去

简单使用:

[root@k8s-node-01 ~]# nerdctl ns ls
NAME       CONTAINERS   IMAGES   VOLUMES   LABELS
default    0            1        0
k8s.io     8            24       0
moby       0            0        0

[root@k8s-node-01 ~]# nerdctl -n k8s.io images

容器客户端命令无法操作镜像与容器两种东西,说到镜像,拉取时就涉及到配置镜像加速的问题,所以这些客户端命令暂且不着急详细介绍使用,先来看下配置镜像加速的问题。

注意: 镜像加速不是关键。镜像加速不是关键,镜像加速不是什么重要知识点。配置镜像加速无非是想从一些开源镜像仓库里拿镜像,这种完全你可以利用阿里云海外服务器的方法来构建,真正在公司中我们使用的是私有镜像仓库。所以镜像加速的问题并不需要纠结。


2.3 containerd配置镜像加速

2.3.1 储备知识

注意: 网上大多数配置containerd镜像加速的文章都是直接修改:`/etc/containerd/config.toml`配置文件,这种方式在较新版本的contaienrd中已经被废弃,将来肯定会被移除,只不过现在还可以使用而已。另外,这种方式有一个不好的地方就是,每次修改`/etc/containerd/config.toml`配置文件,都需要执行`systemctl restart containerd.service`命令重启containerd。

新版本的containerd镜像仓库配置都是建议放在一个单独的文件夹当中,并且在`/etc/containerd/config.toml`配置文件当中打开`config_path`配置,指向镜像仓库配置目录即可。这种方式只需要在第一次修改`/etc/containerd/config.toml`文件打开`config_path`配置时需要重启containerd,后续我们增加镜像仓库配置都无需重启containerd,非常方便。

若我们在/etc/containerd/config.toml配置文件中指定config_path = /etc/containerd/certs.d,那么containerd镜像仓库的格式如下:

$ tree /etc/containerd/certs.d
/etc/containerd/certs.d
/etc/containerd/certs.d/
├── 192.168.11.20
│   └── hosts.toml
└── docker.io
    └── hosts.toml

可以看到,第一级目录为镜像仓库的域名或者IPADDR,第二级为hosts.toml文件。

hosts.toml文件中的内容仅支持: server, capabilities, ca, client, skip_verify, [header], override_path

hosts.toml文件示例如下(了解一下):

[host."https://mirror.registry"]
  capabilities = ["pull"]
  ca = "/etc/certs/mirror.pem"
  skip_verify = false

[host."https://mirror.registry".header]
  x-custom-2 = ["value1", "value2"]

[host."https://mirror-bak.registry/us"]
  capabilities = ["pull"]
  skip_verify = true

[host."http://mirror.registry"]
  capabilities = ["pull"]

[host."https://test-1.registry"]
  capabilities = ["pull", "resolve", "push"]
  ca = ["/etc/certs/test-1-ca.pem", "/etc/certs/special.pem"]
  client = [["/etc/certs/client.cert", "/etc/certs/client.key"],["/etc/certs/client.pem", ""]]

[host."https://test-2.registry"]
  client = "/etc/certs/client.pem"

[host."https://test-3.registry"]
  client = ["/etc/certs/client-1.pem", "/etc/certs/client-2.pem"]

[host."https://non-compliant-mirror.registry/v2/upstream"]
  capabilities = ["pull"]
  override_path = true

配置私有镜像harbor:

新建目录,以实际配置的私有域名为准,如这里私有镜像地址为harbor.node.com,则需要新建这个域名的目录:

mkdir -p /etc/containerd/certs.d/harbor.node.com

在/etc/containerd/certs.d/harbor.node.com创建hosts.toml:

server = "https://harbor.node.com"

[host."https://harbor.node.com"]
  capabilities = ["pull", "resolve"]
  skip_verify = true  # 跳过证书验证

2.3.2 为docker.io配置镜像加速

1、首先配置指定config_path,只配置一次即可,后续为其他库配置镜像加速都无需再次指定了:

$ vim /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry]
   config_path = "/etc/containerd/certs.d"  # 原来config_path = ""

systemctl daemon-reload
systemctl restart containerd

2、然后为docker.io配置镜像加速:

# docker hub镜像加速
mkdir -p /etc/containerd/certs.d/docker.io
cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://docker.io"

[host."https://registry-1.docker.io"]
  capabilities = ["pull", "resolve"]

[host."https://docker.211678.top"]
  capabilities = ["pull", "resolve"]

[host."https://docker.1panel.live"]
  capabilities = ["pull", "resolve"]

[host."https://hub.rat.dev"]
  capabilities = ["pull", "resolve"]

[host."https://docker.m.daocloud.io"]
  capabilities = ["pull", "resolve"]

[host."https://do.nark.eu.org"]
  capabilities = ["pull", "resolve"]

[host."https://dockerpull.com"]
  capabilities = ["pull", "resolve"]

[host."https://dockerproxy.cn"]
  capabilities = ["pull", "resolve"]

[host."https://docker.awsl9527.cn"]
  capabilities = ["pull", "resolve"]
EOF

验证(强调:对于nerdctl命令来说,会自动使用/etc/containerd/certs.d目录下的配置镜像加速,但是对于ctr命令,需要指定--hosts-dir=/etc/containerd/certs.d):

$ ctr image pull docker.io/library/centos:7 --hosts-dir=/etc/containerd/certs.d
$ nerdctl pull docker.io/library/centos:7
$ nerdctl pull docker.io/library/ubuntu:20.04

2.3.3 为其他库配置镜像加速(了解)

注意,下面镜像仓库都是使用了daocloud的镜像仓库,daocloud镜像仓库并非支持所有镜像的下载,其支持的镜像列表可以参考:daocloud镜像仓库支持列表( https://github.com/DaoCloud/public-image-mirror/blob/main/mirror.txt )gitee版本( https://gitee.com/daocloud/public-image-mirror )

# registry.k8s.io镜像加速
mkdir -p /etc/containerd/certs.d/registry.k8s.io
tee /etc/containerd/certs.d/registry.k8s.io/hosts.toml << 'EOF'
server = "https://registry.k8s.io"

[host."https://k8s.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# docker.elastic.co镜像加速
mkdir -p /etc/containerd/certs.d/docker.elastic.co
tee /etc/containerd/certs.d/docker.elastic.co/hosts.toml << 'EOF'
server = "https://docker.elastic.co"

[host."https://elastic.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# gcr.io镜像加速
mkdir -p /etc/containerd/certs.d/gcr.io
tee /etc/containerd/certs.d/gcr.io/hosts.toml << 'EOF'
server = "https://gcr.io"

[host."https://gcr.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# ghcr.io镜像加速
mkdir -p /etc/containerd/certs.d/ghcr.io
tee /etc/containerd/certs.d/ghcr.io/hosts.toml << 'EOF'
server = "https://ghcr.io"

[host."https://ghcr.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# k8s.gcr.io镜像加速
mkdir -p /etc/containerd/certs.d/k8s.gcr.io
tee /etc/containerd/certs.d/k8s.gcr.io/hosts.toml << 'EOF'
server = "https://k8s.gcr.io"

[host."https://k8s-gcr.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# mcr.microsoft.com镜像加速
mkdir -p /etc/containerd/certs.d/mcr.microsoft.com
tee /etc/containerd/certs.d/mcr.microsoft.com/hosts.toml << 'EOF'
server = "https://mcr.microsoft.com"

[host."https://mcr.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# nvcr.io镜像加速
mkdir -p /etc/containerd/certs.d/nvcr.io
tee /etc/containerd/certs.d/nvcr.io/hosts.toml << 'EOF'
server = "https://nvcr.io"

[host."https://nvcr.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# quay.io镜像加速
mkdir -p /etc/containerd/certs.d/quay.io
tee /etc/containerd/certs.d/quay.io/hosts.toml << 'EOF'
server = "https://quay.io"

[host."https://quay.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# registry.jujucharms.com镜像加速
mkdir -p /etc/containerd/certs.d/registry.jujucharms.com
tee /etc/containerd/certs.d/registry.jujucharms.com/hosts.toml << 'EOF'
server = "https://registry.jujucharms.com"

[host."https://jujucharms.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

# rocks.canonical.com镜像加速
mkdir -p /etc/containerd/certs.d/rocks.canonical.com
tee /etc/containerd/certs.d/rocks.canonical.com/hosts.toml << 'EOF'
server = "https://rocks.canonical.com"

[host."https://rocks-canonical.m.daocloud.io"]
  capabilities = ["pull", "resolve", "push"]
EOF

查看目录结构:

$ tree /etc/containerd/certs.d/
/etc/containerd/certs.d/
├── docker.elastic.co
│   └── hosts.toml
├── docker.io
│   └── hosts.toml
├── gcr.io
│   └── hosts.toml
├── ghcr.io
│   └── hosts.toml
├── k8s.gcr.io
│   └── hosts.toml
├── mcr.microsoft.com
│   └── hosts.toml
├── nvcr.io
│   └── hosts.toml
├── quay.io
│   └── hosts.toml
├── registry.jujucharms.com
│   └── hosts.toml
├── registry.k8s.io
│   └── hosts.toml
└── rocks.canonical.com
    └── hosts.toml

各个镜像仓库加速验证操作如下:

注意:
1、对于nerdctl命令来说,会自动使用/etc/containerd/certs.d目录下的配置镜像加速,但是对于ctr命令,需要指定--hosts-dir=/etc/containerd/certs.d。举个栗子:ctr i pull --hosts-dir=/etc/containerd/certs.d registry.k8s.io/sig-storage/csi-provisioner:v3.5.0,如果要确定此命令是否真的使用了镜像加速,可以增加--debug=true参数,譬如:ctr --debug=true i pull --hosts-dir=/etc/containerd/certs.d registry.k8s.io/sig-storage/csi-provisioner:v3.5.0

2、测试不同的仓库加速

# 1、registry.k8s.io镜像仓库验证
nerdctl --debug=true image pull registry.k8s.io/sig-storage/csi-provisioner:v3.5.0

# 2、k8s.gcr.io镜像仓库验证
nerdctl --debug=true image pull k8s.gcr.io/kube-apiserver:v1.17.3

# 3、docker.io镜像仓库验证
nerdctl --debug=true image pull docker.io/library/ubuntu:20.04

2.4 客户端命令

储备知识:镜像与容器存放的名称空间

可以用-n指定名称空间,可以将镜像或者容器分散到不同的空间内,但并非所有命令都支持。

事项 docker ctr(containerd) crictl(kubernetes) nerdctl
是否支持 不支持 支持 不支持 支持
示例 ctr ns ls
ctr -n k8s.io image ls # 查看指定名称空间下的镜像
ctr -n k8s.io container ls # 查看指定名称空间下的容器
默认所有操作都在k8s.io名称空间下 nerdctl -n k8s.io image ls
nerdctl -n k8s.io container ls

再次强调:上面说的名称空间的概念适用于镜像以及容器。

2.4.1 镜像相关命令

命令 docker ctr(containerd) crictl(kubernetes) nerdctl
查看本地镜像列表 docker images ctr image ls crictl images 同docker命令
下载/拉取镜像 docker pull ctr image pull crictl pull 同docker命令
给镜像打标签 docker tag ctr image tag 无 同docker命令
上传/推送镜像 docker push ctr image push 无 同docker命令
删除本地镜像 docker rmi ctr image rm crictl rmi 同docker命令
查看镜像详情 docker inspect 无 crictl inspecti # 注意末尾是小写字母i 同docker命令
导出镜像 docker save ctr image export 无 同docker命令
导入镜像 docker load ctr image import xx.tar docker.io/library/nginx:alpine 无 同docker命令
登录镜像仓库 docker login 不支持,理由:ctr 工具主要是用于底层的容器操作和管理,而不是直接与镜像仓库进行交互如推拉镜像等。 不支持,理由:主要用于管理 Pod 和容器,而非直接与镜像仓库交互。 支持

1、ctr(containerd)

# 1、查看
ctr image ls       # 分字段展示
ctr image ls -q    # 展示一个地址,如docker.io/library/nginx:alpine
ctr image check    # 检测default名称空间下所有镜像的可用性,主要看STATUS为complete代表可用

# 2、拉取 Docker Hub 官方镜像 nginx:alpine,需要注意的是镜像地址需要加上 docker.io Host 地址
ctr images pull docker.io/library/nginx:alpine

# 3、重新打标签
ctr image tag docker.io/library/nginx:alpine harbor.k8s.local/course/nginx:alpine

# 4、上传镜像
ctr images push docker.io/library/nginx:alpine --user xxx

# 5、删除镜像
ctr image rm harbor.k8s.local/course/nginx:alpine

# 6、查看镜像详情
无

# 7、将镜像导出为压缩包
ctr image export nginx.tar.gz docker.io/library/nginx:alpine
ctr -n k8s.io image export a.tar.gz registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.11.1

# 8、从压缩包导入镜像
ctr image import nginx.tar.gz
ctr -n default image import a.tar.gz

直接导入可能会出现类似于 `ctr: content digest sha256:xxxxxx not found` 的错误,要解决这个办法需要 pull 可以通用/适用所有平台的镜像:
➜ ctr i pull --all-platforms docker.io/library/nginx:alpine
➜ ctr i export --all-platforms nginx.tar.gz docker.io/library/nginx:alpine
➜ ctr i rm docker.io/library/nginx:alpine
➜ ctr i import nginx.tar.gz

# 9、将镜像挂载到主机目录
ctr image mount docker.io/library/nginx:alpine /mnt
ctr image unmount /mnt

# 10、命名空间:Containerd 也有 namespaces 的概念,镜像或容器可以分散到不同的空间,对于多租户的场景十分有用
ctr ns ls
ctr ns create test
ctr ns rm test
ctr -n test image ls

说明:

  1. Docker 其实也是默认调用的 containerd,事实上 Docker 使用的 containerd 下面的命名空间默认是 moby,而不是 default
  2. Kubernetes 下使用的 containerd 默认命名空间是 k8s.io

2、crictl(kubernetes)

crictl操作的均在k8s.io命名空间,且crictl 是只有一个k8s.io命名空间,但是没有-n 参数。

# 1、crictl 没有-n参数,操作都在`k8s.io`命名空间下。
# 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

【温馨提示】
1、ctr images pull 拉取的镜像默认放在default
2、而 crictl pull 和 kubelet 默认拉取的镜像都在 k8s.io 命名空间下。
所以通过ctr导入镜像的时候特别注意一点,最好指定命名空间。

3、nerdctl

# 镜像管理
nerdctl images
nerdctl pull docker.io/library/busybox:latest
nerdctl login --username=egonlinhaifeng --password xxx registry.cn-shanghai.aliyuncs.com  # nerdctl logout
nerdctl tag centos:7 registry.cn-shanghai.aliyuncs.com/egon/test:v1.0
nerdctl push registry.cn-shanghai.aliyuncs.com/egon/test:v1.0
nerdctl save -o busybox.tar.gz busybox:latest
nerdctl load -i busybox.tar.gz
nerdctl rmi busybox

ctr不能build镜像,我们可以用nerdctl:

# 1、Dockerfile文件如下
FROM centos:7
CMD sleep 1000

# 2、构建镜像
nerdctl build -t test:v1.0 -f Dockerfile .

可以看到有一个错误提示,需要我们安装 `buildctl` 并运行 `buildkitd`,这是因为 `nerdctl build` 需要依赖 `buildkit` 工具。

buildkit项目也是 Docker 公司开源的一个构建工具包,支持 OCI 标准的镜像构建。它主要包含以下部分:
1. 服务端 `buildkitd`:当前支持 runc 和 containerd 作为 worker,默认是 runc,我们这里使用 containerd
2. 客户端 `buildctl`:负责解析 Dockerfile,并向服务端 buildkitd 发出构建请求

buildkit 是典型的 C/S 架构,客户端和服务端是可以不在一台服务器上,而 `nerdctl` 在构建镜像的时候也作为 `buildkitd` 的客户端,所以需要我们安装并运行 `buildkitd`。

安装buildkit:

wget https://github.com/moby/buildkit/releases/download/v0.13.2/buildkit-v0.13.2.linux-amd64.tar.gz
tar -zxvf buildkit-v0.13.2.linux-amd64.tar.gz -C /usr/local/containerd/
ln -s /usr/local/containerd/bin/buildkitd /usr/local/bin/buildkitd
ln -s /usr/local/containerd/bin/buildctl /usr/local/bin/buildctl

cat > /etc/systemd/system/buildkit.service << "EOF"
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

[Service]
ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable buildkit --now
systemctl status buildkit.service

然后重新构建镜像:

如果不用-f制定构建文件,默认找的不是dockerfile而是Containerfile,-f之后可以是任意名字。
[root@k8s-node-01 test]# nerdctl build -t test:v1.0 -f Dockerfile .
FATA[0000] lstat /test/Containerfile: no such file or directory

[root@k8s-node-01 test]# ls
dockerfile

[root@k8s-node-01 test]# mv dockerfile Containerfile
[root@k8s-node-01 test]# nerdctl build -t test:v1.0 -f Dockerfile .

[root@k8s-node-01 test]# nerdctl images
REPOSITORY   TAG    IMAGE ID        CREATED           PLATFORM       SIZE         BLOB SIZE
test         v1.0   b1dd8c2e8f41    33 seconds ago    linux/amd64    239.6 MiB    79.7 MiB

启动测试:

nerdctl run -d --name=test test:v1.0
nerdctl container ls
nerdctl exec -ti test sh

2.4.2 容器相关命令

命令 docker ctr(containerd) crictl(kubernetes) nerdctl
显示本地运行的容器列表 docker ps ctr task ls/ctr container ls crictl ps 同docker命令
创建一个新的容器 docker create ctr container create crictl create 同docker命令
运行一个新的容器 docker run ctr run 无(最小单元为 pod) 同docker命令
启动容器 docker start ctr task start crictl start 同docker命令
关闭容器 docker stop ctr task kill crictl stop 同docker命令
删除容器 docker rm ctr container rm crictl rm 同docker命令
查看容器详情 docker inspect ctr container info crictl inspect 同docker命令
查看容器日志 docker logs 无 crictl logs 同docker命令
查看容器资源 docker stats 无 crictl stats 同docker命令
登录或在容器内部执行命令 docker exec 无 crictl exec 同docker命令
清空不用的容器 docker image prune 无 crictl rmi --prune 同docker命令

1、ctr(containerd)

# 9、容器操作
# 9.1 创容器
ctr image pull docker.io/library/nginx:alpine --hosts-dir=/etc/containerd/certs.d
ctr container create docker.io/library/nginx:alpine nginx

# 9.2 查看
ctr container ls
ctr container ls -q
ctr container info nginx

# 9.3 删除
ctr container rm nginx

# 9.4 任务
## (1)任务介绍
# 上面用container create只是创建了一个静态的容器对象,把运行容器需要的资源及配置数据例如namespaces、rootfs和容器的配置都初始化完毕了,但是容器内的进程还没有启动,即容器尚未处于运行状态

## (2) 启动任务(激活容器)
ctr task start -d nginx  # nginx是你创建的容器名字

## (3)查看
[root@k8s-node-01 ~]# ctr task ls
TASK     PID      STATUS
nginx    113846   RUNNING

## (4)进入容器
# 注意必须要指定 --exec-id 参数,这个 id 可以随便写,只要唯一就行。
ctr task exec --exec-id 0 -t nginx sh

## (5)暂停容器
ctr task pause nginx  # 可以查看容器ctr task ls发现状态变成PAUSED

## (6)恢复容器
ctr task resume nginx

## (7)ctr无法stop容器,只能暂停或杀死
ctr task kill nginx  # 可以查看容器ctr task ls发现状态变成STOPPED

## (8)删掉
ctr task rm nginx

## (9)获取容器cgroup相关信息(内存、CPU 和 PID 的限额与使用量。)
ctr task metrics nginx  # 记得要先启动才能看:ctr task start -d nginx

## (10)看容器中所有进程在宿主机中的 PID
ctr task ps nginx  # 第一行的就对应容器内的1号进程

2、crictl(略)

3、nerdctl

# 1、容器管理
nerdctl run -d -p 80:80 --name=nginx --restart=always nginx:alpine
nerdctl exec -it nginx /bin/sh
nerdctl ps
nerdctl ps -a
nerdctl inspect nginx
nerdctl logs
nerdctl logs -f
nerdctl stop nginx
nerdctl rm nginx
nerdctl rm -f nginx

2.4.3 pod相关命令

了解即可,主要通过k8s启停管理pod。

命令 docker ctr(containerd) crictl(kubernetes) nerdctl
显示POD列表 无 无 crictl pods 无
查看POD详情 无 无 crictl inspectp pod的id号 无

更多命令操作,可以直接在命令行输入命令查看帮助:

docker --help
ctr --help
crictl --help
posted @ 2026-06-29 21:34  cuckooyang  阅读(57)  评论(0)    收藏  举报