ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Kubectl 命令实战指南:从集群管理到故障排查的系统整理

Kubectl 命令实战指南:从集群管理到故障排查的系统整理

1. 为什么 kubectl 值得花时间系统整理

刚接触容器编排那会儿,我总觉得命令行操作是“过渡方案”,迟早要被图形界面取代。结果几年下来,图形面板换了好几茬,kubectl反而越用越顺手,成了每天打开终端后第一个敲下的命令。这个工具本质上就是集群的遥控器——你用它查看节点状态、部署应用、排查故障、调整副本数,几乎所有日常运维动作都能通过它完成。它解决的核心问题很直接:把复杂的集群操作抽象成一条条语义清晰的子命令,让运维人员不用记一堆接口地址和认证细节,就能对集群发号施令。

这篇文章适合两类人看。一类是刚搭好集群、对着空白终端不知道从哪下手的新手,另一类是已经能用几个基础命令、但遇到报错就卡壳、想系统梳理一遍的中级使用者。我会把常用命令按使用场景重新归类,补充参数背后的逻辑、容易踩的坑,以及我在实际排障中总结出来的组合用法。你不需要背命令手册,跟着场景走,用几次自然就记住了。

需要提前说明的是,下面所有操作都基于一个已经配置好访问凭据的集群环境。如果你还没连上集群,先确认本地配置文件位置是否正确,这是所有命令能跑通的前提。

2. 集群信息查看与上下文管理

2.1 先搞清楚自己在跟哪个集群说话

很多人拿到环境后直接就开始敲部署命令,结果发现资源创建到了错误的集群里。这种情况在同时维护多套环境时特别常见。kubectl config这一组命令就是用来管理“你当前在跟谁对话”的。

查看当前上下文:

kubectl config current-context

列出所有已配置的上下文:

kubectl config get-contexts

切换上下文:

kubectl config use-context <context-name>

我习惯在每次切换环境后立刻执行一次kubectl config current-context,确认自己没切错。这个动作只花一秒钟,但能避免把测试环境的改动误操作到生产环境。

查看集群整体信息:

kubectl cluster-info

这个命令会返回控制平面和核心组件的访问地址。如果返回超时或连接被拒,说明本地配置指向的集群不可达,后面的命令都不用试了,先解决连通性问题。

2.2 节点与组件状态速查

集群能不能正常工作,先看节点。节点是承载所有工作负载的底座,底座不稳,上面跑什么都是白搭。

kubectl get nodes

默认输出只显示名称、状态、角色、版本和运行时长。我通常会加上-o wide看内网地址和操作系统版本:

kubectl get nodes -o wide

如果某个节点状态显示NotReady,需要进一步查看节点详情:

kubectl describe node <node-name>

describe的输出很长,重点看最后的事件区域。常见原因包括磁盘压力、内存不足、网络插件异常。事件里通常会直接告诉你原因,比盲目搜索快得多。

查看集群核心组件健康状况:

kubectl get componentstatuses

这个命令在新版本中逐渐被弃用,但很多存量集群仍然可用。如果返回结果里有Unhealthy,说明对应组件需要关注。

注意:componentstatuses在较新版本中可能返回空结果或报错,这属于正常现象,不代表集群有问题。可以改用kubectl get --raw='/readyz?verbose'来检查各组件就绪状态。

3. 工作负载的日常操作命令

3.1 查看资源:get 命令的常用姿势

kubectl get是使用频率最高的命令,没有之一。它的基本结构是:

kubectl get <资源类型> [资源名称] [参数]

常用资源类型包括pods、deployments、services、configmaps、secrets、namespaces、events等。资源类型支持单数、复数和简写,比如pod、pods、po效果一样。

查看默认命名空间下的所有 Pod:

kubectl get pods

查看指定命名空间:

kubectl get pods -n <namespace>

查看所有命名空间:

kubectl get pods --all-namespaces

输出格式控制是get命令的精髓。-o wide显示更多列,-o yaml输出完整资源定义,-o json输出 JSON 格式,-o name只输出资源名称。我排障时最常用的是-o wide和-o yaml的组合。

实时监听资源变化:

kubectl get pods -w

这个-w参数在观察滚动更新、Pod 重启时特别好用,终端会持续刷新状态变化,不用反复手动执行。

按标签筛选:

kubectl get pods -l app=nginx

标签选择器支持多种运算符,比如-l 'env in (prod,staging)'、-l 'tier!=frontend'。在资源数量多的时候,标签筛选能帮你快速定位目标。

3.2 创建与更新:apply 和 create 的取舍

