news 2026/10/15 14:34:05

Kubernetes kubectl 高频命令速查与排障实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kubernetes kubectl 高频命令速查与排障实战指南

1. 为什么一张 kubectl 速查表能救你一整天

刚接手一个线上集群的排查任务时,我经历过那种手心冒汗的时刻:Pod 起不来,日志刷得飞快,脑子里明明知道该用kubectl describe看事件,手却先敲了kubectl logs,然后对着空输出发呆。等反应过来,五分钟已经没了。后来我养成了一个习惯——把高频命令按“场景”而不是按“字母顺序”整理成一张自己的速查表,贴在显示器边上。这张表救过我不止一次。

kubectl是 Kubernetes 的命令行客户端,也是绝大多数人跟集群交互的第一入口。它能做的事非常多:查资源、看日志、进容器、改配置、扩缩容、排障、导出现状。但它的子命令和参数组合极其庞杂,官方文档动辄几十页,真正高频用到的其实就那么二三十条。这篇内容就是把这些高频命令按真实使用场景重新组织,配上我踩过的坑和参数背后的逻辑,让你不用翻文档也能快速定位到该敲什么。

适合谁看?刚接触 K8s 的运维和开发、需要临时上集群排查问题的后端同学、以及想把自己那套零散命令整理成体系的老手。我不会只给你一堆命令让你背,而是告诉你每条命令在什么场景下用、为什么这么用、参数改了会有什么后果。读完你至少能做到:Pod 出问题时不慌,知道按什么顺序查;日常操作不用反复搜索;看到别人敲的命令能秒懂意图。

下面这张表是我自己长期迭代的版本,按“查、看、改、进、排”五个动作分类,后面每个章节会展开讲。

动作高频命令典型场景
查kubectl get快速看资源状态
看kubectl describe/logs定位异常原因
改kubectl edit/apply/scale调整配置与副本
进kubectl exec/port-forward进容器、连服务
排kubectl get events/top集群级排障

2. get 命令的隐藏玩法:不只是列个清单

2.1 默认输出为什么总是不够用

很多人对kubectl get的印象就是“列一下 Pod”,敲完看到一堆 NAME、READY、STATUS、AGE 就完事了。但默认输出丢掉了太多关键信息。比如你想知道 Pod 跑在哪个节点上,默认列里根本没有;想知道重启了几次,也得额外加参数。我刚开始就吃过亏:一个 Pod 频繁重启,我盯着 STATUS 列的 Running 以为没事,结果 READY 是 0/1,容器其实一直在崩溃循环。

解决办法是-o wide。这个参数会额外输出 IP 和 NODE,排查调度和网络问题时几乎是必加项:

kubectl get pods -o wide kubectl get pods -o wide -n kube-system

-n指定命名空间,不加默认是default。这里有个新手常踩的坑:明明kubectl get pods显示没有资源,但服务确实在跑,八成是资源在别的命名空间里。养成习惯,查不到就先加-A全局扫一遍:

kubectl get pods -A

-A等价于--all-namespaces,会列出所有命名空间的资源。代价是输出很长,所以定位到具体命名空间后还是要切回-n。

2.2 用 -o 定制输出,把结果喂给别的工具

-o是get最强大的参数,没有之一。它决定了输出格式,常用的有json、yaml、wide、name、custom-columns、jsonpath。我分几个真实场景说。

想导出某个资源的完整定义做备份或改完再 apply,用-o yaml:

kubectl get deployment my-app -o yaml > my-app-backup.yaml

注意导出的 yaml 里会带一堆status、metadata.managedFields之类的运行时字段,直接 apply 回去可能报错。我的做法是导出后手动删掉status整段和metadata里的resourceVersion、uid、creationTimestamp、managedFields。这一步很关键,很多人导出来直接改完 apply,结果报“字段不可变”或者版本冲突,就是这些字段在作祟。

只想拿名字做批量操作,用-o name:

kubectl get pods -o name | xargs kubectl delete

这条命令会删掉当前命名空间所有 Pod。危险操作,但能说明-o name的用途——输出格式是pod/xxx,方便管道传递。

