kubectl cluster-info打印 API server 地址和集群里已注册的服务端点(DNS、dashboard 等)。
⚠ 常见坑: 如果挂住,说明 kubeconfig 指向的 server 连不上(VPN 没开、context 选错)。先 kubectl config current-context 看一下。
kubectl cluster-info
kubectl cluster-info dump
kubectl 命令速查,100+ 条 K8s 命令,真实例子和常见坑,含 YAML 片段。
kubectl cluster-info打印 API server 地址和集群里已注册的服务端点(DNS、dashboard 等)。
⚠ 常见坑: 如果挂住,说明 kubeconfig 指向的 server 连不上(VPN 没开、context 选错)。先 kubectl config current-context 看一下。
kubectl cluster-info
kubectl cluster-info dump
kubectl get nodes列出所有 node,含状态、角色、年龄、kubelet 版本。加 -o wide 看内外网 IP 和操作系统。
kubectl get nodes
kubectl get nodes -o wide
kubectl get nodes --show-labels
kubectl top nodes看每个 node 的 CPU / 内存实际用量(数据来自 metrics-server,不是 limits)。
⚠ 常见坑: 要先装 metrics-server 且健康。裸集群上没装会报 error: Metrics API not available,helm 装一下。
kubectl top nodes
kubectl top nodes --sort-by=memory
kubectl describe node <node>深入查看 node:label、taint、可分配资源、状态条件、正在跑的 pod、events。
kubectl describe node ip-10-0-1-23
kubectl describe node | grep -A3 Taints
kubectl cordon <node>把 node 标成不可调度,不再有新 pod 进来,已有的继续跑。
⚠ 常见坑: 只 cordon 不会把负载迁走,维护前要 drain,维护完 uncordon 解锁。
kubectl cordon ip-10-0-1-23
kubectl uncordon ip-10-0-1-23
kubectl drain <node>维护前把 node 上所有 pod 都驱逐出去。会尊重 PodDisruptionBudget。
⚠ 常见坑: daemonset 会卡住 drain,加 --ignore-daemonsets。挂 emptyDir 的要加 --delete-emptydir-data,加了数据就没了。
kubectl drain ip-10-0-1-23 --ignore-daemonsets
kubectl drain ip-10-0-1-23 --ignore-daemonsets --delete-emptydir-data --force
kubectl config current-context打印当前 kubeconfig 指向的 context(集群 + namespace + 用户)。
⚠ 常见坑: 一旦误删,第一句话总是"我刚才在哪个集群",用 kubectx 或 starship 把它接到 shell 提示符里。
kubectl config current-context
kubectl config get-contexts
kubectl config use-context <name>切到 kubeconfig 里定义的另一个 context。
⚠ 常见坑: 经常切环境装 kubectx,敲 kubectx prod 比全命令短得多,还能 fzf 交互选。
kubectl config use-context prod
kubectx prod
kubectl config set-context --current --namespace=<ns>改当前 context 的默认 namespace,不用再到处敲 -n。
⚠ 常见坑: 推荐 kubens <ns>,一行交互式切。原生命令长还容易忘 --current。
kubectl config set-context --current --namespace=staging
kubens staging
kubectl version打印 client 和 server 版本。差 >1 个 minor 版本就不在官方支持范围内了。
kubectl version
kubectl version -o json
kubectl api-resources列出 API server 知道的所有资源类型、短名、group、是否 namespaced。
kubectl api-resources
kubectl api-resources --namespaced=true
kubectl api-resources --api-group=apps
kubectl explain <resource>查任意资源及其字段的内嵌文档。用点路径往下钻。
kubectl explain pod
kubectl explain pod.spec.containers
kubectl explain deployment --recursive
kubectl get componentstatuses老命令,看控制面组件健康。1.19 起弃用,改用 kubectl get --raw=/livez。
⚠ 常见坑: 托管 Kubernetes(EKS、GKE、AKS)上看不到控制面,云商帮你管。命令会报错或空。
kubectl get componentstatuses
kubectl get --raw=/livez?verbose
kubectl get --raw=/readyz?verbose
kubectl config view打印合并后的 kubeconfig。加 --minify 只看当前 context,--flatten 把证书数据内联进来。
⚠ 常见坑: 默认证书和 token 会打码。加 --raw 才输出真实凭据。--raw 的结果别贴到聊天或 issue 里。
kubectl config view --minify
kubectl config view --flatten -o yaml
kubectl config view --raw
kubectl config get-contexts列出 kubeconfig 里所有 context,星号标当前的,并显示各自的集群、用户、namespace。
kubectl config get-contexts
kubectl config get-contexts -o name
kubectl config delete-context <name>从 kubeconfig 删掉一条 context。不会动它引用的 cluster 和 user 条目。
⚠ 常见坑: 会留下孤立的 cluster / user 块。想彻底清干净,再跑 kubectl config delete-cluster 和 delete-user。
kubectl config delete-context old-prod
kubectl config delete-cluster old-prod
kubectl config delete-user old-prod-admin
kubectl uncordon <node>维护完把 node 重新标成可调度。cordon 的反操作。
kubectl uncordon ip-10-0-1-23
kubectl get nodes | grep SchedulingDisabled
kubectl taint nodes <node> <key>=<val>:<effect>给 node 打 taint,只有带匹配 toleration 的 pod 才进得来。effect 有 NoSchedule、PreferNoSchedule、NoExecute。
⚠ 常见坑: NoExecute 还会把已经在跑、又没 toleration 的 pod 赶走。删 taint 在末尾加减号:key=val:NoSchedule-。
kubectl taint nodes ip-10-0-1-23 gpu=true:NoSchedule
kubectl taint nodes ip-10-0-1-23 gpu=true:NoSchedule-
kubectl describe node ip-10-0-1-23 | grep Taints
kubectl label nodes <node> <key>=<val>给 node 打 label,让 pod 用 nodeSelector / nodeAffinity 定向调度(如 disk=ssd、zone=us-east-1a)。
kubectl label nodes ip-10-0-1-23 disk=ssd
kubectl label nodes ip-10-0-1-23 disk-
kubectl get nodes -L disk,zone
kubectl get nodes -o wide列出 node 并附加列:内外网 IP、操作系统镜像、内核版本、容器运行时。
kubectl get nodes -o wide
kubectl get nodes -o custom-columns=NAME:.metadata.name,RUNTIME:.status.nodeInfo.containerRuntimeVersion
kubectl get --raw=/readyz?verbose直接打 API server 的 readiness 端点,逐项列出健康检查及状态。componentstatuses 的现代替代。
kubectl get --raw=/readyz?verbose
kubectl get --raw=/livez?verbose
kubectl get --raw=/healthz
kubectl api-versions列出 server 支持的所有 API group/version(如 apps/v1、batch/v1、networking.k8s.io/v1)。
⚠ 常见坑: 升级前用它确认废弃的 apiVersion(如 extensions/v1beta1)还在不在,免得升完 manifest 全报错。
kubectl api-versions
kubectl api-versions | grep networking
kubectl get pods列出当前 namespace 的 pod。kubectl 最常用命令。
kubectl get pods
kubectl get pods -A
kubectl get pods -o wide
kubectl get pods -w
kubectl get pods -l app=web
kubectl get pod <name>查单个 pod。-o yaml/json 看完整 spec,或 -o jsonpath= 精准提字段。
kubectl get pod web-7d5 -o yaml
kubectl get pod web-7d5 -o jsonpath="{.status.phase}"kubectl get pod web-7d5 -o json | jq .status
kubectl describe pod <name>人类可读的深入视图:spec、状态、容器、卷、events。Pod 出问题第一站。
⚠ 常见坑: 底部的 Events 才是真正的调试金矿,ImagePull 错误、调度失败原因、OOMKilled、livenessProbe 挂了都在那。
kubectl describe pod web-7d5
kubectl describe pod web-7d5 | tail -30
kubectl logs <pod>打印 pod 主容器的 stdout/stderr。
⚠ 常见坑: 多容器 pod 要加 -c <container> 否则报错。应用把日志写文件里、不打 stdout,logs 就是空的。12-factor 写 stdout。
kubectl logs web-7d5
kubectl logs web-7d5 -c sidecar
kubectl logs -l app=web --tail=50
kubectl logs -f <pod>实时跟踪新日志。相当于容器版的 tail -f。
kubectl logs -f web-7d5
kubectl logs -f web-7d5 --since=10m
kubectl logs -f deployment/web
kubectl logs --previous <pod>看上一个容器实例的日志,也就是刚才崩掉的那次。
⚠ 常见坑: 调 CrashLoopBackOff 就靠这条。不加 --previous 看到的是当前重启的日志,要等它再崩才有内容。
kubectl logs --previous web-7d5
kubectl logs -p -c app web-7d5
kubectl exec -it <pod> -- <cmd>在运行中的 pod 里开交互式 shell 或跑一条命令。
⚠ 常见坑: 先试 bash 再回退 sh,alpine 没 bash,distroless 连 sh 都没(用 kubectl debug)。-- 用来分隔 kubectl 的 flag 和容器里的命令。
kubectl exec -it web-7d5 -- bash
kubectl exec -it web-7d5 -- sh
kubectl exec web-7d5 -- ls /app
kubectl exec -it web-7d5 -c sidecar -- sh
kubectl port-forward <pod> <local>:<pod>把本地端口转到 pod(或 service)里的端口。本地调试集群内私有服务必备。
⚠ 常见坑: 空闲、网络抖动、pod 重启都会断。长时间用还是上跳板机或 telepresence,不要靠 port-forward。
kubectl port-forward pod/web-7d5 8080:80
kubectl port-forward svc/web 8080:80
kubectl port-forward deployment/web 8080:80
kubectl cp <pod>:<path> <local>在 pod 和本地之间拷文件。哪边都可以是 pod。
⚠ 常见坑: 容器里要有 tar。distroless 大多没装,镜像里加上,或开 debug 临时容器搞。
kubectl cp web-7d5:/var/log/app.log ./app.log
kubectl cp ./fix.patch web-7d5:/tmp/
kubectl cp web-7d5:/data ./data -c sidecar
kubectl attach <pod>把终端接到 pod 主进程上。Ctrl-C 有可能把容器干掉。
⚠ 常见坑: attach 不是开 shell,是接到已存在的进程上。没特殊需要就 exec -it ... -- sh。
kubectl attach web-7d5
kubectl attach -it web-7d5 -c app
kubectl delete pod <name>删除一个或多个 pod。归控制器管的(Deployment 等)马上有新 pod 顶上。
⚠ 常见坑: 重启 Deployment 用 rollout restart,是官方推荐姿势。删 Terminating 卡住的 pod 要 --grace-period=0 --force(可能泄露 endpoint)。
kubectl delete pod web-7d5
kubectl delete pod web-7d5 --grace-period=0 --force
kubectl delete pods -l app=web
kubectl debug <pod> --image=<dbg>给运行中的 pod 挂一个带工具的临时调试容器(curl、ps、tcpdump 都有),连 distroless 都能用。
⚠ 常见坑: 要 Kubernetes ≥1.23 且 EphemeralContainers 稳定。调试容器共享网络和 PID 命名空间,文件系统不共享。
kubectl debug web-7d5 --image=busybox -it
kubectl debug web-7d5 --image=nicolaka/netshoot --target=app
kubectl debug node/ip-10-0-1-23 -it --image=busybox
kubectl run <name> --image=<img>基于镜像直接起一个裸 pod。一般只在 --rm -it 临时调试时用。
⚠ 常见坑: 裸 pod 没有控制器管,node 挂了不会重建。要常驻的服务用 Deployment。
kubectl run tmp --rm -it --image=busybox -- sh
kubectl run curl --rm -it --image=curlimages/curl -- curl http://web
kubectl run nginx --image=nginx
kubectl logs --since=<duration> <pod>最近一段时间的日志。配 -f 和 --tail 用很顺。
kubectl logs --since=15m web-7d5
kubectl logs --since=1h -f web-7d5
kubectl logs --since-time=2026-05-25T08:00:00Z web-7d5
kubectl logs --tail=<n> <pod>只看最后 N 行。--tail=-1 打印全部(默认有时会截断早期日志)。
kubectl logs --tail=100 web-7d5
kubectl logs --tail=-1 web-7d5 > app.log
kubectl logs --all-containers <pod>一次性输出 pod 里所有容器的日志(应用 + sidecar),不用 -c 一个个挑。
⚠ 常见坑: 不同容器的日志默认混在一起、没前缀。加 --prefix 给每行标上 pod/容器名。
kubectl logs --all-containers web-7d5
kubectl logs --all-containers --prefix -l app=web
kubectl logs --timestamps <pod>给每行日志前面加上容器产生它时的 RFC3339 时间戳。
kubectl logs --timestamps web-7d5
kubectl logs --timestamps --since=10m -f web-7d5
kubectl get pod <name> -o jsonpath=...用 JSONPath 表达式从 pod 里精准抠出你要的字段。可脚本化,不用 jq。
⚠ 常见坑: 表达式用单引号包住,用 range / end 遍历 containers 这种数组。结尾加 {"\n"} 补一个换行。
kubectl get pod web-7d5 -o jsonpath='{.status.podIP}'kubectl get pod web-7d5 -o jsonpath='{range .spec.containers[*]}{.name}{"\t"}{.image}{"\n"}{end}'kubectl get pods -o jsonpath='{.items[*].metadata.name}'kubectl exec <pod> -- env打印运行中容器内可见的环境变量。验证注入的配置 / Secret 是否生效最快的办法。
⚠ 常见坑: 它会把解码后的 Secret 明文打到终端和回滚记录里。共享屏幕或录屏时别用。
kubectl exec web-7d5 -- env
kubectl exec web-7d5 -- env | grep DATABASE
kubectl exec web-7d5 -c app -- printenv LOG_LEVEL
kubectl exec <pod> -- cat /etc/resolv.conf看 pod 真正拿到的 DNS 配置。集群内域名解析出问题时第一步。
⚠ 常见坑: 默认的 ndots:5 会让每个短名先试 5 个搜索域后缀,解析变慢。把 nameserver 和 kube-dns 的 ClusterIP 对一下。
kubectl exec web-7d5 -- cat /etc/resolv.conf
kubectl exec web-7d5 -- nslookup kubernetes.default
kubectl get svc -n kube-system kube-dns
kubectl debug node/<node> -it --image=<img>在指定 node 上起一个带宿主命名空间的调试 pod,/host 下能看 node 文件系统,能跑 tcpdump。
⚠ 常见坑: node 根文件系统挂在 /host,不是 /。要进去用 chroot /host。这要的权限你的 RBAC 不一定给。
kubectl debug node/ip-10-0-1-23 -it --image=busybox
kubectl debug node/ip-10-0-1-23 -it --image=ubuntu -- chroot /host
kubectl debug <pod> --copy-to=<new> --set-image=*=<img>把一个崩溃的 pod 复制成可调试副本,换掉镜像 / 命令,原 pod 不动。
⚠ 常见坑: 副本是裸 pod,不归原控制器管。用完自己删,不然一直留着。
kubectl debug web-7d5 --copy-to=web-debug --set-image=app=busybox -it -- sh
kubectl debug web-7d5 --copy-to=web-debug --container=app -- sleep 1d
kubectl get pods --sort-by=.status.startTime按启动时间排序列出 pod,最新重启的沉到底部。快速揪出反复重启的 pod。
kubectl get pods --sort-by=.status.startTime
kubectl get pods --sort-by=.status.containerStatuses[0].restartCount
kubectl get pods -o custom-columns=...用任意字段拼自定义表格(名字、所在 node、重启次数、镜像),不用默认那几列。
kubectl get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,RESTARTS:.status.containerStatuses[0].restartCount
kubectl get pods -o custom-columns=POD:.metadata.name,IMAGE:.spec.containers[*].image
kubectl get pod <name> -o yaml | kubectl neat把 server 注入的噪音(managedFields、status、默认 annotation)清掉,得到可重新 apply 的干净 YAML。要装 krew 的 neat 插件。
⚠ 常见坑: 直接 get -o yaml 不能原样 apply,它带着 status 和 managedFields,apply 会拒或打架。neat(或手动删)解决这个。
kubectl get pod web-7d5 -o yaml | kubectl neat
kubectl krew install neat
kubectl create deployment <name> --image=<img>一行命令创建 Deployment。Demo 够用;生产还是 YAML + apply。
kubectl create deployment web --image=nginx
kubectl create deployment web --image=nginx --replicas=3 --port=80
kubectl get deployments列出 Deployment 含期望/当前/就绪副本数和年龄。短名 deploy。
kubectl get deployments
kubectl get deploy -A
kubectl get deploy web -o yaml
kubectl scale deployment <name> --replicas=<n>改 Deployment(或 ReplicaSet / StatefulSet)副本数。立即生效。
⚠ 常见坑: 缩到 0 是官方"暂停"姿势,pod 没了但 spec 留着。回拉立刻起。
kubectl scale deployment web --replicas=3
kubectl scale deployment web --replicas=0
kubectl scale --replicas=5 -f deployment.yaml
kubectl rollout status deployment/<name>阻塞跟踪一次 rollout 直到成功、失败、或超时。
kubectl rollout status deployment/web
kubectl rollout status deployment/web --timeout=2m
kubectl rollout history deployment/<name>查看 Deployment 的历史版本。加 --revision=N 看具体某次的内容。
kubectl rollout history deployment/web
kubectl rollout history deployment/web --revision=3
kubectl rollout undo deployment/<name>回滚到上一个版本(或用 --to-revision 指定具体版本)。
⚠ 常见坑: 历史默认只留 10 个。滚出去就回不来了,关键版本在 git 里钉死。
kubectl rollout undo deployment/web
kubectl rollout undo deployment/web --to-revision=3
kubectl rollout restart deployment/<name>通过改 template annotation 触发一次滚动重启。重启 Deployment 的正确姿势。
⚠ 常见坑: 用这个,别 delete pod,标准滚动更新,maxUnavailable 生效,零停机,undo 能用。Deployment / StatefulSet / DaemonSet 从 1.15 起都支持。
kubectl rollout restart deployment/web
kubectl rollout restart statefulset/db
kubectl rollout restart daemonset/log-agent
kubectl autoscale deployment <name> --min=N --max=M --cpu-percent=P基于 CPU 给 Deployment 创建 HPA,在 min 和 max 之间自动伸缩。
⚠ 常见坑: HPA 要 metrics-server。自定义指标 HPA 要 prometheus-adapter 这种。没指标 HPA 显示 unknown,永远不伸缩。
kubectl autoscale deployment web --min=2 --max=10 --cpu-percent=70
kubectl get hpa
kubectl describe hpa web
kubectl get replicaset列出 ReplicaSet。Deployment 每次升级都会生成一个新 ReplicaSet。
kubectl get rs
kubectl get rs -l app=web
kubectl describe rs web-7d5f44
kubectl get statefulset列出 StatefulSet,用于有序、有稳定网络 ID 的负载,比如数据库。
⚠ 常见坑: 删 StatefulSet 不会删 PVC,要自己清,否则数据卷一直留着。
kubectl get sts
kubectl describe sts db
kubectl delete sts db --cascade=orphan
kubectl get daemonset列出 DaemonSet,每个匹配 node 跑一份的 pod(日志采集、CNI、node exporter 这种)。
kubectl get ds
kubectl get ds -A
kubectl rollout restart ds/log-agent
kubectl get job列出 Job(一次性任务)。CronJob 用 cronjob。
kubectl get jobs
kubectl get cronjobs
kubectl create job manual-job --from=cronjob/backup
kubectl expose deployment <name> --port=<p>为已有 Deployment(或 Pod / RS)前面套一个 Service。最快建 ClusterIP 的姿势。
kubectl expose deployment web --port=80 --target-port=8080
kubectl expose deployment web --type=NodePort --port=80
kubectl expose deployment web --type=LoadBalancer --port=80
kubectl get hpa列出 HPA 含当前/目标指标、min、max、年龄。
kubectl get hpa
kubectl describe hpa web
kubectl delete hpa web
kubectl get pdb列出 PodDisruptionBudget。限制自愿性中断(drain、滚动升级)以守住 SLO。
⚠ 常见坑: minAvailable=N 而当前副本就是 N 会让 drain 永远卡住。设合理数字或维护前先扩容。
kubectl get pdb
kubectl create pdb web-pdb --selector=app=web --min-available=2
kubectl describe deployment <name>深入查看 Deployment:副本数、策略、当前 ReplicaSet、events。
kubectl describe deployment web
kubectl describe deploy web | grep -A5 Conditions
kubectl set env deployment/<name> KEY=VAL给 Deployment 加 / 改一个环境变量,触发滚动更新。用 KEY- 删除。
⚠ 常见坑: 和 set image 一样会改线上 spec、跟 git 漂移。用 --from=configmap/<cm> 一次把 ConfigMap 所有 key 注进来。
kubectl set env deployment/web LOG_LEVEL=debug
kubectl set env deployment/web LOG_LEVEL-
kubectl set env deployment/web --from=configmap/app-config
kubectl set resources deployment/<name> --limits=cpu=1,memory=512Mi不改 YAML 直接给 Deployment 改 CPU / 内存的 requests 和 limits。触发滚动更新。
kubectl set resources deployment/web --limits=cpu=1,memory=512Mi --requests=cpu=200m,memory=256Mi
kubectl set resources deployment/web -c=app --limits=memory=1Gi
kubectl create cronjob <name> --image=<img> --schedule="<cron>"命令式创建一个 CronJob,带 cron 表达式。-- 后面的内容作为容器命令。
⚠ 常见坑: CronJob 的时间走 kube-controller-manager 的时区(一般是 UTC),不是你本地的,除非设了 spec.timeZone(1.27 起稳定)。
kubectl create cronjob backup --image=backup:latest --schedule="0 2 * * *" -- /backup.sh
kubectl create cronjob ping --image=busybox --schedule="*/5 * * * *" -- echo hello
kubectl create job <name> --from=cronjob/<cj>从 CronJob 模板派生一个一次性 Job,立刻手动触发。不用等定时就能测一次备份。
kubectl create job manual-backup --from=cronjob/backup
kubectl get jobs -l job-name=manual-backup
kubectl rollout status statefulset/<name>跟踪 StatefulSet 的滚动更新。默认按序号倒序一个一个更新。
⚠ 常见坑: updateStrategy 为 OnDelete 的 StatefulSet,改 spec 不会自动滚动,得自己删每个 pod 才会用新 spec 重建。
kubectl rollout status statefulset/db
kubectl rollout status sts/db --timeout=5m
kubectl scale statefulset <name> --replicas=<n>给 StatefulSet 扩缩容。pod 按序一个一个增减,会等就绪。
⚠ 常见坑: 缩容不会删被移除 pod 的 PVC(除非设了 persistentVolumeClaimRetentionPolicy,1.27+)。数据还留着。
kubectl scale statefulset db --replicas=5
kubectl scale sts db --replicas=1
kubectl get cronjob列出 CronJob 含调度表达式、是否暂停、上次调度时间、当前活跃 job 数。
⚠ 常见坑: SUSPEND=True 的 CronJob 永远不触发。恢复用 kubectl patch cronjob <cj> -p '{"spec":{"suspend":false}}'。
kubectl get cronjob
kubectl patch cronjob backup -p '{"spec":{"suspend":true}}'kubectl get cronjob backup -o jsonpath='{.status.lastScheduleTime}'kubectl describe hpa <name>查看 HPA 的决策过程:当前 vs 目标指标、近期伸缩事件、以及 unable to fetch metrics 这类错误。
⚠ 常见坑: 底部 Events 解释 HPA 为啥伸缩或不伸缩。出现 FailedGetResourceMetric 基本就是 metrics-server 挂了。
kubectl describe hpa web
kubectl get hpa web -o yaml | grep -A10 conditions
kubectl rollout undo statefulset/<name>把 StatefulSet 回滚到上一个版本。和 Deployment 一样有版本历史。
kubectl rollout undo statefulset/db
kubectl rollout history statefulset/db
kubectl get services列出 Service 含类型、ClusterIP、外部 IP、端口、年龄。短名 svc。
kubectl get svc
kubectl get svc -A
kubectl get svc -o wide
kubectl get endpoints <svc>列出 Service 背后真正的 pod IP。endpoints 空 = selector 写错或没有 Ready 的 pod。
⚠ 常见坑: Service 有 IP 但 curl 不通?90% 的情况看 kubectl get endpoints <svc>。endpoints 空说明 selector 没命中或 readinessProbe 一直 fail。
kubectl get endpoints web
kubectl get endpointslices -l kubernetes.io/service-name=web
kubectl port-forward svc/<name> <local>:<svc>把本地端口转到 Service。走 endpoints,不是直连 pod。
kubectl port-forward svc/web 8080:80
kubectl port-forward svc/db 5432:5432 -n staging
kubectl get ingress列出 Ingress 含 host、path、地址、端口。
⚠ 常见坑: 没设 ingressClassName: nginx 这种 IngressClass 的 Ingress,对所有控制器都不可见,看起来建好了,但没人理它。
kubectl get ingress
kubectl describe ingress web
kubectl get ingressclass
kubectl get networkpolicy列出限制 pod 间流量的 NetworkPolicy。没策略 = 全放行(默认)。
⚠ 常见坑: NetworkPolicy 靠 CNI 插件(Calico、Cilium 等)执行。没支持 policy 的 CNI 上,策略会被静默忽略,kubectl get ds -n kube-system 确认装了什么。
kubectl get netpol
kubectl describe netpol deny-all
kubectl get netpol -A
kubectl proxy在 127.0.0.1:8001 起一个本地 API server 代理,访问 dashboard / API 时不用手动处理鉴权。
kubectl proxy
kubectl proxy --port=9090
curl http://127.0.0.1:8001/api/v1/namespaces
kubectl describe ingress <name>查看 Ingress 的规则、后端 service、TLS,底部还有 controller 同步的事件。
⚠ 常见坑: ADDRESS 列一直空说明没 controller 接管这条 Ingress,检查 ingressClassName 和 controller pod 是否在跑。
kubectl describe ingress web
kubectl get ingress web -o jsonpath='{.status.loadBalancer.ingress[0].ip}'kubectl get endpointslices列出 EndpointSlice,Endpoints 的可扩展继任者(1.21 起默认)。每个 slice 最多约 100 个端点。
kubectl get endpointslices
kubectl get endpointslices -l kubernetes.io/service-name=web
kubectl describe endpointslice web-abc12
kubectl get svc <name> -o jsonpath=...从 Service 抠单个字段:LoadBalancer 的外网 IP/域名、NodePort、或 ClusterIP。
⚠ 常见坑: AWS NLB 给的是域名不是 IP,要读 .status.loadBalancer.ingress[0].hostname,不是 .ip,否则拿到空串。
kubectl get svc web -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'kubectl get svc web -o jsonpath='{.spec.clusterIP}'kubectl get svc web -o jsonpath='{.spec.ports[0].nodePort}'kubectl create service clusterip <name> --tcp=<port>:<target>命令式创建一个 ClusterIP Service。--tcp=80:8080 把 service 端口映射到目标端口。
⚠ 常见坑: 它建出来的 Service 没 selector(除非之后补上),适合指向外部端点,但你若指望它路由到 pod 会很意外。
kubectl create service clusterip web --tcp=80:8080
kubectl create service nodeport web --tcp=80:8080 --node-port=30080
kubectl get ingressclass列出已安装的 IngressClass 和哪个是默认。没指定 class 的 Ingress 会落到标了默认的那个。
kubectl get ingressclass
kubectl get ingressclass -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.annotations.ingressclass\.kubernetes\.io/is-default-class}{"\n"}{end}'kubectl create configmap <name> --from-literal=KEY=VAL从字面量 key=value 创建 ConfigMap。可重复多个 --from-literal。
kubectl create configmap app-config --from-literal=LOG_LEVEL=info --from-literal=DEBUG=1
kubectl create configmap app-config --from-literal=DATABASE_HOST=db.local
kubectl create configmap <name> --from-file=<path>从单个文件或整个目录创建 ConfigMap(每个文件作为一个 key)。
⚠ 常见坑: 总大小上限约 1MB(etcd 限制)。更大的配置用挂载 + initContainer,或迁到配置中心。
kubectl create configmap nginx-conf --from-file=./nginx.conf
kubectl create configmap site-conf --from-file=./conf.d/
kubectl get configmap列出 ConfigMap。短名 cm。-o yaml 看内容。
kubectl get cm
kubectl get cm app-config -o yaml
kubectl get cm -A
kubectl create secret generic <name> --from-literal=KEY=VAL从字面量创建 Secret。值在存储里是 base64(除非开了 KMS,否则不算加密)。
⚠ 常见坑: Secret 是 base64,不是加密。任何有 get secrets 权限的人都能解。要真安全得开 apiserver 加密存储 + 考虑 Sealed Secrets / External Secrets。
kubectl create secret generic db --from-literal=password=s3cret
kubectl create secret generic api --from-literal=token=abc123
kubectl create secret docker-registry <name>为私有 registry 创建 imagePullSecret。在 pod spec 的 imagePullSecrets 里引用。
kubectl create secret docker-registry ghcr-pull --docker-server=ghcr.io --docker-username=user --docker-password=$TOKEN
kubectl create secret docker-registry ecr-pull --docker-server=123.dkr.ecr.us-east-1.amazonaws.com --docker-username=AWS --docker-password=$(aws ecr get-login-password)
kubectl get secret <name> -o jsonpath="{.data.<key>}" | base64 -d解码 Secret 里的某一项。经典"密码到底是啥"查询。
⚠ 常见坑: macOS 上 base64 要大写 -D,Linux 上小写 -d。两边通用写 base64 --decode。
kubectl get secret db -o jsonpath="{.data.password}" | base64 -dkubectl get secret api -o json | jq -r ".data.token | @base64d"
kubectl get secret列出 Secret。-o yaml 看(base64 后的)数据。
kubectl get secret
kubectl get secret -A
kubectl get secret db -o yaml
kubectl create secret tls <name> --cert=<file> --key=<file>从证书 + key 创建 TLS Secret。Ingress / webhook 配置按名字引用。
kubectl create secret tls web-tls --cert=tls.crt --key=tls.key
kubectl get secret web-tls -o yaml
kubectl get pvc列出 PVC 含状态、容量、访问模式、StorageClass、年龄。
⚠ 常见坑: PVC 卡 Pending = 没匹配 PV / StorageClass。describe pvc 看原因。删 PVC 是否删底层 PV 取决于 reclaim policy。
kubectl get pvc
kubectl get pv
kubectl describe pvc data-db-0
kubectl create configmap <name> --from-env-file=<file>从 .env 文件建 ConfigMap,每行 KEY=VALUE 变成一个 key。和 --from-file(整个文件作一个 key)不同。
⚠ 常见坑: 每行必须是纯 KEY=VALUE,不能有 export、带空格的引号、或值后面的行内注释。shell 风格的 .env 经常解析失败。
kubectl create configmap app-env --from-env-file=.env
kubectl create secret generic app-env --from-env-file=.env.production
kubectl get configmap <name> -o jsonpath=...直接读 ConfigMap 里的某个 key,不用 -o yaml 再翻。写脚本顺手。
kubectl get configmap app-config -o jsonpath='{.data.LOG_LEVEL}'kubectl get cm app-config -o jsonpath='{.data}'kubectl edit secret <name>在 $EDITOR 里打开 Secret。看到的值是 base64,存之前新值得自己编码。
⚠ 常见坑: 在这里直接贴明文会变成双重乱码。改用 kubectl create secret ... --dry-run=client -o yaml | kubectl apply -f - 省去手动 base64。
kubectl edit secret db
echo -n "newpass" | base64
kubectl create secret generic <name> --from-file=<key>=<path>建一个 Secret,让某个 key 装某文件的内容(如 SSH key 或 kubeconfig)。可重复多个 key。
kubectl create secret generic ssh-key --from-file=id_rsa=/home/me/.ssh/id_rsa
kubectl create secret generic kubeconfig --from-file=config=/home/me/.kube/config
kubectl describe pvc <name>查看 PVC 的状态、绑定的 PV、容量、访问模式,以及关键的 Events(说明为啥 Pending)。
⚠ 常见坑: Pending 且报 no persistent volumes available,说明没 StorageClass 能动态供给,或你写了个不存在的 storageClassName。
kubectl describe pvc data-db-0
kubectl get storageclass
kubectl get pvc -o wide
kubectl get storageclass列出 StorageClass 和哪个是默认(标 (default))。没写 storageClassName 的 PVC 用默认那个。
⚠ 常见坑: 没有默认 StorageClass,每个没显式指定 class 的 PVC 都会永远 Pending。很多裸集群一个都没装。
kubectl get storageclass
kubectl get sc
kubectl patch storageclass gp2 -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'kubectl get pv列出全集群 PV 含容量、访问模式、回收策略、状态、绑定的 claim。
⚠ 常见坑: PVC 删了之后 PV 卡在 Released(不是 Available)不会重新绑定,reclaimPolicy=Retain 保住数据但挡住复用,得清掉 .spec.claimRef 才行。
kubectl get pv
kubectl get pv -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,CLAIM:.spec.claimRef.name
kubectl patch pv pv-001 -p '{"spec":{"claimRef":null}}'kubectl get namespaces列出所有 namespace 含状态(Active / Terminating)和年龄。短名 ns。
kubectl get ns
kubectl create ns staging
kubectl delete ns old-staging
kubectl get serviceaccount列出当前 namespace 的 ServiceAccount。每个 namespace 都有一个 default SA。
kubectl get sa
kubectl create sa ci-bot
kubectl get sa default -o yaml
kubectl create role <name> --verb=get,list --resource=pods在当前 namespace 创建一个 Role,授予指定动词在指定资源上的权限。
kubectl create role pod-reader --verb=get,list,watch --resource=pods
kubectl create role app-admin --verb=* --resource=deployments,services
kubectl create rolebinding <name> --role=<role> --serviceaccount=<ns>:<sa>把 Role 绑定到 ServiceAccount / User / Group(在某个 namespace 内)。
⚠ 常见坑: Role + RoleBinding 是 namespace 级。要全集群权限得用 ClusterRole + ClusterRoleBinding。混着用是常见隐性失败。
kubectl create rolebinding ci-pods --role=pod-reader --serviceaccount=ci:ci-bot
kubectl create rolebinding admin-binding --clusterrole=admin --user=alice
kubectl create clusterrole <name> --verb=... --resource=...创建集群级 Role。访问非 namespaced 资源(nodes、PV)或跨 namespace 时必需。
kubectl create clusterrole node-reader --verb=get,list --resource=nodes
kubectl create clusterrolebinding viewer --clusterrole=view --user=alice
kubectl auth can-i <verb> <resource>检查当前用户(或 --as <user>)能否做某个动作。RBAC 调试就靠这个。
⚠ 常见坑: 加 --list 把当前 namespace 里所有权限列出来。加 --as system:serviceaccount:ns:sa 模拟 pod 的视角。
kubectl auth can-i delete pods
kubectl auth can-i --list -n staging
kubectl auth can-i get secrets --as system:serviceaccount:default:my-bot
kubectl create token <serviceaccount>为 ServiceAccount 申请一个有期限的 bearer token(1.24 起取代了自动创建 Secret token 的老做法)。
⚠ 常见坑: 1.24 起 SA 不再自动创建 Secret token,老脚本读 kubectl get secret 取 token 拿不到东西。改用 kubectl create token,或显式建一个 kubernetes.io/service-account-token 类型的 Secret。
kubectl create token ci-bot
kubectl create token ci-bot --duration=1h
kubectl create token default -n ci > /tmp/token
kubectl create namespace <name>创建一个新 namespace。集群内最小隔离单位。
kubectl create ns staging
kubectl create ns prod --dry-run=client -o yaml > ns.yaml
kubectl auth can-i --list列出当前身份在某 namespace 里所有能做的动作。最快的"我到底能干啥"自查。
kubectl auth can-i --list
kubectl auth can-i --list -n kube-system
kubectl auth can-i --list --as=system:serviceaccount:ci:ci-bot
kubectl auth whoami打印 API server 认定你当前凭据对应的用户名、组、附加属性(1.28 起稳定)。
⚠ 常见坑: OIDC / IAM token 把你映射成预期外的用户时特别有用,RBAC 被拒经常就是这里身份不对。
kubectl auth whoami
kubectl auth whoami -o yaml
kubectl get clusterrolebinding列出集群级 RoleBinding。审计谁有 cluster-admin 或其它高权 ClusterRole 就看这里。
⚠ 常见坑: 绑到 system:masters 组或 cluster-admin ClusterRole 的就是完全上帝模式。安全审查先 grep 这两个。
kubectl get clusterrolebinding
kubectl get clusterrolebinding -o jsonpath='{range .items[?(@.roleRef.name=="cluster-admin")]}{.metadata.name}{"\n"}{end}'kubectl describe clusterrole <name>查看 ClusterRole 到底授了哪些资源的哪些动词。绑给任何人之前先看。
kubectl describe clusterrole view
kubectl describe clusterrole edit
kubectl get clusterrole admin -o yaml
kubectl create rolebinding <name> --clusterrole=<cr> --serviceaccount=<ns>:<sa>把一个 ClusterRole 绑给某 ServiceAccount,但只在单个 namespace 内生效。常见的最小权限套路。
⚠ 常见坑: 在 RoleBinding(不是 ClusterRoleBinding)里用 --clusterrole,权限只在这个 binding 所在 namespace 生效,是个刻意且好用的收窄。
kubectl create rolebinding ci-edit --clusterrole=edit --serviceaccount=ci:ci-bot -n ci
kubectl create rolebinding read-only --clusterrole=view --user=alice -n staging
kubectl get rolebinding,clusterrolebinding -A -o wide宽格式列出所有 namespace 的 binding,输出里带上 subject(用户 / SA / 组)。
kubectl get rolebinding,clusterrolebinding -A -o wide
kubectl get clusterrolebinding -o wide | grep alice
kubectl top pods每个 pod 的 CPU / 内存实际用量(数据来自 metrics-server,不是 requests/limits)。
⚠ 常见坑: 要先装 metrics-server。没装报 Metrics API not available。按容器拆开看:top pods --containers。
kubectl top pods
kubectl top pods --sort-by=memory
kubectl top pods --containers -A
kubectl get events列出近期集群事件。加 --sort-by 让最新的排前面。
⚠ 常见坑: 默认按 ResourceVersion 排,对人没意义。永远加 --sort-by=.lastTimestamp 或 .metadata.creationTimestamp。
kubectl get events --sort-by=.lastTimestamp
kubectl get events -A --sort-by=.lastTimestamp
kubectl get events --field-selector involvedObject.name=web-7d5
kubectl wait --for=condition=Ready pod/<name>阻塞直到资源达到某个条件。CI 脚本里 apply 完用得最多。
kubectl wait --for=condition=Ready pod/web-7d5 --timeout=60s
kubectl wait --for=condition=Available deployment/web --timeout=2m
kubectl wait --for=delete pod/old-7d5 --timeout=30s
kubectl get pods -wwatch 模式:实时流式输出 pod 状态变化。Ctrl-C 停。
kubectl get pods -w
kubectl get pods -w -l app=web
kubectl get pods -w -o wide
kubectl get pods --field-selector=status.phase=Failed按状态筛选 pod。"找出所有失败 / 待调度 pod"经典用法。
kubectl get pods --field-selector=status.phase=Failed -A
kubectl get pods --field-selector=status.phase=Pending
kubectl get pods --field-selector=spec.nodeName=ip-10-0-1-23
kubectl get all一把列出 pod + svc + deploy + rs + sts + ds。看整体状态用。
⚠ 常见坑: all 不包含 configmap、secret、ingress、job、PVC、CRD,名字有误导。要真的全部得遍历 api-resources。
kubectl get all
kubectl get all -A
kubectl get all -n staging -o wide
kubectl top pod <name> --containers把单个 pod 的 CPU / 内存按容器拆开看,揪出是哪个 sidecar 吃内存。
kubectl top pod web-7d5 --containers
kubectl top pod -l app=web --containers --sort-by=memory
kubectl get events --field-selector type=Warning只看 Warning 级事件(过滤掉 Normal),留下要处理的问题,去掉日常噪音。
kubectl get events --field-selector type=Warning --sort-by=.lastTimestamp
kubectl get events -A --field-selector type=Warning --sort-by=.lastTimestamp
kubectl get events --field-selector involvedObject.name=<name>把事件限定到单个对象,只看这个 pod / deployment 发生了什么,不看整个 namespace。
kubectl get events --field-selector involvedObject.name=web-7d5
kubectl get events --field-selector involvedObject.kind=Deployment,involvedObject.name=web
kubectl get pods -A -o wide --field-selector spec.nodeName=<node>列出调度到某个 node 上的所有 pod(跨所有 namespace)。drain 一个 node 前必看。
kubectl get pods -A -o wide --field-selector spec.nodeName=ip-10-0-1-23
kubectl get pods -A --field-selector spec.nodeName=ip-10-0-1-23 -o name | wc -l
kubectl wait --for=jsonpath=<path>=<val> <resource>阻塞直到任意 JSONPath 字段达到某个值,比内置的 condition= 灵活得多(1.23+)。
kubectl wait --for=jsonpath='{.status.phase}'=Running pod/web-7d5 --timeout=60skubectl wait --for=jsonpath='{.status.loadBalancer.ingress}' svc/web --timeout=5mkubectl get pods --watch-only只流式输出之后的变化(跳过开头的全量列表)。配合反应式脚本用。
kubectl get pods --watch-only
kubectl get pods --watch-only -o json | jq .status.phase
kubectl top node --sort-by=cpu按 CPU(或内存)用量给 node 排序,最热的 node 浮到顶。容量规划一眼看清。
kubectl top node --sort-by=cpu
kubectl top node --sort-by=memory
kubectl apply -f <file-or-dir>从 YAML / JSON 声明式创建或更新资源。官方推荐姿势。
⚠ 常见坑: 传 - 从 stdin 读:helm template ... | kubectl apply -f -。apply 用 last-applied-configuration annotation 记字段所有权,手工 edit 这些字段下次 apply 会迷惑。
kubectl apply -f deployment.yaml
kubectl apply -f ./k8s/
kubectl apply -f - <<EOF apiVersion: v1 kind: ConfigMap ... EOF
kubectl apply -k <kustomize-dir>应用一个 Kustomize overlay。1.14 起内置,不需要单独装 kustomize。
kubectl apply -k ./overlays/prod
kubectl kustomize ./overlays/prod | kubectl apply -f -
kubectl create -f <file>命令式从 YAML 创建资源。资源已存在会失败。
⚠ 常见坑: create 一次性;apply 幂等。CI/CD / GitOps 这种反复跑的用 apply。绝对不允许静默更新的(如 Job)用 create。
kubectl create -f job.yaml
kubectl create -f - <<EOF ... EOF
kubectl replace -f <file>用 YAML 完全替换一个已存在资源。--force 走删了重建路径。
⚠ 常见坑: replace --force 会瞬间断服,pod 先删后建。线上别用,apply 让控制器走滚动更新。
kubectl replace -f svc.yaml
kubectl replace --force -f pod.yaml
kubectl patch <resource> <name> -p '<json>'不改文件,给已存在资源打补丁。默认走 strategic merge。
⚠ 常见坑: 三种合并方式:--type=strategic(默认,懂容器结构)、--type=merge(RFC 7396)、--type=json(RFC 6902 操作)。strategic 只对核心类型生效,CRD 用 merge。
kubectl patch deployment web -p '{"spec":{"replicas":5}}'kubectl patch pod web -p '{"metadata":{"labels":{"env":"prod"}}}'kubectl patch deployment web --type=json -p='[{"op":"replace","path":"/spec/replicas","value":3}]'kubectl edit <resource> <name>在 $EDITOR 里打开资源,保存即应用 diff。快但糙,谨慎用。
⚠ 常见坑: edit 不会更新你 git 里的 YAML,线上会漂。git 管的东西改源文件再 apply。edit 只用来快验证。
kubectl edit deployment web
KUBE_EDITOR="code -w" kubectl edit cm app-config
kubectl diff -f <file>预览 apply 会改什么,服务端 diff,对比 live 状态。
kubectl diff -f deployment.yaml
kubectl diff -k ./overlays/prod
kubectl label <resource> <name> KEY=VAL加 / 改 / 删(KEY-)资源上的 label。Selector 到处都靠它。
kubectl label pods web-7d5 env=prod
kubectl label pods web-7d5 env-
kubectl label nodes ip-10-0-1-23 disk=ssd
kubectl annotate <resource> <name> KEY=VAL加 / 改 / 删(KEY-)annotation。任意元数据,不用于 selector。
kubectl annotate pods web-7d5 owner=team-foo
kubectl annotate svc web service.beta.kubernetes.io/aws-load-balancer-type=nlb
kubectl delete -f <file>删除 YAML 文件或目录里定义的所有资源。
⚠ 常见坑: delete -f 一个 namespace YAML 会把整个 namespace 里的东西全删。生产路径上 delete 前一定先 diff -f。
kubectl delete -f deployment.yaml
kubectl delete -k ./overlays/staging
kubectl apply --server-side -f <file>走服务端 apply,字段归 manager 所有,冲突会显式报。是 client-side apply 的现代替代。
⚠ 常见坑: 多个 manager 改同一个字段会冲突中止,加 --force-conflicts 才强推。强推前先看冲突报告。
kubectl apply --server-side -f deployment.yaml
kubectl apply --server-side --force-conflicts -f deployment.yaml
kubectl rollout pause deployment/<name>暂停 / 恢复 rollout,让多次 set / patch 合并成一次发布。
kubectl rollout pause deployment/web
kubectl set image deployment/web app=nginx:1.27 && kubectl set env deployment/web LOG=info && kubectl rollout resume deployment/web
kubectl set image deployment/<name> <ctr>=<img>只改 Deployment 某容器的镜像。不动 YAML 直接触发滚动升级。
⚠ 常见坑: set image 直接改线上 spec,跟 git YAML 漂移。git 管的 Deployment 改源文件再 apply,别 set。
kubectl set image deployment/web app=nginx:1.27
kubectl set image deploy/web app=myorg/app@sha256:abc123
kubectl rollout status deployment/<name> -w实时跟踪 rollout 直到完成。失败时非零退出,CI 卡口必备。
kubectl rollout status deployment/web -w
kubectl apply -f deploy.yaml && kubectl rollout status deployment/web --timeout=3m
kubectl apply -f <file> --dry-run=server把 manifest 发到 API server 做完整校验(准入 webhook、默认值填充)但不真正保存。
⚠ 常见坑: --dry-run=server 能抓到准入 / webhook 的拒绝,纯本地的 --dry-run=client 完全抓不到。CI 卡口用 server 端。
kubectl apply -f deployment.yaml --dry-run=server
kubectl apply -f deployment.yaml --dry-run=client -o yaml
kubectl apply -f <file> --prune -l <selector>apply 一个目录的同时,删掉带匹配 label、但文件里已不存在的线上对象。GitOps 式同步。
⚠ 常见坑: prune 强但危险,selector 写错会删掉不相关的资源。先 --dry-run=client,label 卡死再跑。
kubectl apply -f ./k8s/ --prune -l app=web
kubectl apply -f ./k8s/ --prune -l app=web --dry-run=client
kubectl create -f <file> --dry-run=client -o yaml用命令式 flag 生成干净 YAML,但不真正创建。命令式转声明式的桥梁。
⚠ 常见坑: 这是给记不住的 YAML 起骨架的标准姿势:kubectl create deployment ... --dry-run=client -o yaml > deploy.yaml,再改。
kubectl create deployment web --image=nginx --dry-run=client -o yaml > deploy.yaml
kubectl create configmap c --from-literal=k=v --dry-run=client -o yaml
kubectl get <resource> <name> -o yaml --show-managed-fields显示 managedFields 块(1.21 起默认隐藏),看清服务端 apply 下每个字段归哪个 manager。
⚠ 常见坑: 两个 controller 抢同一字段时,这块能点名谁干的。配 kubectl apply --server-side --force-conflicts 解决。
kubectl get deployment web -o yaml --show-managed-fields
kubectl get deployment web -o jsonpath='{.metadata.managedFields[*].manager}'kubectl delete <resource> --all -n <ns>删掉某 namespace 里某种资源的全部对象。如清空所有 pod 让控制器全新重建。
⚠ 常见坑: --all 是 namespace 范围、不是全集群,但仍会删光该 namespace 里这类资源。回车前再确认 -n。
kubectl delete pods --all -n staging
kubectl delete jobs --all -n batch
kubectl delete pods --all --grace-period=0 --force -n staging
kubectl delete <resource> <name> --cascade=orphan删掉控制器(Deployment / StatefulSet)但让子 pod 继续跑、变成无人管。少见但迁移时有用。
⚠ 常见坑: 孤立的 pod 没控制器了,不自愈、不滚动。要么让新控制器接管,要么手动清。
kubectl delete deployment web --cascade=orphan
kubectl delete statefulset db --cascade=orphan
kubectl rollout resume deployment/<name>恢复被暂停的 Deployment,把暂停期间所有改动合成一次新发布刷下去。
kubectl rollout resume deployment/web
kubectl rollout pause deploy/web && kubectl set image deploy/web app=nginx:1.27 && kubectl set resources deploy/web --limits=memory=512Mi && kubectl rollout resume deploy/web
kubectl kustomize <dir>把 Kustomize overlay 渲染成纯 YAML 打到 stdout,不 apply。先看清 apply -k 到底会发什么。
kubectl kustomize ./overlays/prod
kubectl kustomize ./overlays/prod | kubectl diff -f -
kubectl annotate <resource> <name> kubectl.kubernetes.io/last-applied-configuration-删掉过期的 last-applied-configuration annotation,让下一次 client-side apply 干净地重建字段所有权。
⚠ 常见坑: 资源先用 create 建(没这 annotation)后来又 apply,删字段时行为怪异,可用这个修。或干脆迁到 server-side apply。
kubectl annotate deployment web kubectl.kubernetes.io/last-applied-configuration-
kubectl apply --server-side --force-conflicts -f deployment.yaml
ImagePullBackOffPod 拉不到镜像。describe pod 看 Events,基本都是 tag 拼错、没配 imagePullSecret、或 registry DNS 解析不了。
⚠ 常见坑: BackOff 是指数退避,看着发呆其实在以越来越长间隔重试。修完原因 kubectl delete pod 立即重置退避计时。
kubectl describe pod web-7d5 | tail -20
kubectl get events --sort-by=.lastTimestamp -n default
kubectl create secret docker-registry ghcr --docker-server=ghcr.io --docker-username=user --docker-password=$TOKEN
CrashLoopBackOff容器起来又挂了。kubectl logs <pod> --previous 看真实报错。describe 里看 Exit Code。
⚠ 常见坑: 退出码:0 = CMD 正常跑完(说明你以为是 server 实际不是)、1 = 应用抛错、137 = OOMKilled、143 = 没及时处理 SIGTERM。每种修法都不一样。
kubectl logs web-7d5 --previous
kubectl describe pod web-7d5 | grep -A2 "Last State"
kubectl get pod web-7d5 -o jsonpath="{.status.containerStatuses[*].lastState}"Evictedkubelet 把 pod 从 node 上踢了,通常是 node 压力(磁盘满、内存压力)。换到健康 node + 加 requests/limits。
⚠ 常见坑: 被驱逐的 pod 会一直留在 get pods 里要手工清,kubectl delete pods --field-selector=status.phase=Failed 一把扫掉。
kubectl get pods --field-selector=status.phase=Failed -A
kubectl delete pods --field-selector=status.phase=Failed -A
kubectl describe node ip-10-0-1-23 | grep -A5 Conditions
OOMKilled (exit 137)137 = 128 + SIGKILL(9)。内核 OOM killer 干掉了容器。要么加内存 limit,要么修内存泄漏。
⚠ 常见坑: requests.memory 设到平常用量附近,limits.memory 设到你能承受的上限。JVM 应用要加 -XX:MaxRAMPercentage,否则它压根不看 limits 然后 OOM。
kubectl get pod web-7d5 -o jsonpath="{.status.containerStatuses[*].lastState.terminated.reason}"kubectl describe pod web-7d5 | grep -A2 "Limits:"
kubectl top pod web-7d5 --containers
Pending (unschedulable)没有 node 满足 pod 的 requests / nodeSelector / taint 要求。describe pod 里 FailedScheduling 会说明原因。
⚠ 常见坑: 常见原因:CPU/内存不够、没有匹配 label 的 node、taint 没 toleration、PVC 找不到 PV。每种修法不一样。
kubectl describe pod web-7d5 | grep -A5 Events
kubectl get nodes -o custom-columns=NAME:.metadata.name,CPU:.status.allocatable.cpu,MEM:.status.allocatable.memory
kubectl get nodes --show-labels
Terminating (stuck)Pod 一直卡在 Terminating,几乎都是有 finalizer 没人处理。强删是逃生通道。
⚠ 常见坑: kubectl delete pod web --grace-period=0 --force 跳过优雅停,endpoint 可能短暂泄露。长期正确做法是 kubectl patch 把 finalizer 清掉。
kubectl delete pod web-7d5 --grace-period=0 --force
kubectl patch pod web-7d5 -p '{"metadata":{"finalizers":null}}' --type=mergekubectl get pod web-7d5 -o yaml | grep finalizers -A3
Init:0/N (stuck)Pod 的 init 容器在失败或永远不结束。kubectl logs <pod> -c <init-name> 看原因。
kubectl logs web-7d5 -c wait-for-db
kubectl describe pod web-7d5 | grep -A5 "Init Containers"
ErrImagePull / no such hostImagePullBackOff 的 registry DNS 变种。集群 DNS 解析不了 registry 域名。
⚠ 常见坑: 用 kubectl run dnsutils --rm -it --image=busybox -- nslookup ghcr.io 验证。挂了说明 CoreDNS 或上游有问题。私有 registry 经常要在 pod 里加 hostAliases。
kubectl run dnsutils --rm -it --image=busybox -- nslookup ghcr.io
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50
kubectl get pods -n kube-system -l k8s-app=kube-dns
CreateContainerConfigError容器起不来,因为引用的 ConfigMap / Secret 里某个 key 不存在。describe pod 会点名具体哪个 key。
⚠ 常见坑: 和 ImagePullBackOff 不同,镜像拉下来了。这是配置接线错:secretKeyRef / configMapKeyRef 指向一个还不存在的 key。
kubectl describe pod web-7d5 | grep -A3 Events
kubectl get secret db -o jsonpath='{.data}'kubectl get cm app-config -o jsonpath='{.data}'CreateContainerErrorkubelet 创建容器失败,常见原因是命令写错、挂载路径不存在、或只读根文件系统冲突。
⚠ 常见坑: 看 reason 后面的消息:"exec: no such file" = 命令 / entrypoint 写错;"mkdir read-only file system" = 容器往写不了的地方写。
kubectl describe pod web-7d5 | grep -A2 "State:"
kubectl get pod web-7d5 -o jsonpath='{.status.containerStatuses[0].state.waiting.message}'ContainerCreating (stuck)Pod 在 ContainerCreating 卡好几分钟,通常是某个卷挂不上,或镜像还在拉。
⚠ 常见坑: events 里 FailedMount = PVC 没绑定或 CSI 驱动有问题。云上 FailedAttachVolume = EBS / PD 卷还挂在另一个(已死的)node 上。
kubectl describe pod web-7d5 | grep -A5 Events
kubectl get pvc
kubectl get volumeattachment
exec format error镜像构建的 CPU 架构和 node 不一致(如 arm64 镜像跑在 amd64 node 上)。
⚠ 常见坑: Apple Silicon 经典坑,本地 arm64 构建推到 amd64 集群。用 docker buildx build --platform linux/amd64,linux/arm64 出多架构镜像。
kubectl logs web-7d5 --previous
kubectl get pod web-7d5 -o jsonpath='{.spec.nodeName}'kubectl get node ip-10-0-1-23 -o jsonpath='{.status.nodeInfo.architecture}'connection refused (probe failing)liveness / readiness 探针一直失败,pod 反复重启或拿不到流量。应用还没在探针端口上监听。
⚠ 常见坑: 常见原因:探针 port 和应用真实监听端口对不上,或 initialDelaySeconds 太短、应用还没启动完。对一下探针 spec 和真实端口。
kubectl describe pod web-7d5 | grep -A3 -i probe
kubectl get pod web-7d5 -o jsonpath='{.spec.containers[0].readinessProbe}'kubectl exec web-7d5 -- wget -qO- localhost:8080/healthz
FailedScheduling: untolerated taintpod 一直 Pending,因为每个候选 node 都有 pod 没 toleration 的 taint(如 control-plane 或 GPU node)。
⚠ 常见坑: 给 pod spec 加匹配的 tolerations,或调度到没 taint 的 node。control-plane node 默认带 node-role.kubernetes.io/control-plane:NoSchedule。
kubectl describe pod web-7d5 | grep -A5 Events
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.taints}{"\n"}{end}'error: unable to upgrade connection (exec/logs)kubectl exec / logs / port-forward 打不开流式连接,通常是 API server 连不上 kubelet。
⚠ 常见坑: 托管集群上常是安全组 / 防火墙挡了 apiserver→kubelet(10250 端口),或 node 处于 NotReady。查 node 状态和安全组规则。
kubectl get node ip-10-0-1-23
kubectl describe node ip-10-0-1-23 | grep -A5 Conditions
kubectl get pods -A --field-selector spec.nodeName=ip-10-0-1-23
NotReady (node)node 报 NotReady,kubelet 停止上报状态。上面的 pod 先标 Unknown,过了 toleration 窗口后被驱逐。
⚠ 常见坑: 常见原因:kubelet 崩了、磁盘 / PID 压力、网络分区、或容器运行时挂了。describe node 的 Conditions 加机器上 journalctl -u kubelet 能看出来。
kubectl get nodes
kubectl describe node ip-10-0-1-23 | grep -A8 Conditions
kubectl get pods -A -o wide --field-selector spec.nodeName=ip-10-0-1-23
Pod YAML (minimal)Pod 最小骨架,带资源和单容器。直接抄改名字和镜像。
⚠ 常见坑: 裸 Pod 没人管,node 挂了就没了。除非真要一次性,平时用 Deployment。
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: app
image: nginx:1.27-alpine
ports:
- containerPort: 80
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { cpu: 500m, memory: 256Mi }Deployment YAML标准 Deployment 模板:3 副本、滚动更新策略、探针、资源限制。
⚠ 常见坑: 没 readinessProbe + 应用启动慢 = 升级时流量打到没就绪的 pod 上 = 每次发布 502。永远加一个真正的 readinessProbe。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels: { app: web }
spec:
replicas: 3
selector:
matchLabels: { app: web }
strategy:
type: RollingUpdate
rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }
template:
metadata:
labels: { app: web }
spec:
containers:
- name: app
image: nginx:1.27-alpine
ports: [{ containerPort: 80 }]
readinessProbe:
httpGet: { path: /, port: 80 }
periodSeconds: 5
livenessProbe:
httpGet: { path: /, port: 80 }
periodSeconds: 30
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { cpu: 500m, memory: 256Mi }Service YAML按 label 选中 Deployment、套在前面的 ClusterIP Service。
⚠ 常见坑: targetPort 可以写名字(如 "http")匹配 containerPort 的名字,比写数字安全,版本变端口不用同步改。
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: ClusterIP
selector: { app: web }
ports:
- name: http
port: 80
targetPort: 80ConfigMap + envFrom usage一个 ConfigMap 加 Deployment 片段,演示如何把所有 key 注入成环境变量。
⚠ 常见坑: 改 ConfigMap 不会自动重启 pod。改完要 kubectl rollout restart deployment/<name> 才能生效。
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: info
DATABASE_HOST: db.local
---
# In your Deployment template.spec.containers[0]:
envFrom:
- configMapRef:
name: app-configIngress YAML (nginx class)把 host + path 路由到 Service 的 Ingress。用 nginx IngressClass。
⚠ 常见坑: 不写 ingressClassName: nginx(或对应 annotation)没有任何 controller 接管,看起来建好了,啥也不干。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
spec:
ingressClassName: nginx
rules:
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80CronJob YAMLCronJob 骨架:调度表达式、并发策略、历史保留数、单容器 job 模板。
⚠ 常见坑: 不设 concurrencyPolicy: Forbid,慢 job 会和下一次调度撞上。不设历史保留数,跑完的 Job 会无限堆积。
apiVersion: batch/v1
kind: CronJob
metadata:
name: backup
spec:
schedule: "0 2 * * *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: Never
containers:
- name: backup
image: backup:1.0
command: ["/backup.sh"]Job YAML一次性 Job:并行度、完成数、退避上限、activeDeadline 超时。
⚠ 常见坑: Job 的 restartPolicy 只能是 Never 或 OnFailure(Always 会被拒)。backoffLimit 限制总重试次数,超了 Job 标 Failed。
apiVersion: batch/v1
kind: Job
metadata:
name: migrate
spec:
completions: 1
parallelism: 1
backoffLimit: 3
activeDeadlineSeconds: 600
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: migrate:1.0
command: ["/run-migration.sh"]HorizontalPodAutoscaler YAML (v2)autoscaling/v2 的 HPA,按 CPU 和内存利用率伸缩,带显式 min/max 和缩容稳定窗口。
⚠ 常见坑: autoscaling/v2(不是 v2beta2)从 1.23 起稳定。配多个指标时,HPA 按要副本最多的那个伸缩。要 metrics-server。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
behavior:
scaleDown:
stabilizationWindowSeconds: 300
metrics:
- type: Resource
resource:
name: cpu
target: { type: Utilization, averageUtilization: 70 }
- type: Resource
resource:
name: memory
target: { type: Utilization, averageUtilization: 80 }PersistentVolumeClaim YAML向指定 StorageClass 申请存储的 PVC,带访问模式。通过 volumes + volumeMounts 挂进 pod。
⚠ 常见坑: ReadWriteOnce 同一时刻只绑一个 node,跨 node 的两个 pod 共享不了。要共享得用 ReadWriteMany 且底层存储支持(NFS、EFS、CephFS)。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: gp3
resources:
requests:
storage: 10GiNetworkPolicy YAML (default-deny + allow)一条默认拒绝入站的策略,加一条只允许 role=frontend 的 pod 在 8080 端口访问本应用的放行规则。
⚠ 常见坑: NetworkPolicy 是叠加的(只放行)且要 CNI 支持执行。podSelector: {} 配空 ingress = 拒绝整个 namespace 的所有入站。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes: ["Ingress"]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
spec:
podSelector:
matchLabels: { app: web }
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels: { role: frontend }
ports:
- protocol: TCP
port: 8080ServiceAccount + RBAC YAML一个 ServiceAccount,一个授予 pod 只读的 namespace 级 Role,加一个把它俩绑起来的 RoleBinding。最小权限起手式。
⚠ 常见坑: RoleBinding 里 kind: ServiceAccount 的 subject 必须在 subjects[].namespace 写上 SA 的 namespace,否则绑定静默不授权。
apiVersion: v1 kind: ServiceAccount metadata: name: pod-reader namespace: app --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-reader namespace: app rules: - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pod-reader namespace: app subjects: - kind: ServiceAccount name: pod-reader namespace: app roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
可搜索的 kubectl 速查,覆盖 SRE 和平台工程师日常真正在集群上敲的 100+ 条命令,不是凑数的 hello-minikube 列表。十大分类:集群 (cluster-info、get nodes、top nodes、config use-context、version、 api-resources),Pod(get pods、describe、logs -f、exec -it、 port-forward、cp、attach、delete、debug 临时容器),工作负载 (deployment / replicaset / daemonset / statefulset 的 create、 scale、rollout status / history / undo / restart、autoscale、 expose),Service 和 Ingress(expose、get svc、endpoints、 port-forward),ConfigMap 和 Secret(from-file / from-literal 创建、get、base64 解码),RBAC(get sa、create role / rolebinding / clusterrole / clusterrolebinding、auth can-i、 命名空间切换),资源监控(top pods、events --sort-by、wait --for=condition),apply 流水线(apply、create、replace、patch 的 strategic / json / merge、edit、diff、kustomize、label、 annotate),8 种最容易毁掉一天的 Pod 状态有专门解法 (ImagePullBackOff、ErrImagePull、CrashLoopBackOff、Evicted、 OOMKilled、Pending 调度失败、Terminating 卡住、Init:0/N 卡住), 还有 5 份直接抄就能用的 YAML 模板(Pod、Deployment、Service、 ConfigMap、Ingress)。每条都有完整语法、中英文说明、对应的 "常见坑"(比如 delete pod 不加 --grace-period=0 在 Terminating 卡住的 Pod 上会一直挂、exec 默认走 sh,alpine 有 sh 没 bash, distroless 连 sh 都没、改部署优先 rollout restart 而不是 delete pod、apply -f - 是从 stdin 读所以可以 helm template ... | kubectl apply -f - 串起来用、top pods 要 metrics-server 装好 跑通否则给你一个迷惑的 503),以及 1-3 条可直接复制的真实例子。 搜索框跨命令 / 说明 / 坑 / 例子四个字段一起过滤,分类胶囊缩范围, 每条命令一键复制。完全在浏览器里跑,不上传 kubeconfig,不连任何 集群,不追踪。配合 Docker 速查 / Git 速查 一起用;嫌原生 CLI 太 重的时候上 kubectx / kubens / k9s / helm / stern。
把内容粘贴或拖入工具面板。
点击按钮,在浏览器内本地处理,文件不上传。
一键复制结果或下载到本地。
适合穿插在写代码、查问题、做 Review、上线前的小任务里。
这些入口会把当前任务接到更完整的工具链里。
值班状态没工夫翻文档。直接搜「137」跳到 OOMKilled 那条,复制 `kubectl logs <pod> --previous` 看崩之前最后一次的日志,再复制 `describe pod` 读 Exit Code 那行。三下点完,不用绕 man 手册, 马上判断是该调内存上限还是该改 CMD。
筛到「Pod」和「工作负载」两类,把第一天的 15 条命令从上往下 交给他:get pods、describe、logs -f、exec -it、port-forward、 rollout restart、rollout status。每条都把坑写在旁边,他在当众 踩到 127 之前就先知道「exec 默认走 sh,alpine 有 sh 没 bash」。
堡垒机装不了 helm,但本地能渲染。找到 `apply -f -` 那条,读 「从 stdin 读」的说明,跑 `helm template release ./chart | kubectl apply -f -`。速查里写清楚短横就是 stdin,省得你来回试 kubectl 到底要不要一个真的文件路径。
同事正打算对线上 1 副本的服务 `kubectl delete pod`。搜 「restart」,复制 `rollout restart deployment/<name>`,那条会 解释清楚:delete 会瞬间掉到 0 个副本又没 rollout 历史,restart 则遵守 maxUnavailable,还留着 `rollout undo` 能回滚。
对已经崩掉的 Pod 跑 `kubectl logs <pod>` 看到的是新容器不是崩的那次,加 `--previous` 才是真正失败的那一轮。
在 alpine 或 distroless 上 `kubectl exec -it pod -- bash` 会退 127,先试 `sh`,连 sh 都没的镜像用 `kubectl debug` 挂临时容器。
用 `delete pod --grace-period=0 --force` 硬删 Terminating 会留下悬空 endpoint,该去清 finalizer 或卡住的卷,别强杀。
这份速查就是一个静态页。你搜的关键词、复制的命令、读到的 YAML 都 留在浏览器标签页里,对内存里的命令数组做过滤。不碰你的 kubeconfig, 不连任何集群,搜索内容也不进 URL。边输入边开 DevTools 的 Network 看,零请求,所以气隙跳板机和只有堡垒机的环境都能放心用。
做你这行的人, 还会一起用这些。