如何在我的 Amazon EKS 集群中安装 Karpenter?

4 分钟阅读
0

我想使用 Karpenter 来扩展我的 Amazon Elastic Kubernetes Service (Amazon EKS) 集群中的 Worker 节点。

简短描述

Karpenter 是一个为 Kubernetes 构建的开源节点预置项目。将 Karpenter 添加到 Kubernetes 集群可以显著提高在该集群上运行工作负载的效率和成本。有关更多信息,请参阅 Karpenter 文档。

以下步骤向您展示了如何在 Amazon EKS 集群中部署 Karpenter。

解决方法

先决条件

在开始之前,请完成以下操作:

  • 安装 Helm 客户端 3.11.0 或更高版本。有关安装过程的更多信息,请参阅 Helm Docs
  • 安装 eksctl。有关安装过程的更多信息,请参阅《eksctl 用户指南》。
  • 创建以下环境变量:
export CLUSTER_NAME=your_cluster_name
    
export KARPENTER_VERSION=your_required_version
    
export CLUSTER_ENDPOINT="$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output text)"
    
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)

**注意:**对于 your_cluster_name 输入您的 EKS 集群名称,对于 your_required_version 输入所需的 Karpenter 版本号。检查 karpenter/releases 以获取 Karpenter 版本。

为 Karpenter 和 Karpenter 控制器创建 IAM 角色

1.    为使用 Karpenter 预置的节点创建 AWS Identity and Access Management (IAM) 角色。Karpenter 节点角色 (KarpenterInstanceNodeRole) 类似于 Amazon EKS 节点 IAM 角色。要使用 AWS 管理控制台或 AWS 命令行界面 (AWS CLI) 创建 KapenterInstanceNodeRole,请参阅 Amazon EKS 节点 IAM 角色

**注意:**如果您在运行 CLI 命令时遇到错误,请确保您使用的是最新版本的 AWS CLI。请参阅排查 AWS CLI 错误 - AWS 命令行界面

2.    将这些 IAM 策略添加到您创建的 IAM KarpenterInstanceNodeRole

AmazonEKSWorkerNodePolicy
AmazonEKS_CNI_Policy
AmazonEC2ContainerRegistryReadOnly
AmazonSSMManagedInstanceCore

为 Karpenter 控制器配置 IAM 角色

KarpenterControllerRole 创建 IAM 角色。Karpenter 控制器使用服务账户的 IAM 角色 (IRSA)。

1.    创建具有以下权限的 controller-policy.json 文档:

echo '{
    "Statement": [
        {
            "Action": [
                "ssm:GetParameter",
                "iam:PassRole",
                "ec2:DescribeImages",
                "ec2:RunInstances",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeLaunchTemplates",
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceTypes",
                "ec2:DescribeInstanceTypeOfferings",
                "ec2:DescribeAvailabilityZones",
                "ec2:DeleteLaunchTemplate",
                "ec2:CreateTags",
                "ec2:CreateLaunchTemplate",
                "ec2:CreateFleet",
                "ec2:DescribeSpotPriceHistory",
                "pricing:GetProducts"
            ],
            "Effect": "Allow",
            "Resource": "*",
            "Sid": "Karpenter"
        },
        {
            "Action": "ec2:TerminateInstances",
            "Condition": {
                "StringLike": {
                    "ec2:ResourceTag/Name": "*karpenter*"
                }
            },
            "Effect": "Allow",
            "Resource": "*",
            "Sid": "ConditionalEC2Termination"
        }
    ],
    "Version": "2012-10-17"
}' > controller-policy.json

2.    使用此 controller-policy.json 文档创建 IAM 策略。

aws iam create-policy --policy-name KarpenterControllerPolicy-${CLUSTER_NAME} --policy-document file://controller-policy.json

3.    使用此 eksctl 命令为您的集群创建 IAM OIDC 身份提供者

eksctl utils associate-iam-oidc-provider --cluster ${CLUSTER_NAME} --approve

注意:确保您的 eksctl 版本是 0.32.0 或更高版本。

4.    使用 eksctl 命令为 Karpenter 控制器创建 IAM 角色。使用 IRSA 关联 Kubernetes 服务账户和 IAM 角色。

eksctl create iamserviceaccount \
  --cluster "${CLUSTER_NAME}" --name karpenter --namespace karpenter \
  --role-name "$KarpenterControllerRole-${CLUSTER_NAME}" \
  --attach-policy-arn "arn:aws:iam::${AWS_ACCOUNT_ID}:policy/KarpenterControllerPolicy-${CLUSTER_NAME}" \
  --role-only \
  --approve

向子网和安全组添加标签

1.    向节点组子网添加标签,以便 Karpenter 知道要使用的子网。

for NODEGROUP in $(aws eks list-nodegroups --cluster-name ${CLUSTER_NAME} \
    --query 'nodegroups' --output text); do aws ec2 create-tags \
        --tags "Key=karpenter.sh/discovery,Value=${CLUSTER_NAME}" \
        --resources $(aws eks describe-nodegroup --cluster-name ${CLUSTER_NAME} \
        --nodegroup-name $NODEGROUP --query 'nodegroup.subnets' --output text )
done

2.    向安全组添加标签。

**注意:**以下命令仅向第一个节点组的安全组添加标签。如果您有多个节点组或多个安全组,则必须决定 Karpenter 将使用的安全组。

NODEGROUP=$(aws eks list-nodegroups --cluster-name ${CLUSTER_NAME} \
    --query 'nodegroups[0]' --output text)
 
LAUNCH_TEMPLATE=$(aws eks describe-nodegroup --cluster-name ${CLUSTER_NAME} \
    --nodegroup-name ${NODEGROUP} --query 'nodegroup.launchTemplate.{id:id,version:version}' \
    --output text | tr -s "\t" ",")
 
# If your EKS setup is configured to use only Cluster security group, then please execute -
 
SECURITY_GROUPS=$(aws eks describe-cluster \
    --name ${CLUSTER_NAME} --query cluster.resourcesVpcConfig.clusterSecurityGroupId | tr -d '"')
 
# If your setup uses the security groups in the Launch template of a managed node group, then :
 
SECURITY_GROUPS=$(aws ec2 describe-launch-template-versions \
    --launch-template-id ${LAUNCH_TEMPLATE%,*} --versions ${LAUNCH_TEMPLATE#*,} \
    --query 'LaunchTemplateVersions[0].LaunchTemplateData.[NetworkInterfaces[0].Groups||SecurityGroupIds]' \
    --output text)
 
aws ec2 create-tags \
    --tags "Key=karpenter.sh/discovery,Value=${CLUSTER_NAME}" \
    --resources ${SECURITY_GROUPS}

更新 aws-auth ConfigMap

1.    更新集群中的 aws-auth ConfigMap,以允许使用 KarpenterInstanceNoderole IAM 角色的节点加入集群。运行以下命令:

kubectl edit configmap aws-auth -n kube-system

2.    向 mapRoles 添加一个与以下示例相似的部分:

**注意:**将 ${AWS_ACCOUNT_ID} 变量替换为您的账户,但不要替换 {{EC2PrivateDNSName}}

- groups:
  - system:bootstrappers
  - system:nodes
  rolearn: arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterInstanceNodeRole
  username: system:node:{{EC2PrivateDNSName}}

完整的aws-auth ConfigMap 现在有两个组:一个用于您的 Karpenter 节点角色,另一个用于您现有的节点组。

部署 Karpenter

1.    使用以下命令验证要部署的 Karpenter 版本:

echo $KARPENTER_VERSION

如果没有看到任何输出或看到的版本与预期版本不同,请运行:

export KARPENTER_VERSION=your_required_version

**注意:**请将此示例中的 your_required_version 替换为所需的版本号。请参阅 GitHub 网站上的 aws/karpenter,了解 Karpenter 版本。

2.    从 Helm 图表生成完整的 Karpenter 部署 yaml 文件。在开始之前,请确保 Helm 客户端版本为 v3.11.0 或更高版本。

helm template karpenter oci://public.ecr.aws/karpenter/karpenter --version ${KARPENTER_VERSION} --namespace karpenter \
    --set settings.aws.defaultInstanceProfile=KarpenterInstanceProfile \
    --set settings.aws.clusterEndpoint="${CLUSTER_ENDPOINT}" \
    --set settings.aws.clusterName=${CLUSTER_NAME} \
    --set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"="arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterControllerRole-${CLUSTER_NAME}" > karpenter.yaml

3.    设置关联性,以便 Karpenter 在现有节点组节点之一上运行。找到部署关联性规则,然后在您刚刚创建的 karpenter.yaml 文件中对其进行修改:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: karpenter.sh/provisioner-name
          operator: DoesNotExist
      - matchExpressions:
        - key: eks.amazonaws.com/nodegroup
          operator: In
          values:
          - ${NODEGROUP}

创建 Karpenter 命名空间

创建所需的 Karpenter 命名空间和预置程序 CRD。然后,部署 Karpenter 的其余资源。

kubectl create namespace karpenter
kubectl create -f https://raw.githubusercontent.com/aws/karpenter/${KARPENTER_VERSION}/pkg/apis/crds/karpenter.sh_provisioners.yaml
kubectl create -f https://raw.githubusercontent.com/aws/karpenter/${KARPENTER_VERSION}/pkg/apis/crds/karpenter.k8s.aws_awsnodetemplates.yaml
kubectl apply -f karpenter.yaml

创建默认预置程序

创建默认预置程序,以便 Karpenter 知道您想要用于计划外工作负载的节点类型。有关具体示例的更多信息,请参阅 GitHub 网站上的 aws/karpenter

cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: karpenter.k8s.aws/instance-category
      operator: In
      values: [c, m, r]
    - key: karpenter.k8s.aws/instance-generation
      operator: Gt
      values: ["2"]
  providerRef:
    name: default
  ttlSecondsAfterEmpty: 30
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: default
spec:
  subnetSelector:
    karpenter.sh/discovery: "${CLUSTER_NAME}"
  securityGroupSelector:
    karpenter.sh/discovery: "${CLUSTER_NAME}"
EOF

扩展并验证 Karpenter

使用以下步骤将您的节点组扩展到至少两个节点的最小规模,以支持 Karpenter 和其他关键服务。

1.    配置扩展:

aws eks update-nodegroup-config --cluster-name ${CLUSTER_NAME} \
    --nodegroup-name ${NODEGROUP} \
    --scaling-config "minSize=2,maxSize=2,desiredSize=2"

2.    扩展您的工作负载,然后验证 Karpenter 是否正在创建新节点来预置您的工作负载:

kubectl logs -f -n karpenter -c controller -l app.kubernetes.io/name=karpenter

**注意:**如果在控制器日志中发现任何 webhook.DefaultingWebhook 协调错误,请重启您的 Karpenter 容器组进行修复。

3.    运行以下命令来检查节点的状态:

kubectl get nodes

AWS 官方
AWS 官方已更新 4 个月前