如何在 Amazon EKS 叢集中安裝 Karpenter?

4 分的閱讀內容
0

我想要使用 Karpenter 來擴展 Amazon Elastic Kubernetes Service (Amazon EKS) 叢集中的工作節點。

簡短描述

Karpenter 是專為 Kubernetes 建置的開放原始碼節點佈建專案。將 Karpenter 新增至 Kubernetes 叢集可大幅提升在該叢集上執行工作負載的效率和成本。如需詳細資訊,請參閱 Karpenter 文件。

以下步驟說明如何在 Amazon EKS 叢集中部署 Karpenter。

解決方案

先決條件

在開始之前,請完成以下事項:

  • 安裝 Helm 用戶端,3.11.0 或以上。如需有關安裝程序的詳細資訊,請參閱 Helm 文件
  • 安裝 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 角色。請參閱 Amazon EKS 節點 IAM 角色,以使用 AWS 管理主控台或 AWS Command Line Interface (AWS CLI) 建立 KapenterInstanceNodeRole

**注意:**如果執行 CLI 命令時發生錯誤,請確定您使用的是最新版的 AWS CLI。請參閱故障診斷 AWS CLI 錯誤 – AWS Command Line Interface

2.    將這些 IAM 政策新增至您建立的 IAM KarpenterInstanceNodeRole

AmazonEKSWorkerNodePolicy
AmazonEKS_CNI_Policy
AmazonEC2ContainerRegistryReadOnly
AmazonSSMManagedInstanceCore

設定 Karpenter 控制器的 IAM 角色

針對 KarpenterControllerRole 建立 IAM 角色。Karpenter 控制器使用服務帳戶 (IRSA) 的 IAM 角色。

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

注意:請確保您的版本是 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 網站上 Karpenter 版本的 aws/karpenter

2.    從 Helm Chart 產生完整的 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 Reconcile 錯誤,請重新啟動 Karpenter Pod 以進行修復。

3.    執行下列命令來檢查節點的狀態:

kubectl get nodes

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