1. 这不是命令清单而是一张 Kubernetes 环境里的“生存地图”你刚在某实验室的集群里拿到一个 kubeconfig 文件终端里敲下kubectl get nodes回车后光标闪了三秒——终于跳出两行带Ready状态的机器名。那一刻你松了口气但心里清楚这仅仅是你在 Kubernetes 世界里迈出的第一步连“站稳”都谈不上。kubectl 命令不是语法考试题而是你在容器编排战场上实时调兵遣将的无线电频道。我带过十几期某高校的云原生实训班几乎每届都有学员卡在“明明命令敲对了为什么 pod 一直 Pending”、“日志查不到describe 又看不懂”这类问题上。他们缺的不是命令本身而是命令背后那套“状态-动作-反馈”的闭环思维。这篇内容不罗列 200 条命令只聚焦真正高频、真正容易出错、真正能帮你快速定位和干预的 18 个核心命令组合。它们覆盖了从集群健康快筛、工作负载生命周期管理、网络与存储状态诊断到故障现场取证的完整动线。适合刚通过 CKA 认证但没实操过生产集群的新手也适合运维老手在凌晨三点排查告警时快速翻阅的“应急手册”。所有命令均基于 v1.26 版本实测验证参数取舍有明确依据输出字段解读直指关键信号不堆砌文档原文。2. 命令设计逻辑为什么是这 18 个而不是更多或更少2.1 不是“功能全”而是“路径短”聚焦四类核心操作动线Kubernetes 的命令体系庞大但真实运维中 90% 的操作可归为四条主干路径。我们筛选命令的唯一标准是能否在 3 步内完成一次有效干预或诊断。任何需要嵌套 5 层jsonpath或依赖外部工具链才能看懂的命令一律排除。集群健康快筛路径从get nodes到describe node再到logs组件日志形成“宏观状态→节点细节→组件日志”的三级穿透。例如kubectl get nodes -o wide会同时显示 IP 和 OS-Image比单纯get nodes多出两个关键信息维度却无需额外命令。工作负载生命周期路径create→get→describe→logs→exec→delete是最典型的 Pod 操作链。这里我们砍掉了apply -f它属于声明式管理非即时命令保留run用于快速测试镜像、scale应对突发流量、rollout滚动更新控制这三个无法被apply完全替代的即时动作。网络与存储状态路径get svc和get endpoints必须成对出现。单独看 Service 往往误判——ClusterIP显示正常但endpoints为空说明后端 Pod 根本没注册进来。同理get pvc和get pv要交叉验证PVC 的STATUS是Bound但 PV 的STATUS是Released这就是典型的资源回收陷阱。故障现场取证路径describe是黄金命令但它输出的信息量巨大。我们只提取其中 7 个必看字段Conditions节点就绪条件、Allocated resources资源分配水位、Events最近 10 条事件、Containers容器状态、Volumes挂载详情、Node-Selectors调度约束、Tolerations污点容忍。其他字段如Annotations在 99% 的故障中无直接价值。提示kubectl get默认只显示NAME,READY,STATUS,RESTARTS,AGE五列。但READY列对 Deployment 是2/2对 Pod 是1/1对 StatefulSet 是3/3——这个数字本身不告诉你“为什么是 2”必须结合describe中的Replicas和Available Replicas字段。新手常误以为READY为0/2就是 Pod 启动失败实际可能是 HPA 尚未触发扩缩容。2.2 参数精简原则去掉“看起来有用实则干扰判断”的选项kubectl支持上百个 flag但日常使用中超过 80% 的场景只需 5 个核心参数-n namespace命名空间是 Kubernetes 的第一道隔离墙。不加-n默认操作default而生产环境里default几乎永远是空的。我见过三次线上事故根源都是运维在kube-system下执行了delete pods --all只因忘了加-n monitoring。-o wide这是get类命令的“基础增强包”。get pods只显示 Pod 名和状态get pods -o wide额外增加NODE运行在哪台物理机、IPPod IP、CONTROLLER由哪个控制器创建三列。这三列信息在排查网络不通、节点资源争抢、控制器异常时效率提升 3 倍以上。-l label标签选择器是 Kubernetes 的“精准打击系统”。get pods -l appnginx比get pods | grep nginx更可靠——后者可能匹配到nginx-ingress-controller而前者只认appnginx这个精确标签。标签键值对必须完全匹配-l envprod,teambackend表示 AND 关系不存在 OR 逻辑。--field-selector当标签不够用时的终极武器。例如get pods --field-selector spec.nodeNamenode-03直接筛选运行在特定节点上的所有 Pod绕过标签体系。这个参数在节点故障隔离、批量迁移时不可替代。--sort-byget pods --sort-by.status.startTime按启动时间排序get nodes --sort-by.status.capacity.cpu按 CPU 容量排序。排序本身不解决故障但它让“异常值”自动浮到列表顶部——比如某个节点 CPU 容量突然变成0一眼就能发现。注意-o yaml和-o json是调试神器但绝不该用于日常巡检。它们输出的是完整对象定义包含大量元数据如creationTimestamp、resourceVersion这些字段对判断服务是否可用毫无帮助反而淹没关键信息。-o wide是平衡信息密度与可读性的最优解。2.3 版本兼容性锚点v1.26 的关键行为变更Kubernetes 的命令行为随版本演进有细微但致命的变化。以下三点是 v1.26 引入、且直接影响命令结果的硬性变更kubectl top不再默认启用v1.26 起top nodes和top pods需要 Metrics Server 显式部署且其 API 组从metrics.k8s.io/v1beta1升级为metrics.k8s.io/v1。若执行top nodes报错the server doesnt have a resource type nodes不是命令错了而是 Metrics Server 未安装或版本不匹配。kubectl auth can-i的 RBAC 检查更严格v1.26 对--list参数的响应格式做了调整。旧版返回yes/no新版返回allowed: true/allowed: false且新增reason字段说明拒绝原因如RBAC: clusterrole.rbac.authorization.k8s.io view not found。这意味着自动化脚本若用grep yes判断权限会在 v1.26 环境下全部失效。kubectl get events的默认时间窗口缩短v1.26 将事件默认保留时间从 1 小时缩短为 30 分钟。get events不再显示 1 小时前的事件除非显式指定--field-selector lastTimestampAfter2024-01-01T00:00:00Z。这对排查“昨天晚上发生的间歇性故障”造成障碍必须养成get events --all-namespaces --sort-by.lastTimestamp的习惯。3. 核心命令详解与实操现场记录3.1 集群健康快筛3 条命令锁定 80% 的集群级故障3.1.1kubectl get nodes -o wide这是 Kubernetes 的“体温计”。它不告诉你病因但能第一时间告诉你“是否发烧”。$ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME node-01 Ready control-plane 45d v1.26.3 10.0.1.101 none Ubuntu 22.04.3 LTS 5.15.0-86-generic containerd://1.7.2 node-02 Ready none 45d v1.26.3 10.0.1.102 none Ubuntu 22.04.3 LTS 5.15.0-86-generic containerd://1.7.2 node-03 NotReady none 2h v1.26.3 10.0.1.103 none Ubuntu 22.04.3 LTS 5.15.0-86-generic containerd://1.7.2关键字段解读STATUSReady表示 kubelet 正常上报心跳NotReady是红色警报但需进一步确认是网络中断、kubelet 崩溃还是磁盘压力过大。ROLEScontrol-plane角色节点承担 etcd、API Server 等核心组件。若所有 control-plane 节点STATUS都是NotReady整个集群已瘫痪。INTERNAL-IP必须是集群内部可路由的 IP。若显示none说明 kubelet 未正确配置--node-ipPod 网络将无法通信。CONTAINER-RUNTIMEcontainerd://1.7.2表示运行时版本。v1.26 要求 containerd ≥ v1.6.0若此处显示docker://20.10说明集群仍使用 Docker Engine存在兼容性风险。实操心得我曾在某次升级后发现get nodes输出中VERSION列全部为空。排查发现是 kubelet 配置文件中--kubeconfig路径错误导致 kubelet 无法连接 API Server自然无法上报版本信息。此时get nodes本身仍是成功的因为缓存但describe node会立即暴露Unable to connect to the server错误。3.1.2kubectl describe node node-name当get nodes显示NotReady时describe node是你的“CT 扫描仪”。它输出约 200 行信息但只需盯住三个区块$ kubectl describe node node-03 ... Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message ---- ------ ----------------- ------------------ ------ ------- MemoryPressure False Mon, 01 Jan 2024 10:00:00 0000 Mon, 01 Jan 2024 09:55:00 0000 KubeletHasSufficientMemory kubelet has sufficient memory available DiskPressure True Mon, 01 Jan 2024 10:00:00 0000 Mon, 01 Jan 2024 09:50:00 0000 KubeletHasInsufficientDisk kubelet has insufficient disk space available PIDPressure False Mon, 01 Jan 2024 10:00:00 0000 Mon, 01 Jan 2024 09:55:00 0000 KubeletHasSufficientPID kubelet has sufficient PID available Ready False Mon, 01 Jan 2024 10:00:00 0000 Mon, 01 Jan 2024 09:50:00 0000 KubeletNotReady runtime network not ready: NetworkReadyfalse reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized Allocated resources: (Total limits may be over 100 percent, i.e., overcommitted.) Resource Requests Limits -------- -------- ------ cpu 1100m (55%) 2100m (105%) memory 1800Mi (45%) 3200Mi (80%) ephemeral-storage 0 (0%) 0 (0%) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning ImageGCFailed 2m (x15 over 1h) kubelet failed to garbage collect required amount of images. Wanted to free 123456789 bytes, but freed 0 bytes Normal NodeHasSufficientMemory 1m (x20 over 1h) kubelet Node node-03 status is now: NodeHasSufficientMemory Warning EvictionThresholdMet 30s kubelet Attempting to reclaim ephemeral-storageConditions 区块这是诊断核心。DiskPressure: True直接解释了Ready: False的原因——磁盘空间不足。Reason字段KubeletHasInsufficientDisk和Message字段kubelet has insufficient disk space available是精准定位的关键线索。Allocated resources 区块cpu请求量1100m即 1.1 核占节点总容量2000m的 55%但memory限制量3200Mi占总容量4000Mi的 80%。这说明内存是瓶颈CPU 尚有余量。若此处ephemeral-storage显示10Gi (95%)则印证了磁盘压力。Events 区块ImageGCFailed事件反复出现表明镜像垃圾回收失败这是磁盘空间耗尽的直接前兆。EvictionThresholdMet是 kubelet 启动驱逐的信号。提示describe node输出的Capacity和Allocatable字段常被忽略。Capacity是硬件真实容量Allocatable是 Kubernetes 实际可调度的容量已扣除系统预留资源。若Allocatable远小于Capacity说明 kubelet 配置了过高的--system-reserved导致可用资源被过度预留。3.1.3kubectl get componentstatuses已弃用但必须知道替代方案v1.26 中componentstatuses已被移除因其依赖的/healthz端点不再提供细粒度状态。替代方案是直接检查核心组件的健康端点# 检查 API Server通常暴露在 6443 端口 $ curl -k https://127.0.0.1:6443/healthz ok # 检查 etcd需在 control-plane 节点执行 $ kubectl exec -n kube-system etcd-node-01 -- etcdctl endpoint health --cluster https://10.0.1.101:2379 is healthy: successfully committed proposal: took 12.345ms # 检查 Scheduler 和 Controller Manager通过日志 $ kubectl logs -n kube-system kube-scheduler-node-01 | tail -5 I0101 10:00:00.000000 1 leaderelection.go:248] attempting to acquire leader lease kube-system/kube-scheduler... I0101 10:00:00.000000 1 leaderelection.go:258] successfully acquired lease kube-system/kube-schedulerleaderelection.go:258日志中的successfully acquired lease是 Scheduler 正常工作的铁证。若日志中持续出现failed to renew lease说明 Scheduler 选举失败需检查kube-system命名空间下的endpoints资源。3.2 工作负载生命周期管理从创建到销毁的 7 个关键动作3.2.1kubectl run不只是“跑个容器”而是“快速验证镜像可用性”kubectl run是kubectl create deployment的快捷方式但它的核心价值在于即时性。create deployment创建的是声明式对象需等待控制器同步run则直接启动一个 Pod用于快速验证。# 最简模式启动单个 nginx Pod $ kubectl run nginx-test --imagenginx:alpine # 带端口映射和环境变量模拟真实应用 $ kubectl run web-test \ --imagenginx:alpine \ --port80 \ --envENVstaging \ --labelsappweb-test # 暴露为 Service一步到位 $ kubectl run db-test \ --imagepostgres:13 \ --port5432 \ --expose \ --namedb-service关键参数解析--port80此参数仅设置容器端口不创建 Service。它等价于在 Pod Spec 中添加containers[0].ports[0].containerPort: 80。若想对外提供服务必须配合expose或后续create service。--expose这是run命令的隐藏王牌。它会在创建 Pod 的同时自动生成一个同名的 ClusterIP Service并将 Service 的targetPort自动设为--port指定的值。run db-test --port5432 --expose生成的 Service其spec.ports[0].targetPort就是5432。实操心得run创建的 Pod 默认不带重启策略restartPolicy: Always但若 Pod 因错误退出run不会自动重建——它只是“运行一次”。这与deployment的“确保始终有 N 个副本”有本质区别。因此run仅用于测试切勿用于生产工作负载。3.2.2kubectl scale应对流量洪峰的“手动油门”scale是 Deployment/StatefulSet 的“实时扩缩容开关”它绕过 HPA 的监控-决策-执行循环实现秒级响应。# 将 nginx-deployment 从 3 个副本扩到 10 个 $ kubectl scale deployment nginx-deployment --replicas10 # 缩容到 1 个谨慎 $ kubectl scale deployment nginx-deployment --replicas1 # 对 StatefulSet 扩容注意StatefulSet 扩容是有序的新 Pod 名为 nginx-3 $ kubectl scale statefulset nginx-statefulset --replicas5底层原理scale命令直接 PATCH 更新 Deployment 的spec.replicas字段。API Server 接收到请求后立即触发 Deployment Controller 的 Reconcile 循环Controller 比较当前status.replicas实际运行数与spec.replicas期望数若不一致则创建或删除 ReplicaSet。注意scale不修改 Pod 的resources限制。若原有 Pod 申请 512Mi 内存扩容后的 Pod 依然申请 512Mi。若集群剩余内存不足新 Pod 将处于Pending状态。此时需先scale down其他工作负载或editDeployment 增加资源限制。3.2.3kubectl rollout滚动更新的“手术刀”rollout是管理 Deployment 更新过程的专用命令它把抽象的“滚动更新”变成了可观察、可控制、可回退的具体动作。# 查看 rollout 历史每个 revision 对应一次更新 $ kubectl rollout history deployment nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 1 kubectl run nginx-deployment --imagenginx:1.20 --replicas3 2 kubectl set image deployment nginx-deployment nginxnginx:1.21 # 回退到上一个版本revision 1 $ kubectl rollout undo deployment nginx-deployment # 回退到指定 revision $ kubectl rollout undo deployment nginx-deployment --to-revision1 # 暂停 rollout冻结更新过程便于人工检查 $ kubectl rollout pause deployment nginx-deployment # 恢复 rollout $ kubectl rollout resume deployment nginx-deploymentrollout history输出的CHANGE-CAUSE字段至关重要。它默认为空需在首次创建 Deployment 时添加--record参数才能捕获命令行$ kubectl create deployment nginx-deployment --imagenginx:1.20 --replicas3 --record实操心得rollout pause是我的“安全网”。在更新关键业务 Deployment 前我会先pause然后get pods确认新 Pod 已 Running 且 Ready再logs检查应用日志无 ERROR最后resume。这避免了“更新后才发现数据库连接字符串写错了”的灾难。3.2.4kubectl get pods -o wide --sort-by.status.startTime这不是一个命令而是一个“故障发现流水线”。它把时间维度引入 Pod 状态分析。$ kubectl get pods -n production -o wide --sort-by.status.startTime NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES api-7c8b9d4f5c-abcde 1/1 Running 0 15d 10.244.2.10 node-02 none none worker-5f6b8c7d4e-fghij 1/1 Running 0 15d 10.244.3.15 node-03 none none frontend-6d5c4b3a2f-klmno 0/1 Pending 0 2m none none none noneAGE列显示2m但--sort-by.status.startTime让frontendPod 排在最底部说明它是最新创建的。STATUS为PendingIP和NODE为空这是典型的调度失败信号。此时应立即describe pod frontend-6d5c4b3a2f-klmno重点查看Events中的FailedScheduling事件。提示--sort-by支持任意 JSONPath 表达式。--sort-by.metadata.creationTimestamp按创建时间排序--sort-by.status.phase按状态排序Pending排最前--sort-by.spec.nodeName按节点分组。这些技巧让get pods从“状态快照”变成“动态诊断面板”。3.2.5kubectl logs不止是“看日志”而是“构建上下文”logs命令的威力在于其上下文感知能力。它不是简单地 cat 容器日志而是理解 Kubernetes 的多容器、多副本、多命名空间结构。# 查看单个 Pod 的日志默认第一个容器 $ kubectl logs api-7c8b9d4f5c-abcde # 查看指定容器的日志Pod 内有多个容器时必需 $ kubectl logs api-7c8b9d4f5c-abcde -c api-server # 查看最近 100 行避免刷屏 $ kubectl logs api-7c8b9d4f5c-abcde --tail100 # 查看过去 5 分钟的日志需容器运行时支持 $ kubectl logs api-7c8b9d4f5c-abcde --since5m # 跟踪实时日志类似 tail -f $ kubectl logs api-7c8b9d4f5c-abcde -f # 查看已终止 Pod 的日志容器退出后日志仍可读 $ kubectl logs api-7c8b9d4f5c-abcde --previous--previous是救命参数。当 Pod 因 CrashLoopBackOff 重启时logs默认显示当前容器可能刚启动日志为空而--previous显示上一个崩溃容器的日志这才是错误真相所在。实操心得logs的-f模式在排查间歇性故障时极有用。我曾遇到一个服务每 30 分钟 panic 一次-f模式让我在终端里守株待兔直接捕获到 panic stack trace而不用去翻查分散在各节点的 log 文件。3.2.6kubectl exec进入容器的“物理通道”exec是 Kubernetes 的“SSH”但它比 SSH 更受限、更安全。exec的核心是nsenter它利用 Linux namespace 隔离机制将用户进程注入到目标容器的 PID、NET、UTS 等 namespace 中。# 进入容器执行 shell需容器内有 sh/bash $ kubectl exec -it api-7c8b9d4f5c-abcde -- sh # 执行单条命令无需交互 $ kubectl exec api-7c8b9d4f5c-abcde -- ls /app/config # 指定容器多容器 Pod $ kubectl exec -it api-7c8b9d4f5c-abcde -c api-server -- ps aux # 以特定用户执行绕过容器默认用户限制 $ kubectl exec -it api-7c8b9d4f5c-abcde -u 0 -- sh-u 0参数允许你以 root 用户执行命令这在调试权限问题时必不可少。但生产环境应禁用此功能通过 RBAC 的securityContext严格控制。注意exec依赖容器内存在sh或bash。Alpine 镜像默认只有ash此时需kubectl exec -it pod-name -- ash。若容器是scratch构建的无任何 shellexec将失败只能通过logs或describe间接诊断。3.2.7kubectl delete删除不是终点而是“资源释放确认”delete命令看似简单但其背后的垃圾回收Garbage Collection机制决定了删除是否真正完成。# 立即删除不等待 $ kubectl delete pod nginx-test # 强制删除绕过 graceful termination $ kubectl delete pod nginx-test --force --grace-period0 # 删除时等待所有依赖资源清理完毕 $ kubectl delete deployment nginx-deployment --cascadeforeground # 删除 Deployment 但保留其创建的 Pod孤儿化 $ kubectl delete deployment nginx-deployment --cascadeorphan--cascadeforeground是安全删除的黄金标准。它让 API Server 先将 Deployment 的ownerReferences设置为blockOwnerDeletiontrue然后等待其管理的所有 ReplicaSet 和 Pod 完全终止后才删除 Deployment 本身。这避免了“Deployment 已删但 Pod 还在野跑”的混乱。实操心得--force --grace-period0是“最后手段”。它直接向 etcd 发送 DELETE 请求不通知 kubelet。若 kubelet 正在同步状态可能导致 etcd 中资源已删但节点上容器仍在运行。我只在delete卡死如 Pod 处于Terminating状态超 5 分钟时使用且事后必查get pods --all-namespaces | grep Terminating。3.3 网络与存储状态诊断4 组命令交叉验证3.3.1kubectl get svc与kubectl get endpointsService 的“双盲测试”Service 是 Kubernetes 的网络抽象但它的可用性取决于后端 Endpoint 是否真实存在。$ kubectl get svc -n production NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE api-service ClusterIP 10.96.123.45 none 80/TCP 30d db-service ClusterIP 10.96.234.56 none 5432/TCP 30d $ kubectl get endpoints -n production NAME ENDPOINTS AGE api-service 10.244.2.10:80,10.244.2.11:80 30d db-service none 30dapi-service的ENDPOINTS显示两个 IP说明后端 Pod 注册成功db-service的ENDPOINTS为none这是严重警告。此时get pods -n production -l appdb应返回 0 个 Pod或返回的 PodSTATUS不是Running。提示get endpoints的ENDPOINTS列显示的是PodIP:Port而非 Service IP。这证明 Service 的负载均衡是直接作用于 Pod而非通过中间代理。若此处 IP 是10.244.x.x说明 CNI 插件如 Calico、Flannel工作正常若显示127.0.0.1则是 CNI 配置错误。3.3.2kubectl get pvc与kubectl get pv存储的“供需匹配表”PVCPersistentVolumeClaim和 PVPersistentVolume是 Kubernetes 的存储配对机制它们的状态必须严格匹配。$ kubectl get pvc -n production NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE db-data-pvc Bound pvc-12345678-9abc-def0-1234-567890abcdef 10Gi RWO standard 30d app-config-pvc Pending none 1Gi RWO standard 2h $ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-12345678-9abc-def0-1234-567890abcdef 10Gi RWO Delete Bound production/db-data-pvc standard 30d pv-manual-01 100Gi RWO Retain Available none manual 10ddb-data-pvc的STATUS是BoundPV的STATUS是Bound且CLAIM字段指向production/db-data-pvc匹配成功。app-config-pvc的STATUS是Pending说明没有 PV 满足其要求。查看PV列表pv-manual-01的STATUS是Available但ACCESS MODES是RWOReadWriteOnce而 PVC 要求RWO容量1Gi小于100Gi理论上应匹配。问题出在STORAGECLASSPVC 的STORAGECLASS是standard而pv-manual-01的STORAGECLASS是manual不匹配。实操心得get pvc的VOLUME列显示pvc-xxx这是 PV 的名字。若此处为空说明 PVC 未绑定若此处有值但get pv中找不到对应 PV说明 PV 被手动删除PVC 进入Lost状态需patchPVC 清除volumeName字段才能重新绑定。3.3.3kubectl get networkpolicies网络策略的“隐形防火墙”NetworkPolicy 是 Kubernetes 的微隔离工具它默认是“全通”只有显式定义的策略才生效。$ kubectl get networkpolicies -n production NAME POD-SELECTOR AGE deny-all none 1d api-to-db appdb 1d $ kubectl describe networkpolicy deny-all -n production Name: deny-all Namespace: production Created on: 2024-01-01 00:00:00 0000 UTC Labels: none Annotations: none Spec: PodSelector: none (Allowing the specific traffic to all pods in this namespace) Allowing ingress traffic: none (Selected pods are isolated for ingress connections) Allowing egress traffic: none (Selected pods are isolated for egress connections) Policy Types: Ingress, Egress
阅读完成 · 觉得有帮助?