我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

kubectl实战指南:从高频命令到排障与CI/CD集成

kubectl实战指南:从高频命令到排障与CI/CD集成 做了这么多年 Kubernetes 运维我几乎每天都在跟 kubectl 打交道。刚开始接触那会儿我也只会那几个最基础的命令比如kubectl get pods、kubectl logs一旦 Pod 起不来、集群连不上就得翻半天文档。后来踩的坑多了才慢慢把 kubectl 这套命令体系摸透甚至养成了“先 describe 再下结论”的排障习惯。这篇文章不打算做成命令手册的堆砌而是从实际使用场景出发把 kubectl 里最常用、最能救命的那批命令串起来讲。包括高频命令的使用逻辑、排障时的真实操作流程、kubeconfig 配置的常见坑以及把 kubectl 接到 GitLab CI/CD 这类自动化平台时的处理方案。适合刚入门准备考 CKA 的读者也适合已经在生产环境摸爬滚打、想查漏补缺的同行。1. kubectl 的工作逻辑与配置准备很多人用 kubectl 的第一反应是直接敲命令结果弹出一堆Unable to connect to the server然后就开始怀疑集群坏了。其实大部分情况下不是集群的问题而是 kubectl 压根没找到正确的集群连接信息。这里面的核心就是 kubeconfig。1.1 kubeconfig 文件到底在配置什么kubectl 本身只是一个客户端它要连哪个集群、用什么身份、默认进哪个 namespace全靠 kubeconfig 文件决定。默认路径是$HOME/.kube/config也可以通过--kubeconfig参数或者KUBECONFIG环境变量指定。kubeconfig 本质上是一个 YAML 文件里面有三个核心区块clusters、users、contexts。clusters定义 API Server 的地址和证书信息users定义客户端身份凭证contexts把前两者组合起来形成一个“我以某某身份连接某某集群”的上下文。理解这三者的关系之后你就能明白为什么kubectl config系列命令里有set-cluster、set-credentials、set-context这样的子命令。它们都是在分别维护这三个区块最后用use-context做切换。提示如果你拿到一个别人的 kubeconfig 文件第一件事不是急着用而是先执行kubectl config view看一下里面的 cluster、user、context 内容是否完整。很多时候问题就出在证书字段是空的或者 server 地址写错了。1.2 context 切换是日常最高频的操作实际工作中手里往往不止一套集群比如开发环境、测试环境、预发环境。如果每套环境都要维护一份独立的 kubeconfig 文件然后靠--kubeconfig参数来回指定非常容易搞混。更常见的做法是把多套集群信息合并到一个 kubeconfig 文件里然后用 context 做切换。# 查看当前 kubeconfig 里有哪些 context kubectl config get-contexts # 切换到指定的 context kubectl config use-context prod-cluster # 查看当前所在 context kubectl config current-context我自己的习惯是把 context 命名成容易识别的格式比如dev-cluster、test-cluster、prod-cluster。这样在执行kubectl get nodes之前只要看一眼当前 context就能确认自己没在错误的集群上操作。有个小技巧值得分享如果你经常在多个集群之间切换建议给kubectl config use-context配置一个 shell alias比如alias kctxkubectl config use-context。省得每次敲一长串命令。1.3 用好 KUBECONFIG 环境变量除了合并到一个文件另一种常见的做法是利用KUBECONFIG环境变量同时加载多个 kubeconfig 文件。kubectl 会把这些文件的内容合并起来相当于在内存里生成一个临时 kubeconfig。export KUBECONFIG$HOME/.kube/config:$HOME/.kube/prod.config这种方式的优势是灵活需要哪个环境就把哪个文件加入变量。缺点是如果你在不同终端窗口里设置了不同的KUBECONFIG容易造成混乱。我一般在自动化脚本里用环境变量手动操作时还是习惯用合并后的单一文件。合并多个 kubeconfig 文件可以用下面这条命令kubectl config view --flatten merged-config.yaml再用--kubeconfigmerged-config.yaml去使用。这样处理后不用担心证书字段被省略因为--flatten会把证书内容直接内嵌到文件里而不是保留certificate-authority的文件路径引用。2. 高频命令地图与场景化用法kubectl 命令虽然多但日常用得顺手的基本上就那一批。这里按使用场景分成几类来梳理每一类我会讲清楚命令背后的逻辑和适用场景而不是单纯罗列参数。2.1 资源查询get、describe、explainkubectl get是最常用的命令它解决了“现在集群里有什么”的问题。这里的关键是理解资源类型以及如何用输出格式提取你需要的信息。# 查看所有 namespace 下的 Pod kubectl get pods -A # 查看指定 namespace 下的 Deployment kubectl get deployment -n backend # 查看节点状态 kubectl get nodes -o wide-o参数非常值得花时间研究。-o wide能看到更多列比如 Pod 所在的节点、IP 地址-o yaml能拿到资源的完整定义排障时经常需要把某个资源的 YAML 导出来看-o jsonpath适合在脚本里提取指定字段比如获取某个 Deployment 的副本数。kubectl describe和get的区别在于前者会展示资源的详细事件和状态流转过程后者只展示概要信息。排障的时候describe里的Events字段往往能直接告诉你 Pod 为什么起不来比如镜像拉取失败、探针检查失败、端口冲突等。kubectl explain是个容易被忽略的命令。当你不确定某个字段的含义时kubectl explain pod.spec.containers可以直接查看该字段的说明文档体验比翻网页更快。2.2 Pod 调试logs、exec、port-forward、cpPod 是 Kubernetes 里最基本的调度单元大部分线上问题排查最终都会落到这四个命令上。kubectl logs用于查看容器日志。生产环境里容器重启后旧日志就丢了这时加上--previous参数可以查看上一次容器的日志# 跟随日志输出 kubectl logs -f deployment/nginx-deploy -n web # 查看上一个实例的日志容器异常重启后非常有用 kubectl logs deployment/nginx-deploy --previous -n web # 只看最近 100 行 kubectl logs pod/nginx-pod --tail100当一个 Pod 里有多个容器时必须用-c指定容器名否则 kubectl 会提示你container name is required。这个细节在 sidecar 模式比如 istio-proxy 和应用容器共存下很关键。kubectl exec用来进入容器执行命令。最常见的场景是进入容器检查环境变量、配置文件、网络连通性kubectl exec -it pod/my-pod -n web -- /bin/sh如果容器里没有/bin/sh可以试/bin/bash如果两者都没有说明镜像精简过头了那就要靠 logs 或者临时挂一个调试容器来解决。kubectl exec只支持进入正在运行的容器没法在容器外面诊断一个 CrashLoopBackOff 的问题。kubectl port-forward是一个“曲线救国”的工具。它能把集群里某个 Service 或 Pod 的端口映射到本地让你在本地直接用localhost访问集群内的服务特别适合临时调试 API、访问管理后台这类场景。# 把集群里的 nginx 服务 80 端口映射到本地 8080 kubectl port-forward service/nginx-service -n web 8080:80 # 直接映射某个 Pod 的端口 kubectl port-forward pod/redis-pod-0 6379:6379kubectl cp则用于在本地和 Pod 之间复制文件。升级 Pod 后想保留旧配置或者需要把宿主机上的文件拷进容器里这个命令很实用。2.3 资源管理apply、delete、scale、rolloutkubectl apply是现代 Kubernetes 操作资源的最主要方式。它和kubectl create的最核心区别是apply是声明式操作它会比较 YAML 里的字段与集群中已有状态的差异然后只更新有变化的部分create遇到已存在的资源会直接报错。# 声明式创建或更新 kubectl apply -f deployment.yaml # 从标准输入创建 cat deployment.yaml | kubectl apply -f - # 删除资源 kubectl delete -f deployment.yamlkubectl delete支持资源类型和名称的组合也可以直接删除整个 namespace 下的所有资源但我不建议轻易这么做尤其是生产环境。kubectl scale用于调整副本数是应对流量突增最直接的手段# 扩容到 10 个副本 kubectl scale deployment/nginx-deploy --replicas10 # 根据当前 HPA 配置动态调整 kubectl autoscale deployment/nginx-deploy --min2 --max10 --cpu-percent80kubectl rollout是管理 Deployment 发布流程的命令。每次更新 Deployment 的镜像或配置都会触发一次 rollout“版本回滚”这个概念落到命令行上就是它# 查看发布历史 kubectl rollout history deployment/nginx-deploy # 查看当前发布状态 kubectl rollout status deployment/nginx-deploy # 回滚到上一个版本 kubectl rollout undo deployment/nginx-deploy # 回滚到指定版本 kubectl rollout undo deployment/nginx-deploy --to-revision2我实测下来rollout status在发布脚本里几乎是必用的。在 CI/CD 流水线里更新镜像后直接跟一条kubectl rollout status就能确保发布完成或超时失败而不是盲目等 sleep 固定时间。3. 实操从零排查一个故障 Pod 的完整过程按场景拆命令容易形成“每个命令都认识但不会串联”的尴尬。我拿一个真实发生的故障来串一遍排查流程你跟着从头到尾过一遍就知道这些命令是怎么配合的。3.1 故障现象与排查起点假设开发报告“订单服务挂了”你登录集群后的第一步当然是看 Pod 状态kubectl get pods -n order-service输出显示NAME READY STATUS RESTARTS AGE order-service-6b9f5b7d7d-8kq2 0/1 CrashLoopBackOff 5 12mCrashLoopBackOff意味着容器启动后不断崩溃被 kubelet 反复重启。这个状态下直接kubectl logs通常只能拿到最后一段输出但对定位问题往往已经足够。kubectl logs deployment/order-service -n order-service --tail50但很多时候日志没法解释为什么容器会“崩溃”尤其是进程被 OOM Kill 这类情况。此时需要看退出码和上一次日志# 查看上次容器的日志 kubectl logs deployment/order-service --previous -n order-service # 查看 Pod 详细信息和事件 kubectl describe pod/order-service-6b9f5b7d7d-8kq2 -n order-service3.2 从 describe 输出里读关键信息describe的输出比较长但排障时只需要重点看几个部分。Status里的ContainerStatuses会显示容器的退出码和重启次数。退出码 137 通常表示容器被 OOM Kill 或被强制终止退出码 1 则通常是应用自身异常退出。Events区域能看到 kubelet 在调度、拉取镜像、启动容器过程中的事件记录比如Failed to pull image或Back-off restarting failed container这类信息。有一次我排查一个 Pod 反复重启的问题describe里并没有明显的错误事件但容器日志里出现了io.containerd.runtime.v2.task相关报错。后来发现是镜像包太大节点磁盘空间不足导致容器运行时初始化失败。像这类宿主机层面的问题只看kubectl get pods是看不出来的需要去节点上看系统磁盘占用。3.3 进入容器验证运行环境如果 Pod 能正常运行但业务表现异常比如接口超时、数据不一致就需要进容器里做一层现场验证kubectl exec -it pod/order-service-6b9f5b7d7d-8kq2 -n order-service -- /bin/sh进入容器后我通常会先做三件事检查环境变量是否注入正确确认配置文件是否挂载到预期路径验证下游依赖比如数据库、Redis能否连通。很多“Pod 起来了但业务报错”的问题根因都在这些静态配置上而这些信息光靠kubectl logs不一定看得到。排障过程中如果怀疑是网络问题kubectl run加--rm临时起一个带有调试工具的 Pod 来测连通性是比较快速的手段kubectl run curl-test --imagecurlimages/curl --rm -it --restartNever -n order-service -- curl -v http://order-service:8080/health这种临时调试 Pod 用完即删不会污染 namespace。它和port-forward的定位不同前者是在集群内测服务间访问后者是从本地访问集群内服务。4. 配置管理与 GitLab CI/CD 集成方案前面提到过 kubeconfig 的合并与切换但真正容易被卡住的其实是在自动化平台里怎么配置 kubectl。尤其是把 kubectl 集成进 GitLab CI/CD 后很多同学的流水线能跑过 build却在 deploy 阶段报error: current-context is not set十有八九是 kubeconfig 没有配置好。4.1 在 GitLab CI 中设置 kubeconfig 的几种方式GitLab 里配置 kubectl 的常见思路有三种我按推荐程度排序。第一种是把整个 kubeconfig 文件内容存入 GitLab CI/CD 变量在 job 里写回文件并设置KUBECONFIG环境变量。对于只有一套目标集群的场景这种方式最直观也最容易排查问题。变量类型选择 File 或 Variable 都可以区别在于注入到 runner 时的形式不一样用 Variable 存纯文本需要自己在 job 里写成文件deploy: script: - mkdir -p $HOME/.kube - echo $KUBECONFIG_CONTENT | base64 -d $HOME/.kube/config - kubectl get nodes第二种是利用kubectl config set-cluster系列命令在 job 里动态拼接 kubeconfig。这种适合不想把证书和密钥写进同一个变量的场景。API Server 地址、CA 证书、Token 分别存在不同变量里在 job 里一步步组装 context。缺点是脚本会长一些但如果 kubeconfig 内容经常轮换这样管理起来反而安全。kubectl config set-cluster my-cluster \ --server$CLUSTER_SERVER \ --certificate-authority(echo $CLUSTER_CA | base64 -d)第三种是使用云厂商提供的命令行工具直接生成 kubeconfig。比如某些托管集群支持通过云控制台或 CLI 导出完整 kubeconfig再把生成好的内容作为 CI/CD 变量使用。这种方式胜在生成过程受官方支持不太容易出现证书格式错误。4.2 在 GitLab CI 中部署应用kubectl 配置文件就绪后剩下的步骤就是标准的部署流程。我在流水线里一般这么写deploy: stage: deploy image: bitnami/kubectl:latest only: - main script: - kubectl version --client - kubectl apply -f deployment.yaml - kubectl rollout status deployment/order-service -n order-service --timeout120s用bitnami/kubectl镜像可以省去在 runner 上手动安装 kubectl 的麻烦。kubectl version --client这一步看似多余但它能帮你确认 kubectl 二进制本身没问题排除掉“命令不存在”这种低级错误。如果 Deployment 使用了 ConfigMap 或 Secret更新配置后记得用下面这条命令触发滚动更新否则kubectl apply不会重建 Pod新的配置也就不会生效kubectl rollout restart deployment/order-service -n order-service4.3 权限模型建议在 GitLab CI 中使用的 kubeconfig强烈不建议使用集群管理员权限。生产环境最佳实践是单独创建一个 ServiceAccount并通过 RBAC 绑定最小权限只允许它在某个 namespace 下操作 Deployment、Service、ConfigMap 等特定资源。这样一来即使 kubeconfig 内容泄露攻击者能做的也极为有限。创建最小权限 ServiceAccount 的过程并不复杂先创建一个 namespace再创建 ServiceAccount然后通过 Role 和 RoleBinding 限制权限。获取该 ServiceAccount 的 Token把 token 和集群 CA 证书一起放进 kubeconfig 的users区块这样一个受限的 kubeconfig 就生成了。5. 常见问题与避坑技巧从这个标题相关的技术社区讨论来看很多同学的疑问集中在“连不上集群”“没权限”“命令不对”这几类。我整理了排查思路和操作上的禁忌希望能帮你少走弯路。5.1 常见报错速查表报错信息可能原因排查方向Unable to connect to the serverAPI Server 地址不通检查 server 地址、网络策略、防火墙The connection to the server was refusedAPI Server 端口未监听或服务异常检查集群控制面组件状态certificate signed by unknown authorityCA 证书不匹配或未正确配置重新生成/配置 CA 证书Forbidden (user... cannot list resource ...)RBAC 权限不足检查 Role/RoleBinding 配置error: current-context is not setkubeconfig 里没有指定当前 context执行kubectl config use-contextThe server was unable to return a responseAPI Server 过载或 etcd 异常检查集群组件资源使用率5.2 操作禁忌与实战经验第一不要在多个终端里使用不同的KUBECONFIG环境变量这是造成“我在哪套集群上”认知混乱的头号原因。要么统一用默认路径要么统一用同一个配置文件给每个终端设置好提示。第二不要对生产环境的 namespace 滥用 delete 命令。我之前见过有人想清理异常 Pod直接kubectl delete pods --all -n prod结果把无状态服务全部删掉了幸好有 Deployment 自动重建不然后果不堪设想。正确做法是先kubectl get pods -o wide看清 Pod 归属用kubectl delete pod pod-name单独处理或者通过调整 Deployment/PVC 的方式优雅下线。第三kubectl edit改资源时一定要留意注释和格式。这个命令本质上会拉取资源的 YAML在默认编辑器里改完保存后再提交到 API Server。如果改动过程中误删了某些字段整个资源可能被重置。我的习惯是重要资源先在本地备份再执行kubectl edit改坏了可以用备份恢复。第四善用--dry-runclient -o yaml来生成资源定义而不是凭空手写 YAML。比如你想知道某个 Deployment 的 YAML 长什么样可以执行kubectl create deployment my-app --imagenginx --dry-runclient -o yaml my-app.yaml把生成的 YAML 作为基准再修改比自己从零写要规范得多不容易漏字段。5.3 一些真正提升效率的配置kubectl 自带 bash 补全功能执行下面两条命令就能享受 tab 补全source (kubectl completion bash) echo source (kubectl completion bash) ~/.bashrc用 zsh 的换kubectl completion zsh。有了补全kubectl get deploy不会敲错资源名也能自动补全。另外我强烈建议把最高频的命令设置成 aliasalias kkubectl alias kgpkubectl get pods alias kgdkubectl get deployment alias kdkubectl describe alias klkubectl logs alias kafkubectl apply -f alias kxkubectl exec -it最后再分享一个小技巧。当你想知道某个资源当前到底被哪些字段控制时直接看kubectl get resource name -o yaml比查文档更直观。但有一点要记住——这个命令输出的是集群里的实际状态可能比创建时的 YAML 多了很多系统默认填充的字段比如status、creationTimestamp、resourceVersion。手动改动时要不要保留这些字段取决于你是想做声明式更新还是直接修改现状。理解了这一点你对 kubectl 的理解基本就超越大部分只是“会敲命令”的人了。
返回列表