0 序
- 在完成K8s集群部署之后,就是研发或运维人员对K8s集群的日常使用问题了,本篇对过去几年笔者对K8s集群核心组件、及其命令行工具的总结。
- [虚拟化] K8S概述 - 博客园/千千寰宇
- Kubernetes 安装部署指南 - 博客园/千千寰宇
- Kubernetes 安装部署指南(V2) - 博客园/千千寰宇
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 秒,也可以使用参数进行配置。
参考文献
- kubelet - kubernetes
- 一文看懂 Kubelet - Zhihu
Kubeadm : k8s 部署工具
组件简介
Kubeadm是一个提供了kubeadm init和kubeadm join的工具, 作为创建Kubernetes集群的 “快捷途径” 的最佳实践。kubeadm通过执行必要的操作来启动和运行最小可用集群。
按照设计,它只关注启动引导,而非配置机器。
同样的, 安装各种 “锦上添花” 的扩展,例如 Kubernetes Dashboard、 监控方案、以及特定云平台的扩展,都不在讨论范围内。
相反,k8s官方希望在kubeadm之上构建更高级别以及更加合规的工具, 理想情况下,使用kubeadm作为所有部署工作的基准将会更加易于创建一致性集群。
常用命令
kubeadm init用于搭建控制平面节点kubeadm join用于搭建工作节点并将其加入到集群中
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 使用的令牌
# 在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用于预览一组可用于收集社区反馈的特性
参考文献
- Kubeadm - kubernetes
Kubectl : k8s 命令行工具
组件简介
Kubernetes提供kubectl是使用Kubernetes API与Kubernetes集群的控制面板进行通信的【命令行工具】。
这个工具叫做
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 |
语法格式
$ kubectl [command] [TYPE] [NAME] [flags]
(1)command:子命令,指定要对一个或多个资源执行的操作。例如create、delete、describe、get、apply等。
(2)TYPE:资源对象的类型,不区分大小写,能以单数形式、复数形式或者简写形式表示。例如:以下3种TYPE是等价的。
$ 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的组合表示,示例如下。
$ 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的更多信息
$ kubectl get pod <pod-name> -o wide
或
$ kubectl get pod <pod-name> --namespace <namespace> -o wide
- 以yaml格式显示Pod的详细信息
$ kubectl get pod <pod-name> -o yaml
- 以自定义列名显示Pod的信息
$ kubectl get pod <pod-name> -o=custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion
- 基于文件的自定义列名输出
$ kubectl get pods <pod-name> -o=custom-columns-file=template.txt
- 还可以将输出结果按某个字段排序,通过--sort-by参数以jsonpath表达式进行指定
$ kubectl [command] [TYPE] [NAME] --sort-by=<jsonpath_exp>
例如,按照名字进行排序
$ 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
$ kubectl create -f my-service.yaml -f my-rc.yaml
- 根据
<directory>目录下所有.yaml、.yml、.json文件的定义进行创建操作
$ kubectl create -f <directory>
kubectl apply : 以文件或标准输入为准应用或更新资源
# 使用 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: 编辑指定资源
kubectl edit <资源类型> <资源名称> -n <命名空间># 示例:编辑名为 "nginx" 的 Deployment
kubectl edit deployment nginx -n defaultkubectl edit daemonset -n kube-system kube-proxy
- 方式2: 通过文件格式指定资源
# 编辑指定 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,可通过环境变量切换编辑器:
# 使用 nano 编辑器
export KUBE_EDITOR="nano"
kubectl edit deploy/nginx# 临时指定编辑器(无需修改环境变量)
KUBE_EDITOR="code --wait" kubectl edit deploy/nginx # 使用 VS Code
- 编辑特定资源版本
# 显示资源版本、并指定版本编辑
kubectl get deploy nginx -o yaml | grep resourceVersion # 获取当前版本
kubectl edit deploy/nginx --resource-version=<版本号>
- 编辑多个资源
结合标签选择器批量操作
# 编辑所有包含 "app=web" 标签的 Pod
kubectl edit pods -l app=web -n default
- 快速定位字段
在编辑器中直接搜索关键字(如 replicas、image),快速修改核心参数。
- 常见使用场景
- 实时调整副本数
kubectl edit deploy/nginx
# 修改 replicas 字段 → 保存退出后立即生效
- 更新容器镜像
kubectl edit deploy/nginx
# 修改 spec.template.spec.containers[0].image → 保存退出
- 修改 ConfigMap/Secret
# 编辑 ConfigMap
kubectl edit cm app-config -n default# 编辑 Secret(注意:Base64 编码值需自行处理)
kubectl edit secret db-credentials -n default
- 调试资源限制
kubectl edit deploy/nginx
# 调整 resources.limits 和 resources.requests → 保存退出
- 注意事项
- 并发修改冲突
若资源被其他用户或控制器修改,提交时会提示版本冲突(需重新拉取最新版本后编辑)。
- 格式校验严格
YAML 格式错误(如缩进错误、键名错误)会导致提交失败,需仔细检查。
- 生产环境谨慎使用
直接修改运行中的资源可能引发服务中断,建议在测试环境验证后再操作。
- 备份原始配置
重要操作前备份当前配置:
kubectl get deploy/nginx -o yaml > nginx-backup.yaml
- FAQ / 常见问题排查
- 错误:Edit cancelled, no changes made
原因:编辑器未正确保存修改(如直接关闭未保存)。
解决:重新执行命令并确保保存修改。
- 错误:invalid configuration
原因:YAML 格式或字段值不合法。
解决:
# 关闭验证后强制提交(不推荐)
kubectl edit deploy/nginx --validate=false
- 错误:the object has been modified
原因:资源版本过期(其他人已修改过)。
解决:重新执行 kubectl edit 获取最新版本。
- 替代方案
| 场景 | 替代命令 | 说明 |
|---|---|---|
| 少量字段修改 | kubectl patch | 无需进入编辑器,直接通过 JSON 或 YAML 片段修改 |
| 批量修改 | kubectl apply -f updated.yaml | 通过文件更新配置 |
| 查看历史修改记录 | kubectl rollout history | 查看 Deployment 等资源的修订历史 |
- 参考文献
- kubectl系列(九):kubectl edit命令 - CSDN
kubectl get : 列出一个或多个资源(pod/rc/service/ds)
# 获取集群所有的节点
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
kubectl get pod pod1
kubectl get pods pod1
kubectl get po pod1
- 按命名空间查询pod
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 等)
[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
[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
[root@k8s-master-1 ~]# kubectl get pods -n kube-system | grep ContainerCreating | awk '{print $1}' | xargs
kube-proxy-c7vf9
kubectl delete : 删除资源对象
# 删除所有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个容器执行
$ kubectl exec <pod-name> date
- 指定Pod中某个容器执行date命令
$ kubectl exec <pod-name> -c <container-name> date
- 通过bash获得Pod中某个容器的TTY、在Pod 的容器内进行调试,相当于登陆容器 <remark=IMPORTANT>
$ 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 : 显示一个或多个资源的详细状态,默认情况下包括未初始化的资源
# 显示名为 <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 中容器的日志
# 返回 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(最常用)
kubectl describe pod <pod-name> -n <namespace>
输出中会显示 Containers 部分,列出所有容器名称、镜像、状态等信息。
输出示例:
$ kubectl describe pod nginx-deployment-abc123Name: nginx-deployment-abc123
Namespace: default
...
Containers:nginx: ← 容器1名称Image: nginx:1.21Port: 80/TCPState: Running...sidecar: ← 容器2名称(如果有)Image: busybox:latest...
Init Containers: ← Init 容器(如果有)init-myservice:Image: busybox:1.28
1. crictl ps -p <pod-id> (最常用)
# 查看指定 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(详细信息)
# 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 自定义输出(简洁查看)
# 只显示容器名称列表
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 插件/工具
# 使用 kubectl-view-allocations 等插件
# 或结合 grep
kubectl describe pod <pod-name> | grep -A 20 "Containers:"
Init 容器 vs 普通容器
| 类型 | 查看方式 |
|---|---|
| 普通容器 | .spec.containers |
| Init 容器 | .spec.initContainers |
| Ephemeral 容器 | .spec.ephemeralContainers |
# 查看 Init 容器
kubectl get pod <pod-name> -o jsonpath='{range .spec.initContainers[*]}{.name}{"\n"}{end}'
快速命令别名(可选)
添加到 .bashrc 或 .zshrc:
# 查看 Pod 容器列表
alias kpc='kubectl get pod -o jsonpath="{range .spec.containers[*]}{.name}{\"\n\"}{end}"'# 使用:kpc <pod-name>
这些命令适用于任何 Kubernetes 集群,无需额外工具。
参考文献
- Kubectl - kubernetes
- [云原生] K9S:与 Kubernetes 集群交互的开源终端 UI - 博客园/千千寰宇
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 作为默认命名空间。
# 查看所有命名空间
ctr ns ls# 指定命名空间操作(默认是 default)
ctr -n k8s.io containers ls
ctr -n default images ls
2. 容器(Containers)
# 列出容器(注意:这是 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。
# 查看运行中的任务
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)
# 列出镜像
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)—— 文件系统层
# 查看快照
ctr snapshots ls# 查看快照信息(挂载点、层信息)
ctr snapshots info <snapshot-key>
ctr中镜像、容器、任务、快照的概念与关系?
- ctr 核心概念关系图
- 四层结构速查
| 层级 | 本质 | 生命周期 | 类比 |
|---|---|---|---|
| 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)
# 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 底层问题
# 进入节点,查看 containerd 层面
ctr -n k8s.io tasks ls | grep <pod-id># 对比 crictl(更直观)
crictl ps -p <pod-id> # 直接看到 Pod 关联的容器
场景 3:镜像导入导出(离线传输) : 导出指定节点的 containerd 镜像,并导入到另一节点
核心思路:
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 镜像
# 保存镜像为 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 节点 (可选)
# 方式1: 直接 scp 到目标节点
scp myimage.tar.gz user@k8s-node:/tmp/# 方式2: 如果节点无法直接访问,通过跳板机或共享存储
- step3 导入到 k8s 的 containerd
在 Kubernetes 节点上执行:
# 解压(如果是 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; doctr -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 │
└─────────────────────────────────────┘
配置文件、调试
# 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. 基础信息查询
# 查看运行时版本信息
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 操作
# 查看所有 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. 容器操作
# 查看运行中的容器
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. 镜像操作
# 拉取镜像
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. 实用调试技巧
# 结合 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 概念支持
# 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. 配置方式
# 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
//输出样例: # 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,则可通过配置来设置:
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 |
典型工作流程
# 场景:排查一个 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 调试
crictl是 Kubernetes 运维人员的必备工具,它屏蔽了底层运行时(CRI)的差异,提供了与 kubectl 一致的运维体验。而ctr更适合需要深入理解 containerd 架构的底层开发者。
2 FAQ for K8s 日常使用-镜像篇
Q: 配置镜像加速器?
Docker
Docker 默认配置文件路径是
/etc/docker/daemon.json
阿里云-镜像仓库
- 可以通过修改daemon配置文件
/etc/docker/daemon.json来使用加速器
需登录 阿里云的 容器镜像服务 获取属于自己的镜像地址。
//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 镜像
docker pull nginx:latest
m.daocloud.io 等其他镜像仓库
- 如果阿里云镜像仍不可用,使用其他国内源
方式1:直接基于第三方源拉取镜像
//拉取镜像
# 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
//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
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/mirrorsendpoint = ["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: 查验镜像仓库?
# docker info | grep -A 10 "Registry Mirrors"Registry Mirrors:https://umxxx98d.mirror.aliyuncs.com/Live Restore Enabled: false
Q: 验证加速器/镜像仓库是否真的可用?
# 测试阿里云镜像连通性
curl -I https://umxxx98d.mirror.aliyuncs.com/v2/# 尝试拉取一个常见镜像测试
docker pull nginx:latest
Q: 向指定镜像仓库中拉取镜像?
- case:
calico/cni
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
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
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: 登录阿里云镜像服务?
[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-storeLogin 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 拉取镜像?
/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/mirrorsendpoint = ["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] 很大大概率被忽略了。
推荐的修复方案:
-
修改
config.toml: 定位到[plugins."io.containerd.grpc.v1.cri".registry],将其修改为:[plugins."io.containerd.grpc.v1.cri".registry]config_path = "/etc/containerd/certs.d"注意:此时请删除你之前写的
[plugins...mirrors]那一整段旧配置,避免冲突。 -
创建镜像目录结构: 你需要为每个 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 -
重启 Containerd:
systemctl 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 镜像的拉取逻辑非常特殊。
总结建议
- 优先使用
config_path模式,这是未来的标准。 - 放弃用
ctr测试加速效果,改用crictl或直接在 K8s 中部署一个 Pod 观察。 - 检查版本:如果你的 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
[root@vm-a k8s-deployments]# crictl pull docker.io/library/mysql:8.0WARN[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。请执行以下命令:
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 的实时日志:
-
打开一个新终端,运行监控日志命令:
Bash
journalctl -u containerd -f -
在原终端执行拉取:
Bash
crictl pull docker.io/library/mysql:8.0 -
观察日志:
如果配置成功,你在日志中会看到类似
resolving或trying 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" - 不能有:
mirrors或configs的具体子项(如果有,请全部删掉或注释掉,因为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 环境预检?
#!/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_64docker info | grep -A 10 "Registry Mirrors"
# out samples:
# Registry Mirrors:
# https://umxxx98d.mirror.aliyuncs.com/
# Live Restore Enabled: falseecho "=== 资源使用情况 ==="
docker info | grep -E "Containers|Images|CPUs|Total Memory"
# out samples:
# Containers: 0
# Images: 3
# CPUs: 4
# Total Memory: 7.526GiBecho "=== 安全配置检查 ==="
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: linuxecho "=== 存储检查 ==="
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 服务进程?
//方法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 推荐文献
-
[Docker] Docker 基础教程(概念/原理/基础操作) - 博客园/千千寰宇
-
[虚拟化] K8S概述 - 博客园/千千寰宇
-
Kubernetes 安装部署指南 - 博客园/千千寰宇
-
Kubernetes 安装部署指南(V2) - 博客园/千千寰宇