想自定义列,用custom-columns。比如我经常需要一张“Pod 名 + 节点 + 重启次数”的表:

kubectl get pods -o custom-columns=\ NAME:.metadata.name,\ NODE:.spec.nodeName,\ RESTARTS:.status.containerStatuses[0].restartCount

这里.status.containerStatuses[0]取的是第一个容器的状态。如果一个 Pod 有多个容器,这个写法只取第一个,需要全部的话得用jsonpath配合循环,或者干脆用-o json自己解析。

jsonpath适合精确提取单个值,比如拿某个 Service 的 ClusterIP:

kubectl get svc my-service -o jsonpath='{.spec.clusterIP}'

jsonpath的语法坑比较多,数组索引用[0],通配用[*],范围用[0:2]。我建议复杂提取直接用-o json配合jq,可读性和可维护性都更好:

kubectl get pods -o json | jq '.items[] | {name: .metadata.name, node: .spec.nodeName}'

2.3 排序、筛选与 watch:让 get 变成实时监控

get默认按名字排序,但排障时我更关心谁重启最多、谁最老。--sort-by能按任意字段排序:

kubectl get pods --sort-by=.status.containerStatuses[0].restartCount kubectl get pods --sort-by=.metadata.creationTimestamp

第一条按重启次数升序,想降序就加--sort-by后配合-o再处理,或者用--sort-by本身不支持反向,得靠jq反转。第二条按创建时间排,找最新部署的 Pod 特别有用。

-l按标签筛选是日常高频操作。K8s 里几乎所有资源都带标签,-l就是按标签选择器过滤:

kubectl get pods -l app=my-app kubectl get pods -l 'env in (prod,staging)' kubectl get pods -l app=my-app,tier=frontend

标签选择器支持=、!=、in、notin、exists几种写法。我踩过的坑是:-l后面的表达式如果带空格或特殊字符,一定要用引号包起来,否则 shell 会先解析,导致选择器失效。

-w是 watch 模式,会持续监听资源变化并实时刷新:

kubectl get pods -w

滚动发布时我经常开一个终端跑-w,另一个终端执行rollout,这样能实时看到新 Pod 一个个起来、旧 Pod 一个个退出。比反复敲get高效得多。退出 watch 按Ctrl+C。

3. describe 与 logs:排障时先看哪个

3.1 describe 输出里真正该看的三段

kubectl describe会输出资源的详细信息和关联事件。很多人敲完看到一大坨文字就懵了,其实真正有用的就三段:Status、Conditions、Events。

kubectl describe pod my-pod-xxx

Status段告诉你 Pod 当前处于什么阶段(Pending、Running、Succeeded、Failed、Unknown)。如果是 Pending,基本可以断定是调度问题——资源不够、节点选择器不匹配、污点没容忍。这时候往下看Events,通常会直接告诉你“0/3 nodes are available: insufficient cpu”之类的原因。

Conditions段是 Pod 层面的健康状态,重点看Ready和ContainersReady。如果Ready是 False,说明就绪探针没过,服务不会接流量。这时候要去看容器的State,是Waiting还是Terminated。Waiting常见原因是镜像拉取失败(ImagePullBackOff)或配置缺失(CreateContainerConfigError);Terminated则要看退出码,ExitCode 137通常是 OOMKilled,ExitCode 1多半是应用自己报错退出。

Events段是排障的金矿,但默认只保留最近一小时的事件,而且数量有限。如果事件被刷掉了,可以单独查:

kubectl get events --sort-by=.metadata.creationTimestamp kubectl get events -n my-namespace --field-selector involvedObject.name=my-pod-xxx

--field-selector按字段过滤事件,比翻 describe 输出更精准。我习惯在 Pod 反复重启时用这条命令,能快速看到最近几次失败的原因。

3.2 logs 的参数组合与多容器陷阱

kubectl logs看容器标准输出,但有几个参数组合必须掌握。

-f实时跟踪,等价于tail -f:

kubectl logs -f my-pod-xxx

--tail只看最后 N 行,避免日志太多刷屏:

kubectl logs --tail=100 my-pod-xxx

