news 2026/9/13 2:07:54

kubectl实战指南:常用命令、kubeconfig配置与CI/CD集成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
kubectl实战指南:常用命令、kubeconfig配置与CI/CD集成

1. 动手之前的准备:安装方式与kubeconfig配置文件解析

每次聊到kubectl,我都习惯先提醒一句:别急着背命令,先搞清楚你手里的这个客户端到底是怎么连上集群的。kubectl本质上是Kubernetes的官方命令行工具,它做的事情可以用一句话概括——把你在终端里敲的指令翻译成对API Server的HTTP请求,然后由API Server去调度集群里的各种资源。所以你会发现,kubectl本身并不直接操作容器,它只是一个面向Kubernetes API的客户端。

作为运维或平台工程师,我和kubectl打交道的频率高过绝大多数工具。从看Pod状态、查日志,到发布应用、排查故障,几乎每天都在用。这些年用下来,最大的体会是:kubectl的命令再多,真正高频、核心的就那么几十条,只要把底层逻辑和常用场景吃透,完全可以覆盖日常工作。这篇文章就把我平时最常用的命令和踩过的坑整理出来,顺便聊聊很多人关心的配置文件问题。

1.1 安装kubectl:别小看这一步

安装kubectl本身不复杂,但你会遇到第一个问题:版本。kubectl和集群的版本不建议相差太大,官方建议是允许kubectl版本比集群的minor version大一或小一。实际操作中,我一般直接装跟集群相同或者更新一点点的版本,避免出现API资源列表识别不了的情况。

Linux下最常见的安装方式就是下载官方二进制并放到PATH里,然后chmod加执行权限。macOS可以用brew install kubectl。如果本地装了Docker Desktop,它自己会带一个kubectl,但那个版本往往偏老,我建议还是单独装一份,避免混淆。

装完后先验证一下版本,观察kubectl version输出的Client Version和Server Version。如果Server Version那一栏显示Unable to connect,那说明kubectl本身没问题,问题出在连不上集群,这就要去看kubeconfig配置文件了。

1.2 kubeconfig配置文件:kubectl连接集群的钥匙

这也是为什么会有人在问“gitlab怎么设置kubectl配置文件”的根本原因——kubeconfig(通常默认路径是~/.kube/config)就是kubectl用来确定“连接哪个集群、用什么身份、切换哪个命名空间”的唯一依据。

一个标准的kubeconfig文件由三块核心内容组成:

  • clusters:集群信息。里面保存的是API Server的访问地址(server字段)和证书信息(certificate-authority-data字段)。
  • users:用户凭证。包括客户端证书、私钥,或者token等身份凭据。
  • contexts:上下文。它把cluster和user组合到一起,同时指定默认的namespace。你可以理解为“用哪个身份、连哪个集群、进哪个命名空间”的三元组。

打个比方,clusters是门牌号,users是你手里的钥匙,contexts则是“你拿着这把钥匙去开这个门牌号对应的门,然后直接走进某个房间”的完整路线。kubectl实际工作时会读config文件里的current-context字段,找到当前上下文,再根据上下文里指定的cluster和user去建立连接。

这里有个实际场景值得多说一句:很多人会不小心把集群的admin证书塞进kubeconfig,然后到处分发。从安全角度来说,这是我不太建议的,最小权限原则在任何地方都适用。给开发或CI/CD环境用的kubeconfig,最好单独创建只读或限定命名空间的ServiceAccount,然后把对应的token分发出去。

1.3 多集群与KUBECONFIG环境变量:一份配置走天下

如果你手上同时有好几个集群,比如一个测试环境、一个预发环境,还有一个生产环境,那靠kubectl config view来回翻context就会效率很低。我常用的配置方式是利用KUBECONFIG环境变量,把多个config文件合并起来。

做法是这样的:

export KUBECONFIG=/root/.kube/config:/opt/k8s/test.conf:/opt/k8s/prod.conf kubectl config get-contexts

get-contexts会把所有config文件里的context都列出来,然后你可以用一句话完成切换:

kubectl config use-context prod

切完上下文后,再执行kubectl get pods,它就会去连接生产集群。用这个方案,你再也不用把好多个config文件来回覆盖到~/.kube/config里了。我现在是把所有context名称约定成“环境名-集群名”的格式,比如test-cluster、prod-cluster,一眼就能认出当前在哪个环境。

还有一个小技巧:为了避免在某台机器上误操作生产环境,我习惯给生产环境的context单独配置一个特殊的KUBECONFIG变量,并且只在需要操作生产时才export它。配合kubectl config current-context确认当前位置,基本不会出现“明明想操作测试集群,结果把生产环境搞挂”的悲剧。

2. 日常使用频率最高的kubectl命令

命令不用背太多,但常用的这几个你得形成肌肉记忆。我把它们分成“查看类”“变更类”“运维类”三组,这样记忆起来更有条理。

2.1 查看类三件套:get、describe、logs

kubectl get是最基础的查询命令,负责以列表形式展示资源状态。平时我用得最多的对象是pod、node、deployment、service、event。

kubectl get pods kubectl get pods -n kube-system kubectl get nodes -o wide kubectl get deploy,svc -l app=nginx

-o wide会多显示一些字段,比如Pod所在的节点IP、Pod的IP,排查网络问题时几乎必用。至于-n参数,没什么好说的——不指定命名空间的话,只看default命名空间,很多资源你会“找不到”,但其实它就在别的namespace里待着。

kubectl describe适合看一个资源的详细信息,比如事件、标签、状态变化过程。我很少对着get的输出猜问题,因为get只显示当前状态,不显示历史事件。真正排查Pod为什么起不来,我会先describe一下:

kubectl describe pod nginx-xxxxx

重点看Events这一段。常见的情况是镜像拉取失败(ImagePullBackOff)、健康检查失败(Liveness probe failed)、资源不足(FailedScheduling)等,原因基本在Events里都写得明明白白。

kubectl logs用来查看容器日志,你要是看过Pod里多个容器的情况,得用-c指定容器名:

kubectl logs -f pod-name -n namespace kubectl logs pod-name -c container-name --tail=50

-f是实时跟踪,--tail是只显示最后多少行,这两个参数组合起来用,排查问题的时候效率很高。如果容器之前崩溃过,想查上一次进程的日志,记住加-p参数:

kubectl logs pod-name -p

这个-p参数很多人容易漏,导致查不到崩溃原因。

2.2 变更类:apply、edit、patch、delete

再接着说变更操作。我以前习惯用kubectl create来创建资源,但后来发现,如果要做“有则更新,无则创建”这种幂等操作,kubectl apply才是正道。特别是持续集成环境里,反复执行同一个YAML,用apply完全不会报错。

kubectl apply -f deployment.yaml kubectl apply -f ./manifests/

线上临时改镜像版本,我不太喜欢打开编辑器去edit,直接用set命令最快:

kubectl set image deployment/nginx nginx=nginx:1.25 -n default

不过如果你还是习惯像vim那样改,kubectl edit也行,它会把当前资源的定义拉下来变成YAML,保存后自动apply。注意一点,edit是直接改live object,如果资源和当前声明的配置有冲突,保存时会因为冲突报错,这时候可以用patch去做局部字段的修改。

kubectl patch适合精准修改某个字段,尤其是改一些嵌套很深、用set很难表达的参数。示例:

kubectl patch deployment nginx -p '{"spec":{"replicas":3}}'

这段命令的意思是把nginx这个Deployment的副本数改成3。patch处理JSON格式,注意引号转义,习惯了也就不觉得麻烦。

删除资源的命令看起来简单,但坑不少。kubectl delete会先把资源标记为删除状态,然后看资源是否有finalizer,如果finalizer没处理完,资源会一直处于Terminating状态。遇到Terminating的Pod卡住,可以用强制删除:

kubectl delete pod xxx --force --grace-period=0

但这里要提醒一句:强制删除Pod会导致Pod里正在处理的任务被硬生生掐断,不到万不得已,别乱用。

2.3 手动运维:exec、port-forward、cp

进到容器内部去调试,在Docker时代是docker exec,在Kubernetes时代就是kubectl exec:

kubectl exec -it pod-name -- /bin/sh kubectl exec -it pod-name -c sidecar-container -- /bin/sh

