[云原生] K8s 核心组件使用指南

0 序

  • 1、不论是先前的大数据/移动互联网热潮,还是当下的人工智能热潮,云原生已经成为云的基础设施,而K8s作为云原生 的核心元件,则事实上继续成为了这轮AI浪潮的核心基础设施
  • 2、在前面篇章中,完成K8s集群部署之后,就是研发或运维人员对K8s集群的日常使用问题了,本篇对过去几年笔者对K8s集群核心组件、及其命令行工具的总结。

1 K8s 核心组件使用指南

K8s集群组件

Kubernetes 组件 - Kubernetes

Kubelet : 每个工作节点上运行的节点代理

  • kubelet 是在每个节点上运行的主要 "节点代理"

即: Kubelet 是 kubernetes 工作节点 上的一个代理组件 ,运行在每个节点上。

Kubelet工作节点 上的主要服务 ,定期从kube-apiserver组件接收新的或修改的Pod规范 ,并确保Pod及其容器 在期望规范下运行。

同时该组件作为工作节点的监控组件 ,向kube-apiserver汇报主机的运行状况。

  • 它可以使用以下方式之一向 API 服务器注册:
  • 主机名(hostname);
  • 覆盖主机名的参数;
  • 特定于某云驱动的逻辑。
  • kubelet 是基于 PodSpec 来工作的。
  • 每个 PodSpec 是一个描述 Pod 的 YAML 或 JSON 对象。
  • kubelet 接受通过各种机制(主要是通过 apiserver)提供的一组 PodSpec,并确保这些 PodSpec 中描述的容器处于运行状态且运行状况良好。
  • kubelet 不管理不是由 Kubernetes 创建的容器。
  • 除了来自 API 服务器的 PodSpec 之外,还可以通过以下两种方式将容器清单manifest)提供给 kubelet
  • 文件(File):利用命令行参数传递路径。kubelet 周期性地监视此路径下的文件是否有更新。 监视周期默认为 20s,且可通过参数进行配置。
  • HTTP 端点(HTTP endpoint):利用命令行参数指定 HTTP 端点。 此端点的监视周期默认为 20 秒,也可以使用参数进行配置。

参考文献

Kubeadm : k8s 部署工具

组件简介

  • Kubeadm 是一个提供了 kubeadm initkubeadm join 的工具, 作为创建 Kubernetes 集群的 "快捷途径" 的最佳实践。
  • kubeadm 通过执行必要的操作来启动和运行最小可用集群

按照设计,它只关注启动引导 ,而非配置机器。

同样的, 安装各种 "锦上添花" 的扩展,例如 Kubernetes Dashboard、 监控方案、以及特定云平台的扩展,都不在讨论范围内。

相反,k8s官方希望在 kubeadm 之上构建更高级别以及更加合规的工具, 理想情况下,使用 kubeadm 作为所有部署工作的基准 将会更加易于创建一致性集群

常用命令

  • kubeadm init 用于搭建控制平面节点
  • kubeadm join 用于搭建工作节点并将其加入到集群中
shell 复制代码
kubeadm join 172.16.1.72:6443 --token 67yn2j.pwv6zn6ci59bw8ma \
 --discovery-token-ca-cert-hash sha256:ef39262b36489b6f6e8df35af5d921cdee7a4de01148544e2f28c18f5c3d7d1d 
  • kubeadm upgrade 用于升级 Kubernetes 集群到新版本
  • kubeadm config 如果你使用了 v1.7.x 或更低版本的 kubeadm 版本初始化你的集群,则使用 kubeadm upgrade 来配置你的集群
  • kubeadm token 用于管理 kubeadm join 使用的令牌
shell 复制代码
# 在kubeadm init后,没有记录kubeadm join 及其token信息,如何查询? 答: 再生成一个token即可:
kubeadm token create --print-join-command

# 查看历史的token
kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
zlwgj5.3euou24y2rb9b3sh   23h         2026-04-20T02:00:23Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token


# 再生成一个token
kubeadm token create --print-join-command
  • kubeadm reset 用于恢复通过 kubeadm init 或者 kubeadm join 命令对节点进行的任何变更
  • kubeadm certs 用于管理 Kubernetes 证书
  • kubeadm kubeconfig 用于管理 kubeconfig 文件
  • kubeadm version 用于打印 kubeadm 的版本信息
  • kubeadm alpha 用于预览一组可用于收集社区反馈的特性

参考文献

Kubectl : k8s 命令行工具

组件简介

  • Kubernetes 提供 kubectl 是使用 Kubernetes APIKubernetes 集群控制面板 进行通信的**【命令行工具】**。

这个工具叫做 kubectl

  • 即:kubectl作为客户端CLI工具 ,可以让用户 通过命令行 的方式对Kubernetes集群进行操作。
  • 针对配置信息,kubectl$HOME/.kube 目录中查找一个名为 config 的配置文件。

你可以通过设置 KUBECONFIG 环境变量或设置 --kubeconfig 参数来指定其它 kubeconfig 文件。

  • 有关每个命令的详细信息,包括所有受支持的参数和子命令, 请参阅 kubectl 参考文档。

有关安装说明,请参见安装 kubectl; 如需快速指南,请参见备忘单。

如果你更习惯使用 docker 命令行工具, Docker 用户的 kubectl 介绍了一些 Kubernetes 的等价命令。

kubectl可操作的资源对象类型: ns / svc / rc / ...

资源对象的名称 缩写
cluster
componentstatuses cs
configmaps cm
daemonsets ds
deployments deploy
endpoints ep
events ev
horizontalpodautoscalers hpa
ingresses ing
Jobs
limitranges limits
nodes no
namespaces ns
networkpolicies
statefulsets
persistentvolumeclaims pvc
persistentvolumes pv
pods po
podsecuritypolicies psp
podtemplate
replicasets rs
replicationcontrollers rc
resourcequotas quota
cronjob
secrets
serviceaccounts
services svc
storageclasses sc
thirdpartyresources

语法格式

shell 复制代码
$ kubectl [command] [TYPE] [NAME] [flags]

(1)command :子命令,指定要对一个或多个资源执行的操作。例如create、delete、describe、get、apply等。

(2)TYPE:资源对象的类型,不区分大小写,能以单数形式、复数形式或者简写形式表示。例如:以下3种TYPE是等价的。

shell 复制代码
$ kubectl get pod pod1
$ kubectl get pods pod1
$ kubectl get po pod1

(3)NAME:资源对象的名称,区分大小写。如果不指定名称,则系统将返回属于TYPE的全部对象的列表,例如$ kubectl get pods将返回所有Pod的列表。

在对多个资源执行操作时,你可以按类型和名称指定每个资源,或指定一个或多个文件:
(4)flags :kubectl子命令的可选参数。例如,可使用-s--server 参数指定指定apiserver的URL地址和端口,而不用默认值。

  • 一个命令行 中也可以同时对多个资源对象进行操作,以多个TYPE和NAME的组合表示,示例如下。
shell 复制代码
$ kubectl get pods pod1 pod2

$ kubectl get pod/pod1 rc/rc1

$ kubectl get pod -f pod1.yaml -f pod2.yaml
$ kubectl create -f pod1.yaml -f rc1.yaml -f service1.yaml
  • 用一个或多个文件指定资源:-f file1 -f file2 -f file<#>
  • 使用 YAML 而不是 JSON

因为 YAML 对用户更友好, 特别是对于配置文件。

例子:kubectl get -f ./pod.yaml

  • 注意,从命令行指定的参数 会覆盖默认值和任何相应的环境变量
  • 如果你需要帮助,在终端窗口中运行 kubectl help

kubectl 输出格式

kubectl 的输出格式

