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 yamlSecret 默认只做 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 怎么办
按这个顺序排查:
kubectl describe pod <pod-name>看事件- 检查节点资源是否充足:
kubectl describe nodes看 Allocated resources - 检查是否有污点导致无法调度:
kubectl describe node <node-name> | grep Taints - 检查 Pod 是否指定了不存在的节点选择器或亲和性规则
常见原因速查:
| 现象 | 可能原因 | 解决方向 |
|---|---|---|
| 事件显示 Insufficient cpu | 节点 CPU 不足 | 扩容节点或降低请求 |
| 事件显示 node(s) had taint | 节点有污点 | 添加容忍或去掉污点 |
| 事件显示 no nodes available | 没有可用节点 | 检查节点状态 |
| 无事件产生 | 调度器异常 | 检查调度器组件状态 |
8.2 镜像拉取失败
ImagePullBackOff是最常见的启动失败原因之一。排查步骤:
- 确认镜像地址拼写正确
- 确认镜像仓库可达(在节点上手动拉取测试)
- 检查 Secret 是否存在且配置正确
- 检查 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
节点失联通常意味着节点上的核心组件出了问题。排查顺序:
kubectl describe node <node-name>看事件和条件- 登录节点检查容器运行时状态
- 检查节点磁盘空间:
df -h - 检查节点内存:
free -h - 检查网络插件 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)" >> ~/.bashrczsh:
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 拒绝等。这个习惯帮我避免了好几次把错误配置推到集群里。
命令这东西,看十遍不如敲一遍。建议你对着一个测试集群,把上面这些命令挨个跑一次,遇到报错就查事件、看日志,慢慢就形成肌肉记忆了。真正排障的时候,脑子里自然就会浮现出该用哪个命令、该看哪个字段。