Kubernetes v1.37 Garhwal:扩缩容、控制面韧性与 AI 调度进入新阶段

2026-08-26 24 预计阅读时间: 1 分钟
来源: kubernetes.io AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:14 分钟

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_URLTOKEN 和资源路径替换为实际值:

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=TruelastTransitionTime 可作为“从何时开始闲置”的近似时间。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.minmemory.lowmemory.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 --filenamekubectl 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 的支持,再安排节点池滚动迁移。

采用建议:按风险分层,而不是一次开启所有能力

生产升级可以分成三组决策:

  1. 先处理默认行为变化:验证 API 客户端的 429 退避、CRD 转换 webhook 并发、静态 Pod 配置、cgroup 版本和 SELinux 共享卷。
  2. 按业务收益启用 Beta:队列型任务试用 HPA 缩零;AI/HPC 平台评估 gang scheduling;存储团队把 PVC Unused 条件接入报表,但不要立刻自动删除数据。
  3. 隔离 Alpha 实验:Pod checkpoint/restore 还要求容器运行时实现新的 CRI RPC;StatefulSet Recreate、分层 PodGroup、动态调整内存卷等功能应放在独立节点池或测试集群,并保留完整回滚路径。

v1.37 的价值不在于把 67 项增强全部打开,而在于减少控制面恢复时的尖峰、让事件驱动工作负载真正按需归零,并为成组调度和异构设备建立统一模型。升级成功的标准也应据此制定:API Server 恢复期间没有请求风暴,Webhook 承受得住并发,关键工作负载的冷启动符合 SLO,节点和存储迁移都有可观测、可回退的过程。


相关推荐