k8s常用命令大全:kubectl 查看、排错与运维速查
k8s常用命令几乎都是 kubectl 的子命令,按用途分五组:查看(get、describe)、日志与进入容器(logs、exec)、部署与更新(apply、rollout)、扩缩容(scale)、节点维护(cordon、drain)。排错记住一个顺序:先 get 看状态,再 describe 看事件,最后 logs 看程序输出。
k8s常用命令基本都是 kubectl 的子命令,按日常用途可以分成五组:查看资源用 get、describe,看日志和进容器用 logs、exec,发版和回滚用 apply、rollout,扩缩容用 scale,维护节点用 cordon、drain、uncordon。排错时按“先 get 看状态、再 describe 看事件、最后 logs 看程序输出”的顺序走,大多数问题在这三步里就能定位。下面按组整理成速查表,每条命令都说明输出里该看哪一列、哪一段。示例统一使用命名空间 shop、Deployment web。
先记住格式:动词、资源、名称、参数
kubectl 命令的结构是 kubectl 动词 资源类型 [名称] [参数],例如 kubectl get pods web-7d9c8b6f5-2xkqp -n shop -o wide。资源类型可以用缩写:
| 资源 | 缩写 | 资源 | 缩写 |
|---|---|---|---|
| pods | po | services | svc |
| deployments | deploy | statefulsets | sts |
| daemonsets | ds | replicasets | rs |
| nodes | no | namespaces | ns |
| configmaps | cm | persistentvolumeclaims | pvc |
| ingresses | ing | horizontalpodautoscalers | hpa |
kubectl api-resources 会列出集群里全部资源类型和缩写。几个几乎每条命令都会用到的参数:
| 参数 | 作用 |
|---|---|
-n 命名空间 |
指定命名空间,不写就用当前上下文的默认值,通常是 default |
-A |
所有命名空间 |
-l app=web |
按标签筛选 |
-o wide |
多显示 Pod IP、所在节点等列 |
-o yaml、-o json |
输出完整对象,包括 spec 和 status |
-o name |
只输出“类型/名称”,方便交给其他命令处理 |
-w |
持续观察变化,Ctrl+C 退出 |
--field-selector |
按字段筛选,例如 spec.nodeName=node-2 |
常用别名和补全,写进 ~/.bashrc:
alias k=kubectl
source <(kubectl completion bash)
complete -o default -F __start_kubectl k # 让别名 k 也能 Tab 补全
alias kgp='kubectl get pods -o wide'
export dry='--dry-run=client -o yaml' # 用法:k create deploy web --image=nginx $dry > web.yaml
-o 的几种进阶用法,在写脚本和做巡检时很省事:
kubectl get deploy web -n shop -o yaml > web-live.yaml # 导出线上对象;含 status 等字段,复用前要删掉
kubectl get pods -n shop -o custom-columns='NAME:.metadata.name,NODE:.spec.nodeName,IMAGE:.spec.containers[*].image'
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}'
kubectl get pods -A --sort-by='.status.containerStatuses[0].restartCount' # 按重启次数排序
kubectl explain deployment.spec.strategy # 查某个字段的含义和可选值
查看资源:get 与 describe 的输出看什么
| 命令 | 用途 | 输出要看什么 |
|---|---|---|
kubectl get nodes -o wide |
节点列表 | STATUS 是否为 Ready;Ready,SchedulingDisabled 表示被 cordon 了;VERSION 各节点是否一致 |
kubectl get pods -n shop -o wide |
Pod 列表 | READY 分子是否等于分母、STATUS、RESTARTS 是否在涨、NODE 是否都挤在一台上 |
kubectl get pods -A --field-selector=status.phase!=Running |
全集群不在运行中的 Pod | 已正常结束的 Job Pod 也会列出,状态为 Completed |
kubectl get deploy -n shop |
部署状态 | READY 为 2/3 表示有副本没就绪;UP-TO-DATE 小于期望值表示更新还没走完 |
kubectl get svc -n shop |
服务 | TYPE、CLUSTER-IP、PORT(S);LoadBalancer 类型的 EXTERNAL-IP 一直是 pending,说明集群里没有可用的负载均衡实现,自建机房的集群常见 |
kubectl get endpointslices -n shop -l kubernetes.io/service-name=web |
Service 的后端 | ENDPOINTS 一列没有地址,说明选择器没有选中可用的 Pod;有地址仍不通,用 -o yaml 看各后端的 conditions.ready |
kubectl describe pod 名称 -n shop |
Pod 详情 | 末尾的 Events;容器的 State、Last State、Reason、Exit Code |
kubectl describe node node-2 |
节点详情 | Conditions 里的 MemoryPressure、DiskPressure;Taints;Allocated resources 里 requests 的占比 |
kubectl top nodes、kubectl top pods -n shop |
实时 CPU 和内存 | 需要集群装有 metrics-server,否则报 Metrics API not available |
一段典型的 kubectl get pods -n shop -o wide 输出:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-7d9c8b6f5-2xkqp 1/1 Running 0 3d 10.244.1.12 node-1 <none> <none>
web-7d9c8b6f5-8wz4m 0/1 CrashLoopBackOff 14 (2m ago) 47m 10.244.2.31 node-2 <none> <none>
api-6c5f9d7b8-qtl7n 0/1 Pending 0 12m <none> <none> <none> <none>
第二个 Pod 已经重启 14 次、最近一次在 2 分钟前,是程序启动后反复退出,下一步看它的上一次日志;第三个 Pod 没有 IP 也没有节点,说明还没被调度,原因在 describe 的 Events 里。较新版本的 kubectl 还可以用 kubectl events -n shop --types=Warning 只看告警事件。
日志与进入容器:logs、exec
kubectl logs web-7d9c8b6f5-8wz4m -n shop # 容器当前的标准输出
kubectl logs web-7d9c8b6f5-8wz4m -n shop --previous # 上一次退出前的日志,CrashLoopBackOff 必看
kubectl logs -f deploy/web -n shop --tail=100 # 跟踪输出,从最后 100 行开始
kubectl logs web-7d9c8b6f5-2xkqp -n shop -c nginx # 多容器 Pod 用 -c 指定容器
kubectl logs -l app=web -n shop --since=30m --tail=200 --prefix # 按标签取多个 Pod 的日志,每行标出来源
kubectl exec -it web-7d9c8b6f5-2xkqp -n shop -- sh # 进入容器;镜像里没有 bash 时用 sh
kubectl exec web-7d9c8b6f5-2xkqp -n shop -- cat /etc/resolv.conf # 不进入,直接执行一条命令
kubectl cp shop/web-7d9c8b6f5-2xkqp:/app/logs/error.log ./error.log # 从容器拷出文件,容器里需要有 tar
kubectl port-forward svc/web 8080:80 -n shop # 本机 8080 转到 Service 的 80 端口,临时调试用
要点:
--previous是排查 CrashLoopBackOff 的关键。 容器已经重启过,kubectl logs默认看的是新启动的实例,它可能还没来得及输出错误;上一次崩溃的原因在--previous里。logs deploy/web只取其中一个 Pod。 要看全部副本用-l按标签取;按标签取日志时,每个 Pod 默认只显示最后 10 行,要看更多就加--tail。exec后面的--不能省,它把 kubectl 自己的参数和容器里要执行的命令分开。- 精简镜像里没有 shell,exec 会报找不到可执行文件。可以用
kubectl debug -it 名称 -n shop --image=busybox:1.36 --target=web往 Pod 里加一个临时调试容器,--target填业务容器的名字,就能看到它的进程。 - 日志只保存在节点上。 Pod 被删除后
kubectl logs就查不到了,需要长期保留的日志要接入集中日志系统。
部署、更新、回滚与扩缩容:apply、rollout、scale
kubectl diff -f web.yaml # 先看会改动什么,没有输出说明与线上一致
kubectl apply -f web.yaml # 创建或更新,重复执行是安全的
kubectl apply -f ./manifests/ -R # 整个目录,-R 包含子目录
kubectl set image deploy/web web=registry.example.internal/shop/web:1.4.3 -n shop
kubectl annotate deploy/web -n shop kubernetes.io/change-cause="upgrade to 1.4.3" # 给这次变更写说明
kubectl rollout status deploy/web -n shop # 观察滚动更新进度
kubectl rollout history deploy/web -n shop # 历史版本和 CHANGE-CAUSE
kubectl rollout undo deploy/web -n shop # 回到上一版
kubectl rollout undo deploy/web -n shop --to-revision=3
kubectl rollout restart deploy/web -n shop # 镜像不变,逐个重建 Pod
kubectl scale deploy/web -n shop --replicas=5
rollout status 会持续输出类似 Waiting for deployment "web" rollout to finish: 1 of 3 updated replicas are available... 的进度,全部替换完显示 successfully rolled out。新 Pod 一直起不来时,超过 Deployment 的 progressDeadlineSeconds(默认 600 秒)会报 exceeded its progress deadline。Kubernetes 不会自动回滚,这时先 rollout undo 恢复业务,再排查新版本。
几种写入方式的区别:
| 命令 | 行为 | 适合 |
|---|---|---|
kubectl create -f |
只创建,对象已存在就报错 | 一次性创建 |
kubectl apply -f |
不存在就创建,存在就按文件合并更新 | 日常发布,YAML 放在版本库里 |
kubectl replace -f |
用文件整体替换对象,对象必须已存在 | 少数需要整体覆盖的场景 |
kubectl edit |
在编辑器里直接改线上对象 | 临时应急;改完要同步回 YAML,否则下次 apply 会被覆盖 |
扩缩容的几个注意点:
kubectl scale deploy/web --replicas=0停掉全部 Pod 但保留配置,恢复时再改回原来的数量。- 有 HPA 管理的 Deployment,手工 scale 的结果会被 HPA 改回去,要调整的是 HPA 的最小、最大副本数。
- YAML 里写了
replicas,下一次 apply 会把手工 scale 的数量改回文件里的值。 kubectl get hpa的 TARGETS 列显示<unknown>/70%,说明 metrics-server 没装好,或者 Pod 没有设置 CPU requests。
节点维护:cordon、drain、uncordon
物理服务器换内存、升级内核、更新固件之前,先把节点上的 Pod 迁走:
kubectl cordon node-2 # 标记为不可调度,已有 Pod 不动
kubectl drain node-2 --ignore-daemonsets --delete-emptydir-data --timeout=10m
# 关机维护、开机,确认 kubectl get nodes 里 node-2 重新变成 Ready
kubectl uncordon node-2 # 恢复调度
| 命令或参数 | 作用 | 注意 |
|---|---|---|
cordon |
禁止新 Pod 调度到该节点 | 节点 STATUS 变为 Ready,SchedulingDisabled |
drain |
先 cordon,再驱逐节点上的 Pod,由控制器在其他节点重建 | 驱逐会遵守 PodDisruptionBudget |
--ignore-daemonsets |
跳过 DaemonSet 的 Pod | 不加时,节点上有 DaemonSet Pod 会直接报错退出 |
--delete-emptydir-data |
允许驱逐使用 emptyDir 卷的 Pod | emptyDir 里的数据会丢失 |
--force |
连没有控制器管理的裸 Pod 也删除 | 裸 Pod 删除后不会在别处重建 |
uncordon |
恢复调度 | 已迁走的 Pod 不会自动迁回 |
drain 卡住不动时,输出里通常反复出现 Cannot evict pod as it would violate the pod's disruption budget,说明某个应用的 PodDisruptionBudget 不允许再少一个副本。用 kubectl get pdb -A 找到它,如果副本数本来就等于 minAvailable,先给该应用扩容一个副本,drain 才能继续。维护结束 uncordon 之后,Pod 不会自己回来,节点之间负载不均时,可以对相关 Deployment 执行一次 rollout restart 让调度器重新分布。节点要永久下线,drain 之后执行 kubectl delete node node-2;用 kubeadm 部署的集群,再到这台机器上执行 kubeadm reset 清理。
排错常用组合:按 Pod 状态找原因
| STATUS 或现象 | 常见原因 | 下一步看什么 |
|---|---|---|
| Pending | 资源不够、节点有污点、PVC 没绑定 | describe 的 Events 里的 FailedScheduling,例如 0/3 nodes are available: 3 Insufficient cpu |
| ContainerCreating 很久 | 拉镜像慢、存储卷挂载失败、网络插件异常 | describe 的 Events |
| ErrImagePull、ImagePullBackOff | 镜像名或标签写错、私有仓库没配凭据、节点访问不了仓库 | describe 里 Failed to pull image 后面的原因 |
| CreateContainerConfigError | 引用的 ConfigMap 或 Secret 不存在 | kubectl get cm,secret -n shop |
| CrashLoopBackOff | 程序启动后退出,kubelet 按递增间隔反复重启,最长间隔 5 分钟 | kubectl logs --previous |
| Last State 的 Reason 为 OOMKilled,退出码 137 | 内存超过 limits | 调高 limits,或排查程序的内存占用 |
| Running 但 READY 为 0/1 | 就绪探针失败,Service 不会把流量转给它 | describe 里的 Readiness probe failed |
| Evicted | 节点内存或磁盘紧张,Pod 被驱逐 | kubectl describe node 的 Conditions |
| Terminating 删不掉 | 节点失联,或对象上有 finalizer | kubectl get pod 名称 -n shop -o yaml 里的 finalizers,以及所在节点的状态 |
Service 访问不通时,按下面的顺序查:
# 1. 后端 Pod 是否都已就绪
kubectl get pods -n shop -l app=web -o wide
# 2. Service 是否选中了 Pod
kubectl get endpointslices -n shop -l kubernetes.io/service-name=web
# 3. Service 的选择器与 Pod 标签是否一致
kubectl get svc web -n shop -o yaml | grep -A3 selector
kubectl get pods -n shop --show-labels
# 4. 从集群内部直接访问
kubectl run tmp --rm -it --image=busybox:1.36 --restart=Never -n shop -- wget -qO- http://web.shop.svc.cluster.local
# 5. 报权限错误时,检查某个账号能不能做这个操作
kubectl auth can-i create deployments -n shop --as=system:serviceaccount:shop:deployer
第 1 步 Pod 都正常、第 2 步却为空,几乎总是选择器和标签对不上;第 4 步能访问而外部不通,问题在 Ingress、NodePort 或机房防火墙这一层,和 Pod 本身无关。
在机房里怎么落地
集群跑在自有物理服务器上时,kubectl 管得到 Pod 和节点对象,管不到节点的硬件和操作系统。典型的维护流程是:kubectl drain 把节点上的业务迁走,在 Toplink DCIM 的 IPMI 远程管理里远程关机、设置下次从 PXE 或 ISO 启动来重装系统、打开 VNC 控制台看开机自检,处理完再 uncordon。节点 NotReady、kubelet 连不上 apiserver 时,从控制台本地登录能直接看到网卡和系统状态,不受集群网络影响。节点地址、apiserver 的虚拟 IP 要在机房地址台账里登记,避免被分配给其他服务器:在 IP 地址管理里把这些地址登记为已占用,或把所在的段锁定,开通新服务器自动取址时就会跳过它们。
常见问题
每次都要写 -n,能不能设一个默认命名空间?
可以修改当前上下文的默认命名空间:kubectl config set-context --current --namespace=shop,之后不写 -n 就操作 shop,用 kubectl config view --minify | grep namespace 确认当前值。在多个集群、多个命名空间之间来回切换时容易忘记自己在哪,执行删除类命令前先确认一遍。
kubectl delete pod 之后 Pod 又出现了,怎么彻底删掉?
Pod 由 Deployment、StatefulSet 或 DaemonSet 管理时,删掉 Pod 只会让控制器补一个新的。要停掉业务,删除上层对象,例如 kubectl delete deploy web -n shop,或者把副本数缩到 0。用 kubectl get pod 名称 -o yaml 查看 ownerReferences 能找到上层对象:Deployment 创建的 Pod 先指向 ReplicaSet,再往上才是 Deployment。
Pod 一直卡在 Terminating 怎么办?
先看原因:所在节点已经失联时,Pod 要等节点恢复或节点对象被删除才能清理;对象上有 finalizer 时,要等对应的控制器完成清理。确认容器确实已经停止后,可以用 kubectl delete pod 名称 -n shop --grace-period=0 --force 强制删除。StatefulSet 的 Pod 慎用强删,节点只是网络断开时,可能出现两个同名实例同时写同一份数据。