输出格式 说明
-o=custom-columns=<spec> 根据自定义列名进行输出,以逗号分隔
-o=custom-colimns-file=<filename> 从文件中获取自定义列名进行输出
-o=json 以JSON格式显示结果
-o=jsonpath=<template> 输出jsonpath表达式定义的字段信息
-o=jsonpath-file=<filename> 输出jsonpath表达式定义的字段信息,来源于文件
-o=name 仅输出资源对象的名称
-o=wide 输出额外信息。对于Pod资源,将输出Pod所在的Node
-o=yaml 以yaml格式显示结果

常见输出格式:

  • 显示Pod的更多信息
shell 复制代码
$ kubectl get pod <pod-name> -o wide
或
$ kubectl get pod <pod-name> --namespace <namespace> -o wide
  • 以yaml格式显示Pod的详细信息
shell 复制代码
$ kubectl get pod <pod-name> -o yaml
  • 以自定义列名显示Pod的信息
shell 复制代码
$ kubectl get pod <pod-name> -o=custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion
  • 基于文件的自定义列名输出
shell 复制代码
$ kubectl get pods <pod-name> -o=custom-columns-file=template.txt
  • 还可以将输出结果按某个字段排序,通过--sort-by参数以jsonpath表达式进行指定
shell 复制代码
$ kubectl [command] [TYPE] [NAME] --sort-by=<jsonpath_exp>

例如,按照名字进行排序

shell 复制代码
$ kubectl get pods
NAME                                       READY     STATUS    RESTARTS   AGE
chaosfomoney-deployment-64ccd59bdc-h72gh   1/1       Running   0          1d
chaosfomoney-deployment-64ccd59bdc-spnpj   1/1       Running   0          1d
chaosfomoney-deployment-64ccd59bdc-xhnjr   1/1       Running   0          1d

$ kubectl get pods --sort-by=.metadata.name
NAME                                       READY     STATUS    RESTARTS   AGE
chaosfomoney-deployment-64ccd59bdc-h72gh   1/1       Running   0          1d
chaosfomoney-deployment-64ccd59bdc-spnpj   1/1       Running   0          1d
chaosfomoney-deployment-64ccd59bdc-xhnjr   1/1       Running   0          1d

常用命令

kubectl create : 创建资源对象

  • 根据yaml配置文件一次创建service和rc
shell 复制代码
$ kubectl create -f my-service.yaml -f my-rc.yaml
  • 根据<directory>目录下所有.yaml.yml.json文件的定义进行创建操作
shell 复制代码
$ kubectl create -f <directory>

kubectl apply : 以文件或标准输入为准应用或更新资源

shell 复制代码
# 使用 example-service.yaml 中的定义创建 Service。
kubectl apply -f example-service.yaml

# 使用 example-controller.yaml 中的定义创建 replication controller。
kubectl apply -f example-controller.yaml

# 使用 <directory> 路径下的任意 .yaml、.yml 或 .json 文件 创建对象。
kubectl apply -f <directory>

kubectl edit : 直接编辑 K8s 集群的资源对象(Pod/Deployment/Service/...)

  • 简要介绍
  • kubectl edit : 允许直接编辑 Kubernetes 集群中的资源对象(如 Pod、Deployment、Service 等),修改后会立即生效 ,无需手动执行 kubectl apply
  • 本质流程:拉取资源当前配置 → 打开编辑器修改 → 提交更新到集群。
  • 掌握 kubectl edit 可极大提升 Kubernetes 资源管理效率,但需谨慎操作以避免意外影响。
  • 使用语法
  • 方式1: 编辑指定资源
shell 复制代码
kubectl edit <资源类型> <资源名称> -n <命名空间>
 
# 示例:编辑名为 "nginx" 的 Deployment
kubectl edit deployment nginx -n default

kubectl edit daemonset -n kube-system kube-proxy
  • 方式2: 通过文件格式指定资源
shell 复制代码
# 编辑指定 YAML 文件对应的资源
kubectl edit -f deployment.yaml
  • 核心参数
参数 说明
-o / --output 指定编辑格式(如 yaml、json),默认由 KUBE_EDITOR 环境变量决定
--record 在资源注解中记录本次修改的命令(用于审计)
--windows-line-endings 使用 Windows 换行符(CRLF)
--allow-missing-template-keys 允许模板中缺失字段(默认 true)
--field-manager 指定字段管理器名称(用于 Server-Side Apply)
--validate 修改后验证配置合法性(默认 true,设为 false 可跳过验证)
  • 高级功能与技巧
  • 指定编辑器

默认使用 vim,可通过环境变量切换编辑器:

shell 复制代码
# 使用 nano 编辑器
export KUBE_EDITOR="nano"
kubectl edit deploy/nginx
 
# 临时指定编辑器(无需修改环境变量)
KUBE_EDITOR="code --wait" kubectl edit deploy/nginx  # 使用 VS Code
  • 编辑特定资源版本
shell 复制代码
# 显示资源版本、并指定版本编辑
kubectl get deploy nginx -o yaml | grep resourceVersion  # 获取当前版本
kubectl edit deploy/nginx --resource-version=<版本号>
  • 编辑多个资源

结合标签选择器批量操作

shell 复制代码
# 编辑所有包含 "app=web" 标签的 Pod
kubectl edit pods -l app=web -n default
  • 快速定位字段

在编辑器中直接搜索关键字(如 replicas、image),快速修改核心参数。

  • 常见使用场景
  • 实时调整副本数
shell 复制代码
kubectl edit deploy/nginx
# 修改 replicas 字段 → 保存退出后立即生效
  • 更新容器镜像
shell 复制代码
kubectl edit deploy/nginx
# 修改 spec.template.spec.containers[0].image → 保存退出
  • 修改 ConfigMap/Secret
shell 复制代码
# 编辑 ConfigMap
kubectl edit cm app-config -n default
 
# 编辑 Secret(注意:Base64 编码值需自行处理)
kubectl edit secret db-credentials -n default
  • 调试资源限制
shell 复制代码
kubectl edit deploy/nginx
# 调整 resources.limits 和 resources.requests → 保存退出
  • 注意事项
  • 并发修改冲突
    若资源被其他用户或控制器修改,提交时会提示版本冲突(需重新拉取最新版本后编辑)。
  • 格式校验严格
    YAML 格式错误(如缩进错误、键名错误)会导致提交失败,需仔细检查。
  • 生产环境谨慎使用
    直接修改运行中的资源可能引发服务中断,建议在测试环境验证后再操作。
  • 备份原始配置
    重要操作前备份当前配置:
shell 复制代码
kubectl get deploy/nginx -o yaml > nginx-backup.yaml
  • FAQ / 常见问题排查
  1. 错误:Edit cancelled, no changes made

原因:编辑器未正确保存修改(如直接关闭未保存)。

解决:重新执行命令并确保保存修改。

  1. 错误:invalid configuration

原因:YAML 格式或字段值不合法。

解决:

shell 复制代码
# 关闭验证后强制提交(不推荐)
kubectl edit deploy/nginx --validate=false
  1. 错误:the object has been modified

原因:资源版本过期(其他人已修改过)。

解决:重新执行 kubectl edit 获取最新版本。

  • 替代方案
场景 替代命令 说明
少量字段修改 kubectl patch 无需进入编辑器,直接通过 JSON 或 YAML 片段修改
批量修改 kubectl apply -f updated.yaml 通过文件更新配置
查看历史修改记录 kubectl rollout history 查看 Deployment 等资源的修订历史
  • 参考文献

kubectl get : 列出一个或多个资源(pod/rc/service/ds)

shell 复制代码
# 获取集群所有的节点
kubectl get node 或 kubectl get no

# 查看rc和service列表
kubectl get rc,service

# 以纯文本输出格式列出所有 Pod
kubectl get pods