-c指定容器这点在Pod里有多个容器时非常重要。我在Pod里查完问题之后,通常先敲exit再退出,而不是直接关闭终端,否则偶尔会留下异常会话。

端口转发是另一个高频命令。比如你本地想访问集群里的某个服务,但服务没有对外的NodePort或LoadBalancer,可以直接用port-forward把远端端口映射到本地:

kubectl port-forward svc/nginx-service 8080:80

执行完这条,访问本地的8080端口,就等于访问集群里nginx-service的80端口。调试阶段特别好用,但别把它当成生产环境的流量入口——port-forward走的是kubectl建立的隧道,稳定性跟网络直接相关,扛不住生产流量。

文件拷贝我平时用得也很多,比如把Pod里的日志拉出来或者把本地配置传进去:

kubectl cp pod-name:/var/log/app.log ./app.log kubectl cp ./config.yaml pod-name:/etc/app/config.yaml

kubectl cp的路径规则跟scp很像,但有个细节:如果Pod里有多容器,同样用-c指定容器,否则容易拷错容器,这事我踩过一次,传文件传到sidecar里,找了半天才发现。

3. 把kubectl用出效率的进阶技巧

命令本身不难,真正拉开效率差距的是组合使用和输出处理。下面这几个技巧是我日常使用频率最高、最能节省时间的。

3.1 自定义输出列:只看你想看的信息

kubectl get默认会有一列输出,但有时候字段太多,有时候字段又不够。没有捷径,用-o custom-columns就好:

kubectl get pods -o custom-columns=NAME:.metadata.name,IP:.status.podIP,NODE:.spec.nodeName

这个表达方式简洁地指定了要输出的列。开发环境中我常用这个组合来看所有Pod分布在哪些节点上,一轮肉眼扫描就能发现问题。

另一个极其强大但很多人没用起来的是JSONPath。配合-o jsonpath可以取出某个字段的值。比如要获取某个Deployment的副本数:

kubectl get deploy nginx -o jsonpath='{.spec.replicas}'

再配合shell的循环,你就可以写一些很小但很实用的自动化脚本。比如批量将所有不符合规则的Deployment副本数统一调整。这种能力在日常巡检时很有价值。

如果要沉淀成表格或报告,可以用-o wide或-o yaml导出完整定义,再用yq或jq去解析,比人眼盯着终端输出稳得多。我自己比较常用的习惯是:先kubectl get xxx -o yaml > xxx.yaml,再用编辑器打开,做信息提取或备份。

3.2 标签选择器与字段选择器:从全量中筛出目标

集群里Pod一多,kubectl get pods不带过滤条件输出几百行,基本等于没查。我习惯用标签选择器(-l)来缩小范围:

kubectl get pods -l app=nginx,env=prod kubectl get pods -l 'tier in (frontend,backend)'

标签是Kubernetes里推荐的资源关联方式。平时创建Deployment、Service时,我会提前约定好环境、应用、版本这组标签规范,后续用标签做筛选就非常顺手。

除了标签,还可以用--field-selector按字段过滤。比如查看某个节点上的所有Pod:

kubectl get pods --field-selector spec.nodeName=node01

或者查所有处于Failed阶段的Pod:

kubectl get pods --field-selector status.phase=Failed

标签选择器和字段选择器可以一起用,我自己做故障演练时经常这样组合,能很快圈定一台节点上的异常Pod范围,然后逐一排查。

3.3 命名空间批处理与上下文操作

想要“一键查询所有命名空间里的某个资源”,可以加上--all-namespaces(简写是-A):

kubectl get pods -A kubectl get events -A --sort-by=.lastTimestamp

-A这个参数太重了要慎用,但排查那种“全局范围找不到哪个命名空间的Pod在报错”时特别有效。配合--sort-by排序后,最新发生的异常事件会排在最上面,我一般先看Events,再看报错时间点前后的Pod日志,基本就能定位。

如果你经常在某几个命名空间之间切换,kubectl config set-context可以直接修改当前context的默认namespace:

kubectl config set-context --current --namespace=dev

这比每次敲命名空间省事多了。但小心,这个设置是持久的,下次在这个context里执行命令还是会落到dev命名空间里,如果临时切到别的环境忘了改回来,可能就把资源建错地方了。

