☰
kubectl 实战指南:从入门到故障排查的常用命令详解
2026/10/20 0:31:26 网站建设 项目流程

1. 环境准备与基本配置

1.1 从零开始:安装 kubectl 与版本匹配

先聊点实在的。kubectl 是 Kubernetes 的 CLI 客户端,所有对集群的操作本质上都是通过它发起请求,由 API Server 完成鉴权和资源调度。也就是说,你敲的每一条 kubectl 命令,最后都会转化为 REST API 调用。这个机制理解透了,后面遇到"命令能跑但没生效"的问题,你就知道该往哪个方向查。

安装方式直接按官方文档来就好,Linux/macOS 用 curl 下载二进制,Windows 用 choco 或者直接下载 exe。但我有一件事必须强调:kubectl 版本和集群版本的差异不能太大。官方支持的范围是一个小版本内的差异,比如 kubectl 1.28 可以管理 1.27 和 1.29 的集群。如果你用太老的客户端对接新集群,APIServer 返回的字段这个老版本不认,大概率会报错或字段解析失败;反过来,客户端版本太新,也可能出现服务端不兼容的情况。

# 查看 kubectl 客户端版本 kubectl version --client # 查看客户端和服务端版本 kubectl version

这里有个细节值得注意,kubectl version不加--client时会同时请求服务端,如果你没有集群 kubeconfig 权限,命令会卡在那里等你输入密码或者直接超时。所以排查网络问题时,记得区分客户端版本和服务端版本,不要一看报错就以为是集群挂了。

1.2 kubeconfig:多集群切换的命脉

很多新手最大的困惑在于:为什么我在服务器上执行 kubectl 命令,操作的却不是我以为的那个集群?答案就在 kubeconfig 文件的上下文(context)上。

kubeconfig 默认路径是~/.kube/config,也可以临时通过环境变量指定:

export KUBECONFIG=/path/to/my/config

kubeconfig 的核心结构是三个组合:cluster(集群地址+CA)、user(客户端证书/token)、context(cluster+user+namespace 的组合映射)。日常多集群运维时,我强烈建议用kubectl config系列命令管理,而不是手动改配置文件。

# 查看当前的配置 kubectl config view # 查看所有上下文 kubectl config get-contexts # 切换上下文 kubectl config use-context prod-cluster

一个实战习惯:把生产环境和测试环境的 context 名称区分得非常明确,比如prod-all、dev-namespace1。我见过太多人把测试环境命令直接怼到生产环境却没意识到。在use-context之后,第一时间执行kubectl config current-context确认,这句话能救你无数次。

kubectl config current-context

2. 资源查询命令全集

2.1 get 命令的花式用法

kubectl get是使用率最高的命令,但很多人只停留在kubectl get pods这个层间。实际上它有非常多的参数组合,用好了能大幅提升你的排查效率。

先看最常规的:

# 查看所有 namespace 的 pod kubectl get pods -A # 查看指定 namespace kubectl get pods -n kube-system # 同时查看多种资源 kubectl get pod,service,deployment -n default

-o wide是你排查网络问题时第一眼看的东西。它会额外输出 Pod IP、所在节点、命名空间等关键信息:

kubectl get pods -o wide

再进阶一点,按标签筛选资源(label selector)是生产环境最常用的定位手段。比如分布式应用的前端 Pod 都打了app=frontend标签,你想要看完整的实例列表:

kubectl get pods -l app=frontend -A

还可以用-l组合多个条件,逗号表示 AND 关系:

kubectl get pods -l app=frontend,tier=front -n production

最后是--field-selector,这个参数很多人不熟悉,它允许你按照资源字段进行过滤,比如只看status.phase=Pending状态的 Pod:

kubectl get pods --field-selector=status.phase=Pending -A

--field-selector和-l是可以同时使用的。这个组合在排查"集群里为什么有一堆 Pending 状态的 Pod"时非常有用。

2.2 describe、logs、events 组合排查

get看的是资源的"现状摘要",而describe看的是资源对象的"详细信息",包括事件(Events)、标签、状态条件等。对于容器无法启动、镜像拉取失败、调度失败这类问题,describe提供的信息远比get丰富。

# 查看 Pod 详细状态 kubectl describe pod my-pod -n my-namespace # 查看节点信息,如资源分配、系统版本、磁盘压力等 kubectl describe node node-1

describe输出中最关键的是后面的 Events 部分。如果 Pod 一直卡在 ContainerCreating 状态,Events 里会直接告诉你 Volume 挂载失败、Secret 缺失或镜像拉取超时等具体原因。很多时候,光看事件就定位了问题,根本不需要进容器。

logs是查看容器输出的:

# 查看指定容器日志 kubectl logs my-pod -n default # 容器多实例时指定容器 kubectl logs my-pod -c my-container # 实时跟踪日志,类似 tail -f kubectl logs -f my-pod # 查看之前崩溃的容器日志(容器重启后日志会丢失) kubectl logs my-pod --previous

这里有一个常见的逻辑问题:--previous只能看上一次容器的日志。如果容器一直 CrashLoopBackOff,每次重启都产生新的日志,你想要对比崩溃前后的差异,就可以先用它捞上一次的。在容器反复崩溃时,我最常用的策略是先kubectl get pods确认 STATUS,再用describe看原因,最后用logs --previous瞄崩溃前的日志内容。这三个命令组合起来,能覆盖大多数工作负载故障。

3. 资源变更与删除操作

3.1 apply、edit、patch 如何取舍

资源创建和更新有几种方式,各有利弊。

kubectl apply是声明式 API 的标准用法,也是生产环境使用最多的方式。它的核心逻辑是"该资源期望的状态是什么",如果资源不存在就创建,存在则做差量更新。

kubectl apply -f deployment.yaml kubectl apply -f ./manifest-directory/ kubectl apply -f https://example.com/deploy.yaml

用-f加目录路径时,会自动读取目录下所有 YAML 文件,这个在批量部署时非常高效。但要注意:如果同一个目录下有两个文件描述了同一个 Deployment,后面的会覆盖前面的字段,容易造成混乱,我的习惯是一个目录只放同一套组件的文件。

kubectl edit在你需要临时手动调整线上资源时最顺手,它会打开默认编辑器,保存后自动执行更新:

kubectl edit deployment nginx-deployment -n default

但也要注意:edit是基于当前集群中的实际对象状态去改的,如果你手头有一个本地文件,而集群状态已经是改过的,直接用本地文件apply可能造成回滚。

kubectl patch精确修改单个字段时效率最高,不想要把整个 YAML 抄出来。比如把 Deployment 的副本数从 3 改成 5:

kubectl patch deployment nginx-deployment -n default -p '{"spec":{"replicas":5}}'

对于复杂嵌套字段的更新,patch 比 edit 更稳妥,因为它不会误动其他字段。但这种写法对 JSON 语法有要求,括号引号搞错了会直接报错。

3.2 delete 与 ConfigMap 删除的特殊注意事项

删除操作是"高危"操作,生产环境最好加上-n指定命名空间。一个不小心把整个 namespace 删了,里面所有资源全没了,没多少人会感激你。

# 删除单个资源 kubectl delete pod my-pod -n default # 删除多个资源 kubectl delete pod my-pod-1 my-pod-2 # 按标签批量删除 kubectl delete pods -l app=frontend # 删除 namespace 下所有特定类型的资源 kubectl delete deployment,svc -l app=frontend -n default

热搜词里有"kubectl 删除configmap"这个关键词,这里我专门展开说一下。ConfigMap 删除后,正在使用它的 Pod 不会立即感知,除非 Pod 被重新创建,否则容器内挂载的还是旧数据。也就是说,光删 ConfigMap 不重建 Pod,你的配置变更不会生效。

所以正确的操作顺序是:

# 1. 删除旧的 ConfigMap kubectl delete configmap my-config -n default # 2. 重新创建新的 ConfigMap kubectl create configmap my-config --from-file=config.yaml -n default # 3. 重启关联的 Deployment(滚动重启 Pod) kubectl rollout restart deployment my-app -n default

有些人会问:直接用kubectl rollout restart能解决 ConfigMap 更新不生效的问题吗?答案是不一定。因为 rollout restart 只是重新创建 Pod,它会重新读取 ConfigMap,但如果名字没变,内容变了,Pod 重启后会加载新数据;但如果整个 ConfigMap 已经被删除,而 Deployment 又引用了它,Pod 重启时反而会报 ConfigMap 找不到而挂起。

在实际操作中,我遇到过多次因为 ConfigMap 删了之后没有同步重建,导致 Pod 一直 ContainerCreating 的情况。教训就是:删除 ConfigMap 之前先确认哪些工作负载在引用它。

# 查看 deployment/statefulset 是否引用了我准备删的 configmap kubectl get deployment -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.template.spec.volumes[*].configMap.name}{"\n"}{end}'

这套 JSONPath 在博文后续部分还会展开讲,先用起来。

4. Pod 与集群故障排查实用命令

4.1 exec、port-forward、cp 的日常组合

进入容器内部排查问题,这是故障处理的必经之路。

# 进入容器交互式 shell kubectl exec -it my-pod -n default -- /bin/sh # 指定容器进入 kubectl exec -it my-pod -c my-container -n default -- /bin/bash # 执行单条命令,不进入交互 kubectl exec my-pod -n default -- ls /app

注意不同基础镜像里可用的 shell 不同:busybox 里只有sh,Ubuntu 镜像里可以bash。如果执行-- /bin/bash报 no such file,换成/bin/sh往往就能进入。

port-forward是把集群内服务映射到本地访问的调试利器。比如你本机没有集群内网的访问权限,但想调一下某个 Service 暴露的 API:

# 将本地 8080 端口映射到 Pod 的 80 端口 kubectl port-forward pod/my-pod 8080:80 # 将本地端口映射到 Service kubectl port-forward service/my-service 8080:80

port-forward的原理是建立一条到 API Server 的加密通道,由 API Server 转发到目标资源。这个特性在云端集群中特别有用,因为你的笔记本往往不在集群网络内。要注意它不是高性能通道,只适合临时调试。

文件拷贝方面,用kubectl cp:

# 从 Pod 拷贝到本地 kubectl cp default/my-pod:/var/log/app.log ./app.log # 从本地拷贝到 Pod kubectl cp ./config.yml default/my-pod:/app/config.yml

在实际排障中,这三个命令的组合使用频率极高:先用exec看进程状态,再用cp把日志拉出来分析,最后用port-forward联调。熟练了这组操作,基本能覆盖绝大多数应用层问题的定位。

4.2 节点与集群层的常用诊断

先把节点的资源情况摸清楚:

# 查看节点状态 kubectl get nodes # 查看节点详细信息和资源分配情况 kubectl describe node node-1 # 获取节点资源使用情况 kubectl top node # 获取 Pod 资源使用情况 kubectl top pod -n default

kubectl top依赖 metrics-server 插件,如果集群里没装,这条命令会报Metrics API not available。不装的话,也可以用describe node里的 Allocated resources 来估算,它显示的是 requests 和 limits 的分配量,而不是实时用量。

节点层面最常见的告警是磁盘压力或内存压力。此时查看节点日志基本不可能用 kubectl 直接看到,需要登录到节点本身去查 kubelet 的日志。但 kubectl 那边一般会通过 Events 先反馈出来:

kubectl get events --all-namespaces --sort-by=.lastTimestamp

这个命令会按时间倒序列出所有事件。注意--sort-by的字段是.lastTimestamp,如果你直接复制网上的某些写法,写成.metadata.creationTimestamp也勉强能行,但是事件更新的维度就不那么准确了。

4.3 高频故障速查表

根据自己的实操经验,我把过去两年里在群里被问烂的故障整理成了速查表。这张表可以贴在工位上,出了问题对着查,效率很高。

现象常见原因排查命令解决方案
Pod 一直 Pending节点资源不足、调度约束不满足kubectl describe pod <pod>看 Events扩容节点、调整 request/limit、检查 nodeSelector 与亲和性
ImagePullBackOff镜像名错误、仓库认证失败、镜像不存在kubectl describe pod <pod>看 Events先手动docker pull验证镜像是否存在,再检查 imagePullSecret
CrashLoopBackOff容器启动即退出、健康检查失败、环境变量缺失kubectl logs --previous看崩溃日志修启动命令、补全配置、移除错误的环境变量
ContainerCreating 很长时间存储卷挂载失败、Pull 镜像超时、ConfigMap/Secret 不存在kubectl describe pod <pod>看 Events检查 PVC/PV 状态、确认引用的 CM/Secret 是否存在
Pod 能创建但无法访问 Service 的 ClusterIPService selector 与 Pod label 不匹配kubectl describe endpoints <svc>对比 service.spec.selector 与 pod label,确保一致
Evicted节点内存/磁盘压力过大kubectl get pods --field-selector=status.phase=Failed -A清理节点资源、调整 requests/limits
节点 NotReadykubelet 停止心跳、网络分区间断kubectl describe node <node>查看 ConditionsSSH 登录节点,看 kubelet/Docker/Containerd 服务状态

这张表我每次培训新人都用,建议你也复制一份放进日常工作笔记。遇到故障先按表格对照,没有命中再上 describe 和 logs 去深挖。

5. 输出格式化与脚本化效率技巧

5.1 -o 参数穷举:json、yaml、jsonpath、wide

-o是 kubectl 最强大的输出参数之一,能不能玩转它,几乎决定了你离"普通用户"还是"资深运维"的差距。

# 以 YAML 输出资源清单,可另存为文件做备份 kubectl get deployment nginx -n default -o yaml # 以 JSON 输出,适合程序化处理 kubectl get pods -n default -o json # 只输出 Pod IP 列表 kubectl get pods -n default -o jsonpath='{.items[*].status.podIP}'

YAML 和 JSON 输出常用于将线上资源导出为备份文件,或者分析资源对象的嵌套字段。很多人在做资源迁移时,直接用-o yaml > backup.yaml导出,再在新集群里apply,这个操作简单但很实用。

jsonpath的使用场景更广泛,比如我只想看集群里所有 Pod 所在节点的分布:

kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}'

JSONPath 的语法和 jQuery 的选择器类似,{range .items[*]}是遍历,{"\n"}是换行。一开始用会有点绕,但熟练后你完全可以从 kubectl 输出中提取精确的信息,不用再 grep 一大堆文字。

5.2 custom-columns 自定义表格输出

custom-columns 允许你定义输出的列和字段,相当于自己设计一个"速览表"。我只想看到 Pod 的名字、IP、所在节点、运行时长:

kubectl get pods -n default -o custom-columns=POD:.metadata.name,IP:.status.podIP,NODE:.spec.nodeName,AGE:.metadata.creationTimestamp

这个功能在批量观察环境时非常好用,比如你同时管理几十个 namespace,想要一眼看出哪个 Pod 是 Running、哪个 CrashLoopBackOff:

kubectl get pods -A -o custom-columns='NS:.metadata.namespace,POD:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName'

和jsonpath相比,custom-columns 语法上的可读性更高,适合生成报表或巡检报告。我个人在高频巡检脚本里就是用它把数据拼到表格里,再配合邮件发送。

5.3 常用 alias 与脚本化批处理

单条命令再好用,天天敲一长串也累。这里分享一组我日常必备的 alias,建议直接写进~/.bashrc:

# 常用缩写 alias k='kubectl' alias kgp='kubectl get pods' alias kgpa='kubectl get pods -A' alias kdn='kubectl describe node' alias kdp='kubectl describe pod' alias kl='kubectl logs' alias kex='kubectl exec -it' alias kpf='kubectl port-forward' # 查看所有 ns 中报错/非 Running 的 pod alias kbad='kubectl get pods -A | grep -v Running | grep -v Completed' # 进入 Pod 的快捷方式 alias ksh='kubectl exec -it $(kubectl get pods -n default | grep Running | grep -v Completed | head -1) -- /bin/sh'

这些 alias 在短期会话中提升效率明显,但也不要过度依赖,因为换台机器或换账号就没了。我更推荐你掌握"长命令能理解"的能力,alias 只是加快手速。

脚本化方面,批量操作时用循环结构会很省事。比如要批量重启某个 namespace 下所有 Deployment:

for deploy in $(kubectl get deployment -n default -o name); do kubectl rollout restart $deploy -n default done

6. 线上操作时必须留意的几件事

6.1 小心 --force 和 --grace-period

kubectl delete默认会有优雅删除机制,会等容器内的进程收到 SIGTERM 后自己退出,默认宽限时间是 30 秒。有些命令教学里会让你加--force --grace-period=0强制删除。这个方法在某些场景确实有效,比如 Pod 卡在 Terminating 状态删不掉时。但千万不要在正常环境中随手就加。

强制删除意味着跳过优雅退出过程,直接告诉 API Server 立即清理 Pod。如果你的应用依赖优雅停机去做状态保存、连接池清理、注册中心反注册,那加了这个参数后,很容易出现数据不一致或连接残留的问题。我见过有人批量强制重启 Pod,结果线上服务间歇性不可用,最后排查发现就是这条命令的问题。

6.2 namespace 切分的习惯很重要

操作时永远先确认当前 Namespace:

kubectl get pods

如果你的 default namespace 没有资源,而实际资源都在prod-biz里,光看不带-n的输出会让你误以为集群空了。这是新手最容易犯的错。

给每条命令习惯性带上-n namespace,是我见过的所有"老司机"都遵循的共同习惯。不管多熟,都别省。

6.3 生产环境的删除操作先打草稿

关于删除操作,我的个人规矩是"先做成 dry-run":

kubectl delete deployment nginx -n default --dry-run=client

--dry-run=client只是模拟执行,不会真正发起删除请求。确认无误后,再执行真实的删除。

同样,创建资源也可以先--dry-run=client -o yaml来看最终生成的 YAML:

kubectl create deployment dry-demo --image=nginx --dry-run=client -o yaml

这一步能帮你验证集群的默认值、标签、字段修正等,避免直接 apply 后才发现字段值不符合预期。

7. 深入一点:kubectl 与 CRI/containerd 之间的调用链路

前面说了 kubectl 是客户端,那它和底层容器运行时之间到底是什么关系?很多人把"kubectl 命令"和"容器运行时操作"混为一谈,这里拆开讲。

整个调用关系可以这样理解:

kubectl→API Server→kubelet→CRI (Container Runtime Interface)→containerd→ 容器进程

kubectl 发出的所有 Pod 创建/删除/日志请求,都会先到达 API Server。API Server 通过 etcd 完成资源对象的持久化,随后把指令下发到对应节点上的 kubelet。kubelet 才是那个真正和容器运行时打交道的组件,它通过 CRI 接口(gRPC 协议)与 containerd 通信。

所以你在 kubectl 里执行kubectl exec -it pod -- /bin/sh,实际调用链是:

kubectl → API Server → kubelet → CRI → containerd → 容器运行时 → /bin/sh 进程

这个链路提示了什么?如果你用docker ps或ctr c ls能看到容器,但 kubectl 访问不了,那问题多半出在 API Server 的鉴权、RBAC、或者 kubelet 与 containerd 之间的连接上,而不是容器本身没起来。反之,kubectl 里 Pod 显示 Running,但exec进不去,可以检查是 CRI 配置了受限命令,还是权限不够。

理解这条链,可以帮你把"kubectl 命令不好使"的搜索范围快速缩小。排查时有一个口诀:先看 kubectl 能不能访问 API Server,再看 kubelet 是否健康,最后才去看 containerd/容器本身的状态。层级清晰,定位自然快。

8. 命令速查:把常用的都放进一张大表

为了日常速查方便,我把自己最常敲的命令整理成了一张速查表。这跟之前故障表不同,它是"按操作目的"组织的,更适合背下来或者贴在终端旁边。

操作目的命令示例
查看当前上下文kubectl config current-context
切换上下文kubectl config use-context <ctx-name>
查看所有命名空间kubectl get namespaces
查看某命名空间下所有资源kubectl get all -n <namespace>
查看 Pod 列表(含 IP、节点)kubectl get pods -o wide -n <namespace>
查看 Service 列表kubectl get svc -n <namespace>
查看 Deployment 列表kubectl get deploy -n <namespace>
查看 ConfigMapkubectl get cm -n <namespace>
查看 Secretkubectl get secret -n <namespace>
查看 PVCkubectl get pvc -n <namespace>
查看节点资源kubectl top node
查看 Pod 资源占用kubectl top pod -n <namespace>
查看事件kubectl get events --sort-by=.lastTimestamp -n <namespace>
查看 Deployment 滚动状态kubectl rollout status deployment/<name> -n <namespace>
重新启动 Deploymentkubectl rollout restart deployment/<name> -n <namespace>
查看历史版本kubectl rollout history deployment/<name> -n <namespace>
回滚到上一个版本kubectl rollout undo deployment/<name> -n <namespace>
创建资源kubectl create -f xxx.yaml
更新资源(声明式)kubectl apply -f xxx.yaml
删除资源kubectl delete -f xxx.yaml
查看资源详情kubectl describe <resource> <name> -n <namespace>
进入容器kubectl exec -it <pod> -n <namespace> -- /bin/sh
查看容器日志kubectl logs <pod> -n <namespace>
跟踪容器日志kubectl logs -f <pod> -n <namespace>
端口转发kubectl port-forward pod/<pod> 8080:80
复制文件到 Podkubectl cp ./file.txt <namespace>/<pod>:/tmp/file.txt
从 Pod 复制文件到本地kubectl cp <namespace>/<pod>:/var/log/app.log ./app.log
输出 YAMLkubectl get <resource> <name> -o yaml
输出 JSONkubectl get <resource> <name> -o json
自定义列输出kubectl get pods -o custom-columns=NAME:.metadata.name,IP:.status.podIP
优雅删除(默认30s)kubectl delete pod <pod> --grace-period=30
强制删除(谨慎)kubectl delete pod <pod> --force --grace-period=0

这张表我不建议直接全文背,因为你真正用到的可能只有五分之一。但把它保存好,每次忘记参数时翻一下,几周后你自然就记住高频的那些了。

9. 避坑心得:这些细节我踩过很多次

最后分享几个真正从线上"教训"里沉淀出来的心得,想到哪写到哪,但对新人来说绝对有用。

第一,永远不要相信不加 -n 的命令会对所有 namespace 生效。很多人以为kubectl get pods会列出所有 Pod,其实是只列当前 context 默认 namespace 下的 Pod。想要全量数据必须加-A。这个误解导致的问题,轻则误判资源数量,重则你删错了 namespace 里的资源还以为删的是测试环境。

第二,kubectl 和容器的退出码是有区分的。我在写脚本时,会把 kubectl 命令本身的退出码和容器内命令的退出码分开判断。比如:

kubectl exec <pod> -- /bin/sh -c "exit 3" echo $?

这条命令最终返回的可能是 1(kubectl 报错)或 3(容器内的退出码),取决于 kubectl 和 APIServer 的交互。写自动化编排时,一定要区分容器内命令的状态和 API 调用的状态,否则脚本判断会出错。

第三,优先使用 rollout restart 而不是手动删 Pod。如果目的是让 Deployment 里的 Pod 重新加载配置,永远用rollout restart,这样会触发滚动更新,而不是瞬间全部杀掉再创建,对服务的冲击小得多。

第四,操作前先确认镜像拉取策略。imagePullPolicy是 Always 还是 IfNotPresent,直接决定你在本地没有镜像时能不能顺利创建 Pod。而如果你给 Deployment 改了镜像 tag 但没改 imagePullPolicy,测试环境容易遇到"明明改了镜像还是旧版本"的奇怪问题。排查时一定先看这个字段。

第五,定期导出资源清单做备份。很多人在集群出事故后才想到没备份。但 Kubernetes 资源本身就是声明式的,用kubectl get deploy,svc,cm -n <namespace> -o yaml > backup.yaml定期导出,成本极低,关键时刻能救命。没有 infra 团队的小团队,我建议至少每周导一次。

写到这儿,我把日常用得上的 kubectl 命令和细节都梳理了一遍。这个工具并不难,绝大多数命令的语法结构都一致,真正让人翻车的地方往往就是对上下文、命名空间和资源状态的粗心。你把这些习惯刻进肌肉记忆里,再来解决集群问题,效率会提升一个量级。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询