# 查询指定节点名(如: edge-1)的 所有 pod
kubectl get pod -A -o wide | grep edge-1

# 以纯文本输出格式列出所有 Pod,并包含附加信息(如【节点名】)。
kubectl get pods -o wide

# 以纯文本输出格式列出具有指定名称的副本控制器。提示:你可以使用别名 'rc' 缩短和替换 'replicationcontroller' 资源类型。
kubectl get replicationcontroller <rc-name>

# 以纯文本输出格式列出所有副本控制器和 Service。
kubectl get rc,services

# 以纯文本输出格式列出所有守护程序集,包括未初始化的守护程序集。
kubectl get ds --include-uninitialized

# 列出在节点 server01 上运行的所有 Pod
kubectl get pods --field-selector=spec.nodeName=server01
  • 查询pod
shell 复制代码
kubectl get pod pod1
kubectl get pods pod1
kubectl get po pod1
  • 按命名空间查询pod
shell 复制代码
kubectl get pod 
# 等效于(命名空间=default): kubectl get pod -n default

# 查询所有命名空间下的 pod
kubectl get pod --all-namespaces

# 根据指定命名空间,查询其下的 pod | 不带等同  -n default
kubectl get pods -n kube-system

示例:

kubectl get pod local-path-provisioner-844bd8758f-mvgr9 --namespace local-path-storage -o wide
kubectl describe pod local-path-provisioner-844bd8758f-mvgr9 -n local-path-storage
kubectl logs local-path-provisioner-844bd8758f-6grj7 --namespace local-path-storage --all-containers

  • 查询所有 Pod,并显示 Node 信息(IP / hostname 等)
shell 复制代码
[root@k8s-master-1 ~]# kubectl get pods -A -o wide
//等效于: kubectl get pods --all-namespaces -o wide  或  kubectl get pod --all-namespaces -o wide
NAMESPACE      NAME                                   READY   STATUS              RESTARTS      AGE    IP             NODE           NOMINATED NODE   READINESS GATES
kube-flannel   kube-flannel-ds-lgrbd                  1/1     Running             2 (28h ago)   3d3h   172.12.12.72    k8s-master-1   <none>           <none>
kube-flannel   kube-flannel-ds-wv2j6                  0/1     Init:0/2            0             26h    172.12.12.244   edge-1         <none>           <none>
kube-system    coredns-c676cc86f-nzj2x                1/1     Running             1 (28h ago)   3d3h   172.10.34.4     k8s-master-1   <none>           <none>
kube-system    coredns-c676cc86f-s88tw                1/1     Running             1 (28h ago)   3d3h   172.10.34.5     k8s-master-1   <none>           <none>
kube-system    etcd-k8s-master-1                      1/1     Running             1 (28h ago)   3d3h   172.12.12.72    k8s-master-1   <none>           <none>
kube-system    kube-apiserver-k8s-master-1            1/1     Running             1 (28h ago)   3d3h   172.12.12.72    k8s-master-1   <none>           <none>
kube-system    kube-controller-manager-k8s-master-1   1/1     Running             1 (28h ago)   3d3h   172.12.12.72    k8s-master-1   <none>           <none>
kube-system    kube-proxy-c7vf9                       0/1     ContainerCreating   0             26h    172.12.12.244   edge-1         <none>           <none>
kube-system    kube-proxy-l9g4h                       1/1     Running             1 (28h ago)   3d3h   172.12.12.72    k8s-master-1   <none>           <none>
kube-system    kube-scheduler-k8s-master-1            1/1     Running             1 (28h ago)   3d3h   172.12.12.72    k8s-master-1   <none>           <none>
kubeedge       cloud-iptables-manager-wrdjk           1/1     Running             0             28h    172.12.12.72    k8s-master-1   <none>           <none>
kubeedge       cloudcore-ffd866959-zblcp              1/1     Running             0             32h    172.12.12.72    k8s-master-1   <none>           <none>
  • 查询系统命名空间下的pod
shell 复制代码
[root@k8s-master-1 ~]# kubectl get pods -n kube-system
NAME                                   READY   STATUS              RESTARTS      AGE
coredns-c676cc86f-nzj2x                1/1     Running             1 (29h ago)   3d3h
coredns-c676cc86f-s88tw                1/1     Running             1 (29h ago)   3d3h
etcd-k8s-master-1                      1/1     Running             1 (29h ago)   3d3h
kube-apiserver-k8s-master-1            1/1     Running             1 (29h ago)   3d3h
kube-controller-manager-k8s-master-1   1/1     Running             1 (29h ago)   3d3h
kube-proxy-c7vf9                       0/1     ContainerCreating   0             26h
kube-proxy-l9g4h                       1/1     Running             1 (29h ago)   3d3h
kube-scheduler-k8s-master-1            1/1     Running             1 (29h ago)   3d3h
  • 查询系统命名空间下,Status为ContainerCreating的 pod name
shell 复制代码
[root@k8s-master-1 ~]# kubectl get pods -n kube-system | grep ContainerCreating | awk '{print $1}' | xargs
kube-proxy-c7vf9

kubectl delete : 删除资源对象

shell 复制代码
# 删除所有Pod
kubectl delete pods --all

# 基于pod.yaml定义的名称删除Pod
$ kubectl delete -f pod.yaml

# 删除所有包含某个label的Pod和Service
$ kubectl delete pod,service -l name=<label-name>

kubectl exec : 执行容器的命令

  • 执行Pod的date命令,默认使用Pod的第1个容器执行
shell 复制代码
$ kubectl exec <pod-name> date
  • 指定Pod中某个容器执行date命令
shell 复制代码
$ kubectl exec <pod-name> -c <container-name> date
  • 通过bash获得Pod中某个容器的TTY、在Pod 的容器内进行调试,相当于登陆容器 <remark=IMPORTANT>
shell 复制代码
$ kubectl exec -ti <pod-name> -c <container-name> /bin/bash

或者:
kubectl get pod <pod-name> -o wide    # 获取节点
# SSH 到节点后
crictl pods --name <pod-name>         # 找到 Pod ID
crictl ps -p <pod-id>                 # 查看 Pod 中的容器
crictl logs <container-id>            # 查看日志
crictl exec -it <container-id> /bin/sh # SSH 到节点后

kubectl describe : 显示一个或多个资源的详细状态,默认情况下包括未初始化的资源

shell 复制代码
# 显示名为 <pod-name> 的 Pod 的详细信息。
kubectl describe nodes <node-name>

# 显示名为 <pod-name> 的 Pod 的详细信息。
kubectl describe pods/<pod-name>

# 显示由名为 <rc-name> 的副本控制器管理的所有 Pod 的详细信息。
# 记住:副本控制器创建的任何 Pod 都以副本控制器的名称为前缀。
kubectl describe pods <rc-name>

# 描述所有的 Pod
kubectl describe pods

kubectl logs : 打印 Pod 中容器的日志

shell 复制代码
# 返回 Pod <pod-name> 的日志快照
kubectl logs <pod-name>

# 从 Pod <pod-name> 开始流式传输日志。这类似于 'tail -f' Linux 命令
kubectl logs -f <pod-name>

# 获取最近一小时内的 Pod 日志
kubectl logs --since=1h <pod名称>

# 获取 Pod 的最近 100 行日志 (排查异常Pod的重要命令)
kubectl logs --tail=100 <pod-name> --namespace <namespace>

# 获取 Pod 内所有容器的日志 (排查异常Pod的重要命令,尤其是 Pod 的 init 容器初始化异常时) <remark=IMPORTANT>
kubectl logs --tail=100 <pod-name> --namespace <namespace> --all-containers
如: kubectl logs local-path-provisioner-844bd8758f-6grj7 --namespace local-path-storage --all-containers

典型使用场景

