kubectl 常用命令速查与排障:从看不懂到 5 分钟定位

出事的时候没人会去翻文档。这篇按实际排查顺序排:先看集群是不是活着,再看 Pod 死在哪一步,最后才是网络和调度。命令全部能直接复制。

一、结论先给:90% 的问题走这三步

kubectl get pod -A                          # 1)谁不正常
kubectl describe pod <pod> -n <ns>          # 2)为什么(看 Events,答案基本都在最后 5 行)
kubectl logs <pod> -n <ns> --tail=100 -f    # 3)容器里发生了什么

describe 的 Events 段是 kubectl 里信息密度最高的地方,比 logs 更早该看。日志只告诉你程序想说什么,Events 告诉你 K8s 对它做了什么。

二、开干之前:先把环境配舒服

# 补全(bash)
echo 'source <(kubectl completion bash)' >> ~/.bashrc
# zsh
echo 'source <(kubectl completion zsh)' >> ~/.zshrc

# 别名,能少敲一半
cat >> ~/.bashrc <<'EOF'
alias k='kubectl'
alias kg='kubectl get'
alias kd='kubectl describe'
alias kl='kubectl logs'
alias kx='kubectl exec -it'
alias kn='kubectl config set-context --current --namespace'
complete -F __start_kubectl k
EOF
source ~/.bashrc

kn <ns> 切换默认命名空间是这几个里最省时间的——不用每条命令都带 -n。

多集群别手改 kubeconfig,用上下文切:

kubectl config get-contexts
kubectl config use-context prod
kubectl config view --minify | grep namespace    # 当前上下文

三、第一层:集群活着吗

kubectl cluster-info
kubectl get node -o wide
kubectl get cs            # 新版已废弃,1.19+ 用下面这条
kubectl get --raw='/readyz?verbose' | head -20
kubectl top node          # 需要 metrics-server

top 报错 Metrics API not available 不是集群坏了,是没装 metrics-server,装完就有:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 内网环境常见坑:kubelet 证书自签,需要给 metrics-server 加 --kubelet-insecure-tls

节点 NotReady 的常见原因排前三:kubelet 挂了、磁盘满了、容器运行时挂了。

systemctl status kubelet && journalctl -u kubelet --since "10 min ago" | tail -40
df -h /var/lib/docker /var/lib/containerd 2>/dev/null
systemctl status containerd

磁盘满是最容易被忽略的一个——K8s 默认在磁盘 < 15% 时开始驱逐 Pod,表现为 Pod 莫名被 Evicted。

四、第二层:Pod 死在哪一步

kubectl get pod 的 STATUS 只有那几种,认全了排查就快了:

状态 含义 第一动作
Pending 调度不进去 describe 看 Events,多半是资源不够或污点没容忍
ImagePullBackOff 镜像拉不下来 看仓库地址、tag、imagePullSecrets
CrashLoopBackOff 起来就退 logs --previous 看上一次的报错
Running 但 0/1 存活但探针不过 看 readiness/liveness 配置与端口
Evicted 被驱逐 节点磁盘或内存压力
Terminating 卡住 删不掉 有 finalizer 或节点失联
Init:0/1 初始化容器没跑完 看 initContainer 日志 -c <init-name>

对应命令:

# Pending:为什么调度不进去
kubectl describe pod <pod> -n <ns> | sed -n '/Events/,$p'
# 典型输出:0/3 nodes are available: 3 Insufficient cpu

# CrashLoop:看上一次崩溃的日志(关键在 --previous)
kubectl logs <pod> -n <ns> --previous

# 多容器 Pod 必须指定容器
kubectl logs <pod> -n <ns> -c <container>

# Init 容器卡住
kubectl logs <pod> -n <ns> -c <init-container-name>

# 资源实际用量
kubectl top pod -A --sort-by=memory | head -20

--previous 是被低估最多的一个参数。容器崩溃重启后,不带它看到的是新进程的日志,真正的死因在上一次。

五、第三层:进容器里看

kubectl exec -it <pod> -n <ns> -- /bin/sh      # 镜像没有 bash 时用 sh
kubectl exec -it <pod> -n <ns> -c <container> -- /bin/bash

# 没有 curl / 没有 shell 的极简镜像:临时起一个调试容器共享网络栈
kubectl debug -it <pod> -n <ns> --image=busybox:1.36 --target=<container>

