资讯详情

资讯详情

kubectl高频命令速查:Kubernetes运维排错实战手册

说实话Kubernetes 的命令行工具 kubectl 用熟了效率能翻好几倍。我在日常维护集群、排查问题、发布应用时最依赖的就是那几十条高频命令。这份速查不是把官方文档搬过来而是把我实际项目里反复用到、踩过坑、验证过的命令和参数整理出来每条都标清楚为什么这么用、什么时候需要用、以及哪些参数组合容易让人翻车。不管你是刚入门 K8s还是已经写过不少 yaml这篇都值得收藏下来当手边手册。这份内容的适用对象很直接用 kubectl 管理集群的人不管是开发者、运维还是 SRE。你能从中得到一套可以直接照抄的命令组合遇到 Pod 起不来、服务不通、资源卡住时按着里面的排查顺序走基本上不会跑偏。另外我也把参数部分做了重点拆解像 -o、-l、--field-selector、--dry-run 这些看起来简单实际组合起来的威力很大很多问题定位到根因靠的就是这些参数而不是 echo 打印日志。1. 为什么你需要一份K8s命令速查1.1 这命令到底有多常用kubectl 是 Kubernetes 的官方命令行客户端几乎所有的集群操作都通过它发起。我见过不少同学一开始只会在 get pods 和 logs 之间来回切换等遇到真正的问题比如 Deployment 更新没有生效、节点 NotReady、Pod 卡在 Pending就不知道该用哪条命令去定位。这是很正常的因为 K8s 的资源类型非常多光内置的工作负载类型就有 Deployment、StatefulSet、DaemonSet、Job、CronJob 这几种每个资源又有关联的子资源、事件、状态描述光靠死记硬背肯定不行。但如果有一份按场景组织的命令速查情况就完全不同了。查询类命令负责描述现状排查类命令负责缩小范围操作类命令负责修改状态资源清理类命令负责收尾。这套思路和任何系统运维都一样只是 K8s 的抽象层级更多需要掌握的查询入口也更多。我平时接到一个集群异常反馈脑子里第一反应就是先跑kubectl get events --sort-by.lastTimestamp看最近发生了什么再根据资源类型跑对应的describe这一步能解决大概一半的虚拟化层问题。把常用命令固化成肌肉记忆最大的好处是减少上下文切换。你要在终端和浏览器之间来回翻文档时事故现场早就变了。我自己写过一阵子速查卡贴在工位上后来发现最实用的反而是那些带参数解释的版本——光记命令不够参数之间的配合才是关键比如-o wide不是多显示一列那么简单--all-namespaces在排障时几乎可以救命。1.2 这份速查和官方文档的区别官方文档当然是权威的但它的定位是字典不是场景手册。字典把所有命令按字母排序参数说明写得很严谨但你看完还是不知道“Node 磁盘压力导致 Pod 被驱逐”时应该先查什么。这份速查是按照我实际使用频率和故障类型来组织的每个命令都配了真实场景说明参数部分也不是罗列所有选项而是挑那些最常用、性价比最高的讲并告诉你在什么条件下参数会失效。举个例子kubectl get pods -o jsonpath{.items[?(.status.phaseRunning)].metadata.name}这种命令官方文档里有但你要是没点 JSONPath 的基础根本不知道怎么写。我会把这类的用法拆开讲告诉你 JSONPath 的结构和常见的过滤条件怎么写而不是让你去啃一整章。另一个例子是--field-selector这个参数能按资源的字段精确过滤很多人根本没听说过但在排查“某个节点上的所有 Pod”或“所有 Failed 的 Pod”时非常好用。这份速查还含了不少我自己的习惯。比如我从来不用kubectl edit直接改线上资源而是先get -o yaml备份再改改完用apply回写。这种习惯没法从官方文档里学到但能避免很多事故。我尽量把这些经验也写进去让你少走弯路。2. 基础命令从零到能跑通一次发布2.1 查看集群与节点状态拿到一个新集群第一步永远是确认自己和集群的连接状态。kubectl cluster-info会打印出控制平面和核心组件如 CoreDNS、kube-proxy的访问地址如果集群没就绪这条命令会直接报错。更精细的视角是kubectl get nodes它列出所有节点及其状态、角色通常是 master/worker 或 control-plane/node、K8s 版本、容器运行时版本和操作系统类型。加上-o wide能看到节点的内部 IP、外部 IP 以及所在的可用区这在我们做网络诊断时非常有用。看节点状态时STATUS 列常见值有 Ready、NotReady、SchedulingDisabled 和 Unknown。NotReady 意味着节点上的 kubelet 长时间没上报健康状态通常和负载过高、磁盘满、网络分区有关。SchedulingDisabled 则说明节点被主动调控过比如执行过kubectl cordon设置了不可调度。这时候可以用kubectl describe node node-name查看节点状态的具体 Condition里面有 MemoryPressure、DiskPressure、PIDPressure、Ready 等详细字段能直接看到是哪一个维度的压力触发了异常。另外kubectl get nodes -o jsonpath这种高级查询也可以在日常巡检中使用。我习惯写一条命令同时输出节点名称、可分配 CPU 和内存、以及当前已用比例虽然用 Prometheus 也能看但命令行内直接出结果是最轻量的方式。还有一点节点维护前一定要用kubectl drain把业务 Pod 优雅撤离而不是直接cordon加一步手动删除 Pod否则工作负载可能面临中断。drain 有自动驱逐的功能配合--ignore-daemonsets可以跳过 DaemonSet 管理的 Pod避免卡住。2.2 命名空间与上下文切换命名空间是 K8s 隔离资源的基本单位。刚开始用集群的人最喜欢在所有命令后加-n指定命名空间但系统里通常有多个命名空间每次手打-n很麻烦。更聪明的办法是用kubectl config set-context来切换默认上下文。比如你经常操作 staging 环境可以执行kubectl config set-context context-name --namespacestaging然后kubectl config use-context context-name之后所有的 kubectl 命令都会默认在 staging 命名空间下工作不用再带 -n。查看当前上下文用kubectl config current-context查看所有上下文用kubectl config get-contexts。当多个集群切换时我习惯把每个集群的 context 命名成cluster-env比如 prod-k8s、dev-k8s这样一眼能看出自己在哪个环境避免误操作生产。还有一个容易被忽略的细节有些 cluster 连接需要自定义证书或 token如果多台机器共用 kubeconfig建议用KUBECONFIG环境变量合并多个配置文件而不是直接覆盖默认的 ~/.kube/config。命名空间本身的操作不多创建用kubectl create namespace ns查看列表用kubectl get ns。但你需要知道不同命名空间里的资源是逻辑隔离的网络策略可能进一步限制通信。排查跨服务调用问题时先确认是不是命名空间级网络策略拦截了请求这个排查方向经常比看代码更有效。2.3 部署与Pod生命周期管理部署一个应用最标准的命令是kubectl apply -f deployment.yaml推荐用 apply 而不是 create因为 apply 支持声明式更新后一次提交会对比当前状态做增量变更而 create 只能新建二次执行会报“已存在”错误。我们团队内部几乎所有工作负载都以 yaml 方式维护提交到 git 仓库后用 apply 同步到集群。这样的好处是随时能知道线上资源实际配置和仓库里是否一致。查看部署状态用kubectl get deployment检查滚动更新情况可以用kubectl rollout status deployment/name。这条命令会阻塞住直到部署成功或者超时非常适合写在发布脚本里判断发布是否完成。发布失败时用kubectl rollout undo deployment/name回滚到上一个版本也可以用--to-revisionn回滚到指定历史版本。查看历史版次用kubectl rollout history deployment/name里面会记录每次变更的版本号和变更原因前提是 deployment 没有设置revisionHistoryLimit: 0否则历史会被清空。Pod 是真正运行应用实例的最小单元查看列表用kubectl get pods。很多人不知道-o wide对查看 Pod 所在节点和 IP 非常方便有时 Pod 重启了、IP 变了-o wide能直接看到新旧差异。如果你想一次看到 Pod 的资源请求、限制以及 QoS 等级可以kubectl get pods -o custom-columnsNAME:.metadata.name,CPU:.spec.containers[*].resources.requests.cpu,MEM:.spec.containers[*].resources.requests.memory。这种自定义列输出是替代写脚本的最好方式效率和可读性都很高。Pod 的增删改查要注意一个点直接kubectl delete pod name会让 Deployment 管理下的 Pod 自动重新创建因为 ReplicaSet 会持续维持期望副本数。但如果你删除的是裸 Pod没有控制器管理的那它不会自动恢复。所以在做临时测试时我通常会明确知道自己删的是什么资源类型避免“删了之后怎么又起来了”或者“删了之后没起来”两种尴尬。3. 参数详解别只会加 -n 和 -o3.1 常用输出格式 -o 与自定义列kubectl 的-o参数真的是一个被严重低估的宝藏。基础用法有-o wide显示更多列-o json和-o yaml输出结构化对象-o name只输出资源名称-o jsonpath可以对字段做精确提取。很多人只用到前两个觉得够用就行了但实际上-o jsonpath和-o custom-columns才是命令行排障的效率神器。举个例子我想知道某个 Deploy 管理的所有 Pod 的名称用kubectl get pods -l appnginx -o name就能拿到每行一个 pod/xxx 格式的结果不用 grep 再去抠字段。如果想把 Pod 名称、所在节点、当前状态汇总成表格可以用kubectl get pods -o custom-columnsNAME:.metadata.name,NODE:.spec.nodeName,STATUS:.status.phase这种方式非常直观特别是节点有成百上千个 Pod 时比-o wide默认输出更容易找到关键信息。JSONPath 更灵活但语法也更容易出错。我总结一个经验当你要在 bash 脚本里把命令输出赋值给变量时优先用-o jsonpath配合--output后处理因为返回的是纯文本不会带多余的空格和表头。比如获取某个 Service 的 ClusterIPkubectl get svc nginx -o jsonpath{.spec.clusterIP}写 JSONPath 时建议先跑kubectl get resource -o json看一眼整体结构然后套路径别凭感觉写。我们会经常踩两个坑一是字段名大小写不对K8s 的 JSON 字段基本都是驼峰二是选择器把数组和对象弄混比如.items[*].metadata.name是取多个资源名称而.spec.containers[0].image是取第一个容器的镜像中括号里的*和数字含义完全不同。3.2 标签选择器与字段选择器标签选择器-l是 kubectl 里最常见的过滤方式。K8s 的所有资源都可以打标签所以-l appnginx,envprod这种组合可以精确定位一组资源。标签选择器支持、!、in、notin四种操作符比如-l env in (prod,staging)能选出两个环境的所有资源这个写法在排查多环境问题时特别好用。不过要注意标签不是随机加的工作负载的 selector 一旦创建就不能改否则 Deployment 会认为没有匹配的 Pod。所以设计标签体系时要提前规划尽量包含业务、环境、版本、组件等维度。字段选择器是--field-selector它按资源对象的字段过滤不是按标签。这俩经常被搞混实际应用场景也不同。比如我想列出某个命名空间下所有 Failed 的 Podkubectl get pods --field-selectorstatus.phaseFailed再比如列出所有在 control-plane 节点上的 Pod可以结合节点名过滤kubectl get pods -A --field-selectorspec.nodeNamenode-01-l和--field-selector可以同时使用但要注意field selector 不是所有字段都支持最常见的支持字段包括metadata.name、metadata.namespace、spec.nodeName、status.phase、spec.schedulerName等其他字段不可用时会直接报错。做批量清理时我看过有人用--field-selectorstatus.phaseSucceeded一次性删掉所有已经跑完的 Job Pod比手动一个个删高效得多。3.3 常用命令的隐藏参数有好几个参数平时不怎么被提到但实际价值极大。第一个是--dry-run。kubectl apply -f deployment.yaml --dry-runclient只做本地校验不会真的改集群--dry-runserver会在服务端做校验能提前发现资源冲突或 schema 问题。我以前写过不少 yaml经常在 apply 之后被报 schema 错误后来每次写完先跑一遍--dry-runserver把绝大部分语法问题在发布前就拦下来了。第二个是--validatefalse。在用kubectl apply或者create某些资源时如果希望跳过 schema 校验可以带上它。比如从旧集群导出的 crd 资源可能字段略微过时不兼容当前集群版本先--validatefalse导入再修复比卡死在入口强。当然不是所有的字段都能跳过去服务端会拒绝真正非法的资源这个参数更多是解决那种版本差异带来的“假报错”。第三个是删除类参数组合。kubectl delete pod name --grace-period0 --force可以强制立即删除。正常情况下K8s 会给 Pod 先发 SIGTERM等--grace-period默认 30 秒过后再发 SIGKILL这在测试环境想快速回收卡住的 Pod 时很有用。但强制删除有风险它绕过了一部分优雅终止逻辑如果应用没实现好信号处理可能会产生脏数据。我建议线上不要轻易用强制删除先看日志和事件确认是死锁或资源泄漏再决定。还有一个被忽视的参数是kubectl get events --sort-by.lastTimestamp里的 sort-by。它按事件时间排序把最近发生的问题排在最前面。默认输出按事件创建顺序排列最新的事件反而不在最显眼的地方加了这个排序排查问题时的体验会好很多。4. 排错与Debugkubectl 不只是看日志4.1 事件排查与describe使用技巧当 Pod 卡在某个状态比如一直 Pending、CrashLoopBackOff、ImagePullBackOff第一件事就是看事件。kubectl describe pod pod-name会在 Events 区域列出所有和该 Pod 相关的事件包括调度失败、拉取镜像失败、健康检查不通过、被驱逐等。describe 输出比较冗长你只要盯着两个部分Conditions 和 Events。Conditions 里看 Ready 是否是 True如果 False 会有详细原因Events 里看最下面的几条时间越近越可能是直接原因。describe不只适用于 Pod对节点、Service、Deployment 都适用。kubectl describe node node可以看到节点资源压力、镜像缓存、被驱逐的 Pod 列表以及集群证书过期时间。kubectl describe svc service可以查看 Endpoint 列表和负载均衡配置如果 Service 后端 Pod 数量为 0访问自然会失败。事件虽然好用但它有保留时间限制默认一小时左右会被清理。所以出了问题别磨蹭先立即抓事件。我平时会在脚本里把关键资源的事件追加到日志文件实现简单的问题留痕。还有一个小技巧kubectl get events --all-namespaces --sort-by.lastTimestamp | tail -50可以在多命名空间环境里快速找到全局问题比如某个节点的网络组件异常事件会在所有命名空间里批量出现。4.2 端口转发与exec交互调试用的两大神器是kubectl exec和kubectl port-forward。kubectl exec -it pod -- /bin/sh进入容器和 SSH 到服务器本质类似。进入容器后你可以看进程、看网络、看环境变量还可以直接 curl 内部端口。不过前提是容器镜像里得有 shell如果用的是 distroless 镜像没有 shell那就需要kubectl cp或者临时用调试容器比如kubectl debug。kubectl debug是后来加的能力可以在目标 Pod 旁边启动一个附加容器挂到同一个网络和进程命名空间专门用来排障非常灵活。端口转发适合本地调试。kubectl port-forward svc/my-service 8080:80把本地 8080 端口映射到 Service 的 80 端口。这条命令在你不想暴露服务、又需要访问集群内部服务时特别有用。比如想连集群内的数据库调试直接用 port-forward 到数据库 Service然后本地用数据库客户端连 localhost不用改配置、不用建跳板机。注意 port-forward 是长驻前台进程命令行会被一直占用可以加nohup或者放到后台。另外端口转发只适合低流量调试高并发场景应该走 Ingress 或 LoadBalancer转发路径的性能瓶颈明显。用 exec 调试时我有个习惯进入容器后先把时区、语言环境、代理变量都看一下经常发现问题出在环境变量没传全。比如容器内应用连不上某个内部服务先 exec 进去getent hosts my-service如果解析不到问题大概率不在应用代码而在 DNS 或 Service 定义。4.3 资源使用与节点诊断查看工作负载资源消耗kubectl top是最直接的命令。kubectl top node输出每个节点的 CPU 和内存使用率kubectl top pod输出每个 Pod 的实时用量。但它的前提是你已经部署了 metrics-server 或类似的指标采集组件否则会得到“Metrics API not available”的报错。没有指标组件时我一般用kubectl describe node里的 Allocated resources 来看调度请求量再用节点上的free、df等命令辅助判断。节点诊断方面kubectl get componentstatuses在旧版本里可以用来查看 etcd、kube-scheduler、kube-controller-manager 等核心组件的健康状态但新版本里这个命令已经被弃用推荐用kubectl get --raw/healthz或者直接访问各组件接口。你还可以用kubectl get nodes -o wide确认 kubelet 和容器运行时版本是否一致版本不一致时有时会出现容器运行时接口调用失败导致节点 NotReady。解除节点异常状态有一套固定流程。先确认节点是不是被cordon了如果是kubectl uncordon node恢复调度如果节点因为资源压力 NotReady需要先处理节点的磁盘或内存再重启 kubelet如果是 kubelet 崩溃通常要登录到节点上systemctl status kubelet看日志这已经超出 kubectl 范围但仍然是日常诊断的一部分。5. 实操总结这套命令组合拳怎么用5.1 场景一服务无法访问服务访问不通我会按以下顺序排查# 1. 确认 Service 是否存在以及它选择的 Pod kubectl get svc my-service -o yaml # 2. 查看 Service 的 Endpoint 是否有地址 kubectl get endpoints my-service # 3. 确认后端 Pod 状态 kubectl get pods -l appmy-app -o wide # 4. 查看最近事件 kubectl get events --sort-by.lastTimestamp | grep my-service如果 Endpoint 为空说明 Service 的 selector 没有匹配到任何 Pod最常见的错误是 yaml 里标签写错比如app: myapp写成app: my-app。如果 Endpoint 有地址但访问还是不通可能问题出在 kube-proxy 或 CNI 网络插件。这时用kubectl exec进入某个 Podcurl ClusterIP:port看能否通。通不了就进一步检查 Service 的 targetPort 是否和 Pod 内容器监听端口一致。5.2 场景二Pod起不来Pod 状态一直 Pending我用kubectl describe pod pod查看事件通常能看到调度失败的提示比如节点资源不足、节点亲和性不满足、或者有污点没有容忍。处理方式也对应扩容节点、修改资源请求、加 toleration。如果 Pod 状态是 CrashLoopBackOff说明容器启动后立刻崩溃看kubectl logs pod --previous拿到上一次容器的日志很多应用在重启前会打印 panic 或错误堆栈。注意--previous只适用于容器已经重启过的情况。如果 Pod 一直 ImagePullBackOff用kubectl describe pod pod看事件错误信息一般是拉取镜像超时或认证失败。检查镜像仓库地址是否写错、镜像标签是否存在、私有仓库的 imagePullSecret 是否正确配置。这里有个经验镜像拉取失败的事件会被保留一段时间但如果之前误填了不存在的镜像名后续改了 yaml 再 apply旧事件依然存在别被旧事件干扰看当前 Pod 的最近一次事件为准。5.3 场景三批量清理资源日常开发中经常要清理测试环境。比如清理所有 completed 的 Job使用 field selector 可以一步到位kubectl delete jobs --field-selectorstatus.successful1清理所有处于 Evicted 状态的 Podkubectl delete pods --field-selectorstatus.phaseFailed如果要按命名空间整体清理但保留命名空间本身可以用kubectl delete all --all -n ns。这个命令会删除该命名空间下所有常用资源类型包括 Pod、Service、Deployment、ConfigMap 等。注意它不会删除 PersistentVolumeClaim 和 Secret所以在清理测试环境时还要手动确认有没有要保留的数据卷。批量清理前我强烈建议先加--dry-runclient看一眼影响范围避免误删。6. 常见坑与经验6.1 两个容易忽略的权限坑一个是 kubectl 的权限来自 kubeconfig 中的用户凭证你当前 context 指向的凭证决定了你能操作哪些资源。如果你在生产环境切换到只读的 ServiceAccount却还在跑kubectl delete会收到 forbidden 报错。这个报错本身会让人误以为集群出问题了其实只是 RBAC 权限不足。排查这种事最快的方式是kubectl auth can-i delete pods它会直接告诉你当前用户有没有对应权限。另一个坑是 kubectl 的版本和集群版本不是严格匹配也没关系只要版本差不太远都能工作。但反过来插件或 CRD 需要版本兼容时就会出幺蛾子。如果你本地 kubectl 版本太旧打出来的资源结构可能缺失新字段--validatefalse可以一部分缓解但最好还是保持 kubectl 版本在 API 支持范围内。6.2 别把连接信息写死在命令里有人喜欢把集群地址和 token 直接写在 kubectl 命令里比如kubectl --serverhttps://... --token... get pods。这在临时联调时可以但长期用会带来安全和维护双重问题。正确做法是把连接信息放进 kubeconfig 的 context 中再通过别名来回切换。我用 alias 把各个环境封装成简单命令比如alias k-prodkubectl config use-context prod-k8s这样不仅操作方便还能避免因环境切换失败导致连错集群。6.3 让输出变成脚本可用的格式写自动化脚本时避免解析kubectl get的默认文本输出。默认输出是给人看的列对齐、空格多、表头干扰脚本解析容易崩。要使用-o jsonpath、-o custom-columns或者-o name让输出干净简单。比如我要取所有失败 Pod 的名字做批量删除可以写成kubectl get pods --all-namespaces --field-selectorstatus.phaseFailed -o jsonpath{range .items[*]}{.metadata.namespace}{ }{.metadata.name}{\n}{end}这里range和end是 jsonpath 的循环语法输出两列命名空间和 Pod 名称再用 awk 处理。这个模式我在很多自动化脚本里反复用基本不会出错。6.4 善用 shell 别名和函数kubectl 命令很长别名能减少很多输入。我自己的 bashrc 里长期躺着这几个alias kkubectl alias kgkubectl get alias kdkubectl describe alias klkubectl logs alias kxkubectl exec -it alias kgpkubectl get pods alias kgpakubectl get pods --all-namespaces再加一个函数快速进入某个 Podksh() { kubectl exec -it $1 -- /bin/sh; }用起来就是ksh pod-name清爽很多。但别把命令藏得太深至少你自己一个月后回来还能看懂这些缩写是什么不然脚本维护成本反而上升。最后再分享一个小经验。我刚开始用 K8s 时特别喜欢堆命令一条命令恨不得把全部信息都打出来后来发现格式化输出精确过滤才是王道。大部分排查场景根本不需要那么多输出你真正要找的是那个“不同点”。先把集群基线摸清楚比如节点资源、常见镜像版本、主要命名空间列表出了问题再对照基线去看差异比每次都从头看一遍整个集群状态高效得多。这份速查表里的命令都是我从那几趟折腾里沉淀下来的希望对你也有用。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →