K8s常用命令速查手册:集群运维与故障排查实战
发布时间:2026/10/21 16:11:19 锦皓数字建站

k8s命令记不住这份常用操作手册直接拿去用做容器平台运维这几年跟Kubernetes打交道是每天的必修课。刚接触K8s那会儿面对一大串kubectl命令确实容易懵但随着踩的坑越来越多慢慢总结出了一套自己的常用命令清单。今天把这些命令整理出来分享给大家涵盖集群巡检、资源管理、日志排查、故障恢复等日常高频场景希望对正在学习和使用K8s的朋友有所帮助。1. 基础命令体系与集群信息查询1.1 kubectl命令的基本语法结构先来过一遍kubectl的基础语法掌握了这个后面所有命令都可以举一反三kubectl [command] [TYPE] [NAME] [flags]command针对资源执行的操作比如get、describe、create、delete等TYPE资源类型比如pod、deployment、service、node等NAME资源名称可以指定具体名字也可以省略表示所有flags可选参数比如-n指定命名空间-o指定输出格式-l按标签筛选有个要点需要特别提醒kubectl的版本和集群版本最好保持一致否则可能出现API兼容问题导致命令执行报错或者行为异常。建议在本地装上和集群版本一致的kubectl客户端或者直接使用集群控制节点上的kubectl。查看版本信息可以用kubectl version这个命令会同时输出客户端和服务端的版本号。如果两者之间有较大版本差异建议优先升级客户端版本因为新版客户端通常向后兼容旧版集群API。1.2 集群节点与状态巡检节点是K8s集群的底层基础设施例行巡检第一件事就是看节点状态# 查看集群所有节点 kubectl get nodes # 查看节点详细信息包括内网IP、内核版本、容器运行时等 kubectl get nodes -o wide # 查看单个节点的详细状态包括资源使用情况、系统信息等 kubectl describe node node-name # 查看节点资源使用率需要metrics-server组件 kubectl top nodekubectl get nodes -o wide显示的内容比默认输出丰富很多可以看到节点的内网IP、操作系统版本、内核版本、容器运行时版本等关键信息。当集群跨多个可用区或者物理机房部署时这些信息对排查网络和兼容性问题非常有用。节点状态通常有Ready、NotReady、SchedulingDisabled等几种状态Ready节点健康可以正常调度PodNotReady节点异常通常是网络不通、kubelet宕机或资源耗尽SchedulingDisabled节点被标记为不可调度但不影响已有Pod运行1.3 命名空间与资源列表查询命名空间用于资源隔离多环境、多团队共用一个集群的场景下命名空间的合理使用至关重要# 查看集群所有命名空间 kubectl get namespaces # 查看default命名空间下所有资源 kubectl get all # 查看指定命名空间下的Pod、Service等资源 kubectl get pods -n namespace kubectl get services -n namespace kubectl get deployments -n namespace不指定-n参数时kubectl默认操作default命名空间这点容易踩坑。曾经有同事改了十几个deployment结果最后发现全操作到default命名空间去了生产环境的服务没动到虚惊一场但确实吓人。如果不想每次敲命令都带-n可以通过kubectl config设置当前上下文默认namespace但要注意切换上下文时namespace也会跟着变操作前多看一眼上下文总没错。2. 工作负载管理与部署操作2.1 Deployment的基础操作Deployment是K8s中最常见的无状态工作负载类型负责管理Pod的副本数量、滚动更新和故障自愈# 创建Deployment推荐使用yaml文件声明式创建 kubectl create deployment name --imageimage --dry-runclient -o yaml deployment.yaml kubectl apply -f deployment.yaml # 查看Deployment列表 kubectl get deployments # 查看Deployment详细状态 kubectl describe deployment deployment-name # 扩缩容 kubectl scale deployment deployment-name --replicas3 # 更新镜像直接修改容器镜像版本触发滚动更新 kubectl set image deployment/deployment-name container-namenew-image # 重启Deployment不会改变配置常用于重新拉取镜像或重置Pod状态 kubectl rollout restart deployment deployment-name # 查看滚动更新状态 kubectl rollout status deployment deployment-name # 回滚到上一个版本 kubectl rollout undo deployment deployment-name # 回滚到指定版本 kubectl rollout undo deployment deployment-name --to-revision2 # 查看Deployment的历史版本记录 kubectl rollout history deployment deployment-name # 删除Deployment kubectl delete deployment deployment-name创建Deployment时我习惯先用--dry-runclient -o yaml生成一份yaml模板再根据实际需求手动修改。这样比手写yaml快又比直接命令行创建更灵活可控。生成的模板会包含基本的metadata、spec字段改起来方便也不容易遗漏关键配置。2.2 Pod相关的核心操作Pod是K8s最小的调度单元日常排查故障时和Pod打交道最多# 查看Pod列表默认default命名空间 kubectl get pods # 查看所有命名空间的Pod并显示Pod所在节点 kubectl get pods -A -o wide # 查看Pod详细状态包括事件、容器状态、资源等 kubectl describe pod pod-name # 进入Pod中的容器-c参数指定容器名适用于多容器Pod kubectl exec -it pod-name -- /bin/sh kubectl exec -it pod-name -c container-name -- /bin/bash # 查看Pod日志 kubectl logs pod-name # 实时追踪Pod日志-f参数 kubectl logs -f pod-name # 查看上一个容器实例的日志排查容器反复重启的情况 kubectl logs pod-name --previous # 查看Pod内所有容器的日志多容器Pod场景 kubectl logs pod-name --all-containerstrue # 端口转发本地访问Pod内服务 kubectl port-forward pod-name 8080:80 # 将文件从本地复制到Pod内 kubectl cp local-path pod-name:remote-path # 将文件从Pod内复制到本地 kubectl cp pod-name:remote-path local-pathkubectl exec -it里-i表示交互式连接-t表示分配终端两个参数搭配才能进入容器的交互式shell。有些基础镜像里没有bash只有shdocker和K8s场景下同样存在。还有些精简镜像连shell都没有这时可以借助kubectl debug临时挂一个带调试工具的容器共享进程命名空间来排查问题这个后面会提到。2.3 标签筛选与字段选择器当集群中Pod数量较多时标签就是筛选和操作的利器# 按标签筛选Pod kubectl get pods -l appweb kubectl get pods -l appweb,envproduction # 按标签筛选多个值 kubectl get pods -l app in (web,api) # 按节点名筛选Pod kubectl get pods -o wide --field-selector spec.nodeNamenode-name # 按状态筛选Pod比如查看故障Pod kubectl get pods --field-selectorstatus.phaseFailed # 给资源打标签或修改标签 kubectl label nodes node-name disktypessd kubectl label pod pod-name appweb --overwrite # 删除标签 kubectl label pod pod-name app-标签筛选的语法有一些细节需要注意-l可以用逗号分隔多个条件条件之间是AND关系还支持in、notin、!这些集合操作符。实际排查问题时用-l appweb,envproduction这种组合条件能很快锁定目标Pod避免在几百个Pod里翻来翻去。字段选择器是另一种筛选方式按资源字段的值来筛选比如按节点名、按状态阶段等。它和标签选择器的区别在于标签是自定义的键值对字段是资源本身带的属性。两者的应用场景不同灵活搭配能提升不少排查效率。2.4 其他常见工作负载类型Deployment之外StatefulSet、DaemonSet、Job等类型也是日常高频接触的# StatefulSet有状态应用如数据库、中间件 kubectl get statefulsets kubectl describe statefulset name kubectl scale statefulset name --replicas3 # DaemonSet每个节点上跑一个Pod用于日志采集、监控等 kubectl get daemonsets kubectl describe daemonset name kubectl rollout restart daemonset name # Job和CronJob批处理任务和定时任务 kubectl get jobs kubectl get cronjobs kubectl logs job/job-name kubectl delete job job-nameStatefulSet和Deployment的扩容逻辑差别很大Deployment的Pod是无状态的扩容时可以随意创建和销毁StatefulSet的Pod有稳定的网络标识和存储扩容时按序创建缩容时按序删除操作时要清楚这个特性避免意外中断服务。DaemonSet一般由系统组件创建比如日志采集器、监控Agent日常运维中主要关注它的更新和状态即可不建议随意删除或手动调整副本数。3. 服务发现与网络配置操作3.1 Service相关命令Service负责Pod的负载均衡和服务发现把一组Pod封装成一个稳定的访问入口# 查看Service列表 kubectl get services kubectl get svc # 查看Service详细信息 kubectl describe service service-name # 创建Service从已有Deployment暴露端口 kubectl expose deployment deployment-name --port80 --target-port8080 --typeClusterIP # 查看Service对应的后端Pod端点 kubectl get endpoints service-name # 临时修改Service类型常用NodePort调试 kubectl patch service service-name -p {spec:{type:NodePort}} # 删除Service kubectl delete service service-namekubectl get endpoints查看Service后端Pod的IP列表非常实用。碰上服务间歇性不可用的问题用这个命令能快速确认后端Pod是否都在线IP有没有变化。Service和Pod之间的关联靠的是Selector标签如果标签写错了endpoints列表会是空的服务自然不通。Service类型有ClusterIP、NodePort、LoadBalancer三种另有Headless Service无集群IP用于StatefulSet。ClusterIP只能在集群内部访问NodePort会在每个节点上开一个随机端口让外部访问LoadBalancer则是对接云厂商的负载均衡器。选型时先想清楚访问方在哪里需要跨集群访问就要配合Ingress或外部负载均衡。3.2 Ingress与IngressControllerService解决的是集群内部的服务发现Ingress解决的是外部流量如何进入集群# 查看Ingress列表 kubectl get ingress kubectl get ingress -A # 查看Ingress详细信息 kubectl describe ingress ingress-name # 创建Ingress示例 cat EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress spec: rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-service port: number: 80 EOF # 删除Ingress kubectl delete ingress ingress-name有一点需要特别说明Ingress只是规则定义真正干活的是IngressController。没有部署IngressController的话创建Ingress规则不会产生任何实际效果。常见的IngressController有NGINX Ingress Controller、Traefik、HAProxy等。当访问Ingress地址不通时优先检查IngressController的运行状态和日志而不是盯着Ingress资源本身看。3.3 Service间通信与DNS解析K8s集群内部有一套内置DNS服务CoreDNSService之间的通信依赖DNS解析# 在Pod内解析Service的DNS kubectl run curl-test --imagecurlimages/curl --rm -it --restartNever -- sh -c nslookup web-service kubectl run curl-test --imagecurlimages/curl --rm -it --restartNever -- curl http://web-service:80 # 查看CoreDNS状态 kubectl get pods -n kube-system -l k8s-appkube-dns kubectl logs -n kube-system -l k8s-appkube-dns同一个命名空间下Service通过名称直接访问即可跨命名空间需要带上命名空间比如web-service.production.svc.cluster.local。遇到服务间调用失败的问题第一步先确认DNS解析是否正常第二步确认目标Service的endpoints是否在线第三步确认网络策略NetworkPolicy是否放行。大部分跨服务调用异常都出在这三个环节。4. 配置管理与存储操作4.1 ConfigMap与Secret的增删改查应用配置和敏感信息不应该硬编码到镜像里ConfigMap和Secret就是K8s管理配置和密钥的标准方案# 创建ConfigMap的几种方式 # 从文件创建 kubectl create configmap app-config --from-fileconfig.properties # 从键值对创建 kubectl create configmap app-config --from-literaldb_host10.0.0.1 --from-literaldb_port3306 # 从yaml文件创建 kubectl apply -f configmap.yaml # 查看ConfigMap列表 kubectl get configmaps # 查看ConfigMap内容 kubectl get configmap name -o yaml kubectl describe configmap name # 创建Secretbase64编码存储 kubectl create secret generic db-password --from-literalpasswordMyPass123 # 查看Secret kubectl get secrets kubectl get secret name -o yaml # Secret中的值默认以base64编码展示需要base64解码查看原文 echo base64-string | base64 --decode # 删除ConfigMap或Secret kubectl delete configmap name kubectl delete secret name # 更新ConfigMap或Secret kubectl create configmap app-config --from-fileconfig.properties --dry-runclient -o yaml | kubectl apply -f -修改ConfigMap后已经挂载到Pod里的配置不会自动生效。大部分应用不会监听配置文件变化所以需要滚动重启关联的Deployment或StatefulSetkubectl rollout restart deployment deployment-nameSecret的存储方式默认是base64编码但这个编码不等于加密任何人只要有权限查看Secret就能解码出原文。在正式的集群环境里建议开启etcd加密存储或者配合外部密钥管理服务如云厂商的KMS、Vault来增强安全性。4.2 持久化存储PV与PVC操作有状态应用需要持久化存储这就涉及PVPersistentVolume和PVCPersistentVolumeClaim# 查看PV列表 kubectl get pv # 查看PV详细信息 kubectl describe pv pv-name # 查看PVC列表按命名空间隔离 kubectl get pvc -n namespace # 查看PVC详细信息 kubectl describe pvc pvc-name # 创建PVC示例 cat EOF | kubectl apply -f - apiVersion: v1 kind: PersistentVolumeClaim metadata: name:># 查看Pod的完整信息和事件 kubectl describe pod pod-name # 查看节点的完整信息和事件 kubectl describe node node-name # 只查看事件Event部分 kubectl get events --sort-by.metadata.creationTimestamp kubectl get events -n namespace --sort-by.lastTimestamp # 按资源类型过滤事件 kubectl get events --field-selector involvedObject.nameresource-namedescribe输出中有两段最关键一段是底部的Events记录了从Pod创建以来所有的关键事件包括镜像拉取、容器启动、健康检查等另一段是Conditions展示Pod当前各个条件的满足情况。排查思路基本是先看Events找异常源头再看Conditions确认当前状态然后顺着这两个方向追查。Events默认只会保留一段时间通常是1小时排查历史故障时可以结合Prometheus等监控系统回溯时间线或用kubectl get events --sort-by.lastTimestamp按时间排序查看窗口内的事件这样能把故障发生的完整过程还原出来。5.2 Pod常见异常状态及处理Pod的Phase有Pending、Running、Succeeded、Failed、Unknown几种实际排查中更多遇到的是各种CrashLoopBackOff、ImagePullBackOff、Error状态# 查看Pod状态列快速识别异常Pod kubectl get pods -A | grep -v Running # 查看CrashLoopBackOff状态Pod的日志 kubectl logs pod-name --previous # 查看容器退出原因如果exit code是139之类的信号码通常和内存或代码段错误有关 kubectl describe pod pod-name | grep -A 10 Last State常见异常状态的排查思路PendingScheduler还没把Pod调度到节点上看describe里有没有FailedScheduling事件检查节点资源是否充足、是否有污点或节点亲和性约束ImagePullBackOff镜像拉取失败检查镜像名是否写对、tag是否存在、私有仓库的认证信息是否正确CrashLoopBackOff容器启动后立刻崩溃K8s在不断重启它。用logs --previous看上一个实例的日志定位崩溃原因Running但NotReady容器进程活着但就绪探针readinessProbe没通过。确认探针路径、端口和预期响应是否有调整OOMKilled容器内存超出limit被内核杀掉检查应用的堆内存或缓存设置同时确认内存limit是否合理Terminating卡住Pod删除不干净可能是挂载了存储卷释放慢或者容器进程有僵尸zombie无法退出配合--force强制删除5.3 节点维护与Pod迁移节点要重启或者下线维护时需要先把Pod迁移走这里有几个命令协同操作# 标记节点为不可调度新Pod不会调度上去已有Pod保持运行 kubectl cordon node-name # 驱赶节点上的Pod会重新调度到其他节点 kubectl drain node-name --ignore-daemonsets --delete-emptydir-data # 节点维护完成后重新启用调度 kubectl uncordon node-namedrain命令有几个参数需要特别留意--ignore-daemonsets是必需的因为DaemonSet的Pod本来就应该每个节点跑一个不做忽略会卡在驱赶流程--delete-emptydir-data用来删除emptyDir临时存储的Pod数据如果节点上有使用emptyDir的Pod不加这个参数会被拦截。执行drain前先确认该节点上的Pod是否有其他节点可以承接集群资源紧张时drain可能长时间hang住。有个细节容易忽略cordon只会阻止新的调度已经运行在节点上的Pod不会受到影响。只有drain才会把已有Pod赶走。日常计划内维护节点时两个命令搭配使用先cordon阻止新流量再drain清空已有负载维护结束再uncordon恢复调度。5.4 资源清理与命名空间级操作大规模清理测试环境的资源用一条命令全部删除比一个个删高效得多# 删除指定命名空间下的所有资源 kubectl delete all -n namespace --all # 删除整个命名空间这个命令会把命名空间下所有资源全部清空 kubectl delete namespace namespace # 按标签批量删除 kubectl delete pods -l apptest kubectl delete deployment,statefulset,configmap,secret -l envtest # 处理Terminating状态卡住的命名空间 # 先查看命名空间状态 kubectl get namespace namespace -o json ns.json # 修改finalizers为空数组后用代理方式更新 # 这种操作风险很高非必要不建议在生产环境执行 # 强制删除Pod无响应时 kubectl delete pod pod-name --force --grace-period0 # 强制删除命名空间风险极高慎用 kubectl delete namespace namespace --force --grace-period0先说明一下kubectl delete all -n namespace --all里的all是大意上的资源聚合实际并不会删除ConfigMap和Secret等内容所以测试环境重建后要注意残留问题。如果要彻底清空针对configmap、secret、pvc、role、serviceaccount这些资源单独执行一遍删除命令更靠谱。命名空间卡在Terminating状态是个比较头疼的问题。通常是该命名空间下还有未被彻底清理的资源比如自定义资源CRD实例或者APIService处于异常状态导致资源无法删除。前期排查用kubectl get namespace name -o json | jq .status和kubectl get apiservice | grep False配合定位原因实在需要强清编辑finalizers也要非常谨慎因为这可能掩盖底层依赖关系的破坏问题。5.5 资源对象导出与迁移从集群里导出资源定义用于备份或迁移也是日常高频操作# 导出资源yaml推荐 kubectl get deployment deployment-name -n namespace -o yaml deployment-backup.yaml kubectl get service service-name -n namespace -o yaml service-backup.yaml # 导出资源后去掉状态信息和运行时元数据方便重新apply到新集群 kubectl get deployment deployment-name -n namespace -o yaml --exporttrue clean-deployment.yaml # 导出所有Deployment如果资源太多建议分命名空间执行 kubectl get deployments -n namespace -o yaml all-deployments.yaml # 批量导出多个资源到一个文件 kubectl get deploy,svc,configmap,secret -n namespace -o yaml all-resources.yaml有个地方要留意新版本kubectl1.18以上已经移除了--export参数直接导出的大多包含status字段、uid等运行时数据。要把导出的yaml再次apply到新集群时建议手动清理metadata.uid、metadata.resourceVersion、metadata.creationTimestamp这些字段以及顶层的status块。用sed或yq工具批量处理会省不少事不会的话手删几个资源也很快。6. 进阶命令与实用技巧6.1 多集群管理与上下文切换生产环境通常不止一个集群多集群管理需要熟练使用kubectl context# 查看所有上下文 kubectl config get-contexts # 查看当前上下文 kubectl config current-context # 切换到指定上下文 kubectl config use-context context-name # 查看当前kubeconfig内容 kubectl config view # 配置一个新的集群上下文 kubectl config set-context context-name --clustercluster-name --useruser-name --namespacenamespace # 直接切换默认命名空间等价于修改当前上下文的namespace kubectl config set-context --current --namespacenamespace多集群切换最怕的是在错误的集群里执行了高危命令。我个人的习惯是在敏感操作比如删除资源、drain节点前先执行一次kubectl config current-context确认当前所在环境再执行一个只读的查询命令验证上下文。这个习惯看着笨但真的能救生产环境。6.2 kubectl常用输出格式速查# 不同输出格式的用法 kubectl get pods -o wide # 显示更多字段IP、节点等 kubectl get pods -o yaml # 完整yaml格式输出 kubectl get pods -o json # 完整json格式输出 kubectl get pods -o name # 只输出资源类型和名称 kubectl get pods -o custom-columnsNAME:.metadata.name # 自定义列 kubectl get pods -o jsonpath{.items[*].metadata.name} # 用jsonpath提取字段 # 持续监听资源变化CtrlC退出 kubectl get pods -w # 查看资源标签 kubectl get pods --show-labels # 格式化输出到文件 kubectl get deployment deployment-name -o yaml deploy.yaml-w参数在排障时很实用可以实时看到Pod状态变化比如滚动更新时新Pod的创建过程、旧Pod的终止过程对着屏幕等几秒就能发现更新的节奏和卡点。JSONPath初学时不太好记但掌握了基础语法后从复杂资源对象中提取脚本需要的信息会变得非常顺手。6.3 快速生成yaml模板的技巧遇到需要创建某种资源但记不住完整yaml结构时用--dry-runclient快速生成模板是最快的办法# 生成Deployment模板 kubectl create deployment nginx-demo --imagenginx --dry-runclient -o yaml # 生成Job模板 kubectl create job demo-job --imagebusybox --dry-runclient -o yaml -- sleep 30 # 生成CronJob模板 kubectl create cronjob demo-cron --imagebusybox --schedule*/5 * * * * --dry-runclient -o yaml -- echo hello # 生成Pod模板 kubectl run nginx-pod --imagenginx --dry-runclient -o yaml # 生成Service模板 kubectl create service clusterip demo-svc --tcp80:8080 --dry-runclient -o yaml这个方法能保证生成的yaml格式和字段一定是正确的再在模板基础上增加需要的配置比如探针、资源限制、环境变量、存储挂载等比完全手写yaml节省不少时间也能避免因为API版本或字段名记错导致的校验错误。6.4 临时调试容器的使用Pod处于运行状态但镜像里没有调试工具比如容器连curl、netstat都没有这时kubectl debug命令可以临时往Pod里附加调试容器相当于给运行中的Pod加个带有排查工具的外挂。# 为Pod创建临时调试容器 kubectl debug pod-name -it --imagenicolaka/netshoot --targetcontainer-name # 复制Pod并在新Pod中调试不影响原Pod kubectl debug pod-name --imagenicolaka/netshoot --copy-todebug-pod-name -it--target参数指定和哪个容器共享网络命名空间然后就能在那个容器的网络环境下执行netstat、tcpdump、nslookup等排查命令了。netshoot这个镜像集成了大量网络排查工具做网络问题定位很方便。如果原Pod是因为缺少依赖或库才崩溃的用--copy-to复制一个Pod并在里面手动执行启动命令能快速验证是不是库文件或启动参数的问题。7. 常用命令速查表与避坑建议系统整理了一些按场景分类的速查命令建议截图或收藏备用。7.1 按业务场景快速定位命令场景推荐命令说明查看所有节点状态kubectl get nodes -o wide快速确认节点IP、版本、状态查看指定命名空间所有工作负载kubectl get deploy,sts,ds,pods -n ns一次看清该命名空间下所有无状态、有状态、守护Pod定位Pod调度失败原因kubectl describe pod pod-name重点看Events里的FailedScheduling滚动更新失败回滚kubectl rollout undo deployment/name回滚到上一个版本查看Deployment变更历史kubectl rollout history deployment/name配合--revision查看指定版本细节容器无法进入时排查kubectl logs pod-name --previous查看上一个崩溃实例的日志查看Service后端是否正常kubectl get endpoints svc-name确认后端Pod的IP列表节点维护前驱赶Podkubectl drain node --ignore-daemonsets批量迁移Pod到其他节点确认当前集群环境kubectl config current-context多集群操作前必做查看实时事件kubectl get events -n ns -w实时观察资源状态变化7.2 这些坑我踩过提前帮你避一避写一下实际运维中容易踩的坑省得大家重走弯路。坑一忘了指定命名空间改错了生产资源默认情况下kubectl操作的是default命名空间。如果你不在命令行里加-n参数很可能你本意是操作A环境某个命名空间的资源结果动到了B环境default。多次出现这种情况后我现在每次在操作前都会习惯性地加上-n参数把命名空间显式写出来如果确实需要频繁切换命名空间就在kubeconfig里每个上下文绑定各自的默认namespace切换上下文时顺带切换环境。坑二强行删除Pod导致数据不一致当Pod卡在Terminating状态时很多人的第一反应是--force --grace-period0一把梭。但强制删除Pod是绕过K8s正常终止流程的对无状态应用还好对有状态应用数据库、消息队列等可能导致数据文件损坏或脑裂。实际的建议是先尝试正常删除等待一段时间比如30秒确认卡住的真正原因再决定是否强制如果确实需要强删也建议先用kubectl describe pod和kubectl get pvc -n ns确认存储、分布式锁等关联资源的状态评估好风险后再操作。坑三滚动更新后忘记了回滚的时间窗口kubectl rollout undo可以回滚但如果新版本已经稳定运行了很长时间期间又有其他变更比如修改过配置、扩缩过容回滚可能会把这些变更一并带回旧版本导致回滚后反而出现新问题。建议在以下两种场景谨慎回滚容器镜像升级后运行已超过数小时期间有别的配置变更多副本服务滚动更新期间流量有大量报错但新版本问题已经自行缓解。回滚前先查看rollout history确认要回滚到的版本确实是预期的稳定版本。坑四日志查看时忽略了--previous参数容器崩溃后自动重启用kubectl logs看到的是最新实例的日志退出前打印的错误信息往往沉淀在上一个实例里。排查CrashLoopBackOff时不加上--previous参数看到的只是启动过程中的正常输出真正导致崩溃的异常日志看不到问题定位就无从谈起。现在每当看到Pod状态是CrashLoopBackOff或Error我都会第一时间用kubectl logs pod --previous抓上个实例的日志再结合describe里Last State的exit code一起分析。坑五误以为ConfigMap修改后Pod会自动生效这是很多人初学K8s时的误解。ConfigMap通过volume挂载到Pod后kubelet会把ConfigMap的内容同步到Pod的文件系统里但进程内部已经缓存的配置不会自动刷新很多应用也不会监听配置文件的变化。修改ConfigMap后不重启关联的Pod新的配置不会生效表现就是改了半天重启服务还是旧配置。常规做法是修改ConfigMap后执行kubectl rollout restart滚动重启让Pod重新挂载新配置。坑六用旧版本kubectl操作新集群Kubernetes的API组在持续演进旧版本kubectl可能不认识新集群里的某些API资源或者默认生成的yaml字段和当前集群的schema不一致apply时报错。解决方式很简单用于运维的机器或跳板机上部署和集群版本相近甚至相同版本的kubectl或者用kubectl插件管理工具brew、asdf、kubectx/kubens等多版本共存按集群切换。7.3 快速checklist每天巡检时跑哪几条命令可能会想每天到了工位打开电脑K8s集群巡检应该先看什么分享一套我自己的巡检习惯按顺序跑下来基本一眼能看出集群有没有潜在风险# 1. 先看集群节点状态 kubectl get nodes -o wide # 2. 看有没有异常状态的Pod kubectl get pods -A | grep -vE Running|Completed # 3. 看核心组件kube-system命名空间是否健康 kubectl get pods -n kube-system # 4. 看节点磁盘和资源压力有metrics-server时 kubectl top nodes # 5. 看有没有大量事件堆积快速发现异常动态 kubectl get events -A --sort-by.lastTimestamp | tail -20 # 6. 看证书剩余时间防止集群证书过期导致kubelet失联 openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates # 或者用cert-manager的证书状态 kubectl get certificates -n cert-manager巡检的价值不在多在于能提前摸到苗头。比如某节点磁盘使用率持续走高、某命名空间出现大量OOMKilled事件这类零星的小异常往往是故障的前奏。把巡检变成习惯比等告警平台爆出大问题再冲上去救火要省心得多。8. 从命令到理解掌握K8s操作背后的逻辑我在刚开始接触K8s时喜欢把命令当作记忆负担背来背去总觉得记不住。后来逐渐意识到kubectl的命令本身并不难难的是对K8s设计思想的理解。命令背后对应的是对象的增删改查、状态的编排调度、组件的分工协作。举个例子kubectl scale看似只是改了replicas这个数字实际上触发的是ReplicaSet的期望状态和实际状态趋向一致的调协过程。K8s的ControllerManager会持续监视发现实际Pod数量少于期望值就自动创建Pod多于期望值就自动清理多余Pod。理解了这套声明式API的逻辑很多命令的行为就是自然而然的推演了。同样kubectl rollout restart做的事情不是字面上的重启而是通过修改Pod模板的注解来触发一次新的滚动更新。从用户角度看效果像是重启了所有Pod背后的本质是创建新的ReplicaSet并逐步替换旧Pod。理解了这套机制当滚动更新过程中出现Pod启动失败、健康检查不过等情况时自然能预判到更新会暂停还是回滚而不必死记命令参数。所以我的最后一条建议是命令手册只是起点建立起对K8s控制循环、调协机制、资源对象之间关系的整体认知才能在遇到复杂故障时真正游刃有余。就像用手写代码不一定要背语法书但理解了对象、类和继承关系写起来自然顺手。K8s的学习其实同样是这个道理。在实际使用中我把上面这些命令按频率高低梳理成了一张自己的速查卡高频命令get、describe、logs、exec、apply几乎每天都会用中频命令scale、rollout、label、taint每周用几次低频命令debug、port-forward、cp等在特定场景下才需要。建议同学们也按自己的业务场景做一份类似速查用顺手的工具永远是最高效的。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。