きっかけ
先日、AWS re:Invent 2024に参加しました。普段からEKSを利用していることもあり、re:Inventのセッションで紹介されたKarpenterが気になったため社内環境へKarpenterをインストールしてみました。
その時の結果を共有してみたいと思います。
前提
今回構築で利用する環境について記載します。
- RHEL 8.6
- aws-cli v2.9.19
- kubectl v1.29.0
- eksctl v0.199.0
- helm v3.14.3
多少バージョン古いものもありますが、手元にあった上記の環境を利用します。また、今回の導入時にeksctlは古いと怒られた(EKSクラスタのバージョンと互換性のないeksctlを利用していました)ので最新のもの(v0.199.0)にアップデートしています。
参考にしたもの
karpenter.shサイトに導入手順が掲載されていたため、今回は以下(以後、「参考サイト」
と記述します)に沿って導入してみました。
https://karpenter.sh/docs/getting-started/getting-started-with-karpenter/
インストールしてみた
環境変数の設定
環境変数の設定は参考サイトとほとんど同じです。リージョンとnamespaceの変数のみ変更しています。
export KARPENTER_NAMESPACE="karpenter"
export KARPENTER_VERSION="1.1.1"
export K8S_VERSION="1.31"
export AWS_PARTITION="aws"
export CLUSTER_NAME="${USER}-karpenter-demo"
export AWS_DEFAULT_REGION="ap-noatheast-1"
export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
export TEMPOUT="$(mktemp)"
export ARM_AMI_ID="$(aws ssm get-parameter --name /aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2-arm64/recommended/image_id --query Parameter.Value --output text)"
export AMD_AMI_ID="$(aws ssm get-parameter --name /aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2/recommended/image_id --query Parameter.Value --output text)"
export GPU_AMI_ID="$(aws ssm get-parameter --name /aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2-gpu/recommended/image_id --query Parameter.Value --output text)"
CloudFormationの実行
CloudFormationを実行します。
$ curl -fsSL https://raw.githubusercontent.com/aws/karpenter-provider-aws/v"${KARPENTER_VERSION}"/website/content/en/preview/getting-started/getting-started-with-karpenter/cloudformation.yaml > "${TEMPOUT}" \
&& aws cloudformation deploy \
--stack-name "Karpenter-${CLUSTER_NAME}" \
--template-file "${TEMPOUT}" \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides "ClusterName=${CLUSTER_NAME}"
cloudformationで作成されたリソースは以下のとおりです。
AWSアカウントIDをマスキングしています。
clusterの作成
EKSクラスタを作成します。
用意したyamlファイルは以下のとおりです。
amiFamily: AmazonLinux2
としていますが、もうすぐEOLなのでご注意ください。
cat <<EOF > kerpenter-cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: ${CLUSTER_NAME}
region: ${AWS_DEFAULT_REGION}
version: "${K8S_VERSION}"
tags:
karpenter.sh/discovery: ${CLUSTER_NAME}
iam:
withOIDC: true
podIdentityAssociations:
- namespace: "${KARPENTER_NAMESPACE}"
serviceAccountName: karpenter
roleName: ${CLUSTER_NAME}-karpenter
permissionPolicyARNs:
- arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:policy/KarpenterControllerPolicy-${CLUSTER_NAME}
iamIdentityMappings:
- arn: "arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}"
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
managedNodeGroups:
- instanceType: m5.large
amiFamily: AmazonLinux2
name: ${CLUSTER_NAME}-ng
desiredCapacity: 2
minSize: 1
maxSize: 5
addons:
- name: eks-pod-identity-agent
EOF
作成したyamlファイルを用いてEKSクラスタを作成します。
$ eksctl create cluster -f kerpenter-cluster.yaml
kerpenter-cluster.yamlに従い、二つのNodeが作成されていることやEKSアドオンとしてvpc cni, CoreDNS, EKS Pod Identity Agent,kube-proxyが導入されていることなどを確認しています。(画像は時間の都合上、割愛いたします)
Karpenterのインストール(失敗)
以下、何度かKarpenterのインストールに失敗したのでその時の記録を以下に記述します。
$ helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter --version "${KARPENTER_VERSION}" --namespace "${KARPENTER_NAMESPACE}" --create-namespace \
--set "settings.clusterName=${CLUSTER_NAME}" \
--set "settings.interruptionQueue=${CLUSTER_NAME}" \
--set controller.resources.requests.cpu=1 \
--set controller.resources.requests.memory=1Gi \
--set controller.resources.limits.cpu=1 \
--set controller.resources.limits.memory=1Gi \
--wait
上記を実行した結果、以下のエラーが出力されます。
Error: UPGRADE FAILED: client rate limiter Wait returned an error: context deadline exceeded
--timeout
を追加してみましたが問題は解消されず、導入したkarpenterのPodのログには以下が出力されていました。
panic: operation error SQS: GetQueueUrl, https response error StatusCode: 400, RequestID: XXX, AWS.SimpleQueueService.NonExistentQueue: The specified queue does not exist or you do not have access to it.
この後、いろいろと試行錯誤した結果、Githubで以下のissuesが投稿されていることを確認しました。
https://github.com/aws/karpenter-provider-aws/issues/6623
Spot instances を利用せず、Interruption機能を利用しない場合は以下のラインを削除して問題ないとのことです。
--set "settings.interruptionQueue=${CLUSTER_NAME}" \
Karpenterのインストール(成功)
issues:6623に従い、以下のコマンドでKarpenterをインストールしました。
$ helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter --version "${KARPENTER_VERSION}" --namespace "${KARPENTER_NAMESPACE}" --create-namespace \
> --set "settings.clusterName=${CLUSTER_NAME}" \
> --set controller.resources.requests.cpu=1 \
> --set controller.resources.requests.memory=1Gi \
> --set controller.resources.limits.cpu=1 \
> --set controller.resources.limits.memory=1Gi \
> --wait \
> --timeout 20m
Pulled: public.ecr.aws/karpenter/karpenter:1.1.1
Digest: sha256:b42c6d224e7b19eafb65e2d440734027a8282145569d4d142baf10ba495e90d0
Release "karpenter" has been upgraded. Happy Helming!
NAME: karpenter
LAST DEPLOYED: Sun Dec 22 08:04:56 2024
NAMESPACE: karpenter
STATUS: deployed
REVISION: 5
TEST SUITE: None
導入したリソースを確認
helmにて導入されたリソースを確認してみます。
karpenterのnamespaceを指定しているのでnamespace:karpenterのリソースを確認してみます。
$ kubectl get all -n karpenter
NAME READY STATUS RESTARTS AGE
pod/karpenter-6954f9548b-6p8m9 1/1 Running 0 7m27s
pod/karpenter-6954f9548b-qthd6 1/1 Running 0 7m27s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/karpenter ClusterIP 10.100.109.151 <none> 8080/TCP 3h39m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/karpenter 2/2 2 2 3h39m
NAME DESIRED CURRENT READY AGE
replicaset.apps/karpenter-59d469c97c 0 0 0 3h39m
replicaset.apps/karpenter-6954f9548b 2 2 2 7m27s
2つのkarpenter podや ClusterIPのサービスが作成されていることが確認できました。
今回はKarpenterのインストール記録を記事にまとめました。
実際に動作を確認するにはnode poolなどのリソース作成が必要です。進展があればここでご報告したいと思います。
最後までお読みいただき、ありがとうございました!