- 云原生
- 容器编排
- DevOps
【免费下载链接】eksctl
The official CLI for Amazon EKS
本文基于 eksctl 仓库中的官方发布说明 docs/release_notes/0.151.0.md 展开。v0.151.0 是一次以"节点镜像灵活性"为主题的版本:它让自管(self-managed)Windows 节点组与 EKS 托管(managed)Ubuntu 节点组都可以使用自定义 AMI,同时移除了对 EKS 1.22 的支持,并修复了多可用区子网选择、实例类型可用性分页等多个问题。读完本文,你可以掌握自定义 AMI 在两类节点组上的配置方式、配套的校验规则与限制条件,并理解各修复项在源码层面的实现位置。
版本概览
v0.151.0 的变更按官方发布说明分为以下类别(条目均对应具体 PR 编号):
| 类别 | 变更内容 |
|---|---|
| Features | 自管 Windows 节点组支持自定义 AMI(#6804);EKS 托管节点组支持自定义 Ubuntu AMI(#6850) |
| Improvements | 移除对 EKS 1.22 的支持(#6704) |
| Bug Fixes | 修复 CI 中Post Cache go-build and mod步骤的 tar 错误(#6840);修复 release 版本 link-time 变量设置(#6841);当同一 AZ 存在多个子网且未提供 VPC 配置时只选择一个子网(#6814);对DescribeInstanceTypeOfferings响应做分页处理(#6832) |
| Maintenance | 依赖升级(#6852、#6859);清理 Flux 集成代码(#6836) |
下面逐项展开,并结合仓库源码说明这些能力背后的实现与约束。
特性一:自管 Windows 节点组支持自定义 AMI
配置方式
在自管节点组(nodeGroups)中,通过ami字段指定自定义镜像 ID,并显式声明amiFamily。以 Windows 节点组为例,参考 examples/14-windows-nodes.yaml 的写法,加上自定义镜像后形如:
nodeGroups: - name: windows-windows amiFamily: WindowsServer2019CoreContainer # 必须显式指定 ami: ami-0123456789abcdef0 # 自定义 AMI ID instanceType: c5.large scalingConfig: minSize: 1 maxSize: 3ami字段定义在 pkg/apis/eksctl.io/v1alpha5/types.go 的NodeGroupBase中,自管与托管节点组共用该基础结构,注释中说明其可取值包括auto-ssm、auto、static以及具体的 AMI ID。
校验规则:为什么 Windows 是特殊的一族
v0.151.0 之前,使用自定义 AMI 时校验逻辑会强制要求overrideBootstrapCommand(覆盖引导脚本),因为 eksctl 需要为节点生成启动脚本。Windows 节点的引导机制不同(通过 Windows 启动脚本而非 Linux 风格的 bootstrap 命令),因此 #6804 将 Windows 镜像家族从该强制要求中豁免。
这一豁免可以直接在自管节点组校验函数ValidateNodeGroup中看到,见 pkg/apis/eksctl.io/v1alpha5/validation.go:
if ng.AMI != "" && ng.AMIFamily == "" { return errors.New("when using a custom AMI, amiFamily needs to be explicitly set via config file or via --node-ami-family flag") } ... if ng.AMI != "" && ng.OverrideBootstrapCommand == nil && ng.AMIFamily != NodeImageFamilyAmazonLinux2023 && !IsBottlerocketImage(ng.AMIFamily) && !IsWindowsImage(ng.AMIFamily) { return fmt.Errorf("%[1]s.overrideBootstrapCommand is required when using a custom AMI based on %s (%[1]s.ami)", path, ng.AMIFamily) }从源码结构看,自管节点组使用自定义 AMI 时的约束可归纳为:
| 约束 | 说明 |
|---|---|
amiFamily必填 | 设置ami后必须显式给出amiFamily(配置文件或--node-ami-family标志),否则直接报错 |
overrideBootstrapCommand | 除 AmazonLinux2023、Bottlerocket 家族和 Windows 家族外,使用自定义 AMI 必须提供引导命令覆盖 |
| AMI ID 格式 | 托管侧校验中通过IsAMI()检查 ID 合法性(ami-前缀格式) |
Windows 镜像家族常量本身定义在 pkg/apis/eksctl.io/v1alpha5/types.go 一带,包括WindowsServer2019CoreContainer、WindowsServer2022CoreContainer、WindowsServer2025CoreContainer及对应 Full 变体等;IsWindowsImage()判断函数位于 pkg/apis/eksctl.io/v1alpha5/validation.go。
自动解析 AMI 的背景机制
当不指定ami时,eksctl 通过 pkg/ami/auto_resolver.go 中的AutoResolver.Resolve自动解析默认 AMI:MakeImageSearchPatterns会为每个镜像家族生成按 Kubernetes 版本匹配的镜像名前缀(如Windows_Server-2019-English-Core-EKS_Optimized-%v-*),再按OwnerAccountID(Windows 镜像属于微软账户801119661308)调用 EC2 API 查找。理解了这条自动解析链路,就能明白"自定义 AMI"的价值所在:它让用户可以完全绕过按版本前缀匹配官方镜像的流程,直接使用自行构建、加固或预装软件的镜像。
特性二:EKS 托管节点组支持自定义 Ubuntu AMI
支持的家族范围
对于托管节点组(managedNodeGroups),#6850 将自定义 AMI 允许使用的镜像家族扩展到了 Ubuntu。校验逻辑位于 pkg/apis/eksctl.io/v1alpha5/validation.go:
case ng.AMI != "": if !IsAMI(ng.AMI) { return fmt.Errorf("invalid AMI %q (%s.%s)", ng.AMI, path, "ami") } if ng.AMIFamily == "" { return errors.New("when using a custom AMI, amiFamily needs to be explicitly set via config file or via --node-ami-family flag") } if !IsAmazonLinuxImage(ng.AMIFamily) && !IsBottlerocketImage(ng.AMIFamily) && !IsUbuntuImage(ng.AMIFamily) { return fmt.Errorf("cannot set amiFamily to %s when using a custom AMI for managed nodes, only %s are supported", ng.AMIFamily, ...) } if ng.OverrideBootstrapCommand == nil && ng.AMIFamily != NodeImageFamilyAmazonLinux2023 && !IsBottlerocketImage(ng.AMIFamily) { return fmt.Errorf("%[1]s.overrideBootstrapCommand is required when using a custom AMI based on %s (%[1]s.ami)", path, ng.AMIFamily) }也就是说,托管节点组上自定义 AMI 支持的家族为 Amazon Linux 2 / AL2023、Bottlerocket 与 Ubuntu(各版本变体),且:
- 除 AL2023 与 Bottlerocket 外,Ubuntu 自定义 AMI 必须提供
overrideBootstrapCommand; - 以下字段与自定义 AMI 互斥,设置即报错:
maxPodsPerNode、ssh.enableSSM、releaseVersion(对应源码中的notSupportedWithCustomAMIErr分支)。
与 launch template 的互斥约束
托管节点组若改用 launch template 内置ImageId的方式指定自定义镜像,还有一层独立校验,见 pkg/cfn/builder/managed_nodegroup.go 的validateLaunchTemplate:
- launch template 设置了
ImageId时,UserData(节点引导脚本)必须存在,否则报node bootstrapping script (UserData) must be set when using a custom AMI; managedNodeGroup.ami与managedNodeGroup.releaseVersion不能与 launch template 中的ImageId同时设置;- launch template 中不能设置 IAM instance profile(由 eksctl 管理)。
同一文件中的测试用例 pkg/cfn/builder/managed_launch_template_test.go 覆盖了 "Launch Template with custom AMI" 等场景,可作为行为验证参考。
配置示例
参考 examples/15-managed-nodes.yaml 的结构,Ubuntu 自定义 AMI 的托管节点组配置形如:
managedNodeGroups: - name: ubuntu-custom-ami amiFamily: Ubuntu2004 # Ubuntu 家族之一 ami: ami-0fedcba9876543210 # 自定义 Ubuntu EKS 优化 AMI instanceType: m5.large minSize: 2 maxSize: 4 overrideBootstrapCommand: | # 非 AL2023/Bottlerocket 时必填 ...注意:托管节点组无法像自管节点组那样直接写instanceType之外的引导细节,maxPodsPerNode、enableSSM、releaseVersion均被禁用,配置时需提前确认这些限制。
版本支持变更:移除 EKS 1.22
#6704 移除了对 Kubernetes 1.22 控制面版本的支持。在 eksctl 中,版本能力的核心是 pkg/eks/versions_manager.go 中的ClusterVersionsManager:
- 它通过 EKS API 的
DescribeClusterVersions拉取各版本状态,构建supportedVersions列表,并由resolveDeprecatedVersions以"最老受支持版本"为基准,推导出所有更早的历史版本为 deprecated(见 pkg/eks/versions_manager.go); ValidateVersion对已废弃版本给出明确的错误信息,如invalid version, 1.22 is no longer supported, supported values: ...(见 pkg/eks/versions_manager.go 中ValidateVersion的错误文案);ResolveUpgradeVersion决定eksctl upgrade/update的目标版本,仅允许逐个小版本升级或回退。
从源码结构看,"移除 1.22 支持"意味着:当 AWS 侧 API 不再把 1.22 列为受支持版本时,eksctl 会将其归入 deprecated 列表,用户若继续用--version 1.22创建集群或直接升级跨越该版本都会得到上述报错。对于仍运行 1.22 的集群,正确路径是先按"每次一个小版本"的顺序逐版本升级。
缺陷修复解析
多子网 AZ 的选择问题(#6814)
问题场景:当某个可用区(AZ)下存在多个子网,且用户没有通过vpc.subnets显式指定子网时,此前的逻辑可能在子网挑选上出现歧义;修复后,eksctl 会"在存在多个子网的 AZ 中选择一个子网",保证自动分配的子网集合可用且无冲突。
该修复所处的区域逻辑在 pkg/az/az.go 中:GetAvailabilityZones先经DescribeAvailabilityZones发现可用 AZ,再经FilterBasedOnAvailability过滤掉不支持所选实例类型的 AZ(见 pkg/az/az.go)。相关子网分配行为可在 pkg/cfn/builder/nodegroup_subnets_test.go 的表驱动测试(如 "EFA enabled with multiple subnets selects only one subnet" 条目)中验证。
实例类型可用性查询分页(#6832)
问题场景:查询 EC2 实例类型在某区域各 AZ 的可用性时,若一次调用返回结果超过 API 单页上限,会丢失数据,进而导致 AZ 过滤判断不完整。修复后,pkg/az/az.go 的GetInstanceTypeOfferings改用分页器遍历完整结果集:
p := ec2.NewDescribeInstanceTypeOfferingsPaginator(ec2API, &ec2.DescribeInstanceTypeOfferingsInput{ Filters: []ec2types.Filter{ {Name: aws.String("instance-type"), Values: instances}, {Name: aws.String("location"), Values: zones}, }, LocationType: ec2types.LocationTypeAvailabilityZone, MaxResults: aws.Int32(100), }) for p.HasMorePages() { output, err := p.NextPage(ctx) ... instanceTypeOfferings = append(instanceTypeOfferings, output.InstanceTypeOfferings...) }分页完成后,结果被整理为zoneToInstanceMap[az][instanceType]结构,供上文提到的 AZ 过滤使用。对于配置了大量实例类型或跨多 AZ 的集群,这个修复能避免"某 AZ 明明支持某实例类型却被误判为不支持"的问题。
工程类修复(#6840、#6841)
- CI tar 错误:修复了构建缓存步骤
Post Cache go-build and mod中 tar 命令的错误,属于持续集成管线维护,不影响运行时代码; - link-time 变量:修复了 release 版本 link-time 变量设置。这与版本信息的注入链路相关——pkg/version/version.go 中的
Info结构持有Version、PreReleaseID及BuildMetadata(GitCommit、BuildDate),由go generate与构建期注入填充;GetVersion()会按是否 release candidate 决定是否附带+gitCommit.buildDate形式的构建元数据(见 pkg/version/version.go)。修复确保了发布构建中该元数据被正确写入。
维护项说明
- 依赖升级(#6852、#6859):常规的 Go 模块依赖更新,可结合仓库根目录 go.mod 查看当前锁定的依赖版本;
- Flux 集成清理(#6836):对 GitOps/Flux 相关代码做清理。Flux 的运行时逻辑集中在 pkg/flux/flux.go 与 pkg/actions/flux/ 目录,清理属于代码结构优化,不改变
--flux相关开关的对外行为。
使用建议与升级注意
- 升级到 v0.151.0 前:确认没有工作流依赖
--version 1.22或 1.22 集群的直接升级路径;1.22 集群需逐版本升级。 - 使用自定义 AMI 时(无论自管还是托管):
- 必须显式设置
amiFamily; - 托管 Ubuntu 自定义 AMI 需提供
overrideBootstrapCommand,且不能同时设置maxPodsPerNode、enableSSM、releaseVersion; - 自管节点组中,AL2023、Bottlerocket 与 Windows 家族可豁免
overrideBootstrapCommand要求,其他 Linux 家族(如 AL2、Ubuntu 自管)仍需提供; - 托管节点组若走 launch template 的
ImageId路线,则模板内必须包含UserData,且与ami/releaseVersion字段互斥。
- 必须显式设置
- 多 AZ 集群:若你在同一 AZ 规划了多个子网且未显式指定
vpc.subnets,升级到该版本可获得更确定的子网选择行为;涉及大量实例类型的配置也会受益于DescribeInstanceTypeOfferings的分页修复。
以上所有源码路径与行为描述均基于当前仓库代码,如需进一步深入,建议从 pkg/apis/eksctl.io/v1alpha5/validation.go 的ValidateNodeGroup与validateManagedNodeGroup(托管侧自定义 AMI 校验)两个入口读起。
- 云原生
- 容器编排
- DevOps
【免费下载链接】eksctl
The official CLI for Amazon EKS
相关推荐
eksctl 0.101.0 版本解读:NVIDIA 节点组自动容忍、托管 Bottlerocket GPU 节点与并行 Drain 能力
eksctl 0.101.0 版本解读:NVIDIA 节点组自动容忍、托管 Bottlerocket GPU 节点与并行 Drain 能力 导读 本文围绕 ek
云原生容器编排DevOps解读 eksctl 0.110.0 版本发布:Karpenter v0.15.0 支持、Windows/Ubuntu GPU 节点组与中国区 IPv6 修复
解读 eksctl 0.110.0 版本发布:Karpenter v0.15.0 支持、Windows/Ubuntu GPU 节点组与中国区 IPv6 修复 本
云原生容器编排DevOpseksctl v0.175.0 修复解读:Bottlerocket 托管节点组升级改为显式携带 Version 字段
eksctl v0.175.0 修复解读:Bottlerocket 托管节点组升级改为显式携带 Version 字段 本文围绕 eksctl 发布说明 docs
云原生容器编排DevOps
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考