亚马逊AWS官方博客

Karpenter 简介 – 开源高性能 Kubernetes 集群自动扩缩程序

我们宣布 Karpenter 已准备好投入生产。Karpenter 是使用 AWS 构建的开源、灵活、高性能的 Kubernetes 集群自动扩缩程序。它通过快速启动适当规模的计算资源来响应不断变化的应用程序负载,从而帮助提高应用程序可用性和集群效率。Karpenter 还提供实时计算资源来满足应用程序的需求,并将很快自动优化集群的计算资源占用空间,以降低成本并提高性能。

在 Karpenter 之前,Kubernetes 用户需要动态调整集群的计算容量,以支持使用 Amazon EC2 Auto Scaling 组Kubernetes 集群自动扩缩程序的应用程序。AWS 上将近一半的 Kubernetes 客户报告说,使用 Kubernetes 集群自动扩缩程序配置集群弹性伸缩具有挑战性和限制性。

当您的集群中安装 Karpenter 时,Karpenter 会观察未调度的一组容器 (pod) 的总资源请求,并作出启动和终止新节点的决策,以减少调度延迟并降低基础设施成本。Karpenter 通过观察 Kubernetes 集群内的事件,然后向底层云提供商的计算服务(例如 Amazon EC2)发送命令来做到这一点。

Karpenter 是根据 Apache 许可证 2.0 授权的开源项目。它旨在与在任何环境中运行的任何 Kubernetes 集群一起使用,包括所有主要的云提供商和本地部署环境。我们欢迎为构建其他云提供商或改进核心项目功能作出贡献。如果您发现漏洞、有建议或有什么要贡献的东西,请在 GitHub 上与我们联系。

在 AWS 上开始使用 Karpenter
要在任何 Kubernetes 集群中开始使用 Karpenter,请确保有一些可用的计算容量,然后使用公共存储库中提供的 Helm Chart 进行安装。Karpenter 还需要向您选择的提供商预置计算资源的权限。

一旦安装到集群中,原定设置的 Karpenter 预置程序会观察传入的 Kubernetes 容器组 (pod),其由于集群中的计算资源不足而无法调度,并自动启动新资源以满足其调度和资源需求。

我想根据 在 AWS 上开始使用 Karpenter,向大家展示在 Amazon EKS 集群中使用 Karpenter 的快速入门方法。它需要安装 AWS Command Line Interface (AWS CLI)、kubectleksctlHelm(Kubernetes 的软件包管理器)。设置这些工具后,使用 eksctl 创建一个集群。此示例配置文件指定了具有一个初始节点的基本集群。

cat <<EOF > cluster.yaml
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: eks-karpenter-demo
  region: us-east-1
  version: "1.20"
managedNodeGroups:
  - instanceType: m5.large
    amiFamily: AmazonLinux2
    name: eks-kapenter-demo-ng
    desiredCapacity: 1
    minSize: 1
    maxSize: 5
EOF
$ eksctl create cluster -f cluster.yaml

Karpenter 本身可以在任何地方运行,包括在自我管理的节点组托管式节点组AWS Fargate 上。Karpenter 将在您的账户中预置 EC2 实例。

接下来,您需要使用 AWS CloudFormation 模板 和 IAM Roles for Service Accounts (IRSA) 为 Karpenter 控制器创建必要的 AWS Identity and Access Management (IAM) 资源,以获取启动实例的权限,如以下文档所示。您还需要安装 Helm Chart 才能将 Karpenter 部署到您的集群。

$ helm repo add karpenter https://charts.karpenter.sh
$ helm repo update
$ helm upgrade --install --skip-crds karpenter karpenter/karpenter --namespace karpenter \
  --create-namespace --set serviceAccount.create=false --version 0.5.0 \
  --set controller.clusterName=eks-karpenter-demo
  --set controller.clusterEndpoint=$(aws eks describe-cluster --name eks-karpenter-demo --query "cluster.endpoint" --output json) \
  --wait # for the defaulting webhook to install before creating a Provisioner

Karpenter 预置程序是一种 Kubernetes 资源,可让您在集群中配置 Karpenter 的行为。当您创建原定设置预置程序时,除了 Karpenter 在集群中预置计算资源所需的内容之外,无需进一步自定义,Karpenter 会自动发现节点属性,例如实例类型、区域、架构、操作系统和实例购买类型。如果没有明确的业务要求,则无需定义这些 spec:requirements。

cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: default
spec:
#Requirements(限制预置节点参数).
#Operators { In, NotIn }(支持启用包含或排除值)
  requirements:
    - key: node.k8s.aws/instance-type #If not included, all instance types are considered
      operator: In
      values: ["m5.large", "m5.2xlarge"]
    - key: "topology.kubernetes.io/zone" #If not included, all zones are considered
      operator: In
      values: ["us-east-1a", "us-east-1b"]
    - key: "kubernetes.io/arch" #If not included, all architectures are considered
      values: ["arm64", "amd64"]
    - key: " karpenter.sh/capacity-type" #If not included, the webhook for the AWS cloud provider will default to on-demand
      operator: In
      values: ["spot", "on-demand"]
  provider:
    instanceProfile: KarpenterNodeInstanceProfile-eks-karpenter-demo
  ttlSecondsAfterEmpty: 30  
