使用Karpenter实现节点弹性伸缩
Karpenter是一个适用于Kubernetes平台的动态、高性能、开源的集群自动扩展解决方案,意在正确的时间使用正确的节点,简化Kubernetes基础设施管理。相较于Cluster AutoScaler,它将资源扩容时间由分钟级降为秒级,显著提高集群上工作负载的运行效率并降低成本。
Karpenter的工作原理如下:
- 监听:监控被标记为unschedulable状态的Pod。许多场景会导致Pod的不可调度,例如:CPU/内存资源不足、selector条件不满足、Node的taint/toleration条件不匹配、hostport被占用等。
- 计算:Karpenter分析这些导致Pod无法调度的限制。
- 扩容:选择满足Pod调度限制条件的Node进行扩容。
- 缩容:当节点空闲、资源到期等场景下,进行缩容。
前提条件
- 已创建一个1.29及以上的集群,且集群中包含可运行Karpenter组件的节点。
- 安装模板过程中,需要拉取公网镜像,需要节点绑定有EIP。
- Karpenter容器依赖公网访问能力,普通集群需要Karpenter所在节点绑定EIP,Turbo集群需要Karpenter容器绑定EIP。
约束与限制
- Karpenter需要配置对应的云服务商权限才能创删节点,目前Karpenter暂时使用AK/SK凭据。后续Karpenter将作为CCE插件市场系统插件,支持自定义插件委托或Pod Identity的鉴权方式。
- Karpenter与CCE集群弹性引擎均为节点的扩缩容插件,因此不能同时安装,避免两者间的相互干扰。
- Karpenter无法缩容部分CCE系统插件Pod所在节点。
部署Karpenter
- 获取模板包。
前往模板发布页面,选择合适的版本并下载tgz格式的Helm Chart包。本文以0.2.0版本的模板包为例,该模板包适用于v1.29及以上的CCE集群。由于不同版本的模板包配置项可能存在差异,本文中的配置适用于0.2.0版本。
- 上传模板
- 登录CCE控制台,进入集群,在左侧导航栏中选择“应用模板”,在右上角单击“上传模板”。
- 单击“添加文件”,选中待上传的模板包后,单击“上传”。
- 自定义value.yaml
您可在本地创建一个value.yaml配置文件用于设置安装工作负载参数,在安装时只需导入此配置文件进行自定义安装,其他未指定的参数将会使用默认配置。
默认配置内容如下:# Default values for karpenter-provider-huawei # -- Number of controller replicas replicaCount: 1 # Controller image configuration image: # -- Controller image repository repository: swr.ap-southeast-3.myhuaweicloud.com/huaweiclouddeveloper/cce/karpenter/controller # -- Controller image tag tag: "latest" # -- Image pull policy pullPolicy: IfNotPresent # kube-rbac-proxy sidecar configuration rbacProxy: image: # -- kube-rbac-proxy image repository repository: quay.io/brancz/kube-rbac-proxy # -- kube-rbac-proxy image tag tag: "v0.16.0" # -- Image pull policy pullPolicy: IfNotPresent # -- Image pull secrets for controller pods imagePullSecrets: [] # - name: registry-credentials # -- Name prefix for all resources namePrefix: "karpenter-provider-huawei-" serviceAccount: # -- Create ServiceAccount create: true # -- ServiceAccount name name: controller-manager # Controller arguments controller: # -- Metrics port metricsPort: 8080 # -- Health probe port healthProbePort: 8081 # Huawei Cloud credentials credentials: # -- Create a Secret for credentials create: true # -- Secret name for Huawei Cloud credentials name: "huawei-credentials" # -- Use an existing Secret when credentials.create is false existingSecret: "" # -- Huawei Cloud access key accessKey: "your-access-key" # -- Huawei Cloud secret key secretKey: "your-secret-key" # -- Huawei Cloud region ID region: "your-region-id" # -- Huawei Cloud CCE cluster ID clusterID: "your-cluster-id" clusterInfo: # -- Cluster category: Optional. Enter "eni" for Turbo network types. # For other network types (vpc-router or overlay_l2), enter other values. category: "" # -- yangtseEipInfo: Supports user-defined EIPs (Elastic IPs) bound to Karpenter pods. # This only takes effect when clusterInfo.category is set to "eni". yangtseEipInfo: yangtse.io/pod-with-eip: "true" # Controller resources resources: limits: cpu: "1" memory: 512Mi requests: cpu: 200m memory: 256Mi # -- Pod security context podSecurityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault # -- Container security context for manager securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: - "ALL" # -- Node selector for controller pods nodeSelector: {} # -- Tolerations for controller pods tolerations: [] # -- Affinity for controller pods affinity: {}- clusterInfo.category指定为eni时,会自动为Karpenter Pod绑定EIP,建议在Turbo集群开启,更多EIP参数可在yangtseEipInfo字段中配置,参数配置请参见在CCE Turbo集群中为Pod配置EIP。
- credentials.clusterID、credentials.accessKey、credentials.secretKey、credentials.region等字段为必填字段,其他参数请根据业务实际所需调整。
- 创建模板实例。
- 登录CCE控制台,进入集群,在左侧导航栏中选择“应用模板”。
- 在已上传的模板中,单击“安装”。
- 填写“实例名称”,选择“命名空间”和“选择版本”。
- 单击“配置文件”后的“添加文件”按钮,选择本地创建的YAML配置文件,单击“安装”。

- 在“模板实例”页签下可以查看模板实例的安装情况。
测试验证
- 创建NodePool、CCENodeClass资源。关于该资源配置参数的说明请参见配置参数说明。
apiVersion: karpenter.k8s.huawei/v1alpha1 kind: CCENodeClass metadata: name: demo-cce-elastic-cpu spec: # Add one subnet per target AZ if you want this demo NodePool to launch # across multiple zones. subnetSelectorTerms: - id: "30abcb7b-ddeb-4a93-9e83-0b21f59b07a3" imsSelector: imsFamily: "Huawei Cloud EulerOS 2.0" blockDeviceMappings: root: volumeSize: 40 volumeType: SSD k8s: volumeSize: 100 volumeType: SSD runtimeConfiguration: type: containerd login: userPassword: username: root password: "JDYk*****" --- apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: demo-cce-elastic-cpu spec: disruption: budgets: - nodes: "1" consolidationPolicy: WhenEmptyOrUnderutilized consolidateAfter: 30s limits: # Allow enough headroom for the 600-replica GSS validation to scale past 4 x 12c nodes. cpu: "100" memory: 384Gi template: metadata: labels: demo.huawei.com/scenario: cpu-elastic demo.huawei.com/nodepool-profile: shared-burst-and-consolidation spec: nodeClassRef: group: karpenter.k8s.huawei kind: CCENodeClass name: demo-cce-elastic-cpu 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 # Keep zone unconstrained so Karpenter can use every AZ exposed by the # selected ECSNodeClass subnets. Re-add a topology.kubernetes.io/zone # requirement if you need to pin this demo to specific AZs. - key: node.kubernetes.io/instance-type operator: In values: - c9.large.4 - c9.xlarge.4 - c9.2xlarge.4 - c9.4xlarge.4 - 创建一个工作负载,验证Karpenter扩容节点。
apiVersion: apps/v1 kind: Deployment metadata: name: cpu-burst namespace: default spec: replicas: 0 selector: matchLabels: app: cpu-burst template: metadata: labels: app: cpu-burst spec: terminationGracePeriodSeconds: 10 nodeSelector: demo.huawei.com/scenario: cpu-elastic containers: - name: web image: nginx:1.27-alpine imagePullPolicy: IfNotPresent ports: - containerPort: 80 name: http resources: requests: cpu: "1400m" memory: "1200Mi" limits: cpu: "1400m" memory: "1200Mi" - 扩容工作负载。
kubectl scale deployment cpu-burst --replicas=10
Deployment部署后可以看到新拉起的Pod无法在已有节点调度,一段时间后新的节点被创建,Pod能够被正常调度到新节点上:
$ kubectl get node NAME STATUS ROLES AGE VERSION 192.168.1.15 Ready <none> 3h28m v1.33.5-r20-33.0.4.9 192.168.1.158 Ready <none> 42m v1.33.5-r20-33.0.4.9 192.168.1.168 Ready <none> 4m7s v1.33.5-r20-33.0.4.9 $ kubectl get pod -l app=cpu-burst NAME READY STATUS RESTARTS AGE cpu-burst-5d84f5647c-697j2 1/1 Running 0 9m35s cpu-burst-5d84f5647c-9r9rs 1/1 Running 0 9m35s cpu-burst-5d84f5647c-9swmq 1/1 Running 0 9m35s cpu-burst-5d84f5647c-bqrmw 1/1 Running 0 9m35s cpu-burst-5d84f5647c-jc7f9 1/1 Running 0 9m35s cpu-burst-5d84f5647c-pshpx 1/1 Running 0 9m35s cpu-burst-5d84f5647c-qkzfm 1/1 Running 0 9m36s cpu-burst-5d84f5647c-rl7mk 1/1 Running 0 9m35s cpu-burst-5d84f5647c-tnt92 1/1 Running 0 9m35s cpu-burst-5d84f5647c-w728l 1/1 Running 0 9m35s
- 缩容工作负载
kubectl scale deployment cpu-burst --replicas=5
当工作负载被缩容后,新的小核节点先创建,而后老节点被回收。
$ kubectl get node NAME STATUS ROLES AGE VERSION 192.168.1.15 Ready <none> 3h30m v1.33.5-r20-33.0.4.9 192.168.1.168 Ready <none> 6m25s v1.33.5-r20-33.0.4.9 192.168.1.71 Ready <none> 2m14s v1.33.5-r20-33.0.4.9


模板实例回收
- 登录CCE控制台,进入集群,在左侧导航栏中选择“应用模板”。
- 在“模板实例”中,选择安装的实例,单击“更多”后的“卸载”。
配置参数说明
- NodePool资源参数说明:请参见Karpenter官方说明
- CCENodeClass资源参数说明:
表1 CCENodeClass资源参数 参数
是否必选
参数类型
描述
subnetSelectorTerms
是
SubnetSelectorTerm object
参数解释:
配置节点子网信息的列表
约束限制:
不涉及
ecsGroupId
否
String
参数解释:
云服务器组ID,若指定,将节点创建在该云服务器组下
约束限制:
不涉及
取值范围:
不涉及
默认取值:
imsSelector
是
IMSSelector object
参数解释:
节点操作系统与镜像的配置对象
约束限制:
不涉及
blockDeviceMappings
是
BlockDeviceMappings Object
参数解释:
节点磁盘设备的配置对象
约束限制:
不涉及
login
是
Login Object
参数解释:
节点的登录方式
约束限制:
不涉及
runtimeConfiguration
否
RuntimeConfiguration Object
参数解释:
运行时配置对象
约束限制:
不涉及
表2 SubnetSelectorTerm 参数
是否必选
参数类型
描述
id
是
String
参数解释:
网卡所在子网的网络ID
约束限制:
不涉及
取值范围:
登录VPC控制台,在左侧导航栏选择“子网”,单击子网名称,在“基本信息”页签下找到“网络ID”字段复制即可。
默认取值:
不涉及
表3 IMSSelector 参数
是否必选
参数类型
描述
imsFamily
是
String
参数解释:
节点的操作系统类型。具体支持的操作系统请参见节点操作系统说明。
约束限制:
不涉及
取值范围:
不涉及
默认取值:
不涉及
表4 BlockDeviceMappings 参数
是否必选
参数类型
描述
root
是
BlockDevice Object
参数解释:
系统磁盘
约束限制:
不涉及
k8s
是
BlockDevice Object
参数解释:
runtime及K8s使用数据盘
约束限制:
不涉及
users
否
Array of BlockDevice Objects
参数解释:
用户数据卷
约束限制:
不涉及
表5 BlockDevice 参数
是否必选
参数类型
描述
volumeSize
是
Int
参数解释:
磁盘大小,单位为GiB
约束限制:
不涉及
取值范围:
- root卷取值范围:20-1024
- k8s卷取值范围:20-32768
- 用户卷取值范围:10-32768
默认取值:
不涉及
volumeType
是
String
参数解释:
磁盘类型
约束限制:
不涉及
取值范围:
- SAS:高IO,是指由SAS存储提供资源的磁盘类型。
- SSD:超高IO,是指由SSD存储提供资源的磁盘类型。
- SATA:普通IO,是指由SATA存储提供资源的磁盘类型。EVS已下线SATA磁盘,仅存量节点有此类型的磁盘。
- ESSD:极速型SSD云硬盘,是指由极速型SSD存储提供资源的磁盘类型。
- GPSSD:通用型SSD云硬盘,是指由通用型SSD存储提供资源的磁盘类型。
- ESSD2:极速型SSD V2云硬盘,是指由极速型SSD V2存储提供资源的磁盘类型。
- GPSSD2:通用型SSD V2云硬盘,是指由通用型SSD V2存储提供资源的磁盘类型。
默认取值:
不涉及


