1. 为什么非得用 curl 直连 Kubernetes API Server你可能刚在某次故障排查中被运维同事一句“直接 curl 一下 API server 看看状态”卡住——不是不会敲curl而是敲完之后满屏 JSON 却不知道该盯哪一行、哪个字段代表 Pod 真正就绪了也可能在写 CI/CD 脚本时发现 Helm 或 kubectl 插件太重、启动慢想绕过客户端工具用最轻量的方式获取某个 ConfigMap 的内容结果curl -k https://10.96.0.1:443/api/v1/namespaces/default/configmaps/my-cfg返回 401 Unauthorized连错误原因都摸不着边。这恰恰是绝大多数人对 Kubernetes API 访问的典型认知断层kubectl 不是魔法盒它只是个封装良好的 HTTP 客户端而 API Server 本身就是一个标准的 RESTful HTTPS 服务。你每天用kubectl get pods查看资源背后就是一次带认证头、带路径参数、带 Accept 头的 GET 请求你执行kubectl scale deploy/nginx --replicas3本质就是向/apis/apps/v1/namespaces/default/deployments/nginx/scale发送一个 PATCH 请求。curl 不是“替代方案”而是底层真相的显影液。我曾在某跨平台自动化平台项目中需要让一个无 kubectl 环境的嵌入式容器仅含 busybox curl动态读取集群内 Service 的 ClusterIP用于服务发现。当时团队第一反应是“加个 kubectl 镜像”但镜像体积从 5MB 涨到 50MB启动延迟增加 800msCI 流水线超时频发。最后我们用 12 行 shell curl 实现了等效逻辑从/api/v1/services拉取全量列表用 jq 过滤目标 service提取.spec.clusterIP字段。整个过程耗时稳定在 110ms 内且完全规避了二进制依赖。这件事让我彻底确认掌握 curl 直连 API Server不是炫技而是为高确定性、低耦合、可审计的生产级集成打下地基。关键词里虽未明写但这个标题天然锚定三个核心能力域身份认证Authentication、资源定位Resource Discovery、请求构造Request Crafting。它不面向“如何部署 Kubernetes”而是面向“当 kubectl 失效、当 SDK 不可用、当你要穿透抽象层看清数据流本质”时你手里那把最原始也最可靠的螺丝刀。适合两类人一是正在啃《Kubernetes in Action》第 7 章的中级开发者二是负责编写集群巡检脚本、多租户配额校验、自定义准入控制钩子的 SRE 工程师。接下来我们就从零开始把这把螺丝刀磨出刃。2. 认证三道门ServiceAccount、Bearer Token 与 TLS 双向验证API Server 的认证机制不是单选题而是组合锁。你看到的401 Unauthorized往往不是“密码错了”而是“你连第一道门都没摸到”。Kubernetes 默认启用三类认证插件ServiceAccount、ClientCertificate、TokenReview对接外部 OAuth2。而 curl 场景下最常用、最可控、最易调试的是前两者。我们逐层拆解。2.1 ServiceAccount 是什么它和你的本地 kubeconfig 有什么关系ServiceAccountSA是 Kubernetes 原生的账号对象专为 Pod 内进程设计。当你创建一个 Pod若未显式指定serviceAccountNameKubernetes 会自动挂载默认 SA 的 token 到/var/run/secrets/kubernetes.io/serviceaccount/token。这个 token 是一个 JWTJSON Web Token由 API Server 签发包含audience受众通常是api、exp过期时间、iss签发者以及最重要的kubernetes.io/serviceaccount/namespace和kubernetes.io/serviceaccount/serviceaccount.name声明。关键点来了你本地~/.kube/config里的user配置本质上就是对某个 ServiceAccount token 的封装。比如你执行kubectl config view --minify --output jsonpath{.users[0].user.token}输出的就是当前上下文所用 SA 的 token 字符串。它和 Pod 内挂载的 token 是同一类东西只是来源不同手动复制 vs 自动挂载。提示不要试图用cat /var/run/secrets/kubernetes.io/serviceaccount/token获取 token 后在本地 curl —— 因为该 token 的audience声明通常只允许访问本集群 API且其证书链绑定在集群内部 CA 下。你在本地机器上用它 curl会因 TLS 证书校验失败而报错SSL certificate problem: unable to get local issuer certificate。正确做法是要么在 Pod 内执行 curl此时环境可信要么用client-certificate方式。2.2 Bearer Token 认证三步走通流程Bearer Token 是最直白的认证方式把 token 放在 HTTP Header 的Authorization: Bearer token里。但它有严格前提token 必须有效、未过期、且对应 SA 具备目标资源的 RBAC 权限。我们用一个真实调试链路来演示假设你要在某测试命名空间test-ns中用 SAdebug-sa查询所有 Pod。首先创建 SA 和 RBAC# sa-rbac.yaml apiVersion: v1 kind: ServiceAccount metadata: name: debug-sa namespace: test-ns --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-reader namespace: test-ns rules: - apiGroups: [] resources: [pods] verbs: [get, list, watch] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: test-ns subjects: - kind: ServiceAccount name: debug-sa namespace: test-ns roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io应用后获取 token# 在集群内任意 Pod 中执行或用 kubectl exec 进入 TOKEN$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) # 或在本地从 secret 中提取需有权限 kubectl get secret -n test-ns $(kubectl get sa debug-sa -n test-ns -o jsonpath{.secrets[0].name}) -o jsonpath{.data.token} | base64 -d现在构造 curl 请求# 第一步获取 API Server 地址通常为 https://kubernetes.default.svc.cluster.local:443 # 第二步设置 CA 证书Pod 内自动挂载 CA_CERT/var/run/secrets/kubernetes.io/serviceaccount/ca.crt # 第三步发起请求 curl -v \ --cacert $CA_CERT \ -H Authorization: Bearer $TOKEN \ https://kubernetes.default.svc.cluster.local:443/api/v1/namespaces/test-ns/pods注意-v参数它会打印完整请求头和响应头。你会看到请求头中明确包含Authorization: Bearer eyJhb...响应头中Content-Type: application/json状态码200 OK响应体是标准的PodList对象含items[]数组如果返回403 Forbidden说明 RBAC 权限不足若返回401 Unauthorized检查 token 是否为空、是否过期openssl x509 -in $CA_CERT -text -noout | grep Not After可查 CA 有效期、或 CA 证书路径是否正确。2.3 Client-Certificate 认证当你要从集群外安全接入Bearer Token 适合集群内调用但如果你要从办公网、CI 服务器等集群外部环境访问 API Server就必须用client-certificate。它的安全性更高私钥不外泄且证书可绑定具体 IP 或域名。Kubernetes 安装时会生成一组默认证书存于/etc/kubernetes/pki/目录Master 节点。其中ca.crt根证书用于校验 API Server 的服务端证书admin.crt和admin.key管理员客户端证书和私钥通常用于kubectl将这三个文件拷贝到你的本地机器确保admin.key权限为600# 本地执行 curl -v \ --cacert ca.crt \ --cert admin.crt \ --key admin.key \ https://your-api-server-ip:6443/api/v1/nodes这里的关键是--cert和--key成对出现告诉 curl“用这个证书证明我是谁用这个私钥签名本次请求”。API Server 会用ca.crt校验admin.crt的签名并检查证书中CNCommon Name字段是否在system:masters组中admin.crt默认如此。注意--insecure或-k参数绝对禁止在生产环境使用它跳过 TLS 证书校验等于把通信裸奔在公网。我曾见过某团队为图省事在 Jenkins 脚本里加-k结果 API Server 的 token 被中间人截获整个集群 RBAC 体系形同虚设。真正的安全不是“关掉警告”而是“配齐证书”。3. 资源定位从 /api/v1 到 /apis/apps/v1路径即契约Kubernetes API 不是扁平的 URL 列表而是一套严格分层的资源寻址体系。理解它的路径规则比死记硬背kubectl get命令更有价值。因为当你用 curl 时没有kubectl explain帮你补全字段也没有--dry-run -o yaml生成模板——你必须自己拼出正确的 endpoint。3.1 API Group 与 Version为什么有的路径是 /api/v1有的是 /apis/apps/v1Kubernetes 将资源按功能域划分为API Groups每个 Group 下有多个Versions如v1,v1beta1。这是为了实现 API 的演进与兼容/api/v1核心资源组Core Group包含Pod,Service,ConfigMap,Secret等基础对象。它没有 group 名version 直接跟在/api/后。/apis/group/version命名资源组Named Group如/apis/apps/v1Deployment, StatefulSet、/apis/networking.k8s.io/v1Ingress, NetworkPolicy、/apis/custom.metrics.k8s.io/v1beta1自定义指标。判断一个资源属于哪个 Group最可靠的方法是查官方文档或kubectl api-resources输出。例如$ kubectl api-resources | grep deployment deployments deploy apps/v1 true DeploymentAPPENDIX列显示true表示该资源支持命名空间GROUP列明确写出apps/v1。因此获取 default 命名空间下的 nginx Deploymentendpoint 是https://server/apis/apps/v1/namespaces/default/deployments/nginx而非/api/v1/...。若你误用/api/v1/namespaces/default/deploymentsAPI Server 会返回404 Not Found并附带提示{ kind: Status, apiVersion: v1, metadata: {}, status: Failure, message: the server could not find the requested resource, reason: NotFound, details: {}, code: 404 }3.2 Namespace、Name 与 Subresource路径中的语义分段Kubernetes 资源 URL 遵循/{api-path}/{namespace}/{name}/{subresource}的层级结构。每一级都有明确语义路径段示例说明{api-path}/api/v1,/apis/apps/v1API Group 和 Version决定资源类型{namespace}namespaces/default命名空间限定核心资源Pod/Service必须带集群级资源Node/ClusterRole则无此段直接/api/v1/nodes{name}pods/my-app-5f8c4b9d7d资源实例名称区分大小写{subresource}/scale,/status,/log子资源提供特定操作接口以 Pod 日志为例kubectl logs my-pod -n default底层是向/api/v1/namespaces/default/pods/my-pod/log发 GET 请求。你可以用 curl 直接获取curl -v \ --cacert ca.crt \ --cert admin.crt \ --key admin.key \ https://server:6443/api/v1/namespaces/default/pods/my-pod/log?containerapptailLines100注意 URL 中的查询参数?containerapptailLines100—— 这是日志子资源特有的过滤条件。API Server 会根据这些参数从容器运行时如 containerd拉取对应日志流。再看扩缩容场景kubectl scale deploy/nginx --replicas5实际请求的是/apis/apps/v1/namespaces/default/deployments/nginx/scale方法为PATCHBody 为{ apiVersion: autoscaling/v1, kind: Scale, metadata: { name: nginx, namespace: default }, spec: { replicas: 5 } }实操心得当你不确定某个kubectl命令对应的 API 路径时开启 kubectl 的详细日志模式kubectl --v8 get pods -n default 21 | grep GET\|POST\|PATCH。它会打印出完整的 HTTP 方法、URL 和请求头是逆向工程的最佳帮手。4. 请求构造实战GET、POST、PATCH、DELETE 的 payload 与 header 精要curl 不是万能胶不同 HTTP 方法对请求体body、头部header、查询参数query string的要求天差地别。用错一个 header可能让 200 变成 415少传一个字段可能让 POST 创建直接失败。我们聚焦四个最常用方法给出可直接复用的 curl 模板。4.1 GET查询资源重点在 Accept 与 query stringGET 请求不带 body但 header 和 query string 至关重要Accept: application/json明确告知 API Server “我要 JSON 格式”。虽然多数 endpoint 默认返回 JSON但显式声明是良好实践。?limit500continueabc...分页参数。Kubernetes API 默认每页最多返回 500 条超过则返回metadata.continue字段作为下一页的continue值。?fieldSelectormetadata.namemy-pod字段选择器比 labelSelector 更高效适用于精确匹配元数据字段。示例查询 default 命名空间下所有 status.phase 为 Running 的 Podcurl -v \ --cacert ca.crt \ --cert admin.crt \ --key admin.key \ -H Accept: application/json \ https://server:6443/api/v1/namespaces/default/pods?fieldSelectorstatus.phase%3DRunning注意status.phase%3DRunning中的%3D是的 URL 编码。用curl时建议用--data-urlencode或先编码避免空格、斜杠等特殊字符导致 400 Bad Request。4.2 POST创建资源Content-Type 与 body 结构是命门POST 用于创建新资源如kubectl create -f pod.yaml。它有两大雷区第一Content-Type 必须是application/json。若你漏掉-H Content-Type: application/jsonAPI Server 会返回415 Unsupported Media Type。这不是 bug而是设计Kubernetes 明确拒绝非 JSON 的创建请求防止格式混乱。第二body 必须是合法的 Kubernetes 对象 JSON且apiVersion、kind、metadata.name字段不可缺。例如创建一个最简 Pod{ apiVersion: v1, kind: Pod, metadata: { name: curl-test-pod, namespace: default }, spec: { containers: [ { name: busybox, image: busybox:1.35, command: [sleep, 3600] } ] } }保存为pod.json然后 curlcurl -v \ --cacert ca.crt \ --cert admin.crt \ --key admin.key \ -H Content-Type: application/json \ -X POST \ --data-binary pod.json \ https://server:6443/api/v1/namespaces/default/pods关键点-X POST显式声明方法--data-binary pod.json确保 JSON 文件原样传输-d会处理换行和引号易出错符号表示从文件读取若返回422 Unprocessable Entity检查 JSON 语法用jq . pod.json格式化验证、字段拼写spec不是Speccontainers不是container、或权限RBAC 是否允许pods/create。4.3 PATCH更新资源三种策略与 Content-Type 的微妙差异PATCH 是最易出错的操作。Kubernetes 支持三种 patch 类型通过Content-Type头区分Content-TypePatch 类型特点适用场景application/strategic-merge-patchjsonStrategic Merge Patch默认支持合并数组如 containers、覆盖字段修改 Pod 的 env 或 imageapplication/merge-patchjsonJSON Merge Patch简单键值覆盖数组被整体替换替换整个 labels mapapplication/json-patchjsonJSON PatchRFC 6902 标准支持 add/remove/move/copy精确修改嵌套字段如spec.containers[0].ports[0].containerPort示例用 Strategic Merge Patch 给 Podmy-pod添加一个环境变量// patch-env.json { spec: { containers: [ { name: app, env: [ { name: DEBUG, value: true } ] } ] } }curl 命令curl -v \ --cacert ca.crt \ --cert admin.crt \ --key admin.key \ -H Content-Type: application/strategic-merge-patchjson \ -X PATCH \ --data-binary patch-env.json \ https://server:6443/api/v1/namespaces/default/pods/my-pod踩坑实录某次我用application/merge-patchjson发送相同 JSON结果 Pod 的containers数组被整个替换成单个元素原有其他容器消失因为 Merge Patch 对数组的处理是“全量替换”而 Strategic Merge 是“按 name 字段合并”。务必根据需求选对类型。4.4 DELETE删除资源优雅与强制的两面性DELETE 不仅能删资源还能控制删除行为?gracePeriodSeconds30宽限期默认 30 秒Pod 会收到 SIGTERM 并尝试优雅退出。?propagationPolicyBackground级联删除策略。Background默认异步删除依赖对象如 ReplicaSetForeground同步等待所有依赖删除完成Orphan只删父对象留下子对象孤儿化。示例立即强制删除一个 Deployment不等待滚动更新curl -v \ --cacert ca.crt \ --cert admin.crt \ --key admin.key \ -X DELETE \ https://server:6443/apis/apps/v1/namespaces/default/deployments/nginx?gracePeriodSeconds0propagationPolicyBackgroundgracePeriodSeconds0是关键它让 API Server 跳过等待直接发送 SIGKILL。配合propagationPolicyBackground可快速清理避免阻塞。5. 错误诊断与调试从 401 到 503HTTP 状态码就是你的诊断手册curl 的强大在于透明——它把 HTTP 的每一个字节都摊开给你看。但这也意味着你必须读懂这些字节背后的含义。Kubernetes API 的 HTTP 状态码不是随意分配的而是严格映射到操作语义。掌握它们你就拥有了无需 kubectl 的故障定位能力。5.1 状态码速查表精准定位问题根源状态码含义常见原因排查指令401 Unauthorized认证失败Token 无效/过期证书不被信任--cacert路径错误echo $TOKEN | base64 -d | jq .exp查过期时间openssl verify -CAfile ca.crt admin.crt验证证书链403 Forbidden授权失败RBAC 权限不足缺少get/listServiceAccount 未绑定 RoleBindingkubectl auth can-i list pods -n default --as system:serviceaccount:default:debug-sa模拟检查404 Not Found资源不存在URL 路径错误Group/Version/Name 拼错Namespace 不存在kubectl api-resources | grep resource确认 Groupkubectl get ns ns确认命名空间409 Conflict版本冲突更新资源时resourceVersion过期被他人修改在 GET 响应中提取metadata.resourceVersionPATCH 时带上metadata: {resourceVersion: xxx}422 Unprocessable Entity数据校验失败JSON 格式错误必填字段缺失apiVersion,kind字段值非法如 port 65535jq . file.json格式化验证对照 OpenAPI spec 检查字段500 Internal Server Error服务端崩溃etcd 故障API Server 进程异常自定义 webhook 崩溃kubectl get componentstatuseskubectl logs -n kube-system api-server-pod503 Service Unavailable服务不可用API Server 未就绪启动中负载过高被限流网络策略阻断kubectl get endpoints kubernetes确认 endpointscurl -I https://server:6443/healthz检查健康探针5.2 用 curl -v 解析完整请求-响应链-vverbose是调试的灵魂。它会打印请求行GET /api/v1/namespaces/default/pods HTTP/2请求头Authorization: Bearer ...,Accept: application/json响应行HTTP/2 403响应头Content-Type: application/json,X-Kubernetes-Pf-Flowschema-Uid: ...响应体完整的 JSON 错误对象示例当遇到 403 时-v输出末尾会是 HTTP/2 403 Content-Type: application/json X-Content-Type-Options: nosniff Date: Mon, 15 Apr 2024 08:22:34 GMT Content-Length: 298 {kind:Status,apiVersion:v1,metadata:{},status:Failure,message:pods is forbidden: User \system:serviceaccount:default:debug-sa\ cannot list resource \pods\ in API group \\ in the namespace \default\,reason:Forbidden,details:{kind:pods},code:403}关键信息在message字段User system:serviceaccount:default:debug-sa cannot list resource pods—— 这直接告诉你是debug-sa这个账号缺少pods资源的list权限。无需猜测直击要害。503 故障深度复现当 API Server 拒绝服务503 是最让人焦虑的状态码因为它意味着“服务存在但不工作”。常见于集群升级后、etcd 磁盘满、或网络策略误配置。我们模拟一个典型场景假设你执行curl -v --cacert ca.crt --cert admin.crt --key admin.key https://server:6443/healthz得到 HTTP/2 503 Content-Type: text/plain; charsetutf-8 X-Content-Type-Options: nosniff Date: Mon, 15 Apr 2024 08:25:11 GMT Content-Length: 17 etcd is unhealthy这说明 API Server 自身健康检查失败根源在 etcd。此时任何资源请求都会返回 503。解决方案不是重启 API Server而是登录 Master 节点检查 etcd 容器状态docker ps \| grep etcd查看 etcd 日志docker logs etcd-container-id \| tail -20检查磁盘空间df -h /var/lib/etcd若磁盘满清理旧快照find /var/lib/etcd/member/snap/ -name *.snap -mtime 7 -delete经验之谈我在某次压测中发现 API Server 在 QPS 超过 1200 时频繁返回 503。排查发现是--max-requests-inflight500参数过小默认值导致请求队列溢出。调大至2000后问题消失。这提醒我们503 不一定是故障也可能是容量规划不足。6. 安全加固与生产实践从能用到稳用的七条军规curl 直连 API Server 是一把双刃剑。用得好是运维的瑞士军刀用得糙就是集群的阿喀琉斯之踵。以下是我在多个生产环境落地后总结的七条铁律每一条都来自真实的血泪教训。6.1 军规一永远禁用-k永远校验 CA-k--insecure是安全红线。它关闭 TLS 证书校验使中间人攻击MITM成为可能。攻击者只需劫持 DNS 或 ARP就能伪造一个假的 API Server诱骗你的 curl 请求窃取 token 或执行恶意操作。正确做法是始终使用--cacert指向集群的根 CA 证书。该证书由kubeadm init或托管服务如 EKS/AKS生成是信任链的起点。即使你用client-certificate--cacert仍是必需的——它用来验证 API Server 的服务端证书是否由该 CA 签发。验证命令# 检查 CA 证书是否有效 openssl x509 -in ca.crt -text -noout | grep -E (Issuer|Validity|Subject) # 检查 API Server 证书是否被此 CA 签发 echo | openssl s_client -connect server:6443 2/dev/null | openssl x509 -text -noout | grep Issuer: # 应与 ca.crt 的 Subject 一致6.2 军规二Token 生命周期管理宁短勿长ServiceAccount Token 默认有效期为 1 年--service-account-extend-token-expirationfalse时。但在生产脚本中硬编码一个长期有效的 token 是灾难。最佳实践为每个自动化任务创建专用 SA并设置短生命周期 Token。Kubernetes 1.22 支持TokenRequestAPI可动态申请短期 token默认 1 小时# 在 Pod 内执行申请 10 分钟有效期的 token curl -v \ --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \ -H Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token) \ -X POST \ -H Content-Type: application/json \ --data-binary { apiVersion: authentication.k8s.io/v1, kind: TokenRequest, spec: { expirationSeconds: 600, audiences: [api] } } \ https://kubernetes.default.svc.cluster.local:443/api/v1/namespaces/default/serviceaccounts/debug-sa/token响应体中status.token即为短期 token。脚本用完即弃极大降低泄露风险。6.3 军规三RBAC 权限最小化精确到动词与资源“给 SA 一个 cluster-admin 角色最省事”——这是最危险的懒惰。一个被攻破的监控 Pod若持有 cluster-admin 权限攻击者可在 30 秒内 dump 出所有 Secret。RBAC 必须遵循最小权限原则Principle of Least Privilege。例如一个日志收集器只需要rules: - apiGroups: [] resources: [pods/log] verbs: [get, list] - apiGroups: [] resources: [pods] verbs: [get] # 仅用于获取 Pod 元数据关联日志禁用*通配符。用kubectl auth reconcile命令定期审计权限漂移。6.4 军规四请求频率限制避免压垮 API Servercurl 脚本若无节制轮询如while true; do curl ...; sleep 1; done极易触发 API Server 的--max-requests-inflight限流导致自身和其他组件如 kube-scheduler请求排队引发雪崩。解决方案使用--rate-limit参数curl 7.66curl --rate-limit 1000 --rate 10 ...限制每秒 10 次请求在脚本中加入指数退避Exponential Backoff首次失败后 sleep 1s再次失败 sleep 2s依此类推最大 30s对 Watch 请求?watchtrue利用resourceVersion断点续传避免全量轮询6.5 军规五敏感信息零明文Token 与 Key 不入 Git所有 curl 脚本中TOKEN、admin.key、ca.crt等敏感信息严禁硬编码在代码或配置文件中。必须通过环境变量、Kubernetes Secret 挂载、或 HashiCorp Vault 动态注入。示例Pod 中安全挂载env: - name: TOKEN valueFrom: secretKeyRef: name: debug-token-secret key: token volumeMounts: - name: ca-cert mountPath: /etc/kubernetes/pki/ca.crt subPath: ca.crt readOnly: true volumes: - name: ca-cert secret: secretName: k8s-ca-secret6.6 军规六错误处理必须完备拒绝静默失败一个健壮的 curl 脚本必须处理所有可能的失败分支。不能只写curl ... || echo fail而要检查 HTTP 状态码if [ $HTTP_CODE -ge 400 ] [ $HTTP_CODE -lt 600 ]; then handle_error; fi解析 JSON 响应体中的status字段if echo $RESPONSE | jq -e .status Failure /dev/null; then ...设置超时curl --max-time 30 ...防止请求无限挂起记录完整日志curl -v ... 21 | tee /var/log/curl-debug.log6.7 军规七版本兼容性兜底API Group 与 Version 锁定Kubernetes API 会演进。今天能用的/apis/apps/v1beta2明天可能被废弃。生产脚本必须显式锁定 API Version。正确写法# ✅ 好明确指定 v1稳定可靠 curl ... https://server/apis/apps/v1/namespaces/default/deployments # ❌ 坏用 v1beta2随时可能失效 curl ... https://server/apis/apps/v1beta2/namespaces/default/deployments定期运行kubectl convert命令将旧版 YAML 转为新版并更新脚本中的 API 路径。订阅 Kubernetes Release Notes提前规划迁移。我在某金融客户的核心交易系统巡检脚本中将上述七条全部落地用短期