karpenter
Amazon EKS 研讨会 (eksworkshop.com) (opens new window)
# 设置环境
在安装Karpenter
之前,我们需要在我们的环境中准备一些事情才能使其按预期工作。
# 环境变量
将以下环境变量设置为要安装的Karpenter
版本。
echo $KARPENTER_VERSION $CLUSTER_NAME $ACCOUNT_ID
export KARPENTER_VERSION=v0.23.0
export CLUSTER_NAME=birenchong-k8s-cluster
export ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
2
3
4
5
# 创建 KarpenterNode IAM 角色
Karpenter 启动的实例必须使用 InstanceProfile 运行,该配置文件授予运行容器和配置网络所需的权限。Karpenter使用KarpenterNodeRole-${ClusterName}
名称发现了InstanceProfile。
首先,使用 AWS CloudFormation 创建 IAM 资源。
TEMPOUT=$(mktemp)
curl -fsSL https://karpenter.sh/"${KARPENTER_VERSION}"/getting-started/getting-started-with-eksctl/cloudformation.yaml > $TEMPOUT \
&& aws cloudformation deploy \
--stack-name "Karpenter-${CLUSTER_NAME}" \
--template-file "${TEMPOUT}" \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides "ClusterName=${CLUSTER_NAME}"
2
3
4
5
6
7
8
此步骤可能需要大约 2 分钟。同时,您可以下载文件 (opens new window)并检查 CloudFormation Stack 的内容。检查堆栈如何定义策略、角色和实例配置文件,这些配置文件将用于与启动的实例关联。您还可以前往 CloudFormation 控制台并检查堆栈部署了哪些资源。
其次,使用配置文件授予对实例的访问权限以连接到集群。此命令将Karpenter
节点角色添加到您的 aws-auth 配置映射,从而允许具有此角色的节点连接到集群。
eksctl create iamidentitymapping \
--username system:node:{{EC2PrivateDNSName}} \
--cluster ${CLUSTER_NAME} \
--arn "arn:aws:iam::${ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}" \
--group system:bootstrappers \
--group system:nodes
2
3
4
5
6
您可以通过运行以下命令来验证该条目现在是否在 AWS 身份验证映射中。
kubectl describe configmap -n kube-system aws-auth
# 创建卡彭特控制器 IAM 角色
在为服务账户添加 IAM 角色之前,我们需要为集群创建 IAM OIDC 身份提供商。
eksctl utils associate-iam-oidc-provider --cluster ${CLUSTER_NAME} --approve
Karpenter 需要启动实例等权限。这将创建一个 AWS IAM 角色、Kubernetes 服务账户,并使用服务账户的 IAM 角色 (IRSA) (opens new window)
eksctl create iamserviceaccount \
--cluster "${CLUSTER_NAME}" --name karpenter --namespace karpenter \
--role-name "${CLUSTER_NAME}-karpenter" \
--attach-policy-arn "arn:aws:iam::${ACCOUNT_ID}:policy/KarpenterControllerPolicy-${CLUSTER_NAME}" \
--role-only \
--approve
export KARPENTER_IAM_ROLE_ARN="arn:aws:iam::${ACCOUNT_ID}:role/${CLUSTER_NAME}-karpenter"
2
3
4
5
6
7
8
这一步可能需要2分钟。eksctl将创建并部署一个定义角色的CloudFormation堆栈,并创建kubernetes资源,这些资源定义了我们将在研讨会期间使用的Karpenter
serviceaccount
和Karpenter
名称空间。您还可以在CloudFormation控制台中检查该堆栈创建的资源。
# 创建 EC2 竞价链接角色
最后,我们将创建spotEC2 竞价链接角色 (opens new window).
仅当这是您首次在此账户中使用 EC2 Spot 时,才需要执行此步骤。如果已成功创建角色,您将看到:*调用 CreateServiceLinkedRole 操作时出错 (InvalidInput):此账户中已采用服务角色名称 AWSServiceRoleForEC2Spot,请尝试使用其他后缀。*只需忽略该错误并继续研讨会的其余部分即可。
aws iam create-service-linked-role --aws-service-name spot.amazonaws.com 2> /dev/null || echo 'Already exist'
# 安装卡彭特
在本节中,我们将安装Karpenter
并学习如何配置默认值配置器 CRD (opens new window)以设置配置。Karpenter 安装在具有掌舵 (opens new window)图表。Karpenter 遵循 kubernetes 控制器的最佳实践进行配置。卡彭特使用自定义资源定义 (opens new window)以声明其配置。自定义资源是 Kubernetes API 的扩展。Kubernetes 的前提之一是其 API 的声明性方面 (opens new window).Karpenter通过坚持这一原则简化了其配置。
# 安装卡彭特掌舵图
安装传入集群详细信息和Karpenter
角色 ARN 的图表。
export CLUSTER_ENDPOINT="$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output text)"
helm upgrade --install --namespace karpenter --create-namespace \
karpenter oci://public.ecr.aws/karpenter/karpenter \
--version ${KARPENTER_VERSION} \
--set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=${KARPENTER_IAM_ROLE_ARN} \
--set settings.aws.clusterName=${CLUSTER_NAME} \
--set settings.aws.clusterEndpoint=${CLUSTER_ENDPOINT} \
--set defaultProvisioner.create=false \
--set settings.aws.defaultInstanceProfile=KarpenterNodeInstanceProfile-${CLUSTER_NAME} \
--set settings.aws.interruptionQueueName=${CLUSTER_NAME} \
--wait
2
3
4
5
6
7
8
9
10
11
上面的命令:
- 使用CLUSTER_NAME,以便
Karpenter
控制器可以联系群集 API 服务器。 - Karpenter 配置通过自定义资源定义提供。我们将在下一节中了解提供程序,
--wait
通知 Webhook 控制器等待部署配置器 CRD。
要检查Karpenter
是否正在运行,您可以检查 Pod、Deployment 和 Service 是否正在运行。
kubectl get all -n karpenter
检查部署。应该有一个部署karpenter
kubectl get deployment -n karpenter
要检查正在运行的 pod,请运行以下命令。至少应该有两个pods。
kubectl get pods --namespace karpenter
可以增加部署中的
Karpenter
副本数以实现复原能力。卡彭特将选出一名负责运营的领导者控制者。
# 设置预配程序
# 设置简单(默认)CRD 配置器
Karpenter 配置以配置器 CRD(自定义资源定义)的形式出现。 单个Karpenter
配置器能够处理许多不同的pods形状。Karpenter 根据容器属性(如标签和关联性)做出计划和置备决策。一个集群可能有多个配置器,但目前我们只声明一个:默认配置器。
Karpenter的主要目标之一是简化容量管理。如果您熟悉其他自动缩放器,您会注意到Karpenter
采取了不同的方法。您可能听说过这种方法称为无组自动缩放。其他解决方案传统上使用节点组的概念作为控制元素,用于定义所提供容量的特征(即:按需、EC2 Spot、GPU 节点等),并控制集群中组的所需规模。在 AWS 中,节点组的实施与弹性伸缩组 (opens new window).随着时间的推移,使用此范例的集群(运行需要不同容量类型的不同类型的应用程序)最终会形成复杂的配置和操作模型,其中必须提前定义和提供节点组。
让我们部署以下配置:
cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: test
spec:
labels:
env: prod
env-test: "true"
eks.amazonaws.com/nodegroup: test
providerRef:
name: default
requirements:
- key: kubernetes.io/os
operator: In
values:
- linux
- key: kubernetes.io/arch
operator: In
values:
- amd64
- key: karpenter.sh/capacity-type
operator: In
values:
- on-demand
- key: karpenter.k8s.aws/instance-family
operator: In
values:
- m6a
- key: karpenter.k8s.aws/instance-size
operator: In
values:
- xlarge
ttlSecondsAfterEmpty: 30
ttlSecondsUntilExpired: 2592000
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
name: default
spec:
subnetSelector:
Name: "birenchong-eks-vpc-stack-PrivateSubnet*"
securityGroupSelector:
aws-ids: "sg-0xxxxxxxxxxxxxxxxx6"
tags:
KarpenerProvisionerName: "default"
NodeType: "karpenter-workshop"
IntentLabel: "apps"
EOF
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
提供程序的配置分为两部分。第一个定义预配器相关规范。在我们的例子中,第二部分由提供程序实现定义,并定义适用于该云提供程序的特定配置。目前,让我们专注于使用的一些设置。AWSNodeTemplate
- 要求部分:该配置器 CRD (opens new window)支持定义实例类型和可用区等节点属性。例如,为了响应 topology.kubernetes.io/zone=us-east-1c 标签,Karpenter 将在该可用区中预置节点。在此示例中,我们将 设置为采购 EC2 竞价型实例,并避免使用较小的实例。您可以了解其他属性
karpenter.sh/capacity-type``karpenter.k8s.aws/instance-size
可在此处获得 (opens new window).我们将在研讨会期间再研究一些。 - 限制部分:配置程序可以定义分配给该特定预配程序和群集部分的 CPU 和内存数量的限制。
- 提供程序部分:此预配程序使用和发现用于启动节点的资源。它使用
Karpenter
附加到子网的标签。securityGroupSelector``subnetSelector
- ttlSecondsAfterEmpty:value 将
Karpenter
配置为终止空节点。可以通过不定义值来禁用此行为。在本例中,我们将其设置为30秒的值以进行快速演示。 - ttlSecondsUntilExpire:可选参数。设置后,它定义何时删除节点。这对于强制新节点具有最新的 AMI 非常有用。在此示例中,我们将值设置为 30 天。
- 标签:预置器还可以定义 EC2 实例在创建时将具有的一组标签。这有助于在 EC2 级别启用会计和治理。如您所见,这是作为提供程序部分的一部分完成的。
Karpenter被设计为通用的,并支持其他云和基础设施提供商。您可以阅读有关**此处可用于 AWS 预置程序的配置 (opens new window)**
# 显示卡彭特日志
您可以在Cloud9中创建一个新的终端窗口,并使以下命令保持运行状态,以便每次要查找Karpenter正在执行的操作时都可以返回该终端。
要从控制台读取Karpenter
日志,您可以运行以下命令。
kubectl logs -f deployment/karpenter -n karpenter controller
Karpenter日志配置存储为Kubernetes ConfigMap。您可以通过运行以下命令来读取配置:
kubectl describe configmap config-logging -n karpenter
您可以使用以下命令将日志记录级别提高到debug
:
kubectl patch configmap config-logging -n karpenter --patch '{"data":{"loglevel.controller":"debug"}}'
# 自动节点配置
随着Karpenter
现在处于活动状态,我们可以开始探索Karpenter
如何配置节点。在本节中,我们将使用 我们将观察Karpenter
配置节点作为响应。deployment
在研讨会的这一部分中,我们将使用带有暂停图像的部署。如果您不熟悉暂停窗格 您可以在此处阅读有关它们的更多信息 (opens new window).
运行以下命令并尝试回答以下问题:
cat <<EOF > inflate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 0
selector:
matchLabels:
app: inflate
template:
metadata:
labels:
app: inflate
spec:
nodeSelector:
intent: apps
containers:
- name: inflate
image: public.ecr.aws/eks-distro/kubernetes/pause:3.2
resources:
requests:
cpu: 1
memory: 1.5Gi
EOF
kubectl apply -f inflate.yaml
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 将部署扩展到 1 个副本
kubectl scale deployment inflate --replicas 1
kubectl get deployment inflate
2
3
# 我们在本节中学到了什么:
在本节中,我们学习了:
- Karpenter 以无组方法纵向扩展节点。Karpenter 选择要扩展的节点,具体取决于挂起的 Pod 数量和配置程序配置。它选择工作负载的最佳实例的外观,然后预配这些实例。这与群集自动缩放程序的功能不同。对于集群自动缩放器,首先评估所有现有节点组,并在给定 Pod 约束的情况下找到最适合扩展的节点组。
- 卡彭特使用警戒线和排水管最佳实践 (opens new window)以终止节点。节点终止时的配置可以通过以下方式控制
ttlSecondsAfterEmpty
- 当应用程序具有可用的工作 Pod 时,Karpenter 可以从零横向扩展,在没有正在运行的作业或 Pod 时,可以从零横向缩减到零。
- 可以设置预配程序来定义治理和规则,以定义如何在群集分区中预配节点。我们可以设置要求,例如允许按需和竞价型实例,或用于筛选较小的大小。提供受支持标签的完整列表
karpenter.sh/capacity-type``karpenter.k8s.aws/instance-size
这里 (opens new window)
# 清理卡彭特
# 清理
首先删除部署,然后等待 karpenter 删除节点。
kubectl delete deployment inflate
当不再有由 karpenter 管理的节点时,您可以删除它和相关基础设施。
kubectl get nodes -l karpenter.sh/provisioner-name
您可以通过以下命令清理其余部分:
helm uninstall karpenter --namespace karpenter
eksctl delete iamserviceaccount --cluster ${CLUSTER_NAME} --name karpenter --namespace karpenter
2