尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Karpenter NodePool 完全指南:从节点模板、调度约束到中断与资源限额

Karpenter NodePool 完全指南:从节点模板、调度约束到中断与资源限额 Karpenter NodePool 完全指南从节点模板、调度约束到中断与资源限额【免费下载链接】karpenter-provider-awsKarpenter is a Kubernetes Node Autoscaler built for flexibility, performance, and simplicity.项目地址: https://gitcode.com/GitHub_Trending/ka/karpenter-provider-aws导读NodePool 是 Karpenter 集群节点自动扩缩容的核心配置对象它定义了 Karpenter 可以创建哪些节点实例类型、可用区、架构、容量类型等以及哪些 Pod 可以运行在这些节点上。本文基于 karpenter-provider-aws 仓库 v1.0 版本文档系统讲解 NodePool 的完整配置体系包括节点模板template、调度需求requirements、中断策略disruption、资源限额limits与权重weight并结合仓库内 CRD 定义与示例文件给出可复制、可运行的实战配置。什么是 NodePool安装 Karpenter 时你会同时创建或随 Helm Chart 一并部署一个默认的 NodePool。NodePool 用来对 Karpenter 可以创建的节点以及可以运行在这些节点上的 Pod 设置约束。一个 NodePool 可以做的事包括通过taints限制可以调度到 Karpenter 所建节点上的 Pod通过startupTaints告知 Karpenter 在节点启动时打上临时污点该污点预期会被其他系统移除将节点创建限制在特定可用区、实例类型、CPU 架构范围内为节点设置过期时间expiration等默认值。你可以修改现有 NodePool也可以为 Karpenter 添加更多 NodePool。关于 NodePool需要理解以下核心工作机制Karpenter 只有在至少配置了一个 NodePool 时才会工作没有任何 NodePoolKarpenter 不会做任何事。每个已配置的 NodePool 都会被 Karpenter循环遍历以寻找能满足待调度 Pod 的候选池。如果 NodePool 中存在某个taint 不被 Pod 容忍Karpenter 就不会用该 NodePool 为这个 Pod 供给节点。如果 NodePool 配置了startupTaints这些污点会被打到新建节点上但Pod 无需容忍这些污点——Karpenter 假设污点是临时的会由其他系统通常是 DaemonSet移除。推荐创建互斥的 NodePool即任意 Pod 不应同时匹配多个 NodePool若多个 NodePool 均匹配Karpenter 会使用 weight 最高的那个。另外需要特别说明设置 Kubelet 特性的对象已从 NodePool spec 迁移到 EC2NodeClass spec这样做的目的是不强制其他 Karpenter 云提供商实现这些特性。也就是说maxPods、podsPerCore、systemReserved等 kubelet 参数统一在EC2NodeClass.spec.kubelet中配置见 EC2NodeClasses 文档而 NodePool 只负责跨云提供商的通用调度语义。一个完整的 NodePool 配置示例下面是一个完整的 NodePool 定义对应仓库 v1.0 文档中的示例后续小节将逐字段拆解apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: default spec: # Template section that describes how to template out NodeClaim resources that Karpenter will provision # Karpenter will consider this template to be the minimum requirements needed to provision a Node using this NodePool # It will overlay this NodePool with Pods that need to schedule to further constrain the NodeClaims # Karpenter will provision to launch new Nodes for the cluster template: metadata: # Labels are arbitrary key-values that are applied to all nodes labels: billing-team: my-team # Annotations are arbitrary key-values that are applied to all nodes annotations: example.com/owner: my-team spec: # References the Cloud Providers NodeClass resource, see your cloud provider specific documentation nodeClassRef: group: karpenter.k8s.aws # Updated since only a single version will be served kind: EC2NodeClass name: default # Provisioned nodes will have these taints # Taints may prevent pods from scheduling if they are not tolerated by the pod. taints: - key: example.com/special-taint effect: NoSchedule # Provisioned nodes will have these taints, but pods do not need to tolerate these taints to be provisioned by this # NodePool. These taints are expected to be temporary and some other entity (e.g. a DaemonSet) is responsible for # removing the taint after it has finished initializing the node. startupTaints: - key: example.com/another-taint effect: NoSchedule # The amount of time a Node can live on the cluster before being removed # Avoiding long-running Nodes helps to reduce security vulnerabilities as well as to reduce the chance of issues that can plague Nodes with long uptimes such as file fragmentation or memory leaks from system processes # You can choose to disable expiration entirely by setting the string value Never here # Note: changing this value in the nodepool will drift the nodeclaims. expireAfter: 720h | Never # The amount of time that a node can be draining before its forcibly deleted. A node begins draining when a delete call is made against it, starting # its finalization flow. Pods with TerminationGracePeriodSeconds will be deleted preemptively before this terminationGracePeriod ends to give as much time to cleanup as possible. # If your pods terminationGracePeriodSeconds is larger than this terminationGracePeriod, Karpenter may forcibly delete the pod # before it has its full terminationGracePeriod to cleanup. # Note: changing this value in the nodepool will drift the nodeclaims. terminationGracePeriod: 48h # Requirements that constrain the parameters of provisioned nodes. # These requirements are combined with pod.spec.topologySpreadConstraints, pod.spec.affinity.nodeAffinity, pod.spec.affinity.podAffinity, and pod.spec.nodeSelector rules. # Operators { In, NotIn, Exists, DoesNotExist, Gt, and Lt } are supported. requirements: - key: karpenter.k8s.aws/instance-category operator: In values: [c, m, r] # minValues here enforces the scheduler to consider at least that number of unique instance-category to schedule the pods. # This field is ALPHA and can be dropped or replaced at any time minValues: 2 - key: karpenter.k8s.aws/instance-family operator: In values: [m5,m5d,c5,c5d,c4,r4] minValues: 5 - key: karpenter.k8s.aws/instance-cpu operator: In values: [4, 8, 16, 32] - key: karpenter.k8s.aws/instance-hypervisor operator: In values: [nitro] - key: karpenter.k8s.aws/instance-generation operator: Gt values: [2] - key: topology.kubernetes.io/zone operator: In values: [us-west-2a, us-west-2b] - key: kubernetes.io/arch operator: In values: [arm64, amd64] - key: karpenter.sh/capacity-type operator: In values: [spot, on-demand] # Disruption section which describes the ways in which Karpenter can disrupt and replace Nodes # Configuration in this section constrains how aggressive Karpenter can be with performing operations # like rolling Nodes due to them hitting their maximum lifetime (expiry) or scaling down nodes to reduce cluster cost disruption: # Describes which types of Nodes Karpenter should consider for consolidation # If using WhenEmptyOrUnderutilized, Karpenter will consider all nodes for consolidation and attempt to remove or replace Nodes when it discovers that the Node is empty or underutilized and could be changed to reduce cost # If using WhenEmpty, Karpenter will only consider nodes for consolidation that contain no workload pods consolidationPolicy: WhenEmptyOrUnderutilized | WhenEmpty # The amount of time Karpenter should wait to consolidate a node after a pod has been added or removed from the node. # You can choose to disable consolidation entirely by setting the string value Never here consolidateAfter: 1m | Never # Added to allow additional control over consolidation aggressiveness # Budgets control the speed Karpenter can scale down nodes. # Karpenter will respect the minimum of the currently active budgets, and will round up # when considering percentages. Duration and Schedule must be set together. budgets: - nodes: 10% # On Weekdays during business hours, dont do any deprovisioning. - schedule: 0 9 * * mon-fri duration: 8h nodes: 0 # Resource limits constrain the total size of the pool. # Limits prevent Karpenter from creating new instances once the limit is exceeded. limits: cpu: 1000 memory: 1000Gi # Priority given to the NodePool when the scheduler considers which NodePool # to select. Higher weights indicate higher priority when comparing NodePools. # Specifying no weight is equivalent to specifying a weight of 0. weight: 10 status: conditions: - type: Initialized status: False observedGeneration: 1 lastTransitionTime: 2024-02-02T19:54:34Z reason: NodeClaimNotLaunched message: NodeClaim hasnt succeeded launch resources: cpu: 20 memory: 8192Mi ephemeral-storage: 100Gi注意expireAfter: 720h | Never、consolidationPolicy: WhenEmptyOrUnderutilized | WhenEmpty、consolidateAfter: 1m | Never中的竖线是文档中表达多选一的记号实际 YAML 中请填入其中一个值。节点模板spec.templatespec.template描述 Karpenter 如何渲染出 NodeClaim 资源。Karpenter 把该模板视为供给节点的最低要求并在调度时将待调度 Pod 的需求叠加overlay到模板之上进一步约束 NodeClaim最终创建节点。metadata.nameNodePool 的名称。spec.template.metadata.labels应用到所有节点上的任意键值对标签。注意这些标签在创建 NodeClaim 时也会被传播为 NodeClaim 上的 requirements因此在计算需求总数限制时要一并计入见下文100 个限制。spec.template.metadata.annotations应用到所有节点上的任意键值对注解。spec.template.spec.nodeClassRef该字段指向云提供商的 NodeClass 资源。在 AWS 上即EC2NodeClass格式为nodeClassRef: group: karpenter.k8s.aws kind: EC2NodeClass name: defaultEC2NodeClass 负责所有 AWS 专属配置AMI 选择、子网/安全组发现、IAM 角色、kubelet 参数、块设备映射、UserData 等。一个 EC2NodeClass 可以被多个 NodePool 引用。详见 EC2NodeClasses 文档。仓库中的示例如 general-purpose.yaml展示了 NodePool 与 EC2NodeClass 配套部署的完整形态apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: general-purpose 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 --- apiVersion: karpenter.k8s.aws/v1 kind: EC2NodeClass metadata: name: default spec: role: KarpenterNodeRole-${CLUSTER_NAME} subnetSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} securityGroupSelectorTerms: - tags: karpenter.sh/discovery: ${CLUSTER_NAME} amiSelectorTerms: - alias: al2023latestspec.template.spec.taints添加到被供给节点上的污点。不容忍这些污点的 Pod 将无法调度到这些节点上。污点机制与 Kubernetes 原生 Taints and Tolerations 语义一致key、value、effect三个字段effect常见取值为NoSchedule、NoExecute、PreferNoSchedule。spec.template.spec.startupTaints同样会被添加到节点上用于指示某个条件必须先满足例如启动 agent、配置网络节点才能被初始化。与taints的关键区别是Pod 不需要容忍 startupTaints 就能被该 NodePool 供给。这些污点必须在 Pod 部署到节点之前被清除通常由容忍该污点的 DaemonSet 在完成初始化后移除。spec.template.spec.expireAfter节点在集群中可存活的最长时间到期后 Karpenter 会将其删除节点随即开始排空drain。设置过期时间的价值在于避免长期运行的节点积累安全漏洞降低文件碎片化、系统进程内存泄漏等长期运行带来的问题。可以设置为字符串Never来完全禁用过期机制。需要注意修改 NodePool 中的该值会导致 NodeClaim 漂移driftKarpenter 会据此替换现有节点。从 CRD 定义karpenter.sh_nodepools.yaml可以看到expireAfter的默认值是720h30 天即节点从创建起最多存活 30 天。spec.template.spec.terminationGracePeriod节点可以处于排空draining状态的最长时间超过后 Karpenter 会强制清理节点。排空从对节点发起删除调用、进入终结流程时开始。此期间Pod 的terminationGracePeriodSeconds会被提前删除以便在terminationGracePeriod结束前留出尽可能多的清理时间如果你的 Pod 的terminationGracePeriodSeconds大于该terminationGracePeriodKarpenter 可能在 Pod 用完完整的终止宽限期之前就强制删除 PodPDBPodDisruptionBudget和 do-not-disrupt 等阻塞驱逐的机制在排空期间会被尊重但一旦到达terminationGracePeriod这些 Pod 将被强制删除。同样修改该值会导致 NodeClaim 漂移。仓库示例 max-node-lifetime.yaml 给出了一个组合用法expireAfter: 168h7 天terminationGracePeriod: 24h配合disruption.consolidationPolicy: WhenEmpty与consolidateAfter: 60s。调度需求spec.template.spec.requirementsKubernetes 定义了一系列 Well-Known Labels。这些 well-known 标签可以出现在 NodePool 层级也可以出现在工作负载定义中例如 Pod spec 的nodeSelector。节点的选择同时使用NodePool 的需求与Pod 的需求两者若无交集则不会启动节点换句话说Pod 的需求必须落在 NodePool 的需求范围之内如果某个 well-known 标签未定义任何需求云提供商提供的任意取值都可以被选择。例如Pod 可以用nodeSelector指定实例类型如果请求的实例类型不在 NodePool 的实例类型列表内且 NodePool 定义了实例类型需求Karpenter 既不会创建节点也不会调度该 Pod。Well-Known Labels 分类说明实例类型Instance Types标签键说明node.kubernetes.io/instance-type实例类型如g4dn.8xlargekarpenter.k8s.aws/instance-family实例系列如g4dnkarpenter.k8s.aws/instance-category实例类别通常是代数前的字符串如gkarpenter.k8s.aws/instance-generation实例代数如4一般情况下实例类型应该是一个列表而不是单个值。建议不定义这些需求以便 Karpenter 在为 Pod 高效装箱时有最多的选择空间。AWS 实例类型支持情况可参考 实例类型参考文档大多数实例类型都受支持非 HVM 虚拟化的除外。可用区Availability Zones标签键示例值取值来源topology.kubernetes.io/zoneus-east-1caws ec2 describe-availability-zones --region region-nameKarpenter 可以被配置为只在特定可用区创建节点。注意你 AWS 账号下的us-east-1a与其他账号的us-east-1a地理位置可能不同可用区 ID 才是全局一致的参见 AWS 的 AZ IDs 文档。架构Architecture标签键取值kubernetes.io/archamd64、arm64Karpenter 同时支持amd64与arm64节点。仓库示例 multiple-arch.yaml 展示了如何用多个 NodePool 分别承载不同架构的工作负载。操作系统Operating System标签键取值kubernetes.io/oslinux、windowsKarpenter 支持linux与windows操作系统。容量类型Capacity Type标签键取值karpenter.sh/capacity-typespot、on-demandKarpenter 支持指定容量类型其语义与 EC2 购买选项 对应。容量类型的行为细节如果 NodePool 同时允许 Spot 与 on-demandKarpenter 优先使用 Spot注意此场景下价格高于最便宜 on-demand 实例的 Spot 实例会被临时移出候选集如果提供商 API如 EC2 Fleet 的 API指示某个实例类型在某可用区无 Spot 容量Karpenter 会对该结果缓存 3 分钟期间所有供给 EC2 容量的尝试都会复用该缓存如果 Spot 没有其他可用 offeringKarpenter 会尝试供给 on-demand 实例通常在毫秒级内完成karpenter.sh/capacity-type还可以作为topology key用于拓扑分布约束topology-spread。仓库示例 spot.yaml 就是一个将karpenter.sh/capacity-type固定为spot的完整 NodePool。需求数量上限100 个当前 NodePool 与 NodeClaim 上需求总数上限为 100。特别注意spec.template.metadata.labels在创建 NodeClaim 时也会被传播为 requirements因此NodePool 上的 requirements 与 labels 合起来不能超过 100 个。这一限制在调度文档scheduling.md与 CRD 校验中均有体现。运算符支持spec.requirements支持 Kubernetes 标准的六种运算符In、NotIn、Exists、DoesNotExist、Gt、Lt。其中Gt/Lt用于数值型标签如 CPU 核数、本地 NVMe 容量、网络带宽的大小比较。Min Values最小灵活性约束ALPHA在[key, operator, values]组合之外Karpenter 还支持在 NodePool 的 requirements 块中声明minValues让调度器感知用户指定的灵活性下限。如果 Karpenter 在为某个 Pod 调度时无法为每个声明了minValues的 key 提供足够数量的唯一取值就会让该 NodePool 的调度循环失败转而回退到其他满足 Pod 需求的 NodePool或直接调度失败。例如下面的 spec 强制了多个 key 的minValues调度 Pod 时至少需要 2 个唯一实例类别来自[c, m, r]、5 个唯一实例系列如m5、m5d、r4、c5、c5d、c4等、10 个唯一实例类型如c5.2xlarge、c4.xlarge等spec: template: spec: requirements: - key: kubernetes.io/arch operator: In values: [amd64] - key: kubernetes.io/os operator: In values: [linux] - key: karpenter.k8s.aws/instance-category operator: In values: [c, m, r] minValues: 2 - key: karpenter.k8s.aws/instance-family operator: Exists minValues: 5 - key: node.kubernetes.io/instance-type operator: Exists minValues: 10 - key: karpenter.k8s.aws/instance-generation operator: Gt values: [2]关于minValues的要点minValues可以与多种运算符、多个 requirements 组合使用如果同一个 key 上以多个运算符分别声明了minValues调度器按其中最大值计算。例如下面的 spec 中karpenter.k8s.aws/instance-family同时声明了Exists minValues: 5与In minValues: 3调度器最终要求至少考虑 5 个实例系列spec: template: spec: requirements: - key: kubernetes.io/arch operator: In values: [amd64] - key: kubernetes.io/os operator: In values: [linux] - key: karpenter.k8s.aws/instance-category operator: In values: [c, m, r] minValues: 2 - key: karpenter.k8s.aws/instance-family operator: Exists minValues: 5 - key: karpenter.k8s.aws/instance-family operator: In values: [m5,m5d,c5,c5d,c4,r4] minValues: 3 - key: node.kubernetes.io/instance-type operator: Exists minValues: 10 - key: karpenter.k8s.aws/instance-generation operator: Gt values: [2]从 CRD 定义karpenter.sh_nodepools.yaml可以看到minValues的合法范围是150并且有一条 CEL 校验规则使用In运算符且声明了minValues时values字段中的取值数量必须大于等于minValues。该字段目前处于ALPHA阶段随时可能被移除或替换。仓库还提供了两个专门示例min-values-family.yaml 与 min-values-multiple-keys.yaml。推荐的 requirements 基线Karpenter 允许你在 NodePool 上做非常灵活的约束建议只对集群绝对必要的维度限制实例类型。默认情况下Karpenter 会强制要求填写spec.template.spec.requirements字段但不会强制要求字段内必须有具体条目。如果填写requirements: []意味着你对云提供商支持的所有实例类型完全开放。虽然 Karpenter 不强制这些默认值但对大多数通用负载场景官方推荐至少声明一些 requirements以避免出现奇怪行为或极端实例类型。以下是适合大多数通用工作负载的高层推荐基线spec: template: spec: requirements: - key: kubernetes.io/arch operator: In values: [amd64] - key: kubernetes.io/os operator: In values: [linux] - key: karpenter.sh/capacity-type operator: In values: [on-demand] - key: karpenter.k8s.aws/instance-category operator: In values: [c, m, r] - key: karpenter.k8s.aws/instance-generation operator: Gt values: [2]仓库示例 general-purpose.yaml 中的 NodePool 与此基线完全一致amd64 linux on-demand c/m/r 类别 代数大于 2可作为通用生产配置的起点。中断策略spec.disruption通过spec.disruption你可以用多种方式配置 Karpenter 对节点的中断disrupt行为spec.disruption.consolidationPolicy合并策略spec.disruption.consolidateAfter合并等待时间spec.template.spec.expireAfter节点过期时间见上文spec.disruption.budgets对中断行为做速率限制。consolidationPolicy决定 Karpenter 将哪些节点纳入合并consolidation考量WhenEmptyOrUnderutilized默认Karpenter 会考虑所有节点当发现节点为空或利用率不足、且通过移除或替换节点能够降低成本时尝试执行合并WhenEmptyKarpenter 只考虑不含工作负载 Pod的节点进行合并。consolidateAfter指定在节点上添加或移除 Pod 之后Karpenter 等待多久才对该节点执行合并。可以设置为字符串Never以完全禁用合并。从 CRD 定义karpenter.sh_nodepools.yaml可以看到consolidationPolicy的默认值是WhenEmptyOrUnderutilizedconsolidateAfter的默认值是0s。budgets控制 Karpenter 缩容节点的速度Karpenter 会取当前生效预算中的最小值百分比计算时向上取整duration与schedule必须成对设置示例中第一个预算nodes: 10%始终生效无 schedule表示任何时候最多同时中断 10% 的节点第二个预算在工作日mon-fri9 点到 17 点0 9 * * mon-fri持续 8h之间生效将节点中断数限制为0即业务高峰完全不缩容。disruption: budgets: - nodes: 10% - schedule: 0 9 * * mon-fri duration: 8h nodes: 0关于中断的更多细节合并、过期、drift、预算的完整语义参见 Disruption 文档。资源限额spec.limitsNodePool spec 中的spec.limits段用来约束该 NodePool 可以消耗的最大资源总量如果spec.limits未指定表示没有默认的资源分配限制此时最大资源消耗由云提供商的配额决定一旦限额被超过Karpenter 将停止供给新节点直到部分节点被终止释放资源。apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: default spec: template: spec: requirements: - key: karpenter.sh/capacity-type operator: In values: [spot] limits: cpu: 1000 memory: 1000Gi nvidia.com/gpu: 2关于限额的重要事实CPU 限额使用DecimalSI值如1000表示 1000 核。注意 Kubernetes API 会将其强制转换为字符串因此不建议使用整数以避免 GitOps 漂移例如 Helm 渲染与 kubectl apply 之间出现类型不一致内存限额使用BinarySI值如1000Gi语义同 Kubernetes 容器内存管理中的 memory 含义除了 CPU 与内存还可以对其他资源如nvidia.com/gpu设置限额由于Karpenter 的供给是高度并行的限额检查是最终一致的在快速扩容时可能出现限额超卖overrun可以通过以下命令查看集群中当前 CPU 与内存的消耗情况kubectl get nodepool -ojsonpath{.items[0].status}status输出中的resources段如cpu: 20、memory: 8192Mi、ephemeral-storage: 100Gi即当前已被该 NodePool 占用的资源量。关于resources的更多类型定义可参考 Kubernetes 核心 APIk8s.io/api/core/v1中ResourceList的说明。优先级spec.weightKarpenter 通过weight机制描述 NodePool 的优先级偏好语义与 Pod 与节点的亲和性权重 类似调度器在多个 NodePool 之间做选择时权重越高优先级越高不设置 weight 等价于 weight 为 0。weight 的典型应用场景详见 调度文档的 Weighted NodePools 一节Savings Plans / Reserved Instances 优先如果你购买了 Savings Plan 或预留实例可以创建一个限制为特定实例类型、并设置较高weight的 NodePool同时用spec.limits限制其可供给的最大容量让 Karpenter 优先使用预留容量超出部分再回退到通用实例类型集群级默认配置Fallback对没有声明 nodeSelector / affinity 的 Pod通过设置较高weight并限定特定容量类型或架构的 NodePool为其提供集群级的默认节点配置。需要注意的是基于 Karpenter 的 Pod 批处理batching与装箱bin packing方式并不保证 Karpenter 总是选择权重最高的 NodePool。例如当 Pod 无法用最高优先级 NodePool 调度时会强制用较低优先级 NodePool 创建节点同一批的其他 Pod 也可能随之调度到该节点或者当已有容量可用时kube-scheduler 会直接把 Pod 调度走而不触发 Karpenter 新建节点。状态观测status.conditions 与 status.resourcesstatus.conditionsConditions 对象为 Karpenter 增加可观测性各字段含义如下status.conditions.type反映节点/对象的状态类型如Initialized、Availablestatus.conditions.status指示条件是True还是Falsestatus.conditions.observedGeneration指示实例是否落后于.metadata.generation的当前状态status.conditions.lastTransitionTime上一次状态转换时间的程序化标识status.conditions.reason上一次状态转换的原因status.conditions.message关于上一次状态转换的人类可读细节。NodePool 自身的 status conditions 包括Condition Type描述NodeClassReady底层 nodeClassEC2NodeClass就绪ValidationSucceededNodePool CRD 校验成功Ready顶层条件指示 NodePool 是否就绪只有其余所有条件都为 True 时该条件才为 True如果 NodePool 未就绪Ready 为 False它将不会被纳入调度考虑。status.resourcesstatus.resources下的对象提供资源状态信息如cpu、memory、ephemeral-storage的当前占用示例中为cpu: 20、memory: 8192Mi、ephemeral-storage: 100Gi与spec.limits配合可用于观察限额消耗进度。实战示例示例一隔离昂贵硬件GPU可以创建一个只供给特定处理器类型的 NodePool。下面的示例通过 taint 实现只有带 Nvidia GPU toleration 的 Pod 才能调度上来apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: gpu spec: disruption: consolidationPolicy: WhenEmptyOrUnderutilized template: spec: requirements: - key: node.kubernetes.io/instance-type operator: In values: [p3.8xlarge, p3.16xlarge] taints: - key: nvidia.com/gpu value: true effect: NoSchedule要让 Pod 运行在该 NodePool 供给的节点上Pod spec 必须容忍nvidia.com/gpu并在资源中声明 GPU 需求例如limits: { nvidia.com/gpu: 1 }。完整的工作负载示例可参考仓库 workloads/gpu-nvidia.yaml。需要注意的是供给 GPU 节点时集群中必须部署对应的 GPU device plugin DaemonSet否则 Karpenter 不会将这些节点视为已初始化。示例二Cilium 启动污点startupTaints按 Cilium 官方建议应该在节点上放置node.cilium.io/agent-not-readytrue:NoExecute污点让 Cilium 在其他 Pod 启动前先完成网络配置。这可以通过 Karpenter 的startupTaints实现——污点会被打到节点上但Pod 不需要容忍这些污点就能被纳入供给考量apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: cilium-startup spec: disruption: consolidationPolicy: WhenEmptyOrUnderutilized template: spec: startupTaints: - key: node.cilium.io/agent-not-ready value: true effect: NoExecute未正确配置startupTaints的风险如果节点上有 Karpenter 不知道的 startup taint例如 Cilium 在节点加入后自行添加了该污点Karpenter 会认为待调度 Pod 无法调度到该节点于是不断尝试供给新节点来调度这个 pending Pod导致节点被持续创建。因此凡是通过外部系统DaemonSet 等在节点上打污点的场景都必须把对应污点声明进startupTaints让 Karpenter 提前感知。更多仓库示例仓库 examples/v1 目录提供了大量可直接参考的 NodePool 配置包括general-purpose.yaml通用负载基线配置spot.yaml全部使用 Spot 容量max-node-lifetime.yaml7 天过期 空节点 60 秒回收multiple-arch.yaml多架构amd64/arm64NodePool 拆分min-values-family.yaml 与 min-values-multiple-keys.yamlminValues用法演示100-cpu-limit.yaml资源限额用法large-instances.yaml大实例约束。关键要点速查NodePool 是 Karpenter 的调度入口至少配置一个 NodePool 后 Karpenter 才会工作节点模板spec.template通过nodeClassRef关联云提供商专属的 EC2NodeClassAWS 上 kubelet 参数已迁移至 EC2NodeClass.spec.kubelettaints需要 Pod 容忍startupTaints不需要——但要防止未知污点导致反复建节点的循环供给问题requirements用In/NotIn/Exists/DoesNotExist/Gt/Lt六种运算符组合约束节点属性Pod 需求必须落在 NodePool 需求范围内requirements 与 labels 合计不得超过 100 个minValuesALPHA可为调度器声明灵活性下限同一 key 多运算符时取最大值取值范围 150 且值数量须不小于 minValuesdisruption控制合并/过期/缩容节奏budgets可用 cron 表达式实现高峰不缩容spec.limits约束池子总资源上限未设置时受云提供商配额约束限额检查最终一致快速扩容可能超卖spec.weight决定多 NodePool 匹配时的优先级但受批处理与装箱逻辑影响不保证严格按权重执行status.conditions中Ready为 False 的 NodePool 不会被调度考虑。【免费下载链接】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),仅供参考
返回列表