kubectl debug(1.18+ beta、1.23+ GA)是 distroless 镜像时代的救命功能——目标容器里啥都没有,就在旁边挂一个有工具的容器,共享进程和网络命名空间。

本地调端口:

kubectl port-forward svc/my-svc 8080:80 -n <ns>
kubectl port-forward pod/<pod> 15432:5432     # 连数据库最常用

拷贝文件(没装 kubectl 的机器之间传东西):

kubectl cp <pod>:/app/config.yaml ./config.yaml -n <ns>
kubectl cp ./local.conf <pod>:/etc/nginx/nginx.conf -n <ns>

六、第四层:服务通不通

kubectl get svc,ep -n <ns>          # ep 是 endpoints,空的就是 selector 没匹配上
kubectl get ingress -n <ns>
kubectl describe ingress <name> -n <ns>

Endpoints 为空是 Service 不通的第一大原因:Service 的 selector 和 Pod 的 label 对不上,Service 正常存在但后面没挂任何东西。

# 直接比对
kubectl get svc my-svc -n <ns> -o jsonpath='{.spec.selector}'
kubectl get pod -n <ns> --show-labels | grep my-svc

DNS 解析:

kubectl run -it --rm dns-test --image=busybox:1.36 --restart=Never -- nslookup my-svc.<ns>.svc.cluster.local

Service 的四层连不上,但 Pod IP 直连能通 —— 基本就是 kube-proxy 或 NetworkPolicy 的锅。

七、改东西:apply / edit / scale / rollout

kubectl apply -f deploy.yaml
kubectl edit deploy/<name> -n <ns>                 # 在线改,保存即生效
kubectl scale deploy/<name> --replicas=5 -n <ns>
kubectl set image deploy/<name> app=nginx:1.27 -n <ns>

# 发布状态三件套
kubectl rollout status deploy/<name> -n <ns>
kubectl rollout history deploy/<name> -n <ns>
kubectl rollout undo deploy/<name> -n <ns>         # 回滚上一版
kubectl rollout undo deploy/<name> --to-revision=3 -n <ns>

# 强制重启(配置没变但想重拉)
kubectl rollout restart deploy/<name> -n <ns>

kubectl edit 适合救急,但别把它当常态——改动不在 Git 里,下次 apply 会被覆盖回去。

八、查资源占用与清理

kubectl top pod -A --sort-by=cpu | head -20
kubectl describe node <node> | sed -n '/Allocated resources/,/Events/p'   # 看这台机器还剩多少

# 清理(慎用,按命名空间批量删前先 --dry-run)
kubectl delete pod --field-selector=status.phase=Failed -A
kubectl delete pod --field-selector=status.phase=Succeeded -A
kubectl delete evicted-pod 2>/dev/null || kubectl get pod -A | grep Evicted | awk '{print $1" "$2}' | xargs -n2 sh -c 'kubectl delete pod $1 -n $0'

Requests / Limits 配错是"集群看着很闲但新 Pod 调度不进去"的根源——看 Allocated resources 那段,requests 那列才是调度依据,不是实际用量。

九、一张表收尾

我想… 命令
看谁挂了 kubectl get pod -A | grep -v Running
为什么挂 kubectl describe pod <pod> -n <ns>
崩溃前说了啥 kubectl logs <pod> --previous
进容器 kubectl exec -it <pod> -- sh
本地连集群服务 kubectl port-forward svc/x 8080:80
发版失败回退 kubectl rollout undo deploy/x
重启应用 kubectl rollout restart deploy/x
服务不通 kubectl get ep -n <ns> 看 Endpoints 空不空
别再敲 -n kn <ns>

命令记不全没关系,K8s 命令速查 按场景列好了,直接搜就行。排障时如果要从日志里找规律(比如某个错误码一天出现多少次、集中在哪几个小时),可以把日志贴进 日志分析工具 直接出结论。


相关工具:K8s 命令速查 · Linux 命令速查 · 日志分析工具

延伸阅读:Ubuntu 服务器调优:上线前必须改的 12 个系统参数 · Nginx 跑满并发:Nginx + 系统内核调优

还有 65 个免费在线工具

纯前端实现,不用注册,数据不上传服务器。

浏览全部工具