AWS Controllers for Kubernetes(ACK): AWSサービスをKubernetesカスタムリソースで管理する
Kubernetesを利用した開発では、クラスタ内で動作するアプリケーションやミドルウェアをDeploymentやStatefulSet等のKubernetes APIリソースとして管理します。
また、これにArgoCDやFlux等のデプロイツールを組み合わせて継続的にクラスタに同期することが一般的です。
一方で、クラウド環境を利用する場合は、クラウドベンダーが提供するサービスを使うことが多いかと思います。
これらはKubernetesのマニフェストファイルではなく、TerraformやCloudFormation、CDK等のIaCツールを使って別途プロビジョニングすることがほとんどです。
組織によっては、このようなIaCツールは別チーム管理で開発スピードを阻害する要因となり、フラストレーションが溜まっている現場もあるかもしれません。
AWS環境限定ですが、今回はAWSが提供するサービスもアプリケーションと一緒に管理できるAWS Controllers for Kubernetes(以下ACK)を紹介したいと思います。
以下はACK公式ドキュメントから引用したアーキテクチャです。
引用元: ACK - How it Works
このように、ACKは利用したいAWSサービスをKubernetesのカスタムリソースとしてデプロイすることで、Kubernetesのコントロールループで継続的にAWSインフラと同期してくれます。
これによって、AWSサービスもアプリケーション同様に、Kustomize等のKubernetes向けのツールで管理できるようになります。
今回触れませんが、類似のツールとしてマルチクラウド対応のCrossplaneもあります。
現時点では、こちらの方がより多機能でサポート範囲が広くなっています(若干使い方が難しい感はありますが)。
ACKのIAMロールを準備する
#ACKもKubernetesのPod(コントローラ)として動作します。AWSサービスへのアクセスポリシーを事前に準備する必要があります。
ここではIRSA(IAM Role for ServiceAccount)を利用して、ACKコントローラのIAMロール・ポリシーを作成します。
ここでは事前にAWS EKS環境を準備し、ACKを使用してAWS DynamoDBを作成したいとします。
以下の信頼ポリシー(dynamodb-trust-policy.json
)を準備しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::xxxxxxxxxxxx:oidc-provider/oidc.eks.ap-northeast-1.amazonaws.com/id/A57296AAEB058CF4DC35ADD7C5A70DD7"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.ap-northeast-1.amazonaws.com/id/A57296AAEB058CF4DC35ADD7C5A70DD7:sub": "system:serviceaccount:ack-system:ack-dynamodb-controller"
}
}
}
]
}
PrincipalやConditionで使用しているoidc.eks.....
の部分は、IRSA用のEKS OIDCプロバイダのURL(プロトコルなし)です。ここを経由して、AWSよりセッショントークンを取得します。
URLはマネジメントコンソールのEKSメニューより確認できます。
Conditionの引受条件には、これから作成するKubernetesのServiceAccountを指定します。
以下のフォーマットで指定します。
system:serviceaccount:<k8s-namespace>:<k8s-service-account>
これを信頼ポリシーとして、IAMロールを作成します。
aws iam create-role --role-name ack-dynamodb-controller \
--assume-role-policy-document file://dynamodb-trust-policy.json
続いてこのIAMロールにIAMポリシーをアタッチします。
ここではAWSマネージドポリシーのAmazonDynamoDBFullAccess
をつけます[1]。
aws iam attach-role-policy \
--role-name ack-dynamodb-controller \
--policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
これで準備完了です。このIAMロールを利用して、ACKコントローラがDynamoDBリソースを作成・更新します。
ACK(DynamoDBコントローラ)をインストールする
#ここでEKSにACKをインストールします。
ACKは単一のプロダクトでなく、使用するAWSサービスの単位でインストールします。
まだ未実装のものもありますが、利用できるAWSサービスは以下公式ドキュメントを参照してください。
今回はDynamoDBを対象としますので、以下のようにインストールします。ここでは現時点で最新のv0.1.6
を指定しました。
helm upgrade --install --create-namespace --namespace ack-system ack-dynamodb-controller \
oci://public.ecr.aws/aws-controllers-k8s/dynamodb-chart --version=v0.1.6 \
--set aws.region=ap-northeast-1 \
--set serviceAccount.annotations.eks"\.amazonaws\.com"/role-arn=arn:aws:iam::xxxxxxxxxxxx:role/ack-dynamodb-controller
ACKのHelmチャートはAWS ECRのパブリックレポジトリで管理されています。インストール時は以下のフォーマットでHelmチャートのURLを指定する必要があります。
oci://public.ecr.aws/aws-controllers-k8s/<aws-service>-chart
また、HelmのパラメータserviceAccount.annotations...
の部分で先程作成したIAMロールのARNを指定します[2]。
これでACKコントローラのServiceAccountは、このIAMロールを引き受けるようになります。
実際にインストールしたACKを確認します。
kubectl get deploy,pod -n ack-system
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ack-dynamodb-controller-dynamodb-chart 1/1 1 1 114s
NAME READY STATUS RESTARTS AGE
pod/ack-dynamodb-controller-dynamodb-chart-6c577cb5d9-wvgvr 1/1 Running 0 114s
カスタムリソース(CRD)も確認します。
kubectl get crd | grep dynamodb
backups.dynamodb.services.k8s.aws 2022-09-14T00:51:42Z
globaltables.dynamodb.services.k8s.aws 2022-09-14T00:51:42Z
tables.dynamodb.services.k8s.aws 2022-09-14T00:51:42Z
これを使用して、DynamoDBの構成を記述していく形になります。
ACKでDynamoDBテーブルを作成する
#実際にDynamoDBのテーブルを作成してみます。
Tableカスタムリソースを以下(blog.yaml
)のように作成してみました。
apiVersion: dynamodb.services.k8s.aws/v1alpha1
kind: Table
metadata:
name: blog
spec:
tableName: blog
billingMode: PAY_PER_REQUEST
attributeDefinitions:
- attributeName: Url
attributeType: S
keySchema:
- attributeName: Url
keyType: HASH
ここではプレーンなYAMLファイルとして作成しました。
DynamoDBを使ったことがあれば、内容は自明です。1つのパーティションキーからなるblog
テーブルです。
詳細なAPI仕様は、以下公式ドキュメントを参照してください。
これをEKSクラスタに反映します。
kubectl apply -f blog.yaml -n default
作成したカスタムリソースを参照してみます。
kubectl describe table blog
以下抜粋です。
Name: blog
Namespace: default
API Version: dynamodb.services.k8s.aws/v1alpha1
Kind: Table
Spec:
Attribute Definitions:
Attribute Name: Url
Attribute Type: S
Billing Mode: PAY_PER_REQUEST
Key Schema:
Attribute Name: Url
Key Type: HASH
Table Name: blog
Status:
Ack Resource Metadata:
Arn: arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxxxx:table/blog
Owner Account ID: xxxxxxxxxxxx
Region: ap-northeast-1
Billing Mode Summary:
Billing Mode: PAY_PER_REQUEST
Conditions:
Last Transition Time: 2022-09-14T04:30:27Z
Message: Resource synced successfully
Reason:
Status: True
Type: ACK.ResourceSynced
Creation Date Time: 2022-09-14T04:30:21Z
Item Count: 0
Table ID: fc8a7f59-7c92-452a-9612-43ea70f595ec
Table Size Bytes: 0
Table Status: CREATING
Statusを見るとACKのコントローラが、指定した構成でAWSと同期していることが分かります。
もちろん、作成したDynamoDBテーブルはマネジメントコンソールからも確認できます。
ここで作成したものは、Kubernetesのコントロールループにより同期されますので、カスタムリソースを更新すれば、変更内容は即時反映されます。
カスタムリソースを削除した場合は、該当のDynamoDBテーブルも削除されます[3]
まとめ
#今回は、KubernetesのリソースとしてAWSサービスを管理するツールをご紹介しました。
これを使えば、KubernetesのマニフェストファイルとしてAWSサービスも管理できます。
まだ利用できるサービスに限りはありますが、AWS上のKubernetesでアプリケーション開発しているプロジェクトであれば、かなり魅力的なツールになると思います。
AWSブログでも、ACKでLambdaをデプロイする方法が紹介されています。興味のある方はご参照ください。