CASE 基于 kubectl 查看指定 pod 内有哪些容器

可以通过以下几种方式查看 Pod 内包含的容器:

实现方式
0. kubectl describe(最常用)
bash 复制代码
kubectl describe pod <pod-name> -n <namespace>

输出中会显示 Containers 部分,列出所有容器名称、镜像、状态等信息。

输出示例:

shell 复制代码
$ kubectl describe pod nginx-deployment-abc123

Name:         nginx-deployment-abc123
Namespace:    default
...
Containers:
  nginx:                    ← 容器1名称
    Image:          nginx:1.21
    Port:           80/TCP
    State:          Running
    ...
  sidecar:                  ← 容器2名称(如果有)
    Image:          busybox:latest
    ...
Init Containers:            ← Init 容器(如果有)
  init-myservice:
    Image:          busybox:1.28
1. crictl ps -p <pod-id> (最常用)
shell 复制代码
# 查看指定 Pod 的容器列表
crictl ps -p <pod-id>
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock ps -p <pod-id>
如: crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock  ps -p 65908c4e20d60
CONTAINER           IMAGE               CREATED             STATE               NAME                ATTEMPT             POD ID              POD
6f2f81987f223       73deb9a3f7025       8 hours ago         Running             etcd                3                   65908c4e20d60       etcd-vm-a
2. kubectl get pod -o yaml/json(详细信息)
bash 复制代码
# YAML 格式
kubectl get pod <pod-name> -o yaml

# JSON 格式(可用 jq 过滤)
kubectl get pod <pod-name> -n <namespace>  -o json | jq '.status.containerStatuses[]'
或
kubectl get pod <pod-name> -o json | jq '.spec.containers[].name'
3. kubectl get pod 自定义输出(简洁查看)
bash 复制代码
# 只显示容器名称列表
kubectl get pod <pod-name> -o jsonpath='{range .spec.containers[*]}{.name}{"\n"}{end}'

# 显示容器名 + 镜像
kubectl get pod <pod-name> -o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{.image}{"\n"}{end}'
4. 使用 kubectl 插件/工具
bash 复制代码
# 使用 kubectl-view-allocations 等插件
# 或结合 grep
kubectl describe pod <pod-name> | grep -A 20 "Containers:"
Init 容器 vs 普通容器
类型 查看方式
普通容器 .spec.containers
Init 容器 .spec.initContainers
Ephemeral 容器 .spec.ephemeralContainers
bash 复制代码
# 查看 Init 容器
kubectl get pod <pod-name> -o jsonpath='{range .spec.initContainers[*]}{.name}{"\n"}{end}'
快速命令别名(可选)

添加到 .bashrc.zshrc

bash 复制代码
# 查看 Pod 容器列表
alias kpc='kubectl get pod -o jsonpath="{range .spec.containers[*]}{.name}{\"\n\"}{end}"'

# 使用:kpc <pod-name>

这些命令适用于任何 Kubernetes 集群,无需额外工具。

参考文献

k9s 的部分功能,依赖 kubectl / kubectl 在 windows 的安装与配置

ctr : containerd 的原生命令行工具(基于具体节点)

  • ctr 是 containerd 官方提供的底层命令行工具 ,直接与 containerd 守护进程通信 ,用于管理容器生命周期的各个底层组件。

核心特点

特性 说明
底层原生 直接操作 containerd,无抽象层
功能完整 支持完整的容器、镜像、快照、任务管理能力
学习价值 帮助理解容器运行时内部架构
轻量独立 不依赖 Kubernetes,可单独使用

架构关系

复制代码
┌─────────┐     ┌─────────────┐     ┌─────────────┐
│   ctr   │────→│ containerd  │────→│   runc/shim │
│  (CLI)   │     │  (daemon)   │     │  (runtime)  │
└─────────┘     └─────────────┘     └─────────────┘
        ↑
   直接通过 containerd.sock 通信

常用操作命令

1. 命名空间(Namespace)

containerd 使用命名空间 隔离资源,Kubernetes 使用 k8s.io 作为默认命名空间

bash 复制代码
# 查看所有命名空间
ctr ns ls

# 指定命名空间操作(默认是 default)
ctr -n k8s.io containers ls
ctr -n default images ls

2. 容器(Containers)

bash 复制代码
# 列出容器(注意:这是 containerd 层面的容器,不是 Pod)
ctr containers ls
ctr -n k8s.io c ls  # 简写形式

# 查看容器详情
ctr containers info <container-id>
ctr -n k8s.io containers info <container-id>

# 创建/运行容器(底层操作,通常不直接使用)
ctr containers create <image> <container-id>
ctr tasks start <container-id>

3. 任务(Tasks)------ 实际运行进程

  • containerd 中,容器 是元数据,任务(Task) 才是真正运行的进程。

  • ctr 中 Container 和 Task 是 1:1 关系,Task ID 即 Container ID。

bash 复制代码
# 查看运行中的任务
ctr tasks ls
ctr -n k8s.io t ls
//如:
//TASK                                                                PID       STATUS
//2b7379cd7e8071a759a5da957a4764dbe9abd033b0473bf57938e05e8397342a    5806      RUNNING
//...

# 查看任务详情(包含 PID 等)
ctr tasks info <task-id>
或 ctr -n k8s.io tasks ls | grep -i <container-id / task-id>
//如: ctr -n k8s.io tasks ls | grep -i  2b7379cd7e8071a759a5da957a4764dbe9abd033b0473bf57938e05e8397342a
//TASK                                                                PID       STATUS
//2b7379cd7e8071a759a5da957a4764dbe9abd033b0473bf57938e05e8397342a    5806      RUNNING

# 启动/停止/删除任务
ctr tasks start <container-id>
ctr tasks pause <task-id>
ctr tasks resume <task-id>
ctr tasks kill -9 <task-id>
ctr tasks delete <task-id>

# 进入容器(类似 docker exec)
ctr tasks exec --exec-id shell1 -t <task-id> /bin/sh

4. 镜像(Images)

bash 复制代码
# 列出镜像
ctr images ls
ctr -n k8s.io i ls

# 拉取镜像
ctr images pull docker.io/library/nginx:latest

# 导入/导出镜像
ctr images import /path/to/image.tar
ctr images export nginx.tar docker.io/library/nginx:latest

# 查看镜像内容(不提取)
ctr images mount docker.io/library/nginx:latest /mnt/nginx-fs

5. 快照(Snapshots)------ 文件系统层

bash 复制代码
# 查看快照
ctr snapshots ls

# 查看快照信息(挂载点、层信息)
ctr snapshots info <snapshot-key>

ctr中镜像、容器、任务、快照的概念与关系?

  • ctr 核心概念关系图

graph TB subgraph "Image Layer" I[镜像 Image<br/>只读模板] end subgraph "Snapshot Layer" S[快照 Snapshot<br/>可写文件系统层] S -->|基于| I end subgraph "Container Layer" C[容器 Container<br/>元数据对象] C -->|引用| S end subgraph "Task Layer" T[任务 Task<br/>运行中的进程] T -->|绑定| C end style I fill:#e1f5fe style S fill:#fff3e0 style C fill:#e8f5e9 style T fill:#ffebee

  • 四层结构速查
层级 本质 生命周期 类比
Image 只读模板 持久 类定义
Snapshot 可写文件系统 随容器创建/删除 实例属性
Container 配置元数据 创建后长期存在 实例对象
Task OS 进程 启停频繁 线程
  • 关键关系

    创建流程: Image → [unpack] → Snapshot → [create] → Container → [start] → Task
    删除流程: Task [kill] → Container [delete] → Snapshot [remove] → (Image 保留)

  • 状态对比示例

