3. 基于 NodePool 的实例类型约束配置
NodePool requirements 的约束语义
NodePool 的 spec.template.spec.requirements 是一组键值约束,Karpenter 在调度待处理 Pod 时,会先按这些约束过滤出允许的实例类型集合,再在该集合内按价格与容量做选择。约束不是“指定某一种实例”,而是“划定可选范围”。
node.kubernetes.io/instance-type:直接枚举实例类型,如m5.large、c5.xlarge。karpenter.k8s.aws/instance-family:按实例族约束,如m5、c5、t3。karpenter.k8s.aws/instance-size:按规格约束,如large、xlarge、2xlarge。karpenter.k8s.aws/instance-category:按类别约束,如c(计算优化)、m(通用)、r(内存优化)。karpenter.sh/capacity-type:按容量类型约束,如on-demand、spot。kubernetes.io/arch:按 CPU 架构约束,如amd64、arm64。
每个 requirement 由 key、operator(In、NotIn、Exists、DoesNotExist)和 values 组成。多个 requirement 之间是逻辑与关系,同一 requirement 的多个 value 之间是逻辑或关系。
配置示例
以下 NodePool 将可用实例限制在 m5、c5、t3 三个族,规格仅允许 large 和 xlarge,容量类型仅 on-demand,架构仅 amd64:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: constrained-pool
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-family
operator: In
values: ["m5", "c5", "t3"]
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["large", "xlarge"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
limits:
cpu: "100"
memory: "200Gi"
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
提交不同资源请求的 Pod 并观察选择
创建三个资源请求递增的 Pod,分别观察 Karpenter 选择的实例类型:
# Pod A:小请求
kubectl run pod-a --image=nginx --requests='cpu=500m,memory=1Gi'
# Pod B:中等请求
kubectl run pod-b --image=nginx --requests='cpu=2,memory=4Gi'
# Pod C:大请求,超出允许规格
kubectl run pod-c --image=nginx --requests='cpu=4,memory=16Gi'
查看 Karpenter 为每个 Pod 创建的 NodeClaim 及其选择的实例类型:
kubectl get nodeclaims -o custom-columns=\
NAME:.metadata.name,\
TYPE:.metadata.labels.karpenter\.k8s\.aws/instance-type,\
CPU:.spec.resources.requests.cpu,\
MEMORY:.spec.resources.requests.memory
预期现象:Pod A 和 Pod B 会成功触发节点创建,NodeClaim 的
instance-type 标签落在允许集合内(如 m5.large、c5.xlarge)。Pod C 因请求超出允许规格的最大容量,Karpenter 无法在约束范围内找到匹配实例,Pod 将保持 Pending,事件中会出现类似 no instance type satisfied requirements 的提示。
约束调整与验证
若希望 Pod C 也能被调度,需要放宽 instance-size 约束,加入 2xlarge 或 4xlarge:
kubectl patch nodepool constrained-pool --type=merge -p '
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["large", "xlarge", "2xlarge", "4xlarge"]
'
调整后再次观察 Pod C 的 NodeClaim,应能看到 Karpenter 从扩展后的集合中选择了满足 4 vCPU / 16 GiB 的实例(如 m5.2xlarge 或 c5.2xlarge)。
注意:放宽约束会扩大候选实例范围,可能引入更高单价的实例。建议结合
limits 字段控制 NodePool 的总资源上限,避免意外扩容到超大规格。同时,instance-size 与 instance-family 的组合约束会显著影响候选数量,约束过窄可能导致 Pod 长期 Pending。
关键验证点
| 检查项 | 命令 | 通过条件 |
|---|---|---|
| NodePool 约束生效 | kubectl get nodepool constrained-pool -o yaml | requirements 字段与预期一致 |
| NodeClaim 实例类型 | kubectl get nodeclaims -o wide | instance-type 落在允许集合内 |
| Pod 调度状态 | kubectl get pods -o wide | Pod A/B 为 Running,Pod C 为 Pending |
| Pending 原因 | kubectl describe pod pod-c | 事件提示无匹配实例类型 |