Karpenter 面试题
30 道题- 分类
- Kubernetes
- 子分类
- scheduler
- 题目数
- 30 道
1 Karpenter 的核心架构和目标是什么?
答案:
Karpenter 是开源的 Kubernetes 节点生命周期管理工具,由 AWS 维护,专注于提升集群效率与成本。核心工作流程为四步循环:
- Watch:监听被 Kubernetes Scheduler 标记为 Unschedulable 的 Pod
- Evaluate:评估 Pod 调度约束(资源请求、选择器、亲和性、容忍、拓扑分布)
- Provision:启动满足 Pod 需求的节点(EC2 实例)
- Disrupt:节点不再需要时主动回收(合并、过期、漂移、中断)
核心优势:
- 无需管理节点组(Node Group),直接通过 API 启动实例
- 原生整合 Kubernetes 调度语义(声明式 label/taint/affinity)
- 持续成本优化(Consolidation 机制自动替换为更便宜的实例)
- 支持现货(Spot)、按需(On-Demand)、预留容量(Capacity Reservation)
2 Karpenter 的 CRD 体系包含哪些资源?各自的作用是什么?
答案:
Karpenter 定义三类核心 CRD:
| CRD | API 版本 | 作用 |
|---|---|---|
| NodePool | karpenter.sh/v1 | 定义节点池的调度约束、实例类型限制、中断策略、资源上限 |
| EC2NodeClass | karpenter.k8s.aws/v1 | AWS 特定配置:子网、安全组、AMI 选择、IAM 角色、块设备映射 |
| NodeClaim | karpenter.sh/v1 | 代表一次节点创建请求,不可变,Karpenter 内部管理,跟踪节点生命周期 |
关系:
- NodePool 通过
spec.template.spec.nodeClassRef引用 EC2NodeClass - Karpenter 为每个待调度 Pod 创建 NodeClaim,NodeClaim 成功后再创建 Kubernetes Node
- 一个 NodePool 可引用一个 EC2NodeClass,多个 NodePool 可共享同一个 EC2NodeClass
3 NodePool 的核心配置字段有哪些?
答案:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
taints:
- key: gpu
value: "true"
effect: NoSchedule
startupTaints:
- key: node.cilium.io/agent-not-ready
effect: NoExecute
expireAfter: 720h
terminationGracePeriod: 1h
limits:
cpu: 1000
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
budgets:
- nodes: 10%
weight: 10
replicas: 0 # 静态容量模式(静态节点池)
| 字段 | 说明 |
|---|---|
requirements | 调度约束(实例类型、架构、AZ、容量类型等) |
nodeClassRef | 引用云提供商 NodeClass |
taints | 节点污点,Pod 需匹配容忍 |
startupTaints | 临时污点,初始化完成后自动移除 |
expireAfter | 节点最长寿命,过期后强制驱逐(默认 720h) |
terminationGracePeriod | 强制终止前的最大等待时间 |
limits | NodePool CPU/内存/GPU 上限 |
disruption | 中断策略(合并、预算) |
weight | 多 NodePool 优先级权重 |
replicas | 静态节点池(固定节点数量) |
4 EC2NodeClass 的核心配置字段有哪些?
答案:
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: KarpenterNodeRole
amiFamily: AL2023
amiSelectorTerms:
- alias: al2023@latest
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 100Gi
volumeType: gp3
encrypted: true
tags:
Environment: production
metadataOptions:
httpTokens: required
httpPutResponseHopLimit: 1
detailedMonitoring: true
instanceStorePolicy: RAID0
userData: |
# custom bootstrap script
kubelet:
maxPods: 110
systemReserved:
cpu: 500m
memory: 512Mi
| 字段 | 说明 |
|---|---|
role / instanceProfile | IAM 角色(role 自动管理,instanceProfile 手动管理) |
amiFamily | AMI 类型:AL2、AL2023、Bottlerocket、Windows2019+/Custom |
amiSelectorTerms | AMI 选择(alias/id/tags/name/ssmParameter) |
subnetSelectorTerms | 子网选择(tags / id) |
securityGroupSelectorTerms | 安全组选择(tags / name / id) |
blockDeviceMappings | EBS 卷配置 |
tags | 传播到 EC2/EBS/Launch Template 的标签 |
metadataOptions | IMDS 配置 |
detailedMonitoring | 是否启用 EC2 详细监控(1 分钟 CloudWatch) |
instanceStorePolicy | 实例存储策略(RAID0) |
kubelet | kubelet 参数覆盖 |
userData | 自定义启动脚本,与 AMI 家族默认值合并 |
5 Karpenter 的约束分层模型(Layered Constraints)是如何工作的?
答案:
Karpenter 使用三层约束叠加的调度模型:
第1层(云提供商) → 所有可用实例类型、架构、可用区、购买类型
第2层(NodePool) → 集群管理员设置的 requirements、limits
第3层(Pod Spec) → nodeSelector、nodeAffinity、podAffinity、topologySpreadConstraints、资源请求
- Pod 约束必须在 NodePool 约束范围内,否则不会调度
- NodePool 约束收紧 Pod 的可选范围,但不能扩宽
- 所有约束层叠加后,Karpenter 在交集内选择最优实例类型
- 标签通过
Exists运算符在 NodePool 中声明后,Pod 才能使用
6 Karpenter 如何处理 Pod 与 NodePool 的匹配?
答案:
Karpenter 的匹配流程:
- Pod 被 Kubernetes Scheduler 标记为
Unschedulable=True - Karpenter 遍历所有 NodePool,检查 Pod 约束(资源请求、nodeSelector、亲和性、容忍)是否符合 NodePool 的 requirements
- Pod 必须容忍 NodePool 的 taints
- 匹配到多个 NodePool 时,按
spec.weight优先级选择(高权重优先) - 选择最高权重 NodePool 后,计算合适的实例类型和数量
- 创建 NodeClaim,由 EC2NodeClass 负责启动实例
注意事项:
- NodePool 应尽量互斥,避免模糊匹配
- 由于 Pod 批处理和装箱策略,高权重 NodePool 不保证总是优先选中
status.conditions.Ready为 False 的 NodePool 不会被纳入调度
7 Karpenter 支持的实例类型筛选标签有哪些?
答案:
Karpenter 通过 well-known 标签和 AWS 特定标签筛选实例类型:
| 标签 | 说明 | 示例值 |
|---|---|---|
kubernetes.io/arch | CPU 架构 | amd64, arm64 |
kubernetes.io/os | 操作系统 | linux, windows |
node.kubernetes.io/instance-type | 具体实例类型 | m5.large, p3.8xlarge |
karpenter.k8s.aws/instance-family | 实例家族 | m5, c5, r5 |
karpenter.k8s.aws/instance-category | 实例类别 | c(计算), m(通用), r(内存) |
karpenter.k8s.aws/instance-generation | 实例代数 | Gt 2(大于第 2 代) |
karpenter.k8s.aws/instance-cpu | CPU 核数 | Lte 8 |
karpenter.k8s.aws/instance-memory | 内存大小 | Gte 16384(>= 16GiB) |
karpenter.k8s.aws/instance-gpu-count | GPU 数量 | Gte 1 |
karpenter.k8s.aws/instance-gpu-name | GPU 型号 | In [t4, a10g] |
karpenter.k8s.aws/instance-accelerator-manufacturer | 加速器厂商 | nvidia, amd, aws |
topology.kubernetes.io/zone | 可用区 | us-west-2a |
karpenter.sh/capacity-type | 容量类型 | spot, on-demand, reserved |
Karpenter 扩展了标准 Kubernetes 运算符,额外支持 Gt(>)、Gte(>=)、Lt(<)、Lte(<=) 用于数值比较。
8 Karpenter 如何选择实例类型?
答案:
实例类型选择完全基于 Pod 的 resource.requests(而非 limits),遵循以下流程:
- 收集所有待调度 Pod 的资源需求总和(CPU、内存、GPU、Neuron 等)
- 结合 NodePool 的约束(instance-category、instance-generation、架构等)
- 从可用实例类型中筛选出满足需求的类型列表
- 按价格从低到高排序,选择最优实例
- 支持跨实例家族的灵活选择,不限定单一实例类型
装箱策略:
- 支持 GPU 装箱(同一节点可放置多个 GPU Pod)
- Neuron 资源要求 Pod 的 request 为 2 的幂次(1、2、4、8),否则可能导致 Pod 永久 Pending
nodeSelectorTerms按定义顺序处理,取第一个成功的 term
9 Karpenter 的 Consoldation 机制是如何工作的?
答案:
Consolidation 是 Karpenter 主动降低成本的核心机制,通过三种方式回收节点:
三种合并模式(按优先级顺序执行):
1. Empty Node Consolidation → 并行删除完全空节点
2. Multi Node Consolidation → 合并两个以上节点,启动一个更便宜的替代节点
3. Single Node Consolidation → 删除单个节点,可替换为更低价实例
触发策略:
consolidationPolicy | 行为 |
|---|---|
WhenEmptyOrUnderutilized(默认) | 所有节点只要 consolidateAfter 到期即可考虑合并 |
WhenEmpty | 仅无工作负载 Pod 的空节点才合并 |
注意事项:
- 合并执行前先运行调度模拟,确保工作负载能重新调度到其他节点
- 合并失败时取消节点汚染,回滚操作
- 多节点合并使用启发式算法,单节点合并逐个检查
- 优先选择干扰最小的节点(Pod 少、即将过期、优先级低)
- 使用 preferred Anti-Affinity 和 Topology Spread 会降低合并效果
10 Karpenter 的 Drift(漂移)机制是什么?
答案:
Drift 检测 NodeClaim 与其所属 NodePool 或 EC2NodeClass 配置之间的不一致,自动驱散漂移节点。
触发的字段变更:
| 资源 | 触发 Drift 的字段 |
|---|---|
| NodePool | spec.template.spec.requirements |
| EC2NodeClass | spec.subnetSelectorTerms、spec.securityGroupSelectorTerms、spec.amiSelectorTerms |
不触发 Drift 的字段:
spec.weight、spec.limits、spec.disruption.*
漂移检测机制:
- Karpenter 在 NodeClaim 上添加
karpenter.sh/nodepool-hash和karpenter.k8s.aws/ec2nodeclass-hash注解 - 配置变更时重新计算 Hash,不一致则标记
Drifted状态条件 - EC2NodeClass 的动态字段(如 AMI 选择器解析出新 AMI)即使 CRD 未变化也可能触发漂移
11 Karpenter 的 Expiration(过期)机制是什么?
答案:
Expiration 强制节点在达到最大生命周期后自动驱逐,由 NodePool 的 spec.template.spec.expireAfter 控制(默认 720h / 30 天)。
关键行为:
- 过期是强制性的:跳过 Disruption Budget 检查,不等待预创建替代节点
- 修改
expireAfter会触发已有 NodeClaim 的 Drift,新节点使用新值 - 过期定义的是上限而非保证寿命,其他中断机制(合并、漂移)可提前回收
安全配置:
- 存在
karpenter.sh/do-not-disrupt注解或 PDB 配置不当的 Pod 可能阻塞过期节点排空 - 建议搭配
terminationGracePeriod使用,防止节点永久卡在 Terminating 状态
12 Karpenter 的 Interruption(中断处理)机制是什么?
答案:
Karpenter 监听 AWS 基础设施中断事件,在事件发生前主动驱散节点,减少工作负载中断。
处理的事件类型:
- Spot Interruption Warning(2 分钟提前通知)
- Scheduled Change Health Events(计划维护事件)
- Instance Terminating / Stopping Events
- Instance Status Check Failures(系统状态检查 + 实例状态检查)
工作原理:
AWS EventBridge → SQS Queue → Karpenter Controller
→ Cordon + Drain Pods + Terminate Instance
→ 同时并行启动替代节点
基础设施依赖:
- SQS 队列(通过
--interruption-queue或settings.interruptionQueue配置) - EventBridge 规则转发 AWS 健康事件到 SQS
- EC2 DescribeInstanceStatus API(无需 SQS 即可检测状态检查失败)
注意: Karpenter 目前不支持 Spot Rebalance Recommendation 的 taint/drain/terminate,建议搭配 AWS Node Termination Handler(NTH)处理此类场景。
13 Karpenter 的 Disruption Budget 如何配置?
答案:
Disruption Budget 限制 NodePool 中可同时中断的节点比例,控制合并/漂移速度。
spec:
disruption:
budgets:
- nodes: "20%"
reasons:
- "Empty"
- "Drifted"
- nodes: "5"
- nodes: "0"
schedule: "@daily"
duration: 10m
reasons:
- "Underutilized"
规则:
- 默认 budget:
nodes: 10% - 百分比计算:
allowed = roundup(total × 百分比) - deleting - notReady - 固定值计算:
allowed = 固定值 - deleting - notReady reasons过滤:Drifted、Underutilized、Empty- 支持 cron 定时预算(UTC 时区)
- 多个 budget 同时生效时取最小值
- 不控制 Expiration(过期跳过 budget)
14 Karpenter 的 NodeClaim 生命周期是怎样的?
答案:
NodeClaim 是 Karpenter 管理节点生命周期的核心抽象,不可变,由 Karpenter 自动创建和删除。
6 步生命周期:
步骤 1: Pod Watching & Cross-Referencing
→ Karpenter 发现 Unschedulable Pod,交叉匹配 NodePool + EC2NodeClass
步骤 2: Compute NodeClaim Shape
→ 计算节点形状和大小以容纳待调度 Pod
步骤 3: Object Creation
→ 在集群中创建 NodeClaim 对象(kubectl get nodeclaims 可查看)
步骤 4: Launch(云提供商 API 调用)
→ 调用 EC2 API 启动实例,失败回退(标记类型不可用,换类型重试)
步骤 5: Registration
→ 实例注册到集群后,Karpenter 更新标签/注解/污点/终结器
→ 移除 karpenter.sh/unregistered 污点(15 分钟超时)
步骤 6: Initialization
→ 等待节点就绪、startupTaints 移除、资源注册完成
状态条件追踪:
| 条件 | 含义 |
|---|---|
| Launched | 云提供商实例已创建 |
| Registered | 实例已加入集群 |
| Initialized | 节点就绪、污点移除、资源注册 |
| Ready | 完全可用 |
| Consolidatable | 可参与合并决策 |
15 Karpenter 如何处理 PVC 和存储拓扑感知调度?
答案:
Karpenter 自动检测存储拓扑约束,确保新节点与 Pod 的存储需求在同一可用区。
自动推导流程:
- Pod → 引用 PVC → 检查 PV 的 zone 标签或 StorageClass 的
allowedTopologies - 如果 PV 已存在,其 zone 被纳入调度约束
- EBS CSI 驱动标签
topology.ebs.csi.aws.com/zone在内存中别名为topology.kubernetes.io/zone topology.kubernetes.io/region不支持
权限依赖:
- Karpenter 需要
ec2:DescribeAvailabilityZones权限来验证可用区 - 存储拓扑约束自动缩小实例类型选择范围到对应可用区
16 Karpenter 如何处理 GPU/加速器节点?
答案:
GPU 节点通过 karpenter.k8s.aws/instance-gpu-count 和 karpenter.k8s.aws/instance-gpu-name 标签筛选。
典型 GPU NodePool 配置:
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-gpu-count
operator: Gte
values: ["1"]
- key: karpenter.k8s.aws/instance-gpu-name
operator: In
values: ["t4", "a10g", "a100"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
taints:
- key: nvidia.com/gpu
value: "true"
effect: NoSchedule
nodeClassRef:
name: gpu
注意事项:
- GPU 实例通常打污点防止非 GPU Pod 调度
- NVIDIA 驱动安装依赖 AMI 选择(AL2023 + NVIDIA 加速器 AMI)
- 多个 GPU Pod 可装箱到同一节点(基于
resources.requests["nvidia.com/gpu"]) - 使用
karpenter.k8s.aws/instance-accelerator-manufacturer区分 GPU 提供商(nvidia/amd/aws)
17 Karpenter 的 Spot 容量策略是什么?
答案:
Karpenter 通过 karpenter.sh/capacity-type 标签管理容量类型,优先级为 reserved → spot → on-demand。
Spot 机制:
- 容量类型不可用时缓存 3 分钟,然后降级到下一优先级
- Spot 中断处理通过 Interruption 机制自动驱散(2 分钟提前通知)
- Spot 节点默认启用删除合并,替换合并需要
SpotToSpotConsolidation特性标志 - Spot 到 Spot 的替换使用
price-capacity-optimized策略,要求至少 15 种实例类型灵活性
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"] # 优先 spot,不可用时回退 on-demand
安全建议:
- 混合 spot + on-demand 提高可用性
- 关键工作负载使用
node.kubernetes.io/instance-type固定实例类型,避免 Spot 容量不足时频繁切换
18 Karpenter 与 Cluster Autoscaler 的核心区别是什么?
答案:
| 维度 | Karpenter | Cluster Autoscaler |
|---|---|---|
| 节点管理粒度 | 直接管理单个实例,无需节点组 | 依赖节点组(ASG/MIG),以组为单位扩缩 |
| 调度速度 | 快(直接创建实例,无中间层) | 慢(需节点组拉起实例 + 注册) |
| 实例灵活性 | 自动选择最优实例类型 | 限于节点组预设实例 |
| 成本优化 | 内置 Consolidation(自动替换更低价格实例) | 仅缩容空节点 |
| 配置方式 | 声明式 CRD(NodePool + EC2NodeClass) | 节点组标签 + Autodiscovery |
| 约束模型 | 分层约束(云提供商→NodePool→Pod) | 节点组模板静态配置 |
| 中断处理 | 内置 Spot 中断、漂移、过期支持 | 需额外组件(AWS NTH) |
| 供应商锁定 | AWS 优先,但架构可扩展 | 云厂商无关 |
| 多实例池 | NodePool weight 多池灵活路由 | 多个节点组 + 节点亲和配置 |
选择建议:
- Karpenter 适合追求成本优化、实例灵活性和自动化运维的场景
- Cluster Autoscaler 适合已深度使用节点组/ASG、需要与现有基础设施兼容的场景
19 Karpenter 如何处理 Windows 节点?
答案:
EC2NodeClass 的 amiFamily 支持 Windows2019、Windows2022、Windows2025。
Windows 特征:
- NodePool 的
requirements中设置kubernetes.io/os: In [windows] - AMI 别名仅支持
latest(不支持固定版本) - 默认根卷 50Gi gp3 加密
- UserData 合并:PowerShell 命令前置到 Karpenter 的 bootstrap 部分
- Windows 版本只能通过对应 AMI 家族选择,不支持通过 AMI 选择器混用 Linux AMI
限制:
- 需要 Windows 节点的 EKS 集群
- 需要容器运行时兼容 Windows 镜像
- 部分 Kubernetes 特性(如 hostNetwork)在 Windows 上的行为不同
20 Karpenter 的静态节点池(Static NodePool)是什么?
答案:
静态节点池通过 spec.replicas 字段维护固定数量的节点,不受工作负载需求影响。
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: static-pool
spec:
replicas: 10
template:
spec:
requirements:
- key: topology.kubernetes.io/zone
operator: In
values: ["us-west-2a"]
- key: node.kubernetes.io/instance-type
operator: In
values: ["m5.large", "m5.xlarge"]
nodeClassRef:
name: default
limits:
nodes: 15
disruption:
budgets:
- nodes: 20%
reasons:
- "Drifted"
关键约束:
- 设置
replicas后不可切换回动态模式(单向操作) - limits 中仅允许
nodes字段 - 不可同时设置
weight - 节点不参与合并决策
- 通过
kubectl scale nodepool <name> --replicas=N调整数量 - 允许 Drift 触发节点替换
21 Karpenter 如何处理自有 AMI 的定制化需求?
答案:
EC2NodeClass 的 amiSelectorTerms 支持多种 AMI 选择方式。
选择方式:
amiSelectorTerms:
# 1. 官方别名(自动管理版本)
- alias: al2023@latest # 或 al2023@v20240703 固定版本
# 2. 标签选择(最灵活)
- tags:
karpenter.sh/discovery: my-cluster
environment: custom-ami
# 3. 名称 + 所有者
- name: my-custom-ami-*
owner: "0123456789"
# 4. SSM 参数
- ssmParameter: /aws/service/eks/optimized-ami/1.31/amazon-linux-2023/x86_64/standard/recommended/image_id
# 5. ID 直接指定
- id: ami-0abcdef1234567890
AMI 家族与 UserData 合并策略:
| AMI 家族 | UserData 合并 |
|---|---|
| AL2023 | 支持 bash/NodeConfig/MIME,Karpenter 追加 NodeConfig |
| AL2 | 用户 bash/MIME 追加到 Karpenter bootstrap 部分 |
| Bottlerocket | TOML 格式,Karpenter 值优先 |
| Custom | 无默认值,用户必须自行处理全部启动逻辑 |
生产建议:
- 固定 AMI 而非使用
latest,避免意外漂移 - 使用
DeprecatedAMI 状态标记帮助识别过期 AMI - 使用
spec.blockDeviceMappings自定义根卷大小和类型
22 Karpenter 的私有集群(Private Cluster / Isolated VPC)配置要点?
答案:
私有集群没有公网访问,Karpenter 需要额外配置。
eksctl 配置: privateCluster.enabled: true
Helm 参数: --set settings.isolatedVPC=true
所需 VPC 终端节点:
| 服务 | 用途 |
|---|---|
ec2 | 实例管理 |
ecr.api / ecr.dkr | 容器镜像拉取 |
s3 | 镜像层 |
sts | IRSA(IAM Role for Service Account) |
ssm | 默认 AMI 解析 |
sqs | 中断处理 |
eks | 集群端点发现 |
IAM 实例配置文件(私有集群必须):
IAM API 没有 VPC 终端节点,spec.role 方式无法在私有集群中工作。必须手动创建实例配置文件名:
spec:
instanceProfile: "KarpenterNodeInstanceProfile-${CLUSTER_NAME}"
# 不指定 role(否则 Karpenter 会尝试调用 IAM API)
定价数据: 无 VPC 终端节点用于 Price List API,Karpenter 使用发布时内置的静态定价数据。
23 Karpenter 如何处理 Node 终结器(Finalizer)?
答案:
Karpenter 自动在每个由其创建(管理)的节点上添加 karpenter.sh/termination 终结器。
Termination 流程:
kubectl delete node <name>
→ Karpenter 终结器拦截删除请求
→ cordon 节点(禁用调度)
→ drain 节点(通过 Eviction API,遵守 PDB)
→ 等待 VolumeAttachment 删除
→ 终止 EC2 实例
→ 移除 node 对象和终结器
关键特性:
- 仅对 Karpenter 管理的节点有效(非 Karpenter 创建的节点不受影响)
- 确保节点删除前 Pod 被优雅排空
- 使用 Kuberentes Eviction API,尊重 PodDisruptionBudget
- 如果存在
karpenter.sh/do-not-disrupt注解的 Pod,排空会被阻塞
24 Karpenter 的 StartupTaints 机制是什么?用于什么场景?
答案:
StartupTaints 是节点启动时设置的临时污点,系统组件完成初始化后由外部 Agent 移除。
spec:
template:
spec:
startupTaints:
- key: node.cilium.io/agent-not-ready
effect: NoExecute
与普通 Taints 的区别:
| 维度 | Taints | StartupTaints |
|---|---|---|
| 持久性 | 永久 | 临时(初始化完成后移除) |
| Pod 调度条件 | Pod 必须容忍 | Pod 不需要容忍 |
| 移除方式 | 需手动或 system 组件 | Agent 启动后自动移除 |
| 用途 | 限制谁可以调度 | 阻止 Pod 在依赖初始化完成前调度 |
典型场景:
- Cilium 网络初始化完成前阻止业务 Pod 启动
- CSI 驱动或监控 Agent 先于工作负载启动
- 节点注册后需要执行初始化脚本
警告: StartupTaints 配置不准确会导致 Karpenter 无限循环创建新节点(因为无法触发初始化完成条件时,Karpenter 认为节点未就绪)。
25 Karpenter 支持哪几种 Capacity Reservation?
答案:
EC2NodeClass 通过 spec.capacityReservationSelectorTerms 选择 On-Demand Capacity Reservations(ODCR)。
spec:
capacityReservationSelectorTerms:
- id: cr-123456
- tags:
environment: production
- instanceMatchCriteria: open
- instanceMatchCriteria: targeted
tags:
project: my-app
ownerID: "012345678901"
选择方式:
| 方式 | 说明 |
|---|---|
| ID | 指定具体预留 ID |
| Tags | 标签匹配(AND) |
| instanceMatchCriteria | open(开放匹配)或 targeted(定向匹配) |
| ownerID | 账户 ID,可与 tags 或 criteria 组合 |
优先级: Karpenter 优先使用 Capacity Reservation,然后回退到按需和 Spot。
状态追踪:
status.capacityReservations 输出每个预留的可用区、ID、实例类型、匹配条件、类型(default/capacity-block)、状态(active/expiring)、是否可中断。
26 Karpenter 的 Drift 检测如何处理 AMI 更新场景?
答案:
AMI 更新场景是 Drift 机制中最常见的触发场景之一,行为有所不同于 CRD 字段变更。
场景举例:
- EC2NodeClass 使用
amiSelectorTerms[].alias: al2023@latest - AWS 发布新的 AL2023 AMI(含安全补丁)
- AMI 选择器重新解析指向新 AMI
- Karpenter 检测到已运行节点的 AMI 与当前解析结果不匹配
- 将这些节点标记为
Drifted状态 - 根据 Disruption Budget 逐批驱逐并替换节点
特殊逻辑:
- 即使 EC2NodeClass 的 YAML 未变化(因为
latest本身不变),但解析结果变了,仍触发 Drift - 使用固定别名(如
al2023@v20240703)避免意外漂移 - AMI 的
Deprecated状态帮助标识不可用 AMI
生产建议:
- 生产环境不使用
latest,使用固定版本别名 - 通过 CI/CD 流程控制 AMI 更新节奏
- 结合 Disruption Budget 控制漂移速率,避免大规模节点同时替换
27 Karpenter 的 metrics 体系包含哪些关键指标?
答案:
Karpenter 在 :8080/metrics 暴露 Prometheus 格式指标,覆盖 20 个类别,约 100+ 指标。
关键指标分类:
| 类别 | 关键指标 | 稳定度 |
|---|---|---|
| Provisioning | karpenter_nodeclaims_created_total、karpenter_nodes_created_total | STABLE |
| Termination | karpenter_nodeclaims_terminated_total、karpenter_nodes_terminated_total | STABLE |
| Disruption | karpenter_voluntary_disruption_decisions_total、karpenter_voluntary_disruption_eligible_nodes | STABLE |
| Scheduler | karpenter_scheduler_scheduling_duration_seconds、karpenter_scheduler_unschedulable_pods_count | STABLE |
| Interruption | karpenter_interruption_received_messages_total、karpenter_interruption_message_queue_duration_seconds | STABLE |
| Node 资源 | karpenter_nodes_total_pod_requests、karpenter_nodes_allocatable | BETA |
| CloudProvider | karpenter_cloudprovider_errors_total、karpenter_cloudprovider_duration_seconds | BETA |
| Cluster State | karpenter_cluster_state_synced | STABLE |
推荐告警规则:
karpenter_scheduler_unschedulable_pods_count > 0持续 5 分钟:可能存在配置问题karpenter_cloudprovider_errors_total快速增加:检查 AWS API 权限karpenter_nodeclaims_terminated_total异常突增:排查中断原因karpenter_cluster_state_synced == 0:Karpenter 状态不同步
内置 Grafana Dashboard: Karpenter 提供预构建 Dashboard,通过 Helm 安装。
28 Karpenter 的 Kubelet 配置支持哪些自定义参数?
答案:
EC2NodeClass 的 spec.kubelet 字段支持配置以下 kubelet 参数:
spec:
kubelet:
maxPods: 110 # 覆盖 ENI 默认 Pod 密度上限
podsPerCore: 10 # 动态 Pod 密度(与 maxPods 取小值)
systemReserved:
cpu: 500m
memory: 512Mi
ephemeral-storage: 5Gi
kubeReserved:
cpu: 200m
memory: 256Mi
evictionHard:
memory.available: 5%
nodefs.available: 10%
nodefs.inodesFree: 5%
evictionSoft:
memory.available: 10%
evictionSoftGracePeriod:
memory.available: 1m30s
evictionMaxPodGracePeriod: 60
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
cpuCFSQuota: true
clusterDNS:
- 10.100.0.10
不支持但可通过 UserData 设置的参数:
registryPullQPS、eventRecordQPS等 kubelet 参数- AL2023:通过 UserData 中的
NodeConfigspec 设置 - Bottlerocket:通过 TOML userData 设置
[settings.kubernetes]
29 Karpenter 的节点标签传播规则是什么?
答案:
Karpenter 通过多层标签机制控制节点标签。
标签来源:
| 来源 | 位置 | 说明 |
|---|---|---|
| NodePool labels | spec.template.metadata.labels | 应用到所有该 NodePool 创建的节点 |
| NodePool requirements | spec.template.spec.requirements | In/NotIn 约束转为节点标签 |
| AWS well-known labels | 自动 | 实例类型、可用区、架构等自动标签 |
| EC2NodeClass tags | spec.tags | 传播到 EC2 实例和 EBS,不一定是 K8s 标签 |
自定义标签规则:
- NodePool 必须使用
Exists运算符声明自定义标签的 key - 如果 Pod 不提供 value,Karpenter 自动生成随机值
- labels 和 requirements 合计不超过 100 项
spec:
template:
metadata:
labels:
team: platform
environment: production
spec:
requirements:
- key: custom-label-team
operator: Exists # 允许 Pod 使用此标签选择节点
安全标签(不可复写):
karpenter.sh/前缀karpenter.k8s.aws/前缀kubernetes.io/cluster/前缀
30 Karpenter 生产环境最佳实践?
答案:
NodePool 设计:
- 使用多个 NodePool 隔离负载类型(通用计算、GPU、Windows、Spot)
- NodePool 之间尽量互斥(通过 taints 和 requirements),避免模糊匹配
- GPU 等特殊硬件节点打 taint + toleration 隔离
成本优化:
- 启用
consolidationPolicy: WhenEmptyOrUnderutilized - 混合 Spot + On-Demand 降低计算成本
- 使用 instance-category 和 instance-generation 约束而非固定实例类型
- 设置
limits.cpu/limits.memory防止无限制扩容
稳定性:
- AMI 固定版本而非
latest,避免意外漂移 - 配置 Disruption Budget 控制中断速率(如高峰时段限制为 0)
- 使用
terminationGracePeriod防止 PDB 阻塞的节点永久卡住 - 创建 FlowSchema 防止 Karpenter API 请求被节流
安全:
- IMDS 配置
httpTokens: required,限制 hop limit - 对
karpenter.sh/managed-by、karpenter.sh/nodepool标签实施基于标签的 IAM 策略 - 最小权限 IAM 角色原则
- 定期轮换节点(
expireAfter: 720h)
可观测性:
- 导入预构建 Grafana Dashboard
- 监控
karpenter_scheduler_unschedulable_pods_count和karpenter_cloudprovider_errors_total - 审计 NodeClaim 的 status conditions 排查节点创建失败
- 配置 Karpenter 日志采集到集中式日志系统
容量预留:
- 关键工作负载配置 Capacity Reservation 保证容量可用
- 使用
reserved容量类型作为最高优先级