命令 结果说明
ctr images ls nginx:1.21(模板,无状态)
ctr snapshots ls nginx:1.21 + 可写层(已挂载)
ctr containers ls my-nginx(配置,可能未运行)
ctr tasks ls my-nginx: PID 1234(运行中进程)
  • 核心要点

    • Image ≠ 运行中的东西 --- 只是 tar+metadata

    • Container 不运行 --- 只有配置,类似 docker create 后的状态

    • Task 才是进程 --- 对应 Linux PID,可以 kill 但保留 Container 配置

      • containerd 中,容器 是元数据,任务(Task) 才是真正运行的进程。
      • ctr 中 Container 和 Task 是 1:1 关系,Task ID 即 Container ID。
    • Snapshot 隔离写操作 --- 多个 Container 可共享同一 Image 的不同 Snapshot

与 crictl 核心对比

维度 ctr crictl
操作对象 容器(Container)、任务(Task)、快照(Snapshot) Pod、CRI 容器
命名空间 必须显式指定 -n k8s.io 自动使用 CRI 配置
Pod 概念 ❌ 无 Pod 概念 ✅ 原生支持 Pod
Pause 容器 作为独立任务显示 自动归类到 Pod 中
适用场景 底层调试、镜像管理、学习原理 Kubernetes 运维

典型使用场景

场景 1:手动运行独立容器(无需 K8s)

bash 复制代码
# 1. 拉取镜像
ctr images pull docker.io/library/redis:latest

# 2. 创建容器
ctr containers create docker.io/library/redis:latest redis-demo

# 3. 创建任务(运行)
ctr tasks start redis-demo

# 4. 查看运行状态
ctr tasks ls

场景 2:排查 Kubernetes 底层问题

bash 复制代码
# 进入节点,查看 containerd 层面
ctr -n k8s.io tasks ls | grep <pod-id>

# 对比 crictl(更直观)
crictl ps -p <pod-id>  # 直接看到 Pod 关联的容器

场景 3:镜像导入导出(离线传输) : 导出指定节点的 containerd 镜像,并导入到另一节点

核心思路:

shell 复制代码
ctr -n k8s.io images ls

# 导出节点镜像
ctr -n k8s.io images export nginx-backup.tar docker.io/library/nginx:latest

# 导入到另一节点
ctr images import nginx-backup.tar

场景4:导出 docker 指定镜像、并导入到 k8s 的 containerd

  • step1 导出 docker 镜像
shell 复制代码
# 保存镜像为 tar 包
docker save -o myimage_tag.tar myimage:tag
//如: docker save -o /root/k8s-my-archive-images/busybox_latest.tar busybox:latest

# 或: 压缩保存(推荐,节省空间)
docker save myimage:tag | gzip > myimage.tar.gz
  • step2 传输到 k8s 节点 (可选)
shell 复制代码
# 方式1: 直接 scp 到目标节点
scp myimage.tar.gz user@k8s-node:/tmp/

# 方式2: 如果节点无法直接访问,通过跳板机或共享存储
  • step3 导入到 k8s 的 containerd

在 Kubernetes 节点上执行:

shell 复制代码
# 解压(如果是 tar.gz 压缩包)
gunzip myimage.tar.gz