EOF

ttlSecondsAfterEmpty 值用于将 Karpenter 配置为终止空节点。如果禁用此值,则节点将永远不会因为利用率低而缩减。要了解详情,请参阅 Karpenter 网站上的“预置程序自定义资源定义 (CRD)”。

Karpenter 现在处于活动状态,可以开始在集群中预置节点。使用部署创建一组容器 (pod),然后观察 Karpenter 预置节点的响应。

$ kubectl create deployment --name inflate \
          --image=public.ecr.aws/eks-distro/kubernetes/pause:3.2

让我们扩展部署并查看 Karpenter 控制器的日志。

$ kubectl scale deployment inflate --replicas 10
$ kubectl logs -f -n karpenter $(kubectl get pods -n karpenter -l karpenter=controller -o name)
2021-11-23T04:46:11.280Z        INFO    controller.allocation.provisioner/default       Starting provisioning loop      {"commit": "abc12345"}
2021-11-23T04:46:11.280Z        INFO    controller.allocation.provisioner/default       Waiting to batch additional pods        {"commit": "abc123456"}
2021-11-23T04:46:12.452Z        INFO    controller.allocation.provisioner/default       Found 9 provisionable pods      {"commit": "abc12345"}
2021-11-23T04:46:13.689Z        INFO    controller.allocation.provisioner/default       Computed packing for 10 pod(s) with instance type option(s) [m5.large]  {"commit": " abc123456"}
2021-11-23T04:46:16.228Z        INFO    controller.allocation.provisioner/default       Launched instance: i-01234abcdef, type: m5.large, zone: us-east-1a, hostname: ip-192-168-0-0.ec2.internal    {"commit": "abc12345"}
2021-11-23T04:46:16.265Z        INFO    controller.allocation.provisioner/default       Bound 9 pod(s) to node ip-192-168-0-0.ec2.internal  {"commit": "abc12345"}
2021-11-23T04:46:16.265Z        INFO    controller.allocation.provisioner/default       Watching for pod events {"commit": "abc12345"}

预置程序的控制器会侦听一组容器 (pod) 的更改,这会启动一个新实例并将可预置的一组容器 (pod) 绑定到新节点中。

现在,删除部署。30 秒后 (ttlSecondsAfterEmpty = 30),Karpenter 应该终止空节点。

$ kubectl delete deployment inflate
$ kubectl logs -f -n karpenter $(kubectl get pods -n karpenter -l karpenter=controller -o name)
2021-11-23T04:46:18.953Z        INFO    controller.allocation.provisioner/default       Watching for pod events {"commit": "abc12345"}
2021-11-23T04:49:05.805Z        INFO    controller.Node Added TTL to empty node ip-192-168-0-0.ec2.internal {"commit": "abc12345"}
2021-11-23T04:49:35.823Z        INFO    controller.Node Triggering termination after 30s for empty node ip-192-168-0-0.ec2.internal {"commit": "abc12345"}
2021-11-23T04:49:35.849Z        INFO    controller.Termination  Cordoned node ip-192-168-116-109.ec2.internal   {"commit": "abc12345"}
2021-11-23T04:49:36.521Z        INFO    controller.Termination  Deleted node ip-192-168-0-0.ec2.internal    {"commit": "abc12345"}

如果您用 kubectl 删除节点,则 Karpenter 会优雅地封锁、耗尽和关闭相应的实例。功能揭秘,Karpenter 向节点对象添加了一个终结器,该终结器会阻止删除,直到所有容器组 (pod) 都耗尽并且终止实例。

注意事项
对于 Kapenter 功能,需要注意以下几点:

加速计算:Karpenter 可与各种 Kubernetes 应用程序配合使用,但对于需要快速调配和快速取消调配大量不同计算资源的使用案例,它的性能特别好。例如,这包括用于训练机器学习模型、运行模拟或执行复杂财务计算的批处理任务。对于需要加速 EC2 实例的使用案例,您可以利用 nvidia.com/gpu、amd.com/gpu 和 aws.amazon.com/neuron 的自定义资源。

预置程序兼容性:Kapenter 预置程序旨在与静态容量管理解决方案配合使用,例如 Amazon EKS 托管式节点组和 EC2 Auto Scaling 组。您可以选择使用预置程序、具有动态和静态管理容量的混合模型或完全静态的方法来管理整个容量。建议不要与 Karpenter 同时使用 Kubernetes 集群自动扩缩程序,因为两个系统都会纵向扩展节点以响应不可调度的一组容器。如果同时配置,两个系统将竞相启动或终止这些容器组 (pod) 的实例。

加入 Karpenter 社群
Karpenter 的社群向所有人开放。尝试一下,加入工作组会议,或者按照路线图来发布您感兴趣的未来版本。正如我所说,我们欢迎任何贡献,例如漏洞报告、新功能、更正或其他文档。

要了解有关 Karpenter 的更多信息,请参阅 AWS Container Day 的文档演示视频

Channy