--since按时间过滤,比如只看最近十分钟:

kubectl logs --since=10m my-pod-xxx

--previous看上一个崩溃容器的日志,这是排查 CrashLoopBackOff 的关键:

kubectl logs my-pod-xxx --previous

Pod 重启后,当前容器的日志是空的(因为刚起来),真正报错的信息在上一个容器里。不加--previous你会以为日志丢了,其实只是看错了地方。

多容器 Pod 必须用-c指定容器名,否则报错:

kubectl logs my-pod-xxx -c sidecar

不知道容器名就先 describe 一下,Containers段会列出来。我见过有人对着多容器 Pod 敲了半天 logs 没输出,最后发现是没加-c,命令直接报错被忽略了。

还有一个组合是logs配合标签选择器,一次看一组 Pod 的日志:

kubectl logs -l app=my-app --tail=50 --prefix

--prefix会在每行日志前加上 Pod 名,方便区分是哪个实例输出的。这个在排查“只有一个副本报错”的问题时特别好用。

3.3 先 describe 还是先 logs 的判断逻辑

这个问题我被问过很多次。我的判断逻辑很简单:Pod 没起来,先 describe;Pod 起来了但行为不对,先 logs。

Pod 处于 Pending、ContainerCreating、CrashLoopBackOff 这些状态时,容器可能根本没跑起来,logs 自然没东西。这时候 describe 的 Events 会告诉你卡在哪一步。反过来,Pod 是 Running 且 Ready,但接口返回 500,那问题在应用内部,直接看 logs 更快。

还有一种情况是两者都要看:Pod 反复重启。先用 describe 看退出码和事件,判断是 OOM 还是应用崩溃;如果是应用崩溃,再用logs --previous看崩溃前的堆栈。这个顺序能帮你少走弯路。

4. 改配置、扩缩容与滚动更新:别在生产环境手抖

4.1 edit 与 apply 的取舍

改资源配置有两条路:kubectl edit直接改线上,kubectl apply用文件改。我的原则是:临时调试用 edit,正式变更用 apply。

edit会打开默认编辑器(通常是 vi),改完保存即生效:

kubectl edit deployment my-app

方便,但风险高。一是没有版本记录,改错了不好回滚;二是多人协作时容易覆盖别人的改动。我踩过的坑是:edit 打开后看到的是当前集群状态,如果这期间别人也改了同一个资源,你保存时会直接覆盖,没有任何冲突提示。

apply用声明式文件,配合 Git 做版本管理,是生产环境的正确姿势:

kubectl apply -f deployment.yaml

apply的坑在于它只做“增量合并”,不会删除文件里已经移除的字段。比如你从 yaml 里删了一个环境变量,apply 之后集群里那个变量还在。要彻底同步,得用kubectl replace或者先 delete 再 apply。我一般用kubectl diff -f deployment.yaml先看差异,确认无误再 apply:

kubectl diff -f deployment.yaml

diff会输出集群现状和文件内容的差异,相当于 apply 的预演。这个命令救过我很多次,强烈建议养成习惯。

4.2 scale 与 rollout:扩缩容和发布控制

scale调整副本数,简单直接:

kubectl scale deployment my-app --replicas=5

但要注意,如果 Deployment 的 yaml 里写了replicas: 3,下次 apply 会把副本数改回 3。所以 scale 适合临时调整,长期变更还是要改 yaml。

rollout是发布管理的核心,几个子命令必须记住:

kubectl rollout status deployment my-app kubectl rollout history deployment my-app kubectl rollout undo deployment my-app kubectl rollout restart deployment my-app

status看发布进度,会阻塞直到完成或失败。history看历史版本,配合--revision可以回滚到指定版本:

kubectl rollout undo deployment my-app --to-revision=2

restart是滚动重启,不改变配置,只是让所有 Pod 重建一遍。这个命令在“配置没变但想让 Pod 重新拉镜像”时特别有用。我经常用它来触发一次干净的滚动,比如 Secret 更新后 Pod 不会自动重载,restart 一下就能让新配置生效。