# 使用 ctr 导入镜像(containerd 原生工具)
ctr -n k8s.io images import myimage.tar
//如: 
//# ctr -n k8s.io images import /root/k8s-my-archive-images/busybox_latest.tar
//unpacking docker.io/library/busybox:latest (sha256:b0109bc2759f71080904a173fe95ea9d307e7431b114cc9885b55ae98e09e7e5)...done
# 或 批量导入多个镜像到 containerd:
for img in ./dir/*.tar; do
  ctr -n k8s.io images import "$img"
done


# 验证导入成功
ctr -n k8s.io images list | grep myimage
//如:
//# ctr -n k8s.io images list | grep busybox
// docker.io/library/busybox:latest                                                                                                         application/vnd.oci.image.manifest.v1+json                sha256:b0109bc2759f71080904a173fe95ea9d307e7431b114cc9885b55ae98e09e7e5 4.4 MiB   linux/amd64                                                                   io.cri-containerd.image=managed 

常见操作命令

操作 命令
查看containerd版本 containerd --version "containerd containerd.io 1.6.33 d2d58213f83a351ca8f528a95fbd145f5654e957"
拉取镜像 ctr -n k8s.io images pull docker.io/library/nginx:latest
查看镜像 ctr -n k8s.io images list
查看镜像详情 ctr -n k8s.io images inspect myimage:tag
删除镜像 ctr -n k8s.io images rm myimage:tag
导出镜像 ctr -n k8s.io images export myimage.tar myimage:tag
查看容器列表 ctr -n k8s.io containers ls

重要概念区分

复制代码
┌─────────────────────────────────────┐
│           Kubernetes Pod          │
│  ┌─────────────────────────────┐  │
│  │  Pause Container (sandbox)  │  │  ← crictl 能看到
│  │  ┌─────────────────────────┐ │  │
│  │  │    App Container 1      │ │  │  ← ctr 能看到(作为独立任务)
│  │  │    (nginx)                │ │  │
│  │  └─────────────────────────┘ │  │
│  │  ┌─────────────────────────┐ │  │
│  │  │    App Container 2      │ │  │  ← sidecar,同样独立显示
│  │  │    (sidecar)              │ │  │
│  │  └─────────────────────────┘ │  │
│  └─────────────────────────────┘  │
│           共享 Network NS          │
└─────────────────────────────────────┘

配置文件、调试

bash 复制代码
# ctr 配置文件
cat /etc/containerd/config.toml
    ...
    config_path = "/etc/containerd/certs.d"
    ...

# 查看 ctr 使用的 socket
ctr version  # 显示连接信息

# 调试模式(查看 gRPC 调用)
ctr -d images ls

总结建议

您的角色 推荐工具
Kubernetes 用户/SRE crictl(更直观)
容器运行时开发者 ctr(更底层)
学习 containerd 原理 ctr + 阅读源码
需要脚本化镜像管理 ctr(独立性强)

ctr 是理解 containerd 架构 的钥匙,,而 crictl 才是 Kubernetes 生产环境的实用工具

crictl : K8s 的容器运行时命令行工具(基于具体节点)

  • crictl 是 Kubernetes 社区开发的容器运行时命令行工具 ,用于与遵循 CRI(Container Runtime Interface,容器运行时接口)规范的容器运行时进行交互。

核心特点

特性 说明
标准接口 基于 CRI 规范,与容器运行时解耦
兼容性强 支持 containerd、CRI-O 等主流 CRI 运行时
Kubernetes 原生 专为 Kubernetes 场景设计,命令风格类似 kubectl
调试利器 用于排查 Pod/容器问题,无需直接操作运行时

工作原理

复制代码
┌─────────┐     ┌─────────┐     ┌─────────────┐
│ crictl  │────→│ CRI API │────→│ containerd  │
│ (CLI)   │     │ (gRPC)  │     │ / CRI-O 等   │
└─────────┘     └─────────┘     └─────────────┘

常用操作命令

1. 基础信息查询

bash 复制代码
# 查看运行时版本信息
crictl version
或 crictl --version --runtime-endpoint unix:///var/run/containerd/containerd.sock
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock version
//crictl version v1.26.0


# 查看运行时状态
crictl info
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock info

# 列出所有镜像
crictl images
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock images

# 查看 Pod 列表
crictl pods
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock pods

# 查看指定 Pod 的容器列表
crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock  ps -p <pod-id>
如: crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock  ps -p 65908c4e20d60
CONTAINER           IMAGE               CREATED             STATE               NAME                ATTEMPT             POD ID              POD
6f2f81987f223       73deb9a3f7025       8 hours ago         Running             etcd                3                   65908c4e20d60       etcd-vm-a

# 查看容器列表
crictl ps
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock ps

2. Pod 操作

bash 复制代码
# 查看所有 Pod(包括已停止的)
crictl pods --all
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock pods

# 按标签过滤 Pod
crictl pods --label app=nginx

# 查看 Pod 详细信息
crictl inspectp <pod-id>

# 查看 Pod 日志
crictl logs <pod-id>

# 停止 Pod
crictl stopp <pod-id>

# 删除 Pod
crictl rmp <pod-id>

3. 容器操作

bash 复制代码
# 查看运行中的容器
crictl ps

# 查看所有容器
crictl ps -a

# 查看容器详情
crictl inspect <container-id>

# 查看容器日志
crictl logs <container-id>

# 进入容器执行命令(类似 docker exec)
crictl exec -it <container-id> /bin/sh

# 停止容器
crictl stop <container-id>

# 删除容器
crictl rm <container-id>

4. 镜像操作

bash 复制代码
# 拉取镜像
crictl pull nginx:latest
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock pull docker.io/library/mysql:8.0

# 删除镜像
crictl rmi nginx:latest

# 查看镜像列表
crictl images
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock images

# 查看镜像详情
crictl inspecti nginx:latest

5. 实用调试技巧

bash 复制代码
# 结合 kubectl 使用:找到节点上的容器
kubectl get pod <pod-name> -o wide  # 获取节点

# SSH 到节点后
crictl pods --name <pod-name>         # 找到 Pod ID
crictl ps -p <pod-id>                 # 查看 Pod 中的容器
crictl logs <container-id>            # 查看日志
crictl exec -it <container-id> /bin/sh # 进入调试

等效于: $ kubectl exec -ti <pod-name> -c <container-name> /bin/bash

crictl vs ctr 对比

对比维度 crictl ctr
定位 CRI 接口工具,面向 Kubernetes containerd 原生 CLI,面向底层运维
适用范围 任何 CRI 运行时(containerd、CRI-O) 仅 containerd
抽象层级 高(Pod、Sandbox 概念) 低(Namespace、Task、Snapshot)
命令风格 类似 kubectl/docker,易上手 专业底层,学习曲线陡
Kubernetes 集成 完美支持,能看到 Pod 结构 无法识别 Pod,只能看到独立容器
调试场景 排查 K8s Pod 问题 底层运行时调试、镜像管理

核心区别详解

1. Pod 概念支持

bash 复制代码
# crictl - 能看到 Kubernetes Pod 结构
$ crictl pods
POD ID              CREATED             STATE               NAME                NAMESPACE
abc123              2 hours ago         Ready               nginx-pod           default

# ctr - 看不到 Pod,只能看到独立容器
$ ctr tasks ls
TASK ID    IMAGE                             STATUS
container1 docker.io/library/nginx:latest    RUNNING

2. 容器视角差异

场景 crictl ctr
查看 K8s Pod 容器 crictl ps -p <pod-id> 无法直接关联
查看 Pause 容器 自动包含在 Pod 中 作为独立容器显示
容器命名 使用 K8s 元数据命名 使用 containerd 内部 ID

3. 配置方式

bash 复制代码
# crictl - 通过 /etc/crictl.yaml 配置
cat /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock

# ctr - 直接使用,或指定 namespace
ctr -n k8s.io containers ls  # 必须指定 namespace
txt 复制代码
//输出样例:
# ctr -n k8s.io containers ls
CONTAINER                                                           IMAGE                                                                      RUNTIME                  
0ee4af3caa539bf95183f4673f5b446f7fab60dd8b874ac04a24b1ca3f493ad0    registry.aliyuncs.com/google_containers/kube-proxy:v1.28.0                 io.containerd.runc.v2    
1ae5d5574c03129ad668fa99c0a26f7611d5db3b15888ded91526029da73ac31    registry.aliyuncs.com/google_containers/pause:3.9                          io.containerd.runc.v2    
1c4d94a7ea153a2eb4ef97a169030f5587d2e46f3c9d788a88de5fca43244e8e    docker.io/calico/node:v3.26.1                                              io.containerd.runc.v2    
250db62567abf1ca43e27fe0ab641e8d27f859ade71e548dc1c47c1ef2699682    registry.aliyuncs.com/google_containers/pause:3.9                          io.containerd.runc.v2    
...

配置文件: /etc/crictl.yaml

  • 为避免每次执行crictl命令时都需要带上--runtime-endpoint参数,例如: crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock images,则可通过配置来设置:
shell 复制代码
cat <<EOF > /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

如果既不配置该文件,也不在命令中带上 endpoint 参数,则会报类似错误:transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory

使用建议

场景 推荐工具
Kubernetes 日常运维、Pod 调试 crictl
学习 CRI 接口、跨运行时操作 crictl
containerd 底层原理研究 ctr
镜像导入导出、快照管理 ctr
编写自动化脚本(不依赖 K8s) ctr

典型工作流程

bash 复制代码
# 场景:排查一个 CrashLoopBackOff 的 Pod

# 1. 找到节点上的 Pod ID
crictl pods --name problematic-pod

# 2. 查看容器状态
crictl ps -p <pod-id> --all  # 查看历史容器

# 3. 查看上次退出日志
crictl logs --previous <container-id>

# 4. 进入容器调试
crictl runp <pod-config.json>  # 手动启动 Pod 调试

crictlKubernetes 运维人员 的必备工具,它屏蔽了底层运行时(CRI) 的差异,提供了与 kubectl 一致的运维体验。而 ctr 更适合需要深入理解 containerd 架构的底层开发者。

2 FAQ for K8s 日常使用-镜像篇

Q: 配置镜像加速器?

Docker

Docker 默认配置文件路径是 /etc/docker/daemon.json

阿里云-镜像仓库

  • 可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

需登录 阿里云的 容器镜像服务 获取属于自己的镜像地址。

shell 复制代码
//Linux(Ubuntu / CENTOS)

//配置 daemon.json#registry-mirrors
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://umxxx98d.mirror.aliyuncs.com"]
}
EOF

// 重启 docker 服务进程
sudo systemctl daemon-reload
sudo systemctl restart docker

registry-mirrors = [ "https://registry.cn-hangzhou.aliyuncs.com" ]
注意1:阿里云镜像加速器不一定包含所有 Docker Hub 镜像,特别是较新的或小众的镜像。

注意2:403 Forbidden 错误是因为 阿里云镜像加速器已关闭匿名访问权限 。从 2024 年开始,阿里云调整了镜像加速器功能仅限 【阿里云用户】在【具备公网访问能力】的相关阿里云云产品资源 上使用,并且只支持拉取限定范围内的容器镜像 。会出现类似错误:(详情参见: https://help.aliyun.com/zh/acr/product-overview/product-change-acr-mirror-accelerator-function-adjustment-announcement)

复制代码
[root@vm-a ~]# kubectl describe pod local-path-provisioner-844bd8758f-mvgr9 -n local-path-storage
Events:
Type     Reason   Age                      From     Message
----     ------   ----                     ----     -------
Normal   BackOff  9m16s (x708 over 3h31m)  kubelet  Back-off pulling image "rancher/local-path-provisioner:v0.0.24"
Warning  Failed   4m13s (x37 over 3h31m)   kubelet  Failed to pull image "rancher/local-path-provisioner:v0.0.24": failed to pull and unpack image "docker.io/rancher/local-path-provisioner:v0.0.24": failed to resolve reference "docker.io/rancher/local-path-provisioner:v0.0.24": unexpected status from HEAD request to https://umxxx98d.mirror.aliyuncs.com/v2/rancher/local-path-provisioner/manifests/v0.0.24?ns=docker.io:  403 Forbidden
  • 配置完镜像加速器后,即可拉取 docker 镜像
shell 复制代码
docker pull nginx:latest

m.daocloud.io 等其他镜像仓库

  • 如果阿里云镜像仍不可用,使用其他国内源

方式1:直接基于第三方源拉取镜像

shell 复制代码
//拉取镜像
# docker pull m.daocloud.io/docker.io/calico/cni:v3.26.1
# docker pull m.daocloud.io/docker.io/calico/node:v3.26.1
# docker pull m.daocloud.io/docker.io/calico/kube-controllers:v3.26.1

//重新打标签为原始路径(这样 Kubernetes 能识别)
# docker tag m.daocloud.io/docker.io/calico/cni:v3.26.1 docker.io/calico/cni:v3.26.1
# docker tag m.daocloud.io/docker.io/calico/node:v3.26.1 docker.io/calico/node:v3.26.1
# docker tag m.daocloud.io/docker.io/calico/kube-controllers:v3.26.1 docker.io/calico/kube-controllers:v3.26.1

//查看镜像
# docker images
REPOSITORY                                        TAG       IMAGE ID       CREATED       SIZE
calico/kube-controllers                           v3.26.1   1919f2787fa7   2 years ago   75.1MB
m.daocloud.io/docker.io/calico/kube-controllers   v3.26.1   1919f2787fa7   2 years ago   75.1MB
calico/cni                                        v3.26.1   9dee260ef7f5   2 years ago   210MB
m.daocloud.io/docker.io/calico/cni                v3.26.1   9dee260ef7f5   2 years ago   210MB
m.daocloud.io/docker.io/calico/node               v3.26.1   8065b798a4d6   2 years ago   246MB
calico/node                                       v3.26.1   8065b798a4d6   2 years ago   246MB
  • 方式2:配置 /etc/docker/daemon.json
shell 复制代码
//Linux(Ubuntu / CENTOS)

//配置 daemon.json#registry-mirrors
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://docker.m.daocloud.io"]
}
EOF

// 重启 docker 服务进程
sudo systemctl daemon-reload
sudo systemctl restart docker

K8s 的 Containerd

Containerd 默认配置文件路径是 /etc/containerd/config.toml

shell 复制代码
rm -rf /etc/containerd/config.toml
 
//修改 containerd 配置,添加镜像加速:
//  1) 基于默认配置之上,编辑 containerd 配置
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
 
//修改 /etc/containerd/config.toml :
  ...
  [plugins."io.containerd.grpc.v1.cri"]
    # 修改: 1行配置
    # sandbox_image = "registry.k8s.io/pause:3.6"
    sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
 
    [plugins."io.containerd.grpc.v1.cri".registry]
      ...
      # 新增:3+2行配置(不含注释行或空行)
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          # 阿里云镜像加速获取 from https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
          endpoint = ["https://umxxx98d.mirror.aliyuncs.com","https://docker.m.daocloud.io", "https://registry-1.docker.io"]

        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
          endpoint = ["https://registry.aliyuncs.com/google_containers", "https://k8s.m.daocloud.io"]
    ...
 
 
systemctl restart containerd
systemctl status containerd

curl -v https://umxxx98d.mirror.aliyuncs.com/v2/

Q: 查验镜像仓库?

shell 复制代码
# docker info | grep -A 10 "Registry Mirrors"
 Registry Mirrors:
  https://umxxx98d.mirror.aliyuncs.com/
 Live Restore Enabled: false

Q: 验证加速器/镜像仓库是否真的可用?

shell 复制代码
# 测试阿里云镜像连通性
curl -I https://umxxx98d.mirror.aliyuncs.com/v2/

# 尝试拉取一个常见镜像测试
docker pull nginx:latest

Q: 向指定镜像仓库中拉取镜像?

  • case:calico/cni
shell 复制代码
docker pull m.daocloud.io/docker.io/calico/cni:v3.26.1
# 新增镜像标签
docker tag m.daocloud.io/docker.io/calico/cni:v3.26.1 docker.io/calico/cni:v3.26.1
  • case : minio/minio
shell 复制代码
docker pull quay.io/minio/minio:RELEASE.2024-05-28T17-19-04Z
# 新增镜像标签
docker tag quay.io/minio/minio:RELEASE.2024-05-28T17-19-04Z minio/minio:RELEASE.2024-05-28T17-19-04Z
  • case : milvusdb/milvus
shell 复制代码
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/milvusdb/milvus:v2.5.21
# 新增镜像标签
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/milvusdb/milvus:v2.5.21 docker.io/milvusdb/milvus:v2.5.21

Q: 登录阿里云镜像服务?

shell 复制代码
[root@vm-a ~]# sudo docker login --username=xxx@qq.com crpi-tnk462xxx9q8ghps.cn-chengdu.personal.cr.aliyuncs.com
Password: 
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded


//如果已过期,先登出再重新登录
# docker logout crpi-tnk462xxx9q8ghps.cn-chengdu.personal.cr.aliyuncs.com
# docker login crpi-tnk462xxx9q8ghps.cn-chengdu.personal.cr.aliyuncs.com

[root@vm-a ~]# cat ~/.docker/config.json
{
	"auths": {
		"crpi-tnk462xxx9q8ghps.cn-chengdu.personal.cr.aliyuncs.com": {
			"auth": "MTEyNTQxODU0MExxxxxxxYWx5I2pueSMyMjMwIQ=="
		}
	}
}

docker pull crpi-tnk462xxx9q8ghps.cn-chengdu.personal.cr.aliyuncs.com/calico/cni:v3.26.1


[root@vm-a ~]# docker pull calico/cni:v3.26.1
Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp 108.160.166.9:443: i/o timeout

Q: 为何在 containerd 的 /etc/containerd/config.toml 中配置如下镜像仓库并有重启 containerd,但 k8s containerd 拉取镜像(ctr -n k8s.io images pull docker.io/library/mysql:8.0)时还是从 docker.io 拉取镜像?

问题描述

为何在 containerd (1.6.x) 的 /etc/containerd/config.toml 中配置如下镜像仓库并有重启 containerd,但 k8s containerd 拉取镜像(ctr -n k8s.io images pull docker.io/library/mysql:8.0)时还是从 docker.io 拉取镜像?

shell 复制代码
/etc/containerd/config.toml
    [plugins."io.containerd.grpc.v1.cri".registry]
      config_path = ""
      //... 略
	  
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          # 阿里云镜像加速获取 from https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
          endpoint = ["https://docker.m.daocloud.io"]

        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
          endpoint = ["https://k8s.m.daocloud.io"]

原因分析

这是一个非常经典的"配置过期"问题。简单来说,你使用的配置语法属于 CRI 1.x (Legacy) 版本,而较新版本的 Containerd (通常是 v1.5+,尤其是 v2.0+)已经弃用 了这种直接在 config.toml 中写 mirrors 的方式,转而推荐使用 Registry Configuration Path
此外,你的测试指令 ctr 也有点"坑",下面开始详细排查。

解决方法

1. 核心原因:配置方式已变更

Containerd 现在的推荐做法是开启 config_path。如果你在配置文件中看到了 config_path = "",那么你写的 [plugins."io.containerd.grpc.v1.cri".registry.mirrors] 很大大概率被忽略了。

推荐的修复方案:
  1. 修改 config.toml : 定位到 [plugins."io.containerd.grpc.v1.cri".registry],将其修改为:

    toml 复制代码
    [plugins."io.containerd.grpc.v1.cri".registry]
      config_path = "/etc/containerd/certs.d"

    注意:此时请删除你之前写的 [plugins...mirrors] 那一整段旧配置,避免冲突。

  2. 创建镜像目录结构 : 你需要为每个 Registry 创建对应的目录,并在其中创建 hosts.toml

    复制代码
    # 为 docker.io 创建配置
    mkdir -p /etc/containerd/certs.d/docker.io
    
    # 写入加速器地址
    cat <<EOF > /etc/containerd/certs.d/docker.io/hosts.toml
    server = "https://docker.io"
    
    [host."https://docker.m.daocloud.io"]
      capabilities = ["pull", "resolve"]
    EOF
  3. 重启 Containerdsystemctl restart containerd

2. 测试工具的陷阱:ctr vs crictl

这是很多开发者最容易忽略的一点:ctr 指令是不走 CRI 配置的。

  • ctr :是 Containerd 的原生 CLI,它设计得很底层,完全无视 [plugins."io.containerd.grpc.v1.cri"] 下的配置(因为它不经过 CRI 插件)。
  • crictl:是专门为 Kubernetes 交互设计的工具,它会严格遵循 CRI 配置。
正确的测试指令:

如果你想验证 K8s 镜像加速是否生效,请使用 crictl

复制代码
# 确保 /etc/crictl.yaml 已配置 runtime-endpoint
crictl pull docker.io/library/mysql:8.0
或 crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock pull docker.io/library/mysql:8.0

3. 检查 Sandbox 镜像(Pause 镜像)

如果你的 K8s 集群在启动时卡在 registry.k8s.io/pause,即使你配置了镜像加速,有时也会失效。这是因为 sandbox_image 通常是在 config.toml 中硬编码的。

检查 config.toml 中这一行:

复制代码
sandbox_image = "registry.k8s.io/pause:3.9"

建议直接将其修改为加速后的地址(如 k8s.m.daocloud.io/pause:3.9),因为 Sandbox 镜像的拉取逻辑非常特殊。

总结建议

  1. 优先使用 config_path 模式,这是未来的标准。
  2. 放弃用 ctr 测试加速效果 ,改用 crictl 或直接在 K8s 中部署一个 Pod 观察。
  3. 检查版本 :如果你的 Containerd 版本非常老(< 1.5),旧语法可能生效,但必须确保没有 config_path 的干扰。如果是 1.7 或 2.0,建议立即采用第一种 certs.d 的方案。

Q: crictl 拉取镜像时报:transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory

问题描述

crictl 拉取镜像时报:transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory

shell 复制代码
[root@vm-a k8s-deployments]# crictl pull docker.io/library/mysql:8.0

WARN[0000] image connect using default endpoints: [unix:///var/run/dockershim.sock unix:///run/containerd/containerd.sock unix:///run/crio/crio.sock unix:///var/run/cri-dockerd.sock]. As the default settings are now deprecated, you should set the endpoint instead. 

E0419 16:58:05.774215   14389 remote_image.go:171] "PullImage from image service failed" err="rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory\"" image="docker.io/library/mysql:8.0"

FATA[0000] pulling image: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial unix /var/run/dockershim.sock: connect: no such file or directory" 

看报错信息,这其实不是你的镜像加速配置没生效,而是 crictl 工具本身的配置不对

报错显示 crictl 正在尝试连接 /var/run/dockershim.sock。这是旧版本 Docker 的接口 ,而你目前使用的是纯 Containerd 环境 。由于找不到这个接口,crictl 直接报错退出了,根本还没运行到"拉取镜像"那一步。

1. 修复 crictl 配置

你需要告诉 crictl 去哪里找 Containerd。请执行以下命令:

shell 复制代码
cat <<EOF > /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

设置完成后,再次尝试拉取:

Bash

复制代码
crictl pull docker.io/library/mysql:8.0

2. 如何确认加速真的生效了?

因为 crictl 的输出比较简洁,你看不到具体的下载流。为了验证它确实走了 daocloud 的加速器,你可以查看 Containerd 的实时日志:

  1. 打开一个新终端,运行监控日志命令:

    Bash

    复制代码
    journalctl -u containerd -f
  2. 在原终端执行拉取

    Bash

    复制代码
    crictl pull docker.io/library/mysql:8.0
  3. 观察日志

    如果配置成功,你在日志中会看到类似 resolvingtrying to pull... 的记录,其中会包含 docker.m.daocloud.io 这个域名。


3. 常见"暗坑"排查

如果你配置了 certs.d 路径但依然无效,请检查以下两点:

  • 配置文件的位置 :确认你的 config.toml 是在 /etc/containerd/config.toml
  • 配置是否冲突 :打开 /etc/containerd/config.toml,搜索 [plugins."io.containerd.grpc.v1.cri".registry]
    • 必须有config_path = "/etc/containerd/certs.d"
    • 不能有mirrorsconfigs 的具体子项(如果有,请全部删掉或注释掉,因为 config_path 开启后,旧的内联配置会被忽略)。

4. 深度验证方案 (如果 crictl 还是拉不动)

如果日志里显示还在连接 registry-1.docker.io,请检查你的 hosts.toml 内容。注意: 目录名必须是 docker.io(对应镜像库的主机名)。

Bash

复制代码
# 检查一下你的目录结构是否完全一致:
ls -R /etc/containerd/certs.d/

输出应该是:

Plaintext

复制代码
/etc/containerd/certs.d/:
docker.io

/etc/containerd/certs.d/docker.io:
hosts.toml

修复完 crictl 的 Endpoint 报错后,拉取测试应该就能跑通了。还有其他报错吗?

3 FAQ for K8s 日常使用-其他

Q: Docker 环境预检?

shell 复制代码
#!/bin/bash
# Docker 环境预检脚本

echo "=== Docker 基本信息 ==="
docker info | grep -E "Server Version|Storage Driver|Kernel Version"
# out samples:
# Server Version: 26.1.4
# Storage Driver: overlay2
# Kernel Version: 3.10.0-1160.el7.x86_64

docker info | grep -A 10 "Registry Mirrors"
# out samples:
# Registry Mirrors:
#  https://umxxx98d.mirror.aliyuncs.com/
# Live Restore Enabled: false

echo "=== 资源使用情况 ==="
docker info | grep -E "Containers|Images|CPUs|Total Memory"
# out samples:
# Containers: 0
# Images: 3
# CPUs: 4
# Total Memory: 7.526GiB

echo "=== 安全配置检查 ==="
docker info | grep -A5 "Security Options"
# out samples:
# Security Options:
#  seccomp
#   Profile: builtin
# Kernel Version: 3.10.0-1160.el7.x86_64
# Operating System: CentOS Linux 7 (Core)
# OSType: linux

echo "=== 存储检查 ==="
docker info | grep -A3 "Docker Root Dir"
# out samples:
#  Docker Root Dir: /var/lib/docker
# Debug Mode: false
# Experimental: false
# Insecure Registries:
df -h $(docker info | grep "Docker Root Dir" | cut -d: -f2)
# out samples:
# Filesystem                     Size  Used Avail Use% Mounted on
# /dev/mapper/centos_vm--a-root   15G  7.3G  7.8G  49% /

Q: 重启 docker 服务进程?

shell 复制代码
//方法1
sudo systemctl daemon-reload
sudo systemctl restart docker

//方法2
# sudo systemctl stop docker.service
Warning: Stopping docker.service, but it can still be activated by:
  docker.socket
# sudo systemctl stop docker.socket
# sudo systemctl daemon-reload
# sudo systemctl start docker.socket
# sudo systemctl start docker.service

Y 推荐文献

X 参考文献

相关推荐
千千寰宇1 年前
[虚拟化/云原生] Kubernetes 安装部署指南
docker/k8s/虚拟化/容器化
千千寰宇1 年前
[虚拟化/Docker] Docker Desktop 安装与使用
docker/k8s/虚拟化/容器化
千千寰宇1 年前
[操作系统] 计算机资源虚拟化技术
操作系统·docker/k8s/虚拟化/容器化