EKSのおかげでEC2・ASG・ELBなどが一式揃ったKubernetes環境を楽に構築できるようになりました。
一方で、上記以外のAWSマネージドサービスに依存したアプリケーションの場合、それらマネージドサービスもKubernetes (つまりマニフェストファイル) の管理下に置いて、アプリケーションと共にプロビジョニングしたいケースがしばしばあります。(かくいう私もkubectl apply
でS3バケットとかSQSとか作りたいなーと思っていた次第でした。)
KubernetesのService CatalogとAWSで提供されるService Brokerを組み合わせることでこのユースケースを実現できます。例としてSQSを作成しながら、それらの利用方法をまとめていきます。
Service CatalogとService Broker
(僕にとって) 新しい概念として現れたこの2者について簡単に触れておきます。
Service CatalogおよびService Brokerは、Kubernetesと各社のクラウドインフラが提供するリソース (マネージドサービス) を糊付けするための仕組みで、下図で示す関係となっています。
Service Catalogは、Kubernetesの機能で、Kubernetes APIと複数あるService Brokerを仲介する役割を持ちます。
利用したいService BrokerをService Catalogに登録できるので、任意のリソースとKubernetes APIを連携できるようになります。
Service Brokerは、各クラウドインフラベンダが提供するアプリケーションで、Service Catalogからのリクエストを受けて実際にリソースをプロビジョニングします。Open Service Broker API準拠のインタフェースであるため、Kubernetes以外の他のオーケストレーションシステムとも連携しやすいようになっています。
AWS Service Brokerの実装は↓のレポジトリで管理されています。
- プロビジョニングではCloudFormationが使われています
- サポートしているマネージドサービスの一覧はここで確認できます
- AWSのすべてのサービスについて実装されているわけではないので注意してください
実践: EKSからSQSをプロビジョニング
それではEKSでSQSを生成します。[こちらのポスト]を参考にしながら、次の順番で進めます。
- Service Catalogのインストール
- AWS Service Brokerのインストール
- SQSインスタンスの作成
- バインディング
- アプリケーションからの参照
前提
- EKSでクラスタ・ノードグループの作成されていること
- 作業環境にkubectlがインストールされ、クラスタと接続できていること
- クラスタにHelmがインストールされていること
Service Catalogのインストール
helmでService Catalogをnamespace: catalogにインストールします。
$ helm repo add svc-catalog https://svc-catalog-charts.storage.googleapis.com "svc-catalog" has been added to your repositories $ kubectl create namespace catalog namespace/catalog created $ helm install catalog svc-catalog/catalog --namespace catalog --wait NAME: catalog LAST DEPLOYED: Thu Apr 30 18:33:36 2020 NAMESPACE: catalog STATUS: deployed REVISION: 1 TEST SUITE: None
AWS Service Brokerのインストール
次にService Brokerのインストールです。
その前にDynamoDBとIAMの準備が必要で、prerequisites.yamlをダウンロードして、CloudFormationで適用します。このときaws-service-broker-prerequisites-BrokerUser-*
という名前でユーザが作成されますが、この後作成するService Brokerの認証情報として用います。
$ REGION=ap-northeast-1 $ wget https://raw.githubusercontent.com/awslabs/aws-servicebroker/master/setup/prerequisites.yaml $ BUSERNAME=$(aws cloudformation create-stack \ --capabilities CAPABILITY_IAM \ --template-body file://prerequisites.yaml \ --stack-name aws-service-broker-prerequisites \ --output text --query "StackId" \ --region ${REGION}) $ aws iam create-access-key --user-name ${BUSERNAME} --output json --query 'AccessKey.{KEY_ID:AccessKeyId,SECRET_ACCESS_KEY:SecretAccessKey}' { "KEY_ID": "AAAA", "SECRET_ACCESS_KEY": "BBBB" }
上のCloudFormationスタックが完了したら、namespace: aws-servicebrokerにHelmでインストールします。
$ kubectl create namespace aws-servicebroker namespace/aws-servicebroker created $ helm repo add aws-servicebroker https://awsservicebroker.s3.amazonaws.com/charts "aws-servicebroker" has been added to your repositories $ helm show chart aws-servicebroker/aws-servicebroker apiVersion: v1 description: Deploys the AWS Service Broker name: aws-servicebroker version: 1.0.1 $ helm install awssb aws-servicebroker/aws-servicebroker --wait \ --namespace aws-servicebroker --version 1.0.1 --set aws.region=ap-northeast-1 \ --set aws.accesskeyid=AAAA --set aws.secretkey=BBBB NAME: awssb LAST DEPLOYED: Thu Apr 30 22:28:56 2020 NAMESPACE: aws-servicebroker STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: For more information on usage, see https://github.com/awslabs/aws-servicebroker/docs/ $ kubectl get ClusterServiceBrokers awssb https://awssb-aws-servicebroker.aws-servicebroker.svc.cluster.local Ready 3m39s
SQSインスタンスの作成
yamlファイルのフォーマットはサービスごとに異なります。aws-servicebrokerのレポジトリで確認でき、SQSであればこちらに記載があります。
apiVersion: servicecatalog.k8s.io/v1beta1 kind: ServiceInstance metadata: name: sqs-standard-minimal-example spec: clusterServiceClassExternalName: sqs clusterServicePlanExternalName: standard parameters:
上で定義したsqs_instance.yamlファイルをkubectl applyすることで、CloudFormationのスタックが走り、SQSが生成されます。
$ kubectl apply -f sqs_instance.yaml serviceinstance.servicecatalog.k8s.io/sqs-standard-minimal-example created $ kubectl describe ServiceInstance sqs-standard-minimal-example Name: sqs-standard-minimal-example Namespace: default Labels: <none> Annotations: API Version: servicecatalog.k8s.io/v1beta1 Kind: ServiceInstance Metadata: Creation Timestamp: 2020-04-30T13:38:13Z Finalizers: kubernetes-incubator/service-catalog Generation: 1 Resource Version: 185 Self Link: /apis/servicecatalog.k8s.io/v1beta1/namespaces/default/serviceinstances/sqs-standard-minimal-example UID: d6aad2c5-8ae7-11ea-abb5-9e806396566e Spec: ... Events: <none>
SQSの名前やタグを見ると、どのクラスタのService Brokerで生成されたものかなどがわかります。
バインディング
最後に生成されたSQSをバインディングします。sqs-standard-minimal-exampleを指定したsqs_binding.yamlを作成します。
apiVersion: servicecatalog.k8s.io/v1beta1 kind: ServiceBinding metadata: name: sqs-binding spec: instanceRef: name: sqs-standard-minimal-example
同じくkubectl applyで適用すると、QUEUE_NAMEやQUEUE_URLというsecretsが作成されます。
$ kubectl apply -f sqs_binding.yaml servicebinding.servicecatalog.k8s.io/sqs-binding created $ kubectl describe ServiceBinding sqs-binding Name: sqs-binding Namespace: default Labels: <none> Annotations: API Version: servicecatalog.k8s.io/v1beta1 Kind: ServiceBinding Metadata: Creation Timestamp: 2020-05-01T01:55:40Z Finalizers: kubernetes-incubator/service-catalog Generation: 1 Resource Version: 337 Self Link: /apis/servicecatalog.k8s.io/v1beta1/namespaces/default/servicebindings/sqs-binding UID: dc32e4cc-8b4e-11ea-abb5-9e806396566e Spec: ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal InjectedBindResult 14s service-catalog-controller-manager Injected bind result $ kubectl describe secrets/sqs-binding Name: sqs-binding Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== QUEUE_NAME: 80 bytes QUEUE_URL: 134 bytes SQS_AWS_ACCESS_KEY_ID: 20 bytes SQS_AWS_SECRET_ACCESS_KEY: 40 bytes DEAD_LETTER_QUEUE_ARN: 0 bytes DEAD_LETTER_QUEUE_NAME: 0 bytes DEAD_LETTER_QUEUE_URL: 0 bytes QUEUE_ARN: 120 bytes
アプリケーションからの参照
Podでは上のsecretを環境変数にセットすることで、アプリケーションから参照できるようになります。
apiVersion: v1 kind: Pod metadata: name: example-app labels: name: example-app spec: containers: - name: example-app image: busybox command: ["sh", "-c", "printenv"] env: - name: EXAMPLE_SQS_URL valueFrom: { secretKeyRef: { name: sqs-binding, key: QUEUE_URL } }
試しにprintenvコマンドを実行してログを見ると、EXAMPLE_SQS_URLに作成したSQSのURLが入ってることが確認できます。
... EXAMPLE_SQS_URL=https://sqs.ap-northeast-1.amazonaws.com/123456789012/aws-service-broker-sqs-d6aXXXX ...
まとめ
今回はService CatalogとService Brokerを使ってKubernetesからAWSマネージドサービスをプロビジョニングする方法について整理しました。
マニフェストファイルとkubectlコマンドで環境構築を完結できるのが利点ですが、一方でプロビジョニングされるリソースの名前などを自由に設定できないので、Kubernetes環境 "外" のシステムからはどのリソースがどの環境と紐付いているのかがわかりにくい欠点があります。
なのでユースケースとしては、Kubernetes環境内で閉じて利用されるマネージドサービスのみに限定したほうが簡潔かと思いました。