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 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 のバージョンについては、karpenter/releases を確認してください。

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 ID プロバイダーを作成します。

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 には 2 つのグループができました。1 つは Karpenter ノードロール用で、もう 1 つは既存のノードグループ用です。

Karpenter をデプロイ

1.    次のコマンドを使用して、デプロイする Karpenter リリースのバージョンを確認します。

echo $KARPENTER_VERSION

出力が表示されない場合、または希望とは異なるバージョンが表示される場合は、以下を実行してください。

export KARPENTER_VERSION=your_required_version

注: この例では、your_required_version を目的のバージョン番号に置き換えてください。Karpenter のバージョンについては、GitHub ウェブサイトの aws/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 が既存のノードグループノードの 1 つで実行されるようにアフィニティを設定します。デプロイアフィニティルールを見つけて、作成したばかりの 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 やその他の重要なサービスをサポートするために、ノードグループを少なくとも 2 つのノードの最小サイズにスケーリングしてください。

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公式更新しました 10ヶ月前