ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

kubectl资源管理命令实战:从排查故障到集群运维的完整指南

kubectl资源管理命令实战:从排查故障到集群运维的完整指南 1. 为什么资源管理命令值得系统性掌握1.1 从一次排查半小时的真实经历说起大概两年前的一个工作日下午集群告警突然嗡嗡响起来某核心服务连续三次健康检查失败。我当时的反应和大多数刚上手 Kubernetes 的运维一样先kubectl get pods看到某个 Pod 显示CrashLoopBackOff然后立刻kubectl logs去看日志。日志刷了一屏看起来是连接数据库超时。我又跑去看数据库网络没问题账号密码也没问题折腾了快半小时。最后无意间执行了一次kubectl describe pod才发现在 Events 里有这么一条Error: ImagePullBackOff镜像拉取失败因为私有仓库的凭证过期了。日志里的数据库连接超时只是应用层对上游依赖失败的兜底报错真正的根因和这一个 Pod 相关的事件全都在describe的 Events 里。那次之后我彻底改掉了拿日志当唯一线索的习惯。排障链路应当是先看事件、再看配置、最后看日志。这个习惯的形成正是建立在对资源管理命令的体系化理解之上。1.2 资源管理命令背后的核心机制kubectl 如何工作要真正把命令用好需要理解 kubectl 的工作原理。kubectl 本质上是一个 HTTP 客户端它做的事是把你在终端里输入的命令解析成对 Kubernetes API Server 的 REST API 请求。整个过程大概是读取本地~/.kube/config配置获得集群地址和凭证然后通过 HTTPS 把请求发给 API ServerAPI Server 完成认证和授权校验后会从 etcd 读取对应资源的状态或者将变更写入 etcd。所以你会看到很多命令有相似的结构kubectl get、kubectl describe、kubectl delete都是对同一类资源的操作区别只是 HTTP method 不同。这也解释了为什么在 Pod 上执行kubectl logs不需要进容器就能拿到日志——这个动作在 API Server 层被转成了对 kubelet 的请求再由 kubelet 读取容器运行时日志。理解了这一点就能明白另外两个重要推论。第一只要网络通、Token 有权限你完全可以用curl去调用 APIkubectl 只是把这件事封装得更友好。第二不同资源的字段设计是有规律的绝大多数资源都包含metadata、spec、status三段查询命令的输出格式和过滤方式也都建立在这个统一模型基石之上。1.3 学习路径建议别把命令当死记硬背市面上关于 kubectl 命令的速查表非常多但死记硬背的效果往往不太好。原因很简单命令是跟着资源走的资源的组织逻辑是先有集群层面资源Namespace、Node、RBAC再有工作负载Pod、Deployment、StatefulSet然后是服务发现与配置Service、ConfigMap、Secret最后是存储和其他扩展资源。我建议的学习路径是按照这个资源的逻辑链条去学命令每学一类资源的同时理解它解决什么问题、上层的容器编排概念是什么。这样一来即使遇到一个从没见过的资源类型知道了它属于哪个层级也能立刻推断出大致该用哪些操作。下面我将按这个维度把日常最常用、真正的生产环境中高频率使用的命令串起来讲一遍每一条都会给出使用场景和注意事项这样你可以直接抄作业也看得懂背后为什么这么用。2. 集群与命名空间先看清你的家底2.1 查集群信息和节点状态在工作中进入一个陌生集群的第一件事我建议先执行三连kubectl cluster-info kubectl get nodes -o wide kubectl version --shortcluster-info输出集群的控制面地址可以快速确认自己连的是哪个集群尤其是在本地配置了多个 context 时这一步能避免在测试集群上执行生产操作这种低级且危险的事故。get nodes -o wide会额外显示节点的内网 IP、操作系统、内核版本和容器运行时信息。升级集群或更换运行时之后我通常会先看这个输出确认所有节点版本一致。kubectl version检查客户端和服务端版本差。Kubernetes 官方支持最多前后一个 minor 版本的客户端如果差得太多很多命令行为会变得不可预测。如果你在一个大型集群里工作节点数量几百上千的时候get nodes会刷屏。这种情况下更合适的做法是加 label 过滤kubectl get nodes -l node-role.kubernetes.io/control-plane kubectl get nodes -l disktypessd节点返回状态里有NotReady、SchedulingDisabled等这通常意味着节点有问题。要快速定位可以去查节点上的条件状态kubectl describe node node-name重点关注Conditions部分如果MemoryPressure或DiskPressure是 True说明节点资源告急很可能会导致后续的 Pod 驱逐。2.2 Namespace 的创建、切换与配额管理Namespace 是 Kubernetes 实现资源隔离的第一道边界。老实说很多小团队初期只用一个 default Namespace等业务多起来之后就会变得很痛苦资源混在一起权限说不清楚。创建和删除 Namespace 本身并不复杂kubectl create namespace staging kubectl delete namespace staging不过我需要提醒一点delete namespace是删除性的操作会连带把该命名空间下所有资源一起删掉而且这个过程有时候不会立刻完成当 Namespace 卡在 Terminating 状态时往往是因为里面还有一些自定义资源或者 finalizer 没有清理干净。曾经有个业务方反馈某个命名空间删不掉查了半天是 CRD 实例还有残留把对应的 CR 删掉之后Namespace 才被真正回收。比起创建删除更常用的是 ResourceQuota 和 LimitRangekubectl create quota dev-quota --namespacedev \ --hardpods20,requests.cpu10,requests.memory20Gi,limits.cpu20,limits.memory40Gi这两类资源是用来控制命名空间内总容量和单 Pod 资源上下限的。加了 Quota 之后如果一个 Deployment 扩容时发现配额不足ReplicaSet 会一直无法创建新 Pod此时从get events能看到FailedCreate的报错。生产环境里我见过不少莫名其妙扩不了容的案例最后排查结果都是 Quota 被占满了。2.3 资源信息的完整版检索get、describe、logs 三件套把这三条命令合起来讲是因为它们其实对应了三个诊断层级kubectl get看的是概要是当前有哪些资源、处于什么状态的结论列表。kubectl describe看的是详情包括标签、注解、事件回答这个资源经历了什么。kubectl logs看的是运行时日志回答应用内部到底打印了什么。一个常见的误区是get的结果显示 Pod 是 Running就觉得应用一定没问题。实际上 Running 只代表容器进程活着不代表应用健康。判断应用是否正常还需要看READY列的1/1是否为满以及结合kubectl logs或进入容器执行命令来验证。进入容器执行命令的场景也非常高频kubectl exec -it pod-name -n namespace -- /bin/sh注意如果 Pod 里有多个容器需要加-c container-name指定。否则 kubectl 会默认选择第一个容器如果选错了看到的是错误的应用环境。另外我强烈建议各位养成加命名空间参数的习惯-n用得不勤的人往往会出现命令没报错但操作的是另一个 Namespace 的对象的问题。如果嫌每次敲太麻烦可以通过切换 context 的默认命名空间来简化比如kubectl config set-context --current --namespacedev3. 工作负载资源的日常管理Pod、Deployment、StatefulSet3.1 Pod 的查询与排障命令Pod 是最小的调度单元所以所有排障工作最终几乎都会落到 Pod 上。最基础也是最常用的组合kubectl get pods -n namespace kubectl get pods -n namespace -o wide-o wide会多显示节点 IP、Pod IP 和所在 Node。排查网络问题时看到 Pod IP 和 Node IP 能帮你画出一个简单的流量路径。另一个高频操作是查看某个 Pod 的全部信息并转为 YAMLkubectl get pod pod-name -n namespace -o yaml这个命令在排查问题时极其有用。你可以从status.conditions里看到 Pod 处于什么阶段从spec.containers里核对镜像版本和环境变量从metadata.annotations里看到一些控制器或者服务网格注入的信息。Pod 出现异常时状态通常有以下几种我整理成了一张速查表状态常见原因第一排查命令Pending资源不足、节点亲和性不满足、PVC 无法绑定kubectl describe podImagePullBackOff镜像名称错误、凭证失效kubectl describe pod查看 EventsCrashLoopBackOff应用启动崩溃kubectl logs --previousRunning但READY为 0/1就绪探针失败kubectl describe pod看探针事件Terminating长时间不消失进程不响应 SIGTERM、挂载点问题kubectl get pod -o yaml查看 finalizers在 CrashLoopBackOff 场景里有一个非常容易被忽略的命令kubectl logs pod-name -n namespace --previous因为容器崩溃之后kubectl 默认拿到的当前容器日志可能是空的加上--previous才能看到上一次容器退出前的日志。遇到启动即崩的应用这个命令能救急。3.2 Deployment 的滚动更新、回滚与扩缩容Deployment 是大多数无状态应用的标准载体日常管理中它的核心操作集中在发布和扩容上。先看一次完整的滚动发布常用流程kubectl set image deployment/deployment-name container-namenew-image:tag -n namespace kubectl rollout status deployment/deployment-name -n namespaceset image会触发 ReplicaSet 的滚动更新。执行后一定等到rollout status返回 success 才能认为发布完成。我见过一些同学执行完 set image 就直接走了但实际新版本由于启动探针失败一直没起来旧 Pod 被全部摘掉后服务直接雪崩。如果滚动更新过程中发现异常可以暂停和恢复发布kubectl rollout pause deployment/deployment-name -n namespace kubectl rollout resume deployment/deployment-name -n namespace回滚是发布失败时的保命手段kubectl rollout history deployment/deployment-name -n namespace kubectl rollout undo deployment/deployment-name -n namespace --to-revisionrevision-number这里有一个经验历史版本不能无限保留默认只保留最近的 10 个 ReplicaSet 记录如果回滚目标版本因为保留策略已被清理undo会直接失效。所以每次发布前最好确认一下当前版本号并且在大版本发布前把重要的历史版本 revision 信息记下来。水平扩缩容也经常用到另外如果是定时扩容需求建议使用 HPAkubectl scale deployment/deployment-name --replicas10 -n namespace kubectl autoscale deployment/deployment-name --min3 --max10 --cpu-percent60 -n namespace3.3 StatefulSet 与 Job/CronJob 的特殊处理StatefulSet 用于有状态应用比如数据库、ZooKeeper、Kafka 等。它的管理命令和 Deployment 大体类似但有三个需要特别注意的差异点。第一扩缩容时 Pod 的命名是序号式的删除任意一个节点后控制器会重建相同序号的 Pod而且每个 Pod 的 PVC 是独立绑定的。所以在get pods时你看到的 pod-0、pod-1、pod-2 是有状态的不能像 Deployment 那样随意删。第二StatefulSet 默认滚动更新的策略是从最后一个 Pod 开始即最大序号往小推进所以rollout status观察到的更新顺序和 Deployment 相反这是官方设计里为了尽量降低可用性风险的举措。kubectl rollout status statefulset/statefulset-name -n namespace第三遇到卡在 Pending 的 StatefulSet Pod优先级最高的是查看 PVC 状态。Pod 起来的前提是 PVC 能绑定成功kubectl get pvc -n namespace kubectl get pvJob 和 CronJob 的命令也有自己的特点。Job 的查询通常会关注完成状态和失败原因kubectl get jobs -n namespace kubectl describe job job-name -n namespaceCronJob 排查时最值得注意的是上一次是否成功调度kubectl get cronjob cj-name -n namespace kubectl get jobs -n namespace --watch尤其是当一个 CronJob 执行了但没有产生任何新 Job 时大概率是 suspend 字段被勾选、或者并发策略卡住了上一次执行也可能是因为历史成功记录达到successfulJobsHistoryLimit上限。4. 服务发现与配置管理Service、ConfigMap、Secret4.1 Service 的端点检查与调试Service 做的是 Pod 的逻辑抽象和负载均衡。排障时我几乎每次都会先确认 Endpoints 是否是满的kubectl get svc -n namespace kubectl get endpoints svc-name -n namespace如果ENDPOINTS列表里没有 IP说明 Service 的 selector 没有匹配到任何 Pod。这种场景下最常见的坑是 Pod 上打的 label 和 Service selector 里的 key/value 对不上。查法是用kubectl get pods --show-labels直接看每个 Pod 的标签手动比对一下就能发现是哪里不一致。Service 的类型不同后续调试的切入点也不一样ClusterIP只能在集群内访问通过kubectl port-forward或跳板机测试。NodePort会在每个节点上开一个高端口kubectl get svc -o wide能直接看到端口号。LoadBalancer通常由云平台分配公网/内网 IPEXTERNAL-IP显示 pending 时基本是云控制器管理器的问题。有时需要验证某个 Service 是否真的能转发流量可以用一条临时 Pod 来测试kubectl run curl-test --imagecurlimages/curl -it --rm -- sh # 然后在容器里执行 curl http://service-name.namespace.svc.cluster.local很多同学在测试 Service 时习惯在集群外直接 curl如果 Service 是 ClusterIP 类型外部访问不了是正常行为这时候用上述方法才是正确的验证姿势。4.2 ConfigMap 和 Secret 的实用操作配置管理这块命令本身不多但踩坑率一点都不低。创建 ConfigMap 有多种方式最常见的三种kubectl create configmap app-config --from-literalkey1value1 --from-literalkey2value2 kubectl create configmap app-config --from-fileapplication.yaml kubectl create configmap app-config --from-env-fileenv.properties查看配置内容kubectl get configmap app-config -n namespace -o yamlSecret 的创建类似kubectl create secret generic db-password --from-literalpasswordabc123需要注意的一个关键认知ConfigMap 和 Secret 更新后已经运行的 Pod 不会自动拿到新配置。环境变量注入的配置在容器启动时就已经定下来了热更新只对挂载为 Volume 的方式有效而且通常还需要额外触发一次重启或 reload 才能生效。这几乎是生产环境最常见的配置改了没生效问题根源。实战中的做法一般是先更新资源对象再滚动重启工作负载kubectl rollout restart deployment/deployment-name -n namespace因为 Secret 默认会被 base64 编码存储有些人会误以为它是加密存储的。实际上只是编码不是加密。在真实生产环境里Secret 应该配合加密存储或者在应用层做额外的敏感信息保护这个观念一定要有。4.3 持久化存储的查询与管理持久化卷相关的排查一般集中在两个方面PVC 是否绑定成功、PV 的回收策略是否正确。查看当前存储情况kubectl get pv kubectl get pvc -n namespace kubectl get storageclasskubectl get pv的输出里有一个RECLAIM POLICY列常见值是Retain和Delete。如果你的云盘是按需创建、按量付费Delete会导致 PV 在 PVC 删除时被直接释放数据一并消失。有些业务方不太清楚这个机制手动删了 PVC 之后数据找不回来追悔莫及。在动态供给的环境下kubectl get pv里的STATUS如果一直是Pending大概率是对应 StorageClass 的 provisioner 配置有问题或者云平台额度受限。快速验证方式是查看 PVC 的事件kubectl describe pvc pvc-name -n namespace5. 一个完整的实战推演从异常现象到定位故障5.1 故障现象描述与初步排查某天线上反馈支付服务最近几次发版后偶发超时但没有大面积报错。第一反应当然是先看 Pod 状态和最近事件。kubectl get pods -n payment kubectl get events -n payment --sort-by.lastTimestamp看到的结果是Pod 都处于 Running但 RE ADY 列中有的容器是2/3说明其中一个容器还没通过就绪检查。Events 里出现了Unhealthy的 Readiness probe 失败记录再配合时间点看正好是最近一次发布的镜像带入的。5.2 逐步定位用命令拆解问题接下来按三个方向继续深挖。方向一单 Pod 详细状态。执行kubectl describe pod pod-name查看容器状态里的Last State和探针信息发现失败的是 HTTP 请求探针返回码偶尔是 503。方向二日志。执行kubectl logs pod-name -c container-name看到的是网关模块在启动早期健康检查路由还没注册完成的报错。这就是典型的启动慢导致就绪探针过早判定失败。方向三对比历史版本。执行kubectl rollout history deployment/payment-service kubectl rollout undo deployment/payment-service --to-revision3回滚到上一个稳定版本后kubectl rollout status deployment/payment-service显示成功再观察探针几秒内 READY 回到3/3。这次事故的根因其实就是新版应用的启动时间比就绪探针的initialDelaySeconds更长只需要在 YAML 的探针配置里把initialDelaySeconds调大或者在应用里优化启动阶段的路由注册顺序就能解决。5.3 复盘哪些命令组合最有效这次排查有效组合是get events完成时间线和现象定位describe pod完成探针和容器状态确认logs -c完成应用内部证据补全rollout historyrollout undo完成快速止血值得说明的是rollout undo在生产环境是一个高风险操作因为它相当于一次反向发布。如果旧版本也有兼容性问题回滚本身也会引发新故障。所以稳妥的做法是在回滚之前先把新版本的镜像 tag 和旧版本的配置备份好回滚后持续观察几轮健康检查不要一看到 READY 就放松警惕。6. 权限、安全与日常巡检高级用法与注意事项6.1 认证授权相关的查询命令资源管理命令不仅用于业务资源也用于权限体系的管理。查看当前用户对某个资源是否有操作权限最直观的方式是用auth can-ikubectl auth can-i list pods -n payment kubectl auth can-i create deployment -n payment kubectl auth can-i --list -n payment--list会列出当前用户在该命名空间下所有能执行的操作权限排查时非常高效。曾经有位同事反馈自己创建不了 PVC但是明明给了edit角色。最后用auth can-i --list一看其实那套 RBAC 角色里根本没有包含 PVC 的 create 权限edit角色只覆盖了部分核心资源并不是万能的。查看集群里的 RBAC 配置也属于日常巡检内容kubectl get roles,rolebindings -n namespace kubectl get clusterroles,clusterrolebindings kubectl describe clusterrolebinding binding-name6.2 资源使用情况的巡检技巧日常巡检中我最常使用的两条命令是kubectl top nodes kubectl top pods -n namespacetop命令依赖 metrics-server 或者 Prometheus adapter 提供数据。如果执行时报错metrics not available首先要确认 metrics-server 是否运行正常而不是怀疑命令本身。如果要按 CPU 或内存占用排序找出异常 Pod配合--sort-by很好用kubectl top pods -n namespace --sort-bycpu还有一种更加工程化的巡检方法是给节点打上污点来标记维护状态配合命令查看调度结果kubectl taint nodes node-name keyvalue:NoSchedule kubectl cordon node-name kubectl drain node-name --ignore-daemonsets --delete-emptydir-datacordon是标记节点不再参与新的调度drain则是将已有 Pod 迁移走。执行drain之前要特别注意如果节点上有单独的存储卷或者本地数据--delete-emptydir-data会清除 emptyDir 数据操作前需要仔细评估。6.3 几个我实际踩过的坑和实用技巧最后分享几个非常实际的操作细节希望各位少走弯路。第一个坑kubectl delete pod的时候如果不加--force --grace-period0Pod 会先进入 Terminating 状态如果容器一直不响应 SIGTERM删除操作会卡住。但反过来--force会跳过优雅终止流程可能导致应用来不及做清理动作这要视情况权衡。一般不建议在生产上随手 force 删除除非你明确知道这个应用是无状态且对中断不敏感的。第二个坑kubectl apply -f和kubectl create -f是有区别的。apply是做声明式合并适合反复更新同一个资源create是命令式创建如果资源已存在会直接报错。同一个 YAML用apply做了多次更新后如果在资源里出现了不再需要的字段直接修改 YAML 再apply有时不能将其删除需要手动通过kubectl edit或者删除重建来解决。这也是apply一个经典的“历史字段残留”问题。第三个技巧输出格式是提高效率的利器。-o wide是基础款-o yaml适合导出和备份-o jsonpath和-o custom-columns则适合做字段级提取。比如只列出每个 Pod 的 IP 和命名空间kubectl get pods -A -o custom-columnsNS:.metadata.namespace,POD:.metadata.name,IP:.status.podIP这个命令在写脚本做自动化巡检时非常香。再配合-w参数可以实时追踪资源变化kubectl get pods -n namespace -w我平时做发布观察时一般会开两个终端一个跑get events -w一个跑get pods -w这样发布过程中的任何异常都能第一时间看到不必等到用户报障。Kubernetes 的常见资源管理命令说到底是围绕查看状态、描述详情、查看事件、操作变更这些动作展开的。只要把资源的组织层级和 kubectl 的三大输出视角理解透了大部分排查场景都能从容应对。从我个人经验来说每天花十分钟跑一遍kubectl get nodes、kubectl top pods、kubectl get events对整个集群的健康度会形成一种非常敏锐的直觉。这种直觉比任何告警规则都更早发现问题。最后再分享一个小技巧在自己常用的工作目录里放一个集群信息速查脚本把 context、节点数、核心 Namespace 的异常状态一次性打印出来日常巡检只需要执行一条命令效率提升非常明显。
返回列表