kubectl create和kubectl apply都能创建资源,但行为不同。create是命令式操作,如果资源已存在会报错;apply是声明式操作,资源不存在就创建,存在就更新。

我现在的习惯是:临时测试用create,正式管理用apply。因为apply会记录上次应用的配置,支持三方合并,更适合纳入版本控制的场景。

从文件创建:

kubectl apply -f deployment.yaml

从目录批量创建:

kubectl apply -f ./manifests/

从标准输入创建:

cat deployment.yaml | kubectl apply -f -

直接通过命令行创建 Deployment:

kubectl create deployment nginx --image=nginx:1.25 --replicas=3

这种写法适合快速验证,但不建议用于生产环境,因为参数散落在命令历史里,不好追溯。

3.3 删除资源:优雅与强制之间

删除单个 Pod:

kubectl delete pod <pod-name>

删除 Deployment 及其管理的所有 Pod:

kubectl delete deployment <deployment-name>

按标签批量删除:

kubectl delete pods -l app=test

默认情况下,删除 Pod 会发送终止信号并等待宽限期。如果 Pod 卡在Terminating状态,可以强制删除:

kubectl delete pod <pod-name> --grace-period=0 --force

强制删除是最后手段。先确认 Pod 是否真的无响应,因为强制删除可能导致容器进程没有被正确清理,留下孤儿进程或挂载点残留。我遇到过强制删除后节点上残留挂载目录的情况,需要手动清理才能重新调度。

删除命名空间会级联删除其中所有资源,执行前务必确认:

kubectl delete namespace <namespace-name>

4. 排障必备:describe、logs 与 exec

4.1 describe:资源详情的第一入口

Pod 起不来、服务访问不通,第一个该敲的命令就是describe。它把资源的完整状态、配置、事件都摊开给你看。

kubectl describe pod <pod-name>

输出分几个区域:基本信息、容器列表、条件、卷挂载、事件。事件区域按时间倒序排列,最近的异常通常在最上面。

我排查 Pod 启动失败时,会重点看这几个地方:

  • State字段显示容器当前状态,Waiting通常伴随原因说明
  • Last State显示上一次终止的原因和退出码
  • Events区域显示调度、拉镜像、启动容器各阶段的事件

常见事件信息与对应原因:

事件信息可能原因排查方向
ImagePullBackOff镜像地址错误或凭据缺失检查镜像名、仓库认证
CrashLoopBackOff容器启动后立即退出查看容器日志、启动命令
Pending没有节点满足调度条件检查资源请求、节点标签、污点
Evicted节点资源不足检查节点磁盘和内存压力

4.2 logs:容器日志的查看技巧

查看 Pod 日志:

kubectl logs <pod-name>

如果 Pod 里有多个容器,需要指定容器名:

kubectl logs <pod-name> -c <container-name>

实时跟踪日志:

kubectl logs -f <pod-name>

查看上一次容器实例的日志(容器重启后,当前日志是空的,但上一次的日志还在):

kubectl logs <pod-name> --previous

只查看最近若干行:

kubectl logs --tail=100 <pod-name>

按时间筛选:

kubectl logs --since=1h <pod-name>

--since支持s、m、h单位。排障时我通常先看最近一小时的日志,避免被历史信息淹没。

4.3 exec:进入容器内部

进入容器交互式终端:

kubectl exec -it <pod-name> -- /bin/sh

如果容器里有 bash:

kubectl exec -it <pod-name> -- /bin/bash

执行单条命令:

kubectl exec <pod-name> -- ls /app

多容器 Pod 需要指定容器:

kubectl exec -it <pod-name> -c <container-name> -- /bin/sh

注意:exec进入容器后,你看到的是容器内部的文件系统和进程空间。如果容器以非 root 用户运行,某些目录可能没有权限访问。另外,生产环境建议通过审计日志记录所有exec操作,便于追溯。

5. 服务暴露与网络排查

5.1 Service 与 Endpoint 的关系

Service 为 Pod 提供稳定的访问入口。创建 Service 后,它通过标签选择器匹配后端 Pod,并维护对应的 Endpoint 列表。

查看 Service:

kubectl get services

查看 Service 详情:

kubectl describe service <service-name>

查看 Endpoint:

kubectl get endpoints <service-name>

如果 Endpoint 列表为空,说明 Service 的标签选择器没有匹配到任何就绪的 Pod。这时候需要检查两件事:Pod 的标签是否与 Service 选择器一致,Pod 是否处于 Ready 状态。

5.2 端口转发:本地调试利器

把集群内服务映射到本地端口:

kubectl port-forward <pod-name> 8080:80

或者转发 Service:

kubectl port-forward service/<service-name> 8080:80

这个命令在本地调试时非常实用。比如集群里的数据库不方便直接暴露,就可以通过端口转发在本地连接。转发会话在前台运行,按Ctrl+C终止。

端口转发默认只绑定本地回环地址。如果需要让同网段其他机器访问,可以加--address 0.0.0.0,但这样做会扩大暴露面,仅建议在受控网络中使用。

5.3 网络连通性测试

在集群内部测试服务连通性,最直接的方式是起一个临时 Pod:

kubectl run test-shell --image=busybox:1.36 --rm -it --restart=Never -- sh

进入后可以用wget或nc测试目标服务:

wget -qO- http://<service-name>.<namespace>.svc.cluster.local

--rm参数表示退出后自动删除 Pod,--restart=Never确保它不会被重启。这个临时 Pod 用完即弃,不会在集群里留下垃圾资源。

6. 配置与密钥管理

6.1 ConfigMap 的创建与使用

从字面量创建:

kubectl create configmap app-config --from-literal=LOG_LEVEL=debug --from-literal=MAX_CONN=100

从文件创建:

kubectl create configmap app-config --from-file=config.properties

从目录创建:

kubectl create configmap app-config --from-file=./configs/

查看 ConfigMap 内容:

kubectl get configmap app-config -o yaml

更新 ConfigMap 后,挂载为卷的 Pod 会自动更新文件(有延迟),但作为环境变量注入的不会自动更新,需要重启 Pod。

6.2 Secret 的注意事项

创建 Secret:

kubectl create secret generic db-secret --from-literal=password=mysecret

查看 Secret:

kubectl get secret db-secret -o yaml

Secret 默认只做 Base64 编码,不是加密。任何有权限读取 Secret 的人都能解码看到明文。生产环境需要开启静态加密,并严格控制 RBAC 权限。我见过把数据库密码直接放在 Secret 里、又给了过宽读取权限的配置,这等于把钥匙挂在门上。

7. 资源编辑与扩缩容

7.1 edit:直接修改运行中资源

kubectl edit deployment <deployment-name>

这个命令会用默认编辑器打开资源的实时配置,保存后立即生效。适合快速调整镜像版本、副本数、环境变量等。

但edit有个问题:改动只存在于集群里,没有同步到版本控制文件。下次用apply覆盖时,这些改动就丢了。所以我的原则是:临时调试可以用edit,正式变更必须改文件再apply。

7.2 scale:调整副本数

kubectl scale deployment <deployment-name> --replicas=5

这个命令在应对突发流量时很直接。但要注意,如果 Deployment 配置了 HorizontalPodAutoscaler,手动扩缩容可能会与自动策略冲突。HPA 会在下一次评估时把副本数拉回它计算的值。

7.3 rollout:滚动更新与回滚

查看更新状态:

kubectl rollout status deployment <deployment-name>

查看更新历史:

kubectl rollout history deployment <deployment-name>

回滚到上一版本:

kubectl rollout undo deployment <deployment-name>

回滚到指定版本:

kubectl rollout undo deployment <deployment-name> --to-revision=2

暂停和恢复滚动更新:

kubectl rollout pause deployment <deployment-name> kubectl rollout resume deployment <deployment-name>

暂停功能在需要连续修改多个字段时很有用,避免每次修改都触发一次滚动。

8. 常见问题与排查技巧实录

8.1 Pod 一直 Pending 怎么办

按这个顺序排查:

  1. kubectl describe pod <pod-name>看事件
  2. 检查节点资源是否充足:kubectl describe nodes看 Allocated resources
  3. 检查是否有污点导致无法调度:kubectl describe node <node-name> | grep Taints
  4. 检查 Pod 是否指定了不存在的节点选择器或亲和性规则

常见原因速查:

现象可能原因解决方向
事件显示 Insufficient cpu节点 CPU 不足扩容节点或降低请求
事件显示 node(s) had taint节点有污点添加容忍或去掉污点
事件显示 no nodes available没有可用节点检查节点状态
无事件产生调度器异常检查调度器组件状态

8.2 镜像拉取失败

ImagePullBackOff是最常见的启动失败原因之一。排查步骤:

  1. 确认镜像地址拼写正确
  2. 确认镜像仓库可达(在节点上手动拉取测试)
  3. 检查 Secret 是否存在且配置正确
  4. 检查 ServiceAccount 是否绑定了正确的 imagePullSecrets

我遇到过一次镜像地址里多了个空格,describe事件里显示得很清楚,但如果不看事件直接猜,可能要绕很久。

