Karpenter v1 路线图解析:karpenter-provider-aws 稳定化前的四项关键变更
【免费下载链接】karpenter-provider-awsKarpenter is a Kubernetes Node Autoscaler built for flexibility, performance, and simplicity.项目地址: https://gitcode.com/GitHub_Trending/ka/karpenter-provider-aws
Karpenter 在 2023 年 10 月发布了 beta 版本 API 与特性,而本仓库中的 designs/v1-roadmap.md 正是决定 Karpenter 走向 feature-complete 与 v1 稳定版之前的最小变更清单。这篇文章以该路线图为骨架,结合当前仓库源码(API 定义、启动模板生成、Helm Chart 配置)逐项解析 v1 前的四项核心变更——v1 API 稳定化、移除 Ubuntu AMIFamily、收紧默认拓扑分布策略、移除隐式 ENI 公共 IP 配置,帮助读者理解每项变更的动机、破坏性影响以及迁移路径,为生产环境升级 v1 做好准备。
v1 路线图:从 beta 到 feature-complete 的最小变更集
Karpenter 于 2023 年 10 月发布其 API 与特性的 beta 版本,目的是在正式宣布 v1 feature-complete 之前,通过一段 beta 期的真实使用反馈确定最终需要落地的改动集合。designs/v1-roadmap.md 记录了 Karpenter 在 v1 稳定版之前规划的全部工作,其定位是最小必要变更集——不追求功能堆砌,而是确保 v1 具备合格的运营成熟度(operational excellence)、功能完备性(feature completeness)与稳定性(stability)。
一项变更要进入该路线图,必须满足以下三类标准中的至少一类:
- Breaking(破坏性):该特性需要在 bump 到 v1 之后对 API 进行改动或移除,必须赶在 v1 之前完成;
- Stability(稳定性):该特性修复了 beta 状态下存在泄漏(leaky)或竞态条件(race condition)的行为,确保运营层面的正确性;
- Planned Deprecations(计划内弃用):该特性清理了项目此前规划好的废弃项。
该文档(以及其在kubernetes-sigs/karpenter上游仓库中的扩展)共列出四项路线图工作:
- v1 APIs
- 移除 Ubuntu AMIFamily
- 将 Karpenter Deployment 的默认 TopologySpreadConstraint 从
ScheduleAnyways改为DoNotSchedule - 移除隐式 ENI 公共 IP 配置
下面逐一展开,并在每节结合本仓库源码说明这些规划在实现侧的落点与验证方式。
v1 APIs:CustomResource 的稳定化与自动转换
变更动机与类别
v1 判定标准不仅针对控制器本身,还要求随安装一起分发的 CustomResource(CRD)在 v1 时同样稳定。这属于Breaking + Stability双类别:任何对标签(labels)、注解(annotations)、标签值(tags)的改动在 v1 之后都将是破坏性的,因此必须在 v1 之前定型。本仓库中随 Chart 分发的 CRD 清单见 charts/karpenter/crds/(含karpenter.sh_nodeclaims.yaml、karpenter.sh_nodepools.yaml、karpenter.k8s.aws_ec2nodeclasses.yaml等),以及 pkg/apis/crds/ 下的同源定义。
迁移路径:conversion webhook 自动转换
路线图明确了一个与 v1beta1 迁移截然不同的策略:v1 迁移不再要求用户滚动节点或手工转换资源。v1beta1 时代的迁移之所以痛苦,是因为 v1alpha5 Provisioner → v1beta1 NodePool 之间存在不可 round-trip 的字段变更(详见 designs/v1beta1-api.md 中关于“所有版本必须能安全地相互 round-trip”的约束讨论),最终不得不通过重命名 Kind 让新旧 CRD 并存。而 v1 则计划直接利用 Kubernetes 的 conversion webhook 机制,在代码层面把用户现有资源自动转换到新 schema,API Group 与 Kind 命名保持不变,用户无感知完成升级。
EC2NodeClass v1 API 全貌
v1 路线图的 API 细节沉淀在配套设计文档 designs/v1-api.md 中,其中给出了karpenter.k8s.aws/v1版EC2NodeClass的完整示例。相较 beta,v1 的主要变化点包括:
kubelet字段从 NodePool 层面移入 EC2NodeClass:v1beta1 时期kubeletConfiguration位于 NodePool/NodeClaim 的spec下(见 designs/v1beta1-api.md 示例),而 v1 设计将其收敛到 EC2NodeClass 的kubelet字段,统一管理节点级 kubelet 行为(podsPerCore、maxPods、systemReserved、kubeReserved、evictionHard、evictionSoft、evictionSoftGracePeriod、evictionMaxPodGracePeriod、imageGCHigh/LowThresholdPercent、cpuCFSQuota、clusterDNS等);amiSelectorTerms引入新的alias项类型:例如alias: al2023@v20240625,用于精确选择 EKS 优化 AMI(详见下文);instanceProfile与role并存:文档推荐使用 Node role 并让 Karpenter 代为创建受管实例配置文件;instanceStorePolicy: RAID0、metadataOptions(IMDS 设置)、blockDeviceMappings(含iops、throughput、kmsKeyID、snapshotID、deleteOnTermination等 EBS 参数)、detailedMonitoring等字段在 v1 示例中完整出现。
强制 AMISelectorTerms:引入 alias 终止默认自动升级
类别:Stability, Breaking
这是 v1 API 中最容易影响现有用户的行为变更之一。beta 时代,指定amiFamily但不写amiSelectorTerms时,Karpenter 会在该家族发布新版本 EKS 优化镜像后自动更新 AMI,并让存量节点通过 drift 滚动到新版本。这在预生产环境很方便,但在生产环境极具风险——用户可能意外地在未测试的情况下被滚动升级。
v1 的策略是:amiSelectorTerms变为必填,并新增alias项类型,每个 alias 由「AMI 家族 + 版本」组成。用户可以将版本设为latest继续享受自动升级,也可以固定到具体版本(如al2023@v20240625)实现生产环境钉住。这一设计在当前仓库的 CEL 校验中有直接体现:pkg/apis/v1/ec2nodeclass.go 定义了一组 XValidation 规则,约束 alias 与amiFamily的匹配关系(例如使用al2alias 时amiFamily必须为AL2或Custom),并在 L529 强制“若amiSelectorTerms不含 alias,则必须显式指定amiFamily”。
默认禁用容器访问 IMDS:收紧 Hop Limit
类别:Stability, Breaking
v1 将 EC2 实例元数据服务(IMDS)的HttpPutResponseHopLimit默认收紧到1(示例中注释为 “This is changed to disable IMDS access from containers not on the host network”)。原理是:非hostNetwork的 Pod 处于独立的网络命名空间,访问 IMDS 需要 HopLimit 至少为 2;而放开 HopLimit 意味着任何能拿到 IMDS token 的 Pod 都能获得与实例配置文件同等的权限,属于固有安全风险。v1 默认拒绝 Pod 访问 IMDS,且该新默认值只影响新建的 EC2NodeClass,不影响已部署的资源。
Printer Columns 与状态条件
类别:Stability, Breaking
v1 还为 EC2NodeClass 增强了可观测性:
kubectl get ec2nodeclasses -o wide的输出将从只有NAME AGE变为NAME READY AGE ROLE,新增READY(节点类是否已解析全部数据、可被 NodePool 使用)与ROLE(推荐的 Node role)列;- 最小化引入
Ready状态条件,进一步细化 InstanceProfile、Subnet、SecurityGroup、AMI 等每个「实例启动所需概念」是否已解析的状态条件(对应 designs/v1-api.md 中status.conditions的InstanceProfileReady、SubnetsReady、SecurityGroupsReady、AMIsReady、Ready类型)。
标签与注解变化:移除 karpenter.sh/managed-by
类别:Planned Deprecations, Breaking
v1 将移除 EC2 实例上的karpenter.sh/managed-by标签。该标签是 v0.28.0 引入的,用于 NodeClaim(当时称 Machine)迁移期间把集群名写入标签值;迁移完成后它不再有存在意义。v1 起,Karpenter 改用eks:eks-cluster-name: <cluster-name>标签来圈定实例、卷、主 ENI 等资源,用eks:eks-cluster-arn: <cluster-arn>圈定其创建的实例配置文件,供用户在 ABAC 场景下编写 Pod Identity 策略。
移除 Ubuntu AMIFamily:回归第一方支持边界
类别:Breaking
Karpenter 自 v0.6.2 起支持 Ubuntu AMIFamily,但 EKS 官方对 MNG/SMNG 并不正式支持 Ubuntu 镜像(它属于第三方厂商 AMI),这意味着 Karpenter 无法对镜像上的 Kubernetes 版本支持、内核更新等变化获得直接的可观测性(line-of-sight)。v1 计划将 Ubuntu 从 AMIFamily 支持中移除。
路线图列出的三项任务:
- 从 v1 CRD 的枚举值集合中删除 Ubuntu AMIFamily;
- 从 Karpenter 的 AMIFamily providers 中删除 Ubuntu 引导逻辑;
- 删除 karpenter.sh 文档中的 Ubuntu 专属 AMIFamily 文档。
仍希望使用 Ubuntu 的用户,可以改用Custom AMIFamily,通过amiSelectorTerms钉住最新的 Ubuntu AMI ID,并设置bootstrapMode: AL2获得与之前一致的 userData 配置。从源码侧可以印证这一迁移路径的合理性:pkg/providers/amifamily/al2.go 中的注释明确写着 “AL2 userdata also works on Ubuntu”,即 AL2 的 EKS 引导脚本对 Ubuntu 同样适用;而 pkg/apis/v1/ec2nodeclass.go 中AMIFamily()辅助函数与amiFamilyFromAlias()目前维护的家族集合为 AL2、AL2023、Bottlerocket、Windows2019/2022/2025 及 Custom,不再包含 Ubuntu——这正是路线图“删除 Ubuntu 枚举值”落地的代码形态。
默认拓扑分布策略收紧:从 ScheduleAnyways 到 DoNotSchedule
类别:Stability, Breaking
Karpenter 默认以多副本 + leader election 方式运行,以保证 HA(高可用):一旦某个 Pod 因故障下线,另一个副本能通过 leader election 快速接管。但 beta 版本部署清单中,Karpenter 使用 zonal 维度的ScheduleAnywaysTopologySpreadConstraint 将副本分散到不同可用区——这只是一个偏好,不保证 Pod 一定落在不同 zone,因此在可用区故障时多副本并不能带来预期的韧性提升。beta 时期的默认配置形如:
topologySpreadConstraints: - labelSelector: matchLabels: app.kubernetes.io/instance: karpenter app.kubernetes.io/name: karpenter maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: ScheduleAnywaysv1 将默认值改为whenUnsatisfiable: DoNotSchedule,以更强的最佳实践约束保证 Karpenter 在区域故障时能快速恢复。希望保留旧行为的用户,可以通过覆盖默认的 TopologySpreadConstraint 显式改回ScheduleAnyways。
该变更在当前仓库中已经落地:Helm Chart 的 charts/karpenter/values.yaml 中,topologySpreadConstraints的默认值已是:
topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule并且 charts/karpenter/templates/deployment.yaml 通过karpenter.patchTopologySpreadConstraintshelper 在未显式提供 labelSelector 时自动补充 Pod 选择器(app.kubernetes.io/instance: karpenter、app.kubernetes.io/name: karpenter),与路线图文档中展示的 labelSelector 语义保持一致——用户只需在 Helm values 中覆盖该块即可按需回退到ScheduleAnyways。
移除隐式 ENI 公共 IP 配置:显式化 AssociatePublicIPAddress
类别:Planned Deprecations, Breaking
Karpenter 目前支持在发起实例请求前检查目标子网,当实例仅启动到私有子网时,隐式地在启动模板中设置AssociatePublicIPAddress: false。这一行为源于用户诉求:部分用户通过 IRSA 策略或 SCP 编写 deny 策略,禁止实例创建时关联公网 IP 的网络接口。
随着显式配置能力的引入,v1 将移除这一隐式子网探测逻辑,用户直接在 EC2NodeClass 上设置associatePublicIPAddress: false即可,无需再依赖 Karpenter 对子网的内省(introspection)。路线图列出的任务为:删除启动模板创建过程中的CheckAnyPublicIPAssociations调用。
该显式字段在仓库中的实现已经完备:
- 字段定义于 pkg/apis/v1/ec2nodeclass.go(
AssociatePublicIPAddress *bool,JSON 名为associatePublicIPAddress),对应 CRD 描述见 pkg/apis/crds/karpenter.k8s.aws_ec2nodeclasses.yaml; - 启动模板生成时直接读取该字段:pkg/providers/launchtemplate/launchtemplate.go 处
AssociatePublicIPAddress: nodeClass.Spec.AssociatePublicIPAddress,并在 L324-L357 处理多预配置网络接口场景——当实例带有多个预配置 ENI 时,EC2 不允许将AssociatePublicIPAddress设为true(EFA 场景除外,注释明确说明了这一限制); - 相关行为在测试中有充分覆盖,例如 pkg/providers/launchtemplate/suite_test.go 验证 “should set 'AssociatePublicIPAddress' based on EC2NodeClass”,覆盖
true/false与 EFA 组合的四种用例。
这意味着到 v1 时,associatePublicIPAddress将成为用户控制公网 IP 关联的唯一入口,行为可预期、可审计。
总结:v1 前的升级清单
综合 designs/v1-roadmap.md 与配套的 designs/v1-api.md,Karpenter 走向 v1 的关键动作可以归纳为四类:
| 变更项 | 类别 | 对用户的影响 | 迁移/应对方式 |
|---|---|---|---|
| v1 APIs(CRD 稳定化) | Breaking, Stability | API、标签、注解、tags 在 v1 后不可再破坏性变更 | 依赖 conversion webhook 自动转换,Group/Kind 不变 |
强制amiSelectorTerms(alias) | Stability, Breaking | 不写 selector 的 AMIFamily 自动升级行为消失 | 用alias: <family>@<version>钉版本或用latest保持自动升级 |
| 默认禁用容器访问 IMDS | Stability, Breaking | 新建节点类默认 HopLimit=1,非 hostNetwork Pod 无法访问 IMDS | 如需 Pod 访问 IMDS,显式调整metadataOptions.httpPutResponseHopLimit |
| 移除 Ubuntu AMIFamily | Breaking | Ubuntu 家族不再受支持 | 改用 Custom AMIFamily +bootstrapMode: AL2 |
默认 TSC 改为DoNotSchedule | Stability, Breaking | 副本不再保证跨 zone 部署时会宽松调度 | 在 charts/karpenter/values.yaml 覆盖topologySpreadConstraints回退旧行为 |
| 移除隐式 ENI 公共 IP 配置 | Planned Deprecations, Breaking | 私有子网不再自动设置AssociatePublicIPAddress: false | 在 EC2NodeClass 显式设置associatePublicIPAddress: false |
移除karpenter.sh/managed-by标签 | Planned Deprecations, Breaking | 依赖该标签的 ABAC/Pod Identity 策略需调整 | 改用eks:eks-cluster-name/eks:eks-cluster-arn标签 |
对于生产集群,建议在升级 v1 前:先核对现有 EC2NodeClass 是否依赖“无 selector 自动升级 AMI”的行为,需要时补上alias项;确认是否存在依赖 IMDS 的非 hostNetwork Pod,按需调整 HopLimit;将任何依赖隐式私有子网探测的逻辑改为显式associatePublicIPAddress;并检查基于karpenter.sh/managed-by标签的 IAM/ABAC 策略。路线图中的每一项在 pkg/apis/v1/ec2nodeclass.go、pkg/providers/launchtemplate/launchtemplate.go 与 charts/karpenter/values.yaml 中均已能看到对应的实现锚点,本文列出的源码路径可作为逐项核对与验证的起点。
【免费下载链接】karpenter-provider-awsKarpenter is a Kubernetes Node Autoscaler built for flexibility, performance, and simplicity.项目地址: https://gitcode.com/GitHub_Trending/ka/karpenter-provider-aws
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考