bigywater.tech
Kubernetes · 11

API 版本与弃用:同一个对象用不同版本读出来的样子

同一个 Kubernetes 对象可以用多个 API 版本读写,它们是同一份数据的不同视图。这篇拿 HPA 的 v1 和 v2 对照着读,把 etcd 里存的版本解码出来,再看弃用警告是怎么从服务端传到你终端的,以及 kubectl 到底请求了哪个版本。

1 → 3
v1 视图里比 v2 多出来的 autoscaling.alpha 注解个数(metrics、behavior、conditions)
autoscaling/v2
v1 和 v2 两种方式创建的 HPA 在 etcd 里的 apiVersion
Warning: 299
读弃用 API 时响应头里的警告,kubectl 把它打印在输出末尾

一个对象,两种样子

实测 · 本机执行输出
  v2:apiVersion=autoscaling/v2;spec 的键 ['behavior', 'maxReplicas', 'metrics', 'minReplicas', 'scaleTargetRef'];metrics 有 2 项:cpu=50%, memory=70%
  v1:apiVersion=autoscaling/v1;spec 的键 ['maxReplicas', 'minReplicas', 'scaleTargetRef', 'targetCPUUtilizationPercentage'];targetCPUUtilizationPercentage=50
  v1 多出来的注解:autoscaling.alpha.kubernetes.io/behavior, autoscaling.alpha.kubernetes.io/conditions, autoscaling.alpha.kubernetes.io/metrics
    autoscaling.alpha.kubernetes.io/metrics = [{"type":"Resource","resource":{"name":"memory","targetAverageUtilization":70}}]
  v2 的注解里有 autoscaling.alpha 开头的吗:False

同一个 HPA,v2 读出来 spec 有 metrics(CPU 50%、内存 70% 两项)和 behavior。v1 的 schema 里只有 targetCPUUtilizationPercentage,装不下的内存指标、behavior 和 conditions 被写进 autoscaling.alpha.kubernetes.io/metrics、/behavior、/conditions 三个注解里,所以旧客户端读到的是个“降级”的视图。用 v1 去改这个对象时要特别小心别把这些注解当普通注解弄丢了。

etcd 里存哪个版本

实测 · 本机执行输出
  用 autoscaling/v1 创建 h2:horizontalpodautoscaler.autoscaling/h2 created
  h1:etcd 里的值 1334 字节,开头 b'k8s\x00'(k8s 的 protobuf 封装),解出的 apiVersion=autoscaling/v2 kind=HorizontalPodAutoscaler
  h2:etcd 里的值 1006 字节,开头 b'k8s\x00'(k8s 的 protobuf 封装),解出的 apiVersion=autoscaling/v2 kind=HorizontalPodAutoscaler

不管用 v2 还是 v1 创建,etcd 里的值都以 k8s\x00 开头(内置资源用 protobuf 封装),解出的类型头都是 autoscaling/v2 HorizontalPodAutoscaler。写入时先转成存储版本,读取时再转成请求的版本。注意内置资源在 etcd 里不是 JSON(CRD 才是)。

弃用警告怎么传到终端

实测 · 本机执行输出
  kubectl get endpoints -n default 的输出:
    NAME         ENDPOINTS         AGE
    kubernetes   172.18.0.3:6443   22m
    Warning: v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice
  /metrics 里的弃用记录:
    # TYPE apiserver_requested_deprecated_apis gauge
    apiserver_requested_deprecated_apis{group="",removed_release="",resource="endpoints",subresource="",version="v1"} 1
    apiserver_requested_deprecated_apis{group="k5.example.com",removed_release="",resource="things",subresource="",version="v1beta1"} 1
  响应头里的警告:299 - "v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice"
  kubectl get things.v1beta1.k5.example.com:Warning: k5.example.com/v1beta1 Thing 已弃用,请改用 k5.example.com/v1 Thing | No resources found in k5 namespace.
  kubectl get things.v1.k5.example.com:No resources found in k5 namespace.

读 v1 的 Endpoints,服务端在响应头里加了 Warning: 299 - "v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice",kubectl 把它打印在输出末尾。/metrics 里 apiserver_requested_deprecated_apis 是 gauge:请求过就是 1,不是请求次数,标签里有 removed_release(会被移除的版本,这里为空)。自己的 CRD 也可以给版本标 deprecated: true 并写自定义的 deprecationWarning,用旧版本读就会收到,metrics 里也会多出对应的一行。

kubectl 请求哪个版本

实测 · 本机执行输出
  kubectl api-versions 里 autoscaling 的版本:autoscaling/v1 autoscaling/v2
  /apis/autoscaling:preferredVersion=autoscaling/v2;versions 的顺序 ['autoscaling/v2', 'autoscaling/v1']
  kubectl get hpa 实际请求的路径:/apis/autoscaling/v2/namespaces/k5/horizontalpodautoscalers?limit=500
  kubectl get horizontalpodautoscalers.v1.autoscaling 实际请求的路径:/apis/autoscaling/v1/namespaces/k5/horizontalpodautoscalers?limit=500
  kubectl get horizontalpodautoscalers.v2.autoscaling 实际请求的路径:/apis/autoscaling/v2/namespaces/k5/horizontalpodautoscalers?limit=500
  kubectl get hpa.v1.autoscaling(短名带版本) 实际请求的路径:/apis/autoscaling/v2/namespaces/k5/horizontalpodautoscalers?limit=500

/apis/autoscaling 返回 preferredVersion: autoscaling/v2,versions 里 v2 排在前面。kubectl get hpa 请求 /apis/autoscaling/v2/…;想读 v1 要写全名 horizontalpodautoscalers.v1.autoscaling。hpa.v1.autoscaling 这种“短名加版本”的写法版本会被忽略,仍然请求 v2——排查旧版本问题时要用 -v=6 确认请求路径。

分步演示

API 版本与弃用
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / kind(Docker 里的单节点或多节点真实集群,节点是 Docker Desktop 虚拟机里的容器)/ kubectl;用空的 kubeconfig 之外的独立 kubeconfig,不碰用户自己的集群;计时用 date +%s%N / kubectl 事件时间戳,数字每次运行会有小幅抖动。三节点 kind 集群 kx-main(Kubernetes v1.37.0);HPA h1 用 kubectl create 以 autoscaling/v2 创建(目标是 replicas=0 的 Deployment,不需要真的有 metrics-server),h2 以 autoscaling/v1 创建;两个版本的内容都用 kubectl get --raw 读出来;etcd 里的值用 etcdctl get -w json 取出 base64 解码,按 protobuf 头解析 apiVersion/kind;弃用警告取自 kubectl -v=8 的响应头;请求路径取自 kubectl -v=6 的日志;弃用的 CRD 版本是自己建的 things.k5.example.com;每种情形各一次
    • 没有验证:真正会被移除的 API(removed_release 不为空的)在本版本 v1.37.0 里没有可请求的;kubectl convert 与 kubent 这类迁移工具;服务端 discovery 的聚合格式(/apis 的 aggregated discovery);API 版本被移除之后存量对象的处理;v1 与 v2 之间所有字段的完整对照
    京ICP备2026067502号-1京公网安备11010502063487号