3.4 自动补全与别名:终端效率翻倍

kubectl的命令参数又多又长,手敲很费劲。我强烈建议开启自动补全。以bash为例:

source <(kubectl completion bash) echo "source <(kubectl completion bash)" >> ~/.bashrc

zsh用户就换成kubectl completion zsh。补全之后,敲kubectl get po再加两下Tab键,namespace、资源名都会自动提示,节省的时间相当可观。

别名这件事,我的建议是只给那些你自己确实高频使用的命令配别名,不要贪多。我自己的几个常用别名供参考:

alias k='kubectl' alias kgp='kubectl get pods' alias kgd='kubectl get deploy' alias ksys='kubectl -n kube-system' alias kdesc='kubectl describe'

注意一点:如果用了类似kubectx和kubens这类切换工具,别名系统会跟它们有交互,自己按照习惯调整即可。

4. 生产环境排障:从Pod事件到核心命令的串联使用

命令单个拿出来都好理解,难的是在出问题时把这些命令串成一条排障流水线。下面分享一下我的排查思路和几个高频问题的处理方案。

4.1 一次Pod故障的排查路径

假设现在有个Pod一直处于CrashLoopBackOff状态,我会按下面的次序来排查:

第一步,先get pods看看整体状态,确认是哪个命名空间下的哪个Pod出了问题。

kubectl get pods -A | grep CrashLoopBackOff

第二步,describe这个Pod,重点看Events和Status里的信息。Events里如果有Back-off restarting failed container,说明容器启动后不断退出;如果看到Failed to pull image,那基本是镜像仓库认证或镜像名写错的问题。

第三步,看日志。如果容器还在运行或者刚崩溃,用kubectl logs调试失败原因:

kubectl logs -f pod-name --previous

--previous参数能看到上一次容器退出前的日志,这一步往往能直接看到业务报错。如果是应用启动时报配置错误,就在这里暴露无遗。

第四步,如果日志没输出,可能是健康检查失败导致容器被杀。手动进入容器看一眼进程情况:

kubectl exec -it pod-name -- /bin/sh

进去后检查进程是否存在、监听端口是否正常。有时候应用起来比较慢,而readinessProbe的超时时间设得太短,也会导致Pod被反复重启。这种问题在describe里也能看到线索。

第五步,结合事件中的调度信息确认资源是否充足。如果Events里有FailedScheduling且提示Insufficient cpu或Insufficient memory,那就是节点资源不足,要么扩容节点,要么调低资源请求。

这套流程走完,90%以上的Pod异常都能找到原因。剩下的那10%,大多是集群层面的问题,这时就需要去查节点状态、网络组件、存储卷之类的内容,那是另一个话题了。

4.2 常见报错速查:问题现象与原因对照

我把工作中高频见过的kubectl报错做了一个整理,方便对照参考。

报错信息常见原因排查方向
Unable to connect to the server: dial tcp ... i/o timeout集群APIServer网络不通或安全组拦截检查本机到APIServer地址的连通性,telnet或nc测试对应端口
server returned 401 Unauthorizedkubeconfig里的token过期或证书不匹配重新生成ServiceAccount的token,或更新config里的client-certificate
server returned 403 Forbidden当前用户的RBAC权限不足检查RoleBinding或ClusterRoleBinding,确认用户是否有相应命名空间的权限
No resources found命名空间写错,或该命名空间下确实没有这个资源确认-n参数,或改用-A全命名空间查看
error: You must be logged in to the server未设置KUBECONFIG或config文件为空检查KUBECONFIG环境变量和~/.kube/config是否存在
The connection to the server ... was refusedAPIServer端口拒绝连接或服务未监听在集群节点上检查kube-apiserver进程与443端口状态
pod has unbound PersistentVolumeClaimsPVC未绑定PV检查StorageClass和PV状态,确认动态供给是否正常
Error from server: etcdserver: request timed out集群存储层出现性能问题或etcd不稳定检查etcd集群健康状态、磁盘IO和节点负载

上面这些都是实际工作中比较高频遇到的。我的经验是,报错本身不可怕,关键是先判断是client端问题还是server端问题。凡是出现Unable to connect、Unauthorized,先查client侧的网络和配置;凡是出现FailedScheduling、ImagePullBackOff,再去查集群内部。

4.3 在GitLab CI/CD中设置kubectl配置文件的实操

最后来回答一下很多人关心的“gitlab怎么设置kubectl配置文件”这个问题。实际上GitLab本身不会直接操作Kubernetes集群,它需要在CI/CD的job里让kubectl具备访问集群的能力。最稳妥的办法是在GitLab项目的CI/CD Variables里保存KUBECONFIG的内容,然后在job里写入指定路径。

第一步,把kubeconfig文件内容作为变量存到GitLab里。打开项目的Settings -> CI/CD -> Variables,添加一个变量,类型选择File,变量名建议叫KUBECONFIG,然后粘贴kubeconfig文件的内容。选File类型的好处是,GitLab会在runner上把它生成一个临时文件,并把文件路径传给CI,这样比直接把内容写到代码仓库安全得多。

第二步,在.gitlab-ci.yml里用这个变量。示例配置:

deploy-job: stage: deploy before_script: - mkdir -p $HOME/.kube - cp $KUBECONFIG $HOME/.kube/config script: - kubectl get namespaces - kubectl apply -f manifests/

第三步,是安全性设置。如果你的runner是共享的,我建议不要在Runner上长期保留任何kubeconfig文件。更好的做法是基于短期token来动态生成kubeconfig。具体思路是在job里先使用一个只拥有临时权限的token创建config,然后执行完任务后立即删除。这部分逻辑可以写成一个脚本作为公共模板复用:

cat <<EOF > $HOME/.kube/config apiVersion: v1 kind: Config clusters: - cluster: server: ${K8S_APISERVER} certificate-authority-data: ${K8S_CA_DATA} name: gitlab-cluster users: - name: gitlab-user user: token: ${K8S_TOKEN} contexts: - context: cluster: gitlab-cluster user: gitlab-user namespace: ${CI_ENVIRONMENT_NAME} name: gitlab-context current-context: gitlab-context EOF

这里把APIServer地址、CA证书、token全部通过CI/CD变量注入,安全性和灵活性都得到了保障。而且注意,我将namespace设置为当前环境名,这样同一份模板可以同时用在test、preview、production多个环境上,互不干扰。

这种做法的好处是显而易见的:不用把集群管理员凭证长时间暴露在CI系统里,每个环境仅用最小权限的token,出现安全问题时回收凭证也很方便。从我接触过的项目来看,很多团队早期图省事直接拿admin kubeconfig塞进GitLab,后面权限一旦泄露,整个集群都暴露在风险之中,所以这个成本值得花。

最后再分享一个实际工作里的细节:CI里执行kubectl apply之后,建议加一步检查部署状态,而不是apply完就算结束。可以在job里循环等待Rollout完成:

kubectl rollout status deployment/my-service -n my-namespace --timeout=2m

这条命令会阻塞到Deployment滚动更新完成或超时。如果超时,CI job会直接失败,这比发布完才发现服务没起来要舒服得多。很多真实事故的核心根源,就是发布脚本只做了apply,没有做rollout status校验,结果上线报错半天后才被监控发现。这个习惯我现在一直保留着,也建议读到这里的各位写进团队模板里。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 2:06:40

高并发面试必问10题:缓存、锁、限流与秒杀系统实战解析

说实话&#xff0c;这两年我面试别人和被别人面试&#xff0c;问得最多的就是高并发。不是大家故意卷&#xff0c;而是高并发这个问题一头连着业务场景&#xff0c;另一头连着基础原理&#xff0c;从一条问题链能串出缓存、队列、锁、线程池、数据库、JVM一堆东西&#xff0c;特…

作者头像 李华
网站建设 2026/9/13 2:02:07

Spring Boot企业管理系统:权限管控、多数据源与集群部署实战

简介&#xff1a;面向毕业设计、课程设计与 Java 后端学习的 Spring Boot 企业信息化管理系统资料包&#xff0c;涵盖部门管理、角色用户、菜单与按钮授权、数据权限、系统参数、日志管理、通知公告等核心模块&#xff0c;并支持在线定时任务配置、集群部署与多数据源。技术栈包…

作者头像 李华