Kubernetes v1.37 代号 Garhwal,包含 67 项增强:16 项进入 Stable、23 项进入 Beta、27 项进入 Alpha,另有 1 项弃用或移除。相比单纯增加 API,这一版本更值得关注的是几条清晰的工程主线:控制面在大规模集群中更能承受启动和恢复压力,HPA 可以按外部需求缩容到零,工作负载感知调度开始服务 AI/HPC 场景,存储与设备管理也进一步走向标准化。
控制面恢复不再把压力直接传给 etcd
v1.37 完成了弹性 watch cache 初始化相关工作。WatchCacheInitializationPostStartHook 进入 Stable 并锁定开启;在缓存预热期间,kube-apiserver 会限制昂贵请求,将无法立即承载的请求以 HTTP 429 拒绝,而不是让 List、Watch 请求堆积并拖垮 etcd 或 API Priority and Fairness 容量。
这项变化降低了大型集群在 API Server 重启、故障恢复时出现控制面雪崩的风险,但它也把一项责任明确交给 API 客户端:自定义控制器和 Operator 必须正确处理 429 Too Many Requests,读取 Retry-After,并采用指数退避。
可以这样实践一个适合普通 HTTP 客户端的重试策略。运行前将 KUBE_API_URL、TOKEN 和资源路径替换为实际值:
import os
import random
import time
import requests
api_url = os.environ["KUBE_API_URL"].rstrip("/")
token = os.environ["TOKEN"]
resource_path = "/apis/example.com/v1/widgets"
headers = {"Authorization": f"Bearer {token}"}
for attempt in range(8):
response = requests.get(
f"{api_url}{resource_path}",
headers=headers,
timeout=10,
verify=True,
)
if response.status_code != 429:
response.raise_for_status()
print(response.json())
break
retry_after = response.headers.get("Retry-After")
if retry_after and retry_after.isdigit():
delay = float(retry_after)
else:
delay = min(30.0, 0.5 * (2**attempt))
delay += random.uniform(0, delay * 0.2)
print(f"rate limited; retrying in {delay:.2f}s")
time.sleep(delay)
else:
raise RuntimeError("Kubernetes API remained rate limited")
安装依赖并执行:
python -m pip install requests
export KUBE_API_URL='https://your-api-server:6443'
export TOKEN='replace-with-a-short-lived-token'
python retry_kubernetes_api.py
生产控制器还应限制并发、设置整体重试期限,并记录限流次数。不要无限重试非幂等写请求,也不要用固定的短间隔持续冲击 API Server。
与此相关的两项 Beta 能力也在降低大对象列表的成本。EtcdRangeStream 默认开启,但要求 etcd 3.7 或更新版本;面对旧版 etcd 时,API Server 会自动回退到原有 Range RPC。ConcurrentWatchObjectDecode 则改为默认开启,通过有界工作池并发解码 watch 事件,同时保持交付顺序。需要关注的代价是:CRD 转换 webhook 在缓存初始化期间可能同时收到最多约 10 个转换调用,升级前应检查 webhook 的并发上限、超时和副本数。
HPA 缩容到零:省下空闲副本,但要选对指标
HPA scale-to-zero 在 v1.37 进入 Beta,并默认启用。配置 spec.minReplicas: 0 后,HPA 可以让队列消费者、批处理 Worker 或 GPU 推理任务在空闲时完全退出,在需求恢复后重新拉起。
这项能力只适用于对象指标或外部指标。CPU、内存利用率依赖正在运行的 Pod;副本数已经为零时,这些指标无法承担唤醒信号。一个典型设计是让指标适配器把消息队列积压量暴露为 External Metric。
下面是可改造的 HPA 清单。它假设集群已经安装指标适配器,并提供名为 jobs_ready 的外部指标:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: queue-worker
namespace: workloads
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: queue-worker
minReplicas: 0
maxReplicas: 20
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 2
periodSeconds: 60
metrics:
- type: External
external:
metric:
name: jobs_ready
target:
type: AverageValue
averageValue: "5"
部署并检查状态:
kubectl create namespace workloads --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f hpa.yaml
kubectl -n workloads describe hpa queue-worker
kubectl -n workloads get hpa queue-worker -o jsonpath='{range .status.conditions[*]}{.type}{"="}{.status}{" reason="}{.reason}{"\n"}{end}'
HPA 将自己缩到零时,会写入 ScaledToZero=True 条件;恢复副本后,该条件变为 False,原因为 NotScaledToZero。运维系统可以利用这一状态区分“由 HPA 主动缩零”和“人工把 Deployment 副本改成零”。
采用前还要计算冷启动成本。镜像拉取、GPU 初始化、JIT 编译和外部指标采集延迟都会增加首个任务的等待时间。对延迟敏感的在线服务,保留一个预热副本通常比彻底缩零更稳妥。
AI/HPC 调度从单个 Pod 转向完整工作负载
传统调度器逐个处理 Pod。分布式训练如果需要 16 个 Worker,集群却只能容纳 12 个,就可能出现部分 Pod 占着资源、其余 Pod 长期 Pending 的局面。v1.37 将 gang scheduling 推进到 Beta,通过 Workload API 和 PodGroup 表达整组资源需求,只有资源足以让工作负载取得进展时才进行调度。
同一方向上的 Beta 更新还包括工作负载感知抢占和 DRA ResourceClaim 工作负载支持。调度器能够以 PodGroup 为单位评估抢占,避免驱逐了一批低优先级 Pod,却仍无法为训练任务腾出足够资源。共享 ResourceClaim 则更适合一组 Pod 共同使用特殊设备的场景。
这一版本同时继续扩展 Dynamic Resource Allocation:
- DRA 驱动可以直接满足传统扩展资源请求,例如
vendor.example/gpu: 1,无需同时运行独立 Device Plugin。 - 设备 taint 和 toleration 进入 Stable,可阻止故障、维护中或不适配的物理设备参与分配。
resource.kubernetes.io/numaNode成为标准 NUMA 属性,方便不同驱动用统一字段比较拓扑位置。ResourceClaim.status.devices可携带标准化网络接口状态,让其他组件获得设备 IP 等分配结果。
Alpha 阶段还出现了分层的 CompositePodGroup、设备派生属性和设备兼容组。这些能力针对多级训练拓扑、GPU 与网卡协同选择,以及 MIG、vGPU 等互斥配置,但暂时不适合直接成为生产平台的强依赖。
存储、身份与节点资源管理的变化
Storage Version Migrator 进入 Stable,并以内置控制器的形式默认启用。API 或 CRD 的首选存储版本发生变化后,管理员可以创建声明式 StorageVersionMigration 对象,逐步重写 etcd 中的旧资源。它也适用于静态加密配置轮换后的数据重写,替代容易出错的 kubectl get | kubectl replace 脚本。
PVC 闲置跟踪进入 Beta 且默认启用。PVC 不再被非终止 Pod 引用后,控制器会设置 Unused=True,lastTransitionTime 可作为“从何时开始闲置”的近似时间。Kubernetes 不会自动删除这些 PVC,因此更适合先用于报告和成本审计:
kubectl get pvc -A -o json | jq -r '
.items[]
| . as $p
| [.status.conditions[]? | select(.type == "Unused" and .status == "True")] as $unused
| select($unused | length > 0)
| [$p.metadata.namespace, $p.metadata.name, $unused[0].lastTransitionTime]
| @tsv
'
Pod Certificates 与 ClusterTrustBundles 进入 Stable,为 Pod 分发私钥、X.509 证书和信任锚提供一等 API。不过 Kubernetes 不会替你提供完整的签发体系;平台团队仍需选择 signer 名称、部署签发控制器,并设计权限、轮换与吊销机制。
节点侧,Memory QoS 在 cgroups v2 上进入 Beta并默认启用,利用 memory.min、memory.low 和 memory.high 提供保护与节流。默认设置尽量避免升级后突然节流现有工作负载,但开启更积极的内存保护策略前,仍应在真实节点压力下验证延迟、OOM 和回收行为。
升级前必须处理的兼容性项
v1.37 的升级检查不能只看 Feature Gate。以下变化可能直接影响现有节点和工作负载:
- kube-proxy 的 IPVS 模式开始输出弃用警告,预计到 v1.40 默认禁用、v1.43 移除。应开始评估 nftables 后端。
- kube-dns 已长期被 CoreDNS 取代,预计 v1.40 后不再构建新包。
- 静态 Pod 不能再引用 Secret 或 ConfigMap。此前允许这种配置是缺陷行为,相关逃生 Feature Gate 已被移除。
- cgroup v1 正在退出。
failCgroupV1已默认设为true;设为false只能作为迁移到 cgroup v2 前的临时措施。 - SELinux 卷挂载优化进入 Stable。CSI 驱动声明
spec.seLinuxMount: true后,卷会通过挂载上下文设置标签;同一节点上以不同 SELinux 标签共享同一卷的 Pod 可能启动失败。需要旧行为的 Pod 可设置spec.seLinuxChangePolicy: Recursive。 kubectl run --filename和kubectl run -f正在弃用,不应继续用于新脚本。
可以先执行一组只读检查,建立集群清单:
# 查看 kube-proxy 模式
kubectl -n kube-system get configmap kube-proxy \
-o jsonpath='{.data.config\.conf}' | sed -n '/mode:/p'
# 查找可能引用 API 对象的静态 Pod 配置,需在每个节点执行
sudo grep -RInE 'secretRef|configMapRef|secretKeyRef|configMapKeyRef' \
/etc/kubernetes/manifests || true
# 判断节点使用的 cgroup 版本
stat -fc %T /sys/fs/cgroup
# 查看启用 SELinux 挂载能力的 CSI 驱动
kubectl get csidriver \
-o custom-columns='NAME:.metadata.name,SELINUX_MOUNT:.spec.seLinuxMount'
stat 返回 cgroup2fs 表示正在使用 cgroup v2。若仍是 cgroup v1,应先验证操作系统、容器运行时和监控组件对 v2 的支持,再安排节点池滚动迁移。
采用建议:按风险分层,而不是一次开启所有能力
生产升级可以分成三组决策:
- 先处理默认行为变化:验证 API 客户端的 429 退避、CRD 转换 webhook 并发、静态 Pod 配置、cgroup 版本和 SELinux 共享卷。
- 按业务收益启用 Beta:队列型任务试用 HPA 缩零;AI/HPC 平台评估 gang scheduling;存储团队把 PVC
Unused条件接入报表,但不要立刻自动删除数据。 - 隔离 Alpha 实验:Pod checkpoint/restore 还要求容器运行时实现新的 CRI RPC;StatefulSet Recreate、分层 PodGroup、动态调整内存卷等功能应放在独立节点池或测试集群,并保留完整回滚路径。
v1.37 的价值不在于把 67 项增强全部打开,而在于减少控制面恢复时的尖峰、让事件驱动工作负载真正按需归零,并为成组调度和异构设备建立统一模型。升级成功的标准也应据此制定:API Server 恢复期间没有请求风暴,Webhook 承受得住并发,关键工作负载的冷启动符合 SLO,节点和存储迁移都有可观测、可回退的过程。