8.3 服务访问不通

从集群内部和外部两个方向排查:

集群内部:

kubectl run test --image=busybox --rm -it --restart=Never -- sh wget -qO- http://<service-name>.<namespace>:<port>

外部访问:

  • 检查 Service 类型是否为 NodePort 或 LoadBalancer
  • 检查防火墙规则是否放行对应端口
  • 检查 Ingress 配置是否正确

8.4 节点 NotReady

节点失联通常意味着节点上的核心组件出了问题。排查顺序:

  1. kubectl describe node <node-name>看事件和条件
  2. 登录节点检查容器运行时状态
  3. 检查节点磁盘空间:df -h
  4. 检查节点内存:free -h
  5. 检查网络插件 Pod 是否正常

磁盘压力是最常见的诱因。镜像和日志堆积会迅速吃掉磁盘空间,触发驱逐策略。

9. 效率提升:别名、补全与批量操作

9.1 设置命令别名

在~/.bashrc或~/.zshrc里加几行别名,能省下大量敲键盘的时间:

alias k='kubectl' alias kgp='kubectl get pods' alias kgs='kubectl get services' alias kgd='kubectl get deployments' alias kdp='kubectl describe pod' alias kl='kubectl logs' alias kex='kubectl exec -it'

我用了几年下来,k和kgp是使用频率最高的两个。

9.2 开启命令补全

bash:

source <(kubectl completion bash) echo "source <(kubectl completion bash)" >> ~/.bashrc

zsh:

source <(kubectl completion zsh) echo "source <(kubectl completion zsh)" >> ~/.zshrc

补全不仅补命令名,还能补资源名、命名空间、参数值。开启之后,输入kubectl get po再按 Tab,会自动列出当前命名空间下的 Pod 名称。

9.3 批量操作技巧

删除所有 Evicted 状态的 Pod:

kubectl get pods --all-namespaces | grep Evicted | awk '{print $2 " -n " $1}' | xargs -n 2 kubectl delete pod

这个命令组合看起来复杂,拆开看就清楚了:先列出所有 Pod,筛选出 Evicted 状态的,提取命名空间和 Pod 名,再批量删除。我把它存成了一个脚本,节点磁盘告警时直接跑。

查看所有命名空间下非 Running 状态的 Pod:

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

--field-selector是服务端过滤,比用 grep 筛选更高效,尤其在大规模集群里。

10. 我踩过的坑与实操心得

第一个坑是关于kubectl apply的。早期我习惯用create创建资源,后来想改用apply管理,结果发现apply报错说缺少last-applied-configuration注解。原因是create创建的资源没有这个注解,apply无法进行三方合并。解决办法是先kubectl apply -f一次,或者手动补上注解。从那以后,我所有正式资源一律用apply创建。

第二个坑是关于命名空间的。有次排查一个服务不通的问题,查了半天 Service 和 Endpoint 都正常,最后发现是kubectl默认命名空间不对,我看的根本不是同一个命名空间下的资源。现在我养成了一个习惯:所有命令都显式加-n参数,哪怕当前上下文已经切到了目标命名空间。多打几个字符,换来的是一致性和可复现性。

第三个坑是关于exec的。有次在容器里改了一个配置文件,重启 Pod 后改动全没了。因为容器重启会重建文件系统,所有运行时改动都会丢失。正确的做法是改 ConfigMap 或镜像,而不是进容器改文件。这个教训让我彻底放弃了“进容器修配置”的念头。

第四个坑是关于资源删除的。有次删除一个 Deployment,发现对应的 Pod 还在。原因是那些 Pod 不是这个 Deployment 管理的,只是标签恰好相同。kubectl delete deployment只删除它自己管理的 ReplicaSet 和 Pod。删除前用kubectl get pods -l <label>确认一下归属关系,能避免误判。

最后一个心得是关于--dry-run的。在真正执行变更前,用--dry-run=client或--dry-run=server预览结果,能发现很多低级错误。比如:

kubectl apply -f deployment.yaml --dry-run=server

服务端 dry-run 会走完整的准入控制链,能发现客户端 dry-run 发现不了的问题,比如资源配额不足、准入 webhook 拒绝等。这个习惯帮我避免了好几次把错误配置推到集群里。

命令这东西,看十遍不如敲一遍。建议你对着一个测试集群,把上面这些命令挨个跑一次,遇到报错就查事件、看日志,慢慢就形成肌肉记忆了。真正排障的时候,脑子里自然就会浮现出该用哪个命令、该看哪个字段。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进