rollout的坑在于:如果 Deployment 的strategy是Recreate,restart 会导致服务短暂中断。生产环境务必确认是RollingUpdate,并且配好maxUnavailable和maxSurge。

4.3 用 patch 做精准修改

patch是介于 edit 和 apply 之间的选择,适合脚本化地改单个字段:

kubectl patch deployment my-app -p '{"spec":{"replicas":5}}'

patch支持strategic、merge、json三种类型,默认是strategic。改副本数、改镜像、加标签这些操作,patch 比 edit 安全,因为它只动你指定的字段,不会覆盖整个资源。

我常用的一个场景是改镜像:

kubectl set image deployment/my-app my-app=my-registry/my-app:v2

set image本质就是 patch 的封装,比手写 patch 更直观。类似的还有set env、set resources,都是高频操作。

5. exec、port-forward 与 cp:进容器和连服务的正确姿势

5.1 exec 进容器的参数细节

exec在容器里执行命令,最常用的是开个 shell:

kubectl exec -it my-pod-xxx -- /bin/bash

-it是-i(标准输入)和-t(分配终端)的组合,交互式操作必须加。--后面跟要执行的命令,这个分隔符不能省,否则 kubectl 会把命令参数当成自己的参数解析。

如果容器里没有 bash,用 sh:

kubectl exec -it my-pod-xxx -- /bin/sh

多容器 Pod 同样要加-c:

kubectl exec -it my-pod-xxx -c sidecar -- /bin/sh

exec的坑在于:如果 Pod 没有Ready,exec 可能失败或行为异常。另外,exec 进去的环境变量和容器主进程不一定完全一致,因为主进程可能通过 entrypoint 设置了额外变量。排查环境变量问题时,最好直接看容器的/proc/1/environ。

5.2 port-forward 打通本地与集群

port-forward把本地端口转发到 Pod 或 Service 的端口,是本地调试的利器:

kubectl port-forward pod/my-pod-xxx 8080:80 kubectl port-forward svc/my-service 8080:80

第一条把本地 8080 转发到 Pod 的 80,第二条转发到 Service 的 80。区别在于:转发到 Pod 时,流量直接进那个 Pod;转发到 Service 时,会经过 Service 的负载均衡,可能落到任意后端 Pod。

port-forward默认只监听localhost,想被其他机器访问要加--address:

kubectl port-forward --address 0.0.0.0 svc/my-service 8080:80

这个命令在连数据库、调试内部 API 时特别有用。但它有个限制:只支持 TCP,不支持 UDP。而且连接不稳定时会自动断开,需要重新执行。我一般配合while true循环让它自动重连:

while true; do kubectl port-forward svc/my-service 8080:80; sleep 1; done

5.3 cp 在容器和本地之间传文件

kubectl cp复制文件,语法类似scp:

kubectl cp my-pod-xxx:/var/log/app.log ./app.log kubectl cp ./config.yaml my-pod-xxx:/etc/config/config.yaml

从容器往外拷,源在前;往容器里拷,源在后。多容器 Pod 要加-c。

cp的坑不少。一是它依赖容器里有tar,如果镜像极简(比如 distroless),cp 会失败。二是大文件传输慢且容易断。三是路径里的冒号是分隔符,Windows 路径带盘符时容易混淆。我的经验是:小文件用 cp,大文件或者容器没 tar 时,用exec配合cat重定向:

kubectl exec my-pod-xxx -- cat /var/log/app.log > ./app.log

反过来往容器里写:

cat ./config.yaml | kubectl exec -i my-pod-xxx -- sh -c 'cat > /etc/config/config.yaml'

这种方式不依赖 tar,兼容性更好。

6. 集群级排障:从节点到资源的完整链路

6.1 top 看资源占用

kubectl top看节点和 Pod 的 CPU、内存占用:

kubectl top nodes kubectl top pods kubectl top pods -A --sort-by=memory

top依赖 metrics-server 组件,如果报“metrics not available”,说明集群没装或者没配好。这个命令的输出是瞬时值,不是平均值,所以看到某个 Pod 内存飙高不一定代表它一直这么高,要结合--sort-by和多次采样判断。

我常用的组合是top pods -A --sort-by=memory,一眼看出哪个命名空间、哪个 Pod 最吃内存。排查 OOM 问题时,先看 top,再看 describe 里的 limits 和实际用量对比。

6.2 cordon、drain 与 taint:节点维护三件套

节点要维护时,先把 Pod 赶走:

kubectl cordon my-node kubectl drain my-node --ignore-daemonsets --delete-emptydir-data

cordon标记节点不可调度,新 Pod 不会上来。drain驱逐节点上的 Pod,配合--ignore-daemonsets忽略 DaemonSet(因为 DaemonSet 本来就要在每个节点跑),--delete-emptydir-data允许删除使用 emptyDir 的 Pod(数据会丢,确认后再加)。

维护完恢复调度:

kubectl uncordon my-node

drain的坑在于:如果 Pod 没有控制器管理(裸 Pod),drain 会拒绝驱逐,需要加--force。但强制驱逐裸 Pod 意味着它不会自动重建,数据也可能丢,生产环境慎用。

taint给节点打污点,配合 Pod 的toleration实现定向调度:

kubectl taint nodes my-node key=value:NoSchedule kubectl taint nodes my-node key=value:NoSchedule-

末尾加-是删除污点。NoSchedule是不调度新 Pod,NoExecute还会驱逐不容忍的现有 Pod。这个机制在专用节点(比如 GPU 节点)上很常见。

6.3 用 api-resources 和 explain 查文档

K8s 资源类型太多,记不住很正常。api-resources列出所有资源类型:

kubectl api-resources kubectl api-resources --namespaced=false

--namespaced=false只看集群级资源,比如 Node、PersistentVolume、ClusterRole。这个命令在写 RBAC 或者确认某个资源是否分命名空间时特别有用。

explain查字段文档,不用离开终端:

kubectl explain deployment.spec.strategy kubectl explain pod.spec.containers --recursive

--recursive递归展开所有子字段,输出很长但很全。我写复杂 yaml 时经常用它确认字段名和类型,比翻官网快。

6.4 一个完整的排障链路示例

假设有人反馈某个服务 502。我的排查顺序是:

  1. kubectl get pods -n my-ns -o wide看 Pod 状态和节点。
  2. 如果有 Pod 不 Ready,kubectl describe pod看 Events。
  3. 如果 Pod 都 Ready,kubectl get svc my-service -o yaml看 Service 的 selector 和 endpoints。
  4. kubectl get endpoints my-service看后端有没有正确注册。
  5. 如果 endpoints 为空,说明 selector 不匹配或者 Pod 没 Ready。
  6. 如果 endpoints 正常,kubectl logs看应用日志。
  7. 还不行就kubectl exec进去,curl localhost:port确认应用本身是否正常。

这个链路覆盖了从调度到网络到应用的完整路径。每一步都有明确的判断依据,不会盲目乱试。

7. 把命令变成肌肉记忆的几个实操心得

7.1 别名与补全:让手速跟上思路

kubectl敲全拼太慢,我习惯设别名:

alias k=kubectl alias kgp='kubectl get pods' alias kgs='kubectl get svc' alias kd='kubectl describe' alias kl='kubectl logs'

但别名有个问题:换台机器就没了。所以我会把这些写进~/.bashrc或~/.zshrc,并且用 Git 管理 dotfiles,换环境一键同步。

补全更重要。kubectl 自带补全脚本:

source <(kubectl completion bash)

zsh 用户:

source <(kubectl completion zsh)

补全不仅能补命令,还能补资源名、命名空间、字段。开了补全之后,敲kubectl get pod <Tab>会自动列出当前命名空间的 Pod 名,效率提升非常明显。

7.2 上下文与命名空间切换

多集群环境下,kubectl config是必备:

kubectl config get-contexts kubectl config use-context my-cluster kubectl config set-context --current --namespace=my-ns

get-contexts列出所有上下文,use-context切换。set-context --current --namespace把当前上下文的默认命名空间改掉,省得每次加-n。

我踩过的坑是:切了上下文忘了切回来,对着测试集群敲了生产环境的命令。后来我养成了习惯,在 shell 提示符里显示当前上下文和命名空间:

export PS1='[\u@\h \W $(kubectl config current-context)]\$ '

这样一眼就能看到自己在哪个集群,避免误操作。

7.3 输出格式化与常用组合

最后分享几个我高频使用的组合命令,都是实战中磨出来的:

查所有命名空间下不 Ready 的 Pod:

kubectl get pods -A --field-selector=status.phase!=Running

查最近重启的 Pod:

kubectl get pods -A --sort-by=.status.containerStatuses[0].restartCount | tail -20

批量删除 Evicted 状态的 Pod:

kubectl get pods -A | grep Evicted | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n

这条命令要小心,先确认输出再执行。awk取命名空间和 Pod 名,xargs -n2每次传两个参数给 delete。

查节点资源分配率:

kubectl describe node my-node | grep -A5 "Allocated resources"

这个输出能看到节点上所有 Pod 的 requests 和 limits 总和,判断节点是否过载。

这些命令单独看都不复杂,但组合起来能解决很多实际问题。我的建议是:不要试图一次记住所有命令,先把最常用的十条练到不用想就能敲出来,剩下的用到时再查。速查表的意义不是让你背,而是让你在需要的时候能快速找到,并且知道为什么这么用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 14:33:47

单周期CPU设计实战:从指令集到Verilog仿真的完整流程

简介&#xff1a;这份资源是一套面向计算机组成原理与处理器设计课程教学的十六位单周期CPU硬件工程&#xff0c;主要采用Verilog语言编写&#xff0c;适用于高校本科生、课程设计者以及希望在FPGA平台上验证处理器设计的硬件爱好者。压缩包内共有140个文件&#xff0c;整体大小…

作者头像 李华
网站建设 2026/10/15 14:32:26

MATLAB医学影像分割工具开发与优化实践

1. 项目背景与工具定位去年接手了一个医学影像分析项目&#xff0c;需要批量处理上千张CT扫描片。当时试了好几个开源工具&#xff0c;要么功能太臃肿&#xff0c;要么缺少特定算法&#xff0c;调试起来特别费时间。一怒之下干脆用MATLAB自己写了这个轻量级图像分割工具&#x…

作者头像 李华
网站建设 2026/10/15 14:31:42

Android SQLite数据库查看与调试全指南

1. 为什么一个SQLite数据库查看问题&#xff0c;会让80%的Android开发者卡在调试第一关 “Android开发中你是怎么查看sqlite数据库的”——这句看似平平无奇的提问&#xff0c;背后藏着整个Android本地数据调试链中最脆弱的一环。我带过三届某高校移动开发实训班&#xff0c;每…

作者头像 李华
网站建设 2026/10/15 14:31:30

当工具成为类:Softmax困境与连接器过载的算法根源

从多类分类的margin理论看Function Call为什么会在工具数超过临界点时突然失效 原创算法分析 不依赖外部文献 2026 目录 隐式分类问题&#xff1a;Function Call的统计学习本质Softmax Margin与类别数的数学关系类间相似性&#xff1a;当工具描述撞车时决策边界如何崩塌In…

作者头像 李华
网站建设 2026/10/15 14:31:14

BIM与智能设计:建筑行业的数字化转型实践

1. 智能设计在建造行业的变革意义十年前我第一次接触BIM系统时&#xff0c;施工图纸还停留在二维平面阶段。设计师们用CAD画出的线条&#xff0c;需要施工方在脑海中重构为立体空间。这种信息传递的损耗&#xff0c;常常导致现场施工与设计意图出现偏差。如今走进任何一家头部建…

作者头像 李华
网站建设 2026/10/15 14:31:09

STM32F103 TIM1硬件SPWM实现:载波锁频与调制波双可调

简介&#xff1a;本资源是一套基于STM32F103系列MCU实现SPWM波形生成的完整工程代码与配置方案&#xff0c;面向嵌入式初学者、电机驱动开发者及逆变电源设计工程师&#xff0c;解决频率与幅度实时可调、载波频率恒定的三相互补SPWM信号生成难题。工程依托TIM1高级定时器&#…

作者头像 李华