AWS SAM connectors を試してみた
前回と同じく、今回も AWS SAM ネタです。
下記の AWS ブログの記事を読んだので、 AWS SAM connectors を試してみたいと思います。
AWS SAM connectors は、AWS SAM テンプレートで指定するリソースタイプの一種で、サーバーレスアプリケーションを構成するコンポーネント間のアクセス権限設定を容易に指定することができます。
今回は、次のドキュメントの記載内容を少しアレンジして、Node.js の AWS Lambda 関数から Amazon DynamoDB のテーブルにアイテムを Put するシンプルなアプリケーションの権限を AWS SAM connectors を使って設定していきます。
前提として、この記事の内容は、2022年 10月 16日時点のものです。
東京リージョンを使用し、AWS Cloud9 を使用して SAM CLI version 1.52.0 のコマンドを発行します。
また、AWS アカウント ID は12桁すべて 0 で表記します。
ではまず、sam init
を実行します。今回は Node.js 16.x をランタイムに指定します。
sam init --runtime nodejs16.x
その後、対話形式で尋ねられる項目へは、次のように応答しました。今回は AWS X-Ray のトレースは有効化していません。
Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Choose an AWS Quick Start application template 1 - Hello World Example 2 - Multi-step workflow 3 - Standalone function 4 - Scheduled task 5 - Data processing 6 - Serverless API Template: 1 Based on your selections, the only Package type available is Zip. We will proceed to selecting the Package type as Zip. Based on your selections, the only dependency manager available is npm. We will proceed copying the template using npm. Select your starter template 1 - Hello World Example 2 - Hello World Example TypeScript Template: 1 Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: Project name [sam-app]: sam-connectors-test
これで、SAM のリソースを取得できました。
次に、AWS Lambda 関数のコードを書き替えます。
今回だと、sam-connectors-test/hello-world/app.js というファイルが作成されているので、それを開きます。
そして、既存のコードをすべて削除し、次のコードに置換えます。
const AWS = require("aws-sdk"); const docClient = new AWS.DynamoDB.DocumentClient(); exports.handler = async (event, context) => { await docClient.put({ TableName: process.env.TABLE_NAME, Item: { id: context.awsRequestId, event: JSON.stringify(event) } }).promise(); }
このコードでは、環境変数で Amazon DynamoDB のテーブル名を取得して、リクエスト ID をキー属性に、イベントオブジェクトの内容をバリュー属性として Put を行っています。
では、次は SAM テンプレートを編集します。
今回だと、sam-connectors-test/template.yaml というファイルがあるので、それを開きます。
前述の AWS のドキュメントのサンプルの一部を流用、アレンジして、次のような内容にしました。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > sam-connectors-test Sample SAM Template for sam-connectors-test # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 3 Resources: MyTable: Type: AWS::Serverless::SimpleTable HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello-world/ Handler: app.handler Runtime: nodejs16.x Architectures: - x86_64 Environment: Variables: TABLE_NAME: !Ref MyTable MyConnector: Type: AWS::Serverless::Connector Properties: Source: Id: HelloWorldFunction Destination: Id: MyTable Permissions: - Write Outputs: HelloWorldFunction: Description: "Hello World Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn
このテンプレート内の、MyConnector が AWS SAM connectors になります。
MyConnector: Type: AWS::Serverless::Connector Properties: Source: Id: HelloWorldFunction Destination: Id: MyTable Permissions: - Write
今回だと、HelloWorldFunction 関数から MyTable テーブルへの Write 権限を許可するという指定になります。 IAMポリシーを直接作成するよりは、シンプルな書き方といえますね。
では、ビルドしてデプロイを実行します。
今回は、デプロイで --guided
オプションをつけています。
cd sam-connectors-test sam build sam deploy --guided
--guided
オプション を付けた場合にプロンプトで求められる入力の例を記載しておきます。
Configuring SAM deploy ====================== Looking for config file [samconfig.toml] : Not found Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: sam-connectors-test AWS Region [ap-northeast-1]: #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: Save arguments to configuration file [Y/n]: SAM configuration file [samconfig.toml]: SAM configuration environment [default]:
デプロイが正常に完了すると、次のようなメッセージが出力されます。
Successfully created/updated stack - sam-connectors-test in ap-northeast-1
また、今回の例だと次のような IAM ロールの ARN の Output があります。
これは、AWS Lambda 関数に付与された実行ロールの ARN になります。
Key HelloWorldFunctionIamRole Description Implicit IAM Role created for Hello World function Value arn:aws:iam::000000000000:role/sam-connectors-test-HelloWorldFunctionRole- WB0KUJXSC9YP
この IAM ロールの ARN うち、 arn:aws:iam::000000000000:role/より後のロールの名前の部分をメモします。
今回の例だと、sam-connectors-test-HelloWorldFunctionRole-WB0KUJXSC9YP になります。
そして、次のようにロール名を環境変数で指定して AWS CLI を実行し、ロールにアタッチされているポリシーの内容を表示してみましょう。
ROLE_NAME=sam-connectors-test-HelloWorldFunctionRole-WB0KUJXSC9YP aws iam list-attached-role-policies --role-name ${ROLE_NAME} --query "AttachedPolicies[].[PolicyArn]" --output text
出力例
arn:aws:iam::000000000000:policy/sam-connectors-test-MyConnectorPolicy-1LGRZ5UMK7FFY arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
出力結果のうち、MyConnector という文字を含んでいる ポリシーがあります。
これが、AWS SAM connectors により作成された IAM ポリシーになります。
この IAM ポリシーの ARN をメモして、次のように環境変数で指定して AWS CLI コマンドを実行します。
POLICY_ARN=arn:aws:iam::000000000000:policy/sam-connectors-test-MyConnectorPolicy-1LGRZ5UMK7FFY VERSION_ID=`aws iam get-policy --policy-arn ${POLICY_ARN} --query "Policy.DefaultVersionId" --output text` aws iam get-policy-version --policy-arn ${POLICY_ARN} --version-id ${VERSION_ID}
出力例
{ "PolicyVersion": { "CreateDate": "2022-10-16T01:29:31Z", "VersionId": "v1", "Document": { "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:BatchWriteItem", "dynamodb:PartiQLDelete", "dynamodb:PartiQLInsert", "dynamodb:PartiQLUpdate" ], "Resource": [ "arn:aws:dynamodb:ap-northeast-1:000000000000:table/sam-connectors-test-MyTable-1ONWBBRN2LWXQ", "arn:aws:dynamodb:ap-northeast-1:000000000000:table/sam-connectors-test-MyTable-1ONWBBRN2LWXQ/index/*" ], "Effect": "Allow" } ] }, "IsDefaultVersion": true } }
AWS SAM connectors により作成された IAM ポリシーの内容が確認できました。PutItem や UpdateItem や DeleteItem など Action として許可されていますね。
今回は、AWS Lambda 関数から、Amazon DynamoDB へのアクセスを例にしましたが、他にも次のようなパターンがサポートされているので、今後は他のパターンも試していきたいです!
AWS SAM で 初期化時に AWS X-Ray のトレースの有効化を指定できるようになった
AWS SAM の CLI では、sam init
というコマンドで SAM で使用するリソースを対話形式で指定して取得できますが、その対話の中に AWS Lambda と Amazon API Gateway に対して AWS X-Ray のトレース取得が指定できるようになったようです。
また sam init
時に --tracing
のオプションを指定して AWS X-Ray の有効化を指定することもできます。
今回は、対話形式での指定について、Cloud9 の環境を使って試していきます。
なお、この記事の内容は 2022 年 10 月 10日 時点に確認したものです。
まずは Cloud9 のターミナルから AWS SAM のバージョンを確認してみます。
$ sam --version SAM CLI, version 1.57.0
1.57.0 というバージョンが表示されました。
私が 少し前に使った Cloud9 の SAM CLI のバージョンは 1.33.0 だったので、なんか一気に新しくなった気がします。
次に 初期化します。なお今回は、Runtime に python3.7 を指定します。
$ sam init --runtime python3.7
この後、対話形式でいろいろと選択していきます。 まず、テンプレートについて選択します。今回は AWS のテンプレートを選択します。
Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1
次にアプリケーションのテンプレートを選択します。今回は Hello World レベルのシンプルなものを選択します。
Choose an AWS Quick Start application template 1 - Hello World Example 2 - Infrastructure event management 3 - Multi-step workflow Template: 1
そして次に、AWS X-Ray の有効化をするか、否かを選択します。今回は、有効化するため y を入力します。
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: y X-Ray will incur an additional cost. View https://aws.amazon.com/xray/pricing/ for more details
最後に SAM のプロジェクト名の入力を求められます。今回はデフォルトの sam-app でよいので、そのまま Enter キーを押下します。
Project name [sam-app]:
これにより、プロジェクト名のフォルダ、つまり今回だと sam-app というフォルダに必要なリソースが保存されます。
このフォルダの直下にある、template.yaml というファイルを開いて内容を確認してみます。
これは、SAM でデプロイを行う時に使用する SAM テンプレートファイルです。
Globals: Function: Timeout: 3 Tracing: Active Api: TracingEnabled: True
sam init 時に X-Ray の有効化を指定したので、SAM テンプレートの Globals セクションをみると、Lambda関数に対する設定である Function のプロパティで Tracing: Active
が、Amazon API Gateway のAPI に対する設定である Api のプロパティで、TracingEnabled: True
が設定されているのがわかります。
では、SAM CLI のコマンドでビルドしてデプロイしてみましょう。
まず、プロジェクト名のフォルダに移動して sam build
を実行します。
$ cd sam-app/
$ sam build
そしてデプロイですが、今回は sam deploy --guided
でデプロイを行います。
$ sam deploy --guided
sam deploy --guided
実行によりデプロイに関する入力が求められます。
次は、その入力例です。
Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: AWS Region [ap-northeast-1]: #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: #Preserves the state of previously provisioned resources when an operation fails Disable rollback [y/N]: HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y Save arguments to configuration file [Y/n]: SAM configuration file [samconfig.toml]: SAM configuration environment [default]:
デプロイが終了すると、SAM テンプレートの Outputs セクションで指定した内容が表示されます。
その中の、API Gateway の API のエンドポイントを見つけます。下記は例です。
Key HelloWorldApi Description API Gateway endpoint URL for Prod stage for Hello World function Value https://qtm166m8r2.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
この Value で表示されているURLをコピーして Webブラウザでアクセスしてみると、次のようなメッセージが表示されます。
{"message": "hello world"}
これは、作成した Lambda 関数で リターンしているメッセージですので、API Gateway の API から Lambda 関数を呼び出せたことを確認できます。
また、この呼び出しにより、AWS X-Ray のトレースも出力されているはずです。
AWS マネジメントコンソールで AWS X-Ray のコンソールを開き、左側のメニューから [トレース] を選択します。
次のように、 API Gateway と Lambda 関数のトレースが表示されることを確認します。
sam init の対話形式やオプションで AWS X-Ray の有効化を指定できるようになったことで、後でプロパティを書き足す必要がなくなりました。
私は、X-Ray をよく使うのでありがたいです。
Amazon EKS にて Ingress で SSL を有効化してみる
Amazon EKS クラスターでは、AWS Load Balancer Controller を導入すると Ingress オブジェクトを作成時に、ELB のロードバランサーを作成できます。
今回は、IngressからSSL を有効化したELB ( Application Load Balancer ) を作成する手順をまとめてみます。
これは、2022年 10 月 1 日時点で試した内容です。
前提
Amazon EKS クラスターは構成済で、AWS Load Balancer Controller も導入済です。
このクラスターに接続できる クライアントも用意できています。
また、サーバー証明書を発行するのに必要なドメインの管理者であり、Amazon Route 53 でドメインレコードを設定できる前提です。
目標
次のような構成で、https://ingress.nobelabo.net で Pod にアクセスできるようにすることが目標です。
AWS Certificate Manager ( ACM ) でサーバー証明書を発行
AWS マネジメントコンソールから、完全修飾ドメイン名を指定してパブリック証明書のリクエストを発行します。
Eメールまたは DNSによる検証を行うと証明書が発行されます。
検証は、ドメインの管理者である証明としてEメールを受信、または 対象のDNSに検証用のレコードを追加します。詳細は、次のドキュメントを参照しましょう。
発行された証明書の ARN をメモしておきます。
Deployment の作成
ingress からアクセスする Pod 用の Deployment を作成します。
次はあくまで例であり個人的に作ったコンテナイメージを指定してますが、もっとシンプルに nginx などを使っても良いと思います。
ここでは、deployment.yaml に保存した前提とします。
apiVersion: apps/v1 kind: Deployment metadata: name: python-web-ec2-deployment spec: replicas: 2 selector: matchLabels: app: python-web-ec2 template: metadata: labels: app: python-web-ec2 spec: containers: - name: python-web-ec2 image: tnobe/python-web-ec2 ports: - containerPort: 8000
マニフェストが用意出来たら、作成して Pod が起動したことを確認します。
kubectl apply -f deployment.yaml
kubectl get pods
Ingress と Service の作成
ではいよいよ Ingress と Service を作成します。
次のようなマニフェストを用意します。
ここでは、ingress.yaml に保存した前提とします。
apiVersion: v1 kind: Service metadata: name: my-service-ingress-ssl spec: ports: - port: 80 targetPort: 8000 protocol: TCP type: ClusterIP selector: app: python-web-ec2 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress-alb-ip-ssl annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]' alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-1:000000000000:certificate/6654fefe-7976-4ce7-8cad-44455fc79291 spec: rules: - http: paths: - path: / pathType: Prefix backend: service: name: my-service-ingress-ssl port: number: 80
annotations で alb.ingress.kubernetes.io/listen-ports
を指定し、HTTPS: 443 も使用するように指定します。
また、alb.ingress.kubernetes.io/certificate-arn
で発行した ACM の証明書の ARN を指定します。
マニフェストが用意出来たら、作成して ingress が起動したことを確認します。
kubectl apply -f ingress.yaml
kubectl get ingress
次は、出力から抜粋した例です。
NAME CLASS HOSTS ADDRESS my-ingress-alb-ip-ssl <none> * xxxxx.ap-northeast-1.elb.amazonaws.com
ADDRESS 列に表示されているのが、Application Load Balancer (ALB) のDNS名になります。
この段階で、ブラウザから http://(ALBのDNS名) で Pod にアクセスできることを確認しておきます。
DNS に 別名レコードを追加
今回は 個人的に管理している 別の AWS アカウントのRoute 53 のホストゾーンで DNS レコードを管理しているので、 AWS マネジメントコンソールから CNAME レコードを追加します。
レコード名: ingress.nobelabo.net
レコードタイプ: CNAME
値: ALBのDNS名
ルーティングポリシー:シンプル
これで、https://ingress.nobelabo.net で Pod にアクセスできるようになりました!
(現在は、https://ingress.nobelabo.net はアクセスできないようにしています。)
最後に
Amazon EKS に AWS Load Balancer Controller を導入したとき Ingress で SSL でリスニングする時の方法について、これまで日本語で説明されたドキュメントを見つけることができなかったので、このブログを自分用のメモにしておきたいと思います。
AWS での分散負荷テスト ソリューションを試してみた
AWS ソリューションライブラリの一つである「AWS での分散負荷テスト」ソリューションを試してみました。
このソリューションは、Amazon ECS の Fargateのタスクをクライアントとして任意のWebのエンドポイントに負荷テストを実施できるようで、 前からその存在は知っていたんですが、実際に試してみるのは初めてです。
なおこの記事に記述している内容は、2022年9月24日時点の内容に基づいていますのでご了承ください。
このソリューションを導入する事前準備としては、基本的に VPC と 2つ以上のサブネットが存在してればいけそうです。
詳細についてはソリューションガイドを参照しましょう。
https://d1.awsstatic.com/Solutions/ja_JP/distributed-load-testing-on-aws.pdf
では、このソリューションを導入していきます。
まず自分のAWSアカウントにサインインした状態にして、このソリューションのページにある [AWS コンソールで起動する] をクリックします。
そうすると CloudFormation でスタックを作成するページが表示されるので、必要なパラメータの入力を行います。
ここで入力する管理者の ID は、ソリューションが導入された後にテストを管理するコンソールにサインインするために必要になります。
なお、サブネットは Fargate のタスクの実行に使用するものを指定します。Public でも Private でも大丈夫ですが、Private の場合は Fargate がイメージを Pull するために NAT ゲートウェイを構成しておく必要があります。
必要なパラメータを入力後、CloudFormation でスタックを作成します。
無事にスタック作成が完了すると、パラメータで指定した管理者のメールアドレスに次のようなメールが届きます。
サブジェクト:
Welcome to Distributed Load Testing
本文:
Please use the credentials below to login to the Distributed Load Testing console. Username: admin1 Password: B2ZXkPR0D.1d Console: https://xxxxxxxxxxxxxx.cloudfront.net/
このメールに記載されている [Console:] のURL で、テストを実行、管理するためのコンソールへのアクセスできます。
アクセスすると、次のようにサインインが求められます。( 少し前の AWS Amplify の 認証の UI ですね。)
ここで、メールに記載されている [Username:] の値と [Password:] の値を入力してサインインを行います。
入力内容が正しければ、パスワード変更が求められますので新しいパスワードを入力します。
そうすると、テストを管理するコンソールが開き、テストシナリオ一覧が表示されます。まだテストは実行していないので何も表示されません。
これからテストシナリオを作成するので、[CREATE TEST] をクリックします。
そして、次の図のようにテストの設定を入力します。
今回は、シンプルに単一のエンドポイントにアクセスを行うだけの設定にすることにしました。
なお、上図ではチェックされていませんが、今回はテスト中も Liveデータをモニタリングしたいので [Include Live Data ] をチェックします。
すぐにテストを実行したかったので、[Run Now] を選択してページ右下にある [RUN NOW]ボタンをクリックします。
すると、テストの詳細ページに切り替わります。
この詳細ページを少し下にスクロールすると、Amazon ECS の Fargate のタスクの起動状況も表示されます。
[Running] の値が指定したタスク数になることを確認します。
ここには Amazon ECS のコンソールへのリンクも表示されています。タスクの状況はこのリンクをクリックして表示される Amazon ECS のコンソールからでも確認できます。
さらにページを下にスクロールすると、チャートでLive データが表示されます。これは、[Include Live Data ] をチェックした場合に表示されます。
もしページの内容が更新されない場合は、右上にある [REFRESH] ボタンを選択してみましょう。
テストが終了すると、結果が表示されます。
今回はシンプルなシナリオでテストしてみましたが、JMeterを使用したテストや、複数のリージョンを使用したテストなどもできるようです。
多くの AWS サービスのリソースを使用して構築されているソリューションですが、CloudFormation を使用して比較的シンプルに導入できるのがいいですね!
Amazon EKS で Pod から AWS Secrets Manager のシークレットを取得する
今回は、AWS Secrets Manager で管理しているシークレットの情報を Amazon EKS の Pod から取得させてみます。
これを実現するために、AWS Secrets and Config Provider (ASCP) を使用します。
下図がそのイメージです。
ASCP については、次の AWS ブログの記事や、AWS のドキュメントにも情報があるので、併せてご参照ください。
ここに記述している内容は、2022 年 9 月13 日時点で動作を確認しています。
また、対象にしている Kubernetes のバージョンは 1.23 です。
前提と環境
今回は、大阪リージョンの「 ASCP-cluster 」という名前の EKS クラスター (バージョンは 1.23 ) を使う前提とします。
kubectl や eksctl 、AWS CLI 、Helm、git が使用でき、対象のクラスターに接続できる Amazon Linux2 の環境で実施していきます。
AWS Secrets and Config Provider (ASCP) のインストール
これは、AWS のドキュメントに基づいて行います。
まず Helm を使って Secrets Store CSI ドライバーをインストールします。
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm install -n kube-system csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver
次に ASCP をインストールします。
kubectl apply -f https://raw.githubusercontent.com/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml
環境変数の作成
このあとの手順でよく利用する情報を環境変数に格納しておきます。
REGION=ap-northeast-3 CLUSTERNAME=ASCP-cluster
AWS Secrets Manager のシークレットの作成
今回は、ユーザー名: admin とパスワード: admin1234 という値をシークレットとして作成します。
aws --region "$REGION" secretsmanager create-secret --name ascp-demo-secret --secret-string '{"username":"admin", "password":"admin1234"}'
作成後に表示されるシークレットの ARN をメモしておきましょう。
Service Account の作成
Amazon EKS の Pod には、 AWS Secrets Manager のシークレットを取得するための権限を付与する必要があるので、Service Account を作成します。
まず 作成したシークレットの取得を許可する IAM ポリシーを作成します。次の例では、ポリシー名を ascp-demo-secret-policy にしています。
下記で、 <作成したシークレットのARN> の部分に、メモしておいた ARN を記載します。
POLICY_ARN=$(aws --region "$REGION" --query Policy.Arn --output text iam create-policy --policy-name ascp-demo-secret-policy --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret"], "Resource": ["<作成したシークレットのARN>"] } ] }')
次に EKS クラスターの OIDC プロバイダを AWS IAM に関連付けます。これはクラスター単位で 1回行うだけで OK です。
eksctl utils associate-iam-oidc-provider --region="$REGION" --cluster="$CLUSTERNAME" --approve
そして、Service Account を作成します。次の例では、Service Account 名を ascp-demo-secret-sa にしています。
eksctl create iamserviceaccount --name ascp-demo-secret-sa --region="$REGION" --cluster "$CLUSTERNAME" --attach-policy-arn "$POLICY_ARN" --approve --override-existing-serviceaccounts
SecretProviderClass の作成
SecretProviderClass を作成するためのマニフェストを用意します。
次の例では、secret-provider-class.yaml
というファイルで作成しています。
このマニフェストの objectName
に作成したシークレットの名前を指定します。
apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: ascp-demo-secrets-provider-class spec: provider: aws parameters: objects: | - objectName: "ascp-demo-secret" objectType: "secretsmanager"
マニフェスト作成後、適用します。
kubectl apply -f secret-provider-class.yaml
Deployment の作成
それでは、Pod から シークレットの情報を取得してみます。
まず Deployment のマニフェストを作成します。Pod の spec には、Service Account や SecretProviderClass を正しく指定しましょう。
次の例では、/mnt/secrets-store をマウントに指定し、シークレットを取得できるようにして example-deployment.yaml
というファイルに保存しています。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: serviceAccountName: ascp-demo-secret-sa volumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "ascp-demo-secrets-provider-class" containers: - name: nginx-deployment image: nginx ports: - containerPort: 80 volumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true
マニフェスト作成後、適用します。
kubectl apply -f example-deployment.yaml
無事に Deployment の Pod が作成されたことを確認します。
kubectl get deploy nginx-deployment
次の出力例ように、2つの Pod が READY になっていれば OK です。
出力例
NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 2/2 2 2 15s
もし Pod が作成されない場合は、kubectl describe で イベントに エラー情報が出力されているか確認しましょう。
kubectl get pods kubectl describe pod <Pod名>
Pod が作成されたら、シークレットの値を参照してみます。
まず、Pod 名を確認します。
kubectl get pods
次に Pod 名を指定して コンテナのシェルに接続します。
kubectl exec -it <Pod名> -- /bin/bash
シェルに接続したらシークレットの情報を参照してみます。
cat /mnt/secrets-store/ascp-demo-secret
次の例のように表示されれば OK です。
出力例
{"username":"admin", "password":"admin1234"}
最後に
Kubernetes には Secrets というリソースがありますが、Amazon EKS にて Pod から AWS Secrets Manager を使い、認証情報などのシークレットを取得したい場合は、この AWS Secrets and Config Provider (ASCP) が役立ちそうですね。
Amazon EKS で Amazon EFS CSI ドライバー を使ってみる
今回は、Amazon EKS で Amazon EFS CSI ドライバー を使って、Podから EFSボリュームにアクセスしてみます。
手順としては前回の「Amazon EKS で Amazon EBS CSI ドライバー を使ってみる 」の記事の内容と似ているところが多いので、今回の記事も内容や構成が似ていることはご容赦下さいww
ここに記述している内容は、2022 年 9 月11 日時点で動作を確認しています。
また、対象にしている Kubernetes のバージョンは 1.23 です。
今後の Update により、手順等が変更される可能性があることをご留意ください。
なお、下記のドキュメントを参考にしていますので、こちらも併せてご参照ください。
前提と環境
今回は、東京リージョンの「 test123-cluster 」という名前の EKS クラスター (バージョンは 1.23 ) を使う前提とします。
kubectl や eksctl 、AWS CLI 、git が使用でき、対象のクラスターに接続できる Amazon Linux2 の環境で実施していきます。
記事の中で出てくる AWS アカウント ID は、12 桁すべてゼロで表記しています。
Amazon EFS CSI ドライバー用の Service Account の作成
Amazon EFS CSI ドライバーには、Amazon EFS のファイルシステムを操作する権限を付与する必要があります。
その権限を付与するため、AWS の IAM ロールと関連づいた Kubernetes の Service Account を作成します。
まず、クラスター用に IAM OpenID Connect (OIDC) プロバイダーを用意します。 (もし前に IAM ロールと関連付けた Service Account を作成したことがあるなら、すでに実施済のはずなので、その場合は不要です。)
eksctl utils associate-iam-oidc-provider --cluster test123-cluster --approve
次に、IAM ロール に付与する許可ポリシーを作成します。
ここでは、ポリシー名を AmazonEKS_EFS_CSI_Driver_Policy にしています。
curl -o iam-policy-example.json https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/docs/iam-policy-example.json aws iam create-policy \ --policy-name AmazonEKS_EFS_CSI_Driver_Policy \ --policy-document file://iam-policy-example.json
ダウンロードした iam-policy-example.json にも目を通しておくと、どのようなポリシーが必要か確認できます。
そして、Service Account を作成します。
ここでは、Service Account 名を ebs-csi-controller-sa に、IAM ロール名を AmazonEKS_EBS_CSI_DriverRole にしています。
eksctl create iamserviceaccount \ --cluster test123-cluster \ --namespace kube-system \ --name efs-csi-controller-sa \ --attach-policy-arn arn:aws:iam::000000000000:policy/AmazonEKS_EFS_CSI_Driver_Policy \ --approve \ --region ap-northeast-1
Amazon EFS CSI ドライバー を Amazon EKS アドオンとしてインストールする
インストールではHelm も使用できますが、今回は kubectl でマニフェストを使って行います。
また、マニフェストで参照するイメージは、パブリック Amazon ECR レジストリに保存されているイメージを使う前提とします。
最初にマニフェストを取得します。
kubectl kustomize \ "github.com/kubernetes-sigs/aws-efs-csi-driver/deploy/kubernetes/overlays/stable/?ref=release-1.4" > public-ecr-driver.yaml
public-ecr-driver.yaml
ファイルを編集して、次の行を削除します。
これは、Service Account は前の手順ですでに作成しているためです。
この作業は注意して下さい。ファイル内に Service Account のマニフェストが複数存在している場合、削除する対象を間違えないようにしましょう。
apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/name: aws-efs-csi-driver name: efs-csi-controller-sa namespace: kube-system ---
これでマニフェストの準備が完了したので、適用します。
kubectl apply -f public-ecr-driver.yaml
インストールを確認します。
kubectl get deploy efs-csi-controller -n kube-system
次の出力例のように、efs-csi-controller の Deployment が起動できていることを確認します。
NAME READY UP-TO-DATE AVAILABLE AGE efs-csi-controller 2/2 2 2 3m1s
EFS ファイルシステムを作成する
EFS ファイルシステムを作成するために、まずは VPC の情報を環境変数に入れておきます。
vpc_id=$(aws eks describe-cluster \ --name test123-cluster \ --query "cluster.resourcesVpcConfig.vpcId" \ --output text)
cidr_range=$(aws ec2 describe-vpcs \ --vpc-ids $vpc_id \ --query "Vpcs[].CidrBlock" \ --output text)
次に EFS ファイルシステムのマウントポイントに適用するセキュリティグループを作成します。 今回は、セキュリティグループ名を MyEfsSecurityGroup にしています。
security_group_id=$(aws ec2 create-security-group \ --group-name MyEfsSecurityGroup \ --description "My EFS security group" \ --vpc-id $vpc_id \ --output text)
作成したセキュリティグループに イングレスルールを設定します。
今回は、アクセス元がクラスターの VPC の CIDR であれば NFS トラフィックを許可するルールにします。
aws ec2 authorize-security-group-ingress \ --group-id $security_group_id \ --protocol tcp \ --port 2049 \ --cidr $cidr_range
これで EFS ファイルシステムを作成する準備ができました。
リージョンを指定して EFS ファイルシステムを作成します。
file_system_id=$(aws efs create-file-system \ --region ap-northeast-1 \ --performance-mode generalPurpose \ --query 'FileSystemId' \ --output text)
EFS ファイルシステムのマウントターゲットを作成します。
そのために、まず EKS クラスターのVPCのサブネットの ID を取得します。
aws ec2 describe-subnets \ --filters "Name=vpc-id,Values=$vpc_id" \ --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \ --output table
出力された表形式の内容から、EKS で EFS ファイルシステムをマウントするノードのサブネットの ID をメモしておきます。
そのサブネット ID を指定して、EFS のマウントターゲットを作成します。 次の例では、サブネット ID を subnet-0b10aaaaaaaaaaaaa と指定しています。
aws efs create-mount-target \ --file-system-id $file_system_id \ --subnet-id subnet-0b10aaaaaaaaaaaaa \ --security-groups $security_group_id
サンプルアプリケーションで確認する
では、Pod から EFS ファイルシステムにアクセスできるかをサンプルアプリケーションを使って試していきます。
まず、作成した EFS ファイルシステムの ID をメモしておきます。 これまでの手順で、$file_system_id という環境変数で参照できます。
echo $file_system_id
aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text
次に、EFS の StorageClass を作成するためのマニフェストを入手します。
curl -o storageclass.yaml https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/storageclass.yaml
ダウンロードした storageclass.yaml
を編集し、fileSystemId: 部分をメモしておいた ファイルシステム ID に変更します。
次の例では、ファイルシステム ID として fs-54321abc を指定してます。
fileSystemId: fs-54321abc
これで準備ができたので、StorageClassを作成します。
kubectl apply -f storageclass.yaml
Storage Class の情報を表示してみます。NAME に efs-sc 、PROVISONER に efs.csi.aws.com の Storage Class が表示されることを確認します。
kubectl get sc
次にサンプルアプリケーションを取得します。
curl -o pod.yaml https://raw.githubusercontent.com/kubernetes-sigs/aws-efs-csi-driver/master/examples/kubernetes/dynamic_provisioning/specs/pod.yaml
今回は、動的に EFS のボリュームをプロビジョニングするサンプルを動かしていきます。
ダウンロードしたマニフェスト pod.yaml
を適用することで、Persistent Volume、Persistent Volume Claim、それを指定するサンプルの Pod が作成されます。
kubectl apply -f pod.yaml
Persistent Volume と Persistent Volume Claim の STATUS が Bound になっていることを確認します。
kubectl get pv kubectl get pvc
efs-app というPod の STATUS が Running になっていることを確認します。
kubectl get pod efs-app
次のコマンドを実行し、このサンプルアプリケーションの Pod のマニフェストをみてみます。
cat pod.yaml
次のように、Persistent Volume Claim を指定し、/data というパスにボリュームをマウントしています。
そして、echo コマンドを使用し、/data/out に日時を繰り返し書き込んでいます。
apiVersion: v1 kind: Pod metadata: name: efs-app spec: containers: - name: app image: centos command: ["/bin/sh"] args: ["-c", "while true; do echo $(date -u) >> /data/out; sleep 5; done"] volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim:
では、この Pod が EFS ボリュームに書き込み出来ているかを確認してみましょう。
kubectl exec efs-app -- bash -c "cat data/out"
次のような表示が確認できれば OK です。
出力例
Sun Sep 11 03:15:25 UTC 2022 Sun Sep 11 03:15:30 UTC 2022 Sun Sep 11 03:15:35 UTC 2022 Sun Sep 11 03:15:40 UTC 2022 Sun Sep 11 03:15:45 UTC 2022 Sun Sep 11 03:15:50 UTC 2022 Sun Sep 11 03:15:55 UTC 2022
ここで、もう1つ、同じ EFS のマウントターゲットを使用するPod を作成してみます。
次のマニフェストを作成して、nginx.yaml
として保存します。
apiVersion: v1 kind: Pod metadata: name: efs-app-nginx spec: containers: - name: nginx image: nginx volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim: claimName: efs-claim
この Pod を作成します。
kubectl create -f nginx.yaml
作成した Pod のシェルに接続してみます。
kubectl exec efs-app-nginx -it -- /bin/bash
次のコマンドを実行し、efs-app の Pod が書き込んだファイルを参照できることを確認します。
cat /data/out
出力例
Sun Sep 11 03:15:25 UTC 2022 Sun Sep 11 03:15:30 UTC 2022 Sun Sep 11 03:15:35 UTC 2022 Sun Sep 11 03:15:40 UTC 2022 Sun Sep 11 03:15:45 UTC 2022 Sun Sep 11 03:15:50 UTC 2022 Sun Sep 11 03:15:55 UTC 2022
これで EFS なので、2つのコンピューティング環境から同時にマウントしてアクセスできることが確認できました!
確認出来たら、シェルを終了します。
exit
サンプルアプリケーションを停止する場合は、次を実行します。
これで、EFS ボリュームも削除されます。( EFS ファイルシステムは削除されません)
kubectl delete po efs-app-nginx
kubectl delete -f pod.yaml
最後に
前回と今回の記事で、Amazon EKS の CSI ドライバーを使用して Amazon EBS や Amazon EFS のボリュームをプロビジョニングして Pod から使用する手順を確認しました。 AWS の公式のドキュメント の内容をベースにしていますが、少し補足しつつ、よりシンプルに確認できる手順にしたつもりです。 これがどなたかのお役に立てば嬉しいです。
Amazon EKS で Amazon EBS CSI ドライバー を使ってみる
今回は、Amazon EKS で Amazon EBS CSI ドライバー を使って、Podから EBSボリュームにアクセスしてみます。
ここに記述している内容は、2022 年 9 月1 日時点で動作を確認しています。
また、対象にしている Kubernetes のバージョンは 1.23 です。
今後の Update により、手順等が変更される可能性があることをご留意ください。
なお、下記のドキュメントを参考にしていますので、こちらも併せてご参照ください。
前提と環境
今回は、東京リージョンの「 test123-cluster 」という名前の EKS クラスター (バージョンは 1.23 ) を使う前提とします。
kubectl や eksctl 、AWS CLI 、git が使用でき、対象のクラスターに接続できる Amazon Linux2 の環境で実施していきます。
記事の中で出てくる AWS アカウント ID は、12 桁すべてゼロで表記しています。
Amazon EBS CSI ドライバー用の Service Account の作成
Amazon EBS CSI ドライバーには、Amazon EBS のボリュームを作成したり削除する権限を付与する必要があります。
その権限を付与するため、AWS の IAM ロールと関連づいた Kubernetes の Service Account を作成します。
まず、クラスター用に IAM OpenID Connect (OIDC) プロバイダーを用意します。 (もし前に IAM ロールと関連付けた Service Account を作成したことがあるなら、すでに実施済のはずなので、その場合は不要です。)
eksctl utils associate-iam-oidc-provider --cluster test123-cluster --approve
次に、IAM ロール に 付与する許可ポリシーを作成します。
ここでは、ポリシー名を AmazonEBSCSIDriverPolicy にしています。
curl -o example-iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-ebs-csi-driver/v0.9.0/docs/example-iam-policy.json aws iam create-policy --policy-name AmazonEKS_EBS_CSI_Driver_Policy --policy-document file://example-iam-policy.json
ダウンロードした example-iam-policy.json にも目を通しておくと、どのようなポリシーが必要か確認できます。
そして、Service Account を作成します。
ここでは、Service Account 名を ebs-csi-controller-sa に、IAM ロール名を AmazonEKS_EBS_CSI_DriverRole にしています。
eksctl create iamserviceaccount \ --name ebs-csi-controller-sa \ --namespace kube-system \ --cluster test123-cluster \ --attach-policy-arn arn:aws:iam::000000000000:policy/AmazonEKS_EBS_CSI_Driver_Policy \ --approve \ --role-only \ --role-name AmazonEKS_EBS_CSI_DriverRole
Amazon EBS CSI ドライバー を Amazon EKS アドオンとしてインストールする
インストールは、AWS マネジメントコンソール や AWS CLI も使用できますが、今回は eksctl を使用します。
eksctl create addon --name aws-ebs-csi-driver --cluster test123-cluster --service-account-role-arn arn:aws:iam::000000000000:role/AmazonEKS_EBS_CSI_DriverRole --force
インストールできたか確認してみます。
eksctl get addon --name aws-ebs-csi-driver --cluster test123-cluster
STATUS が ACTIVE と表示されることを確認します。
出力例 (UPDATE AVAILABLE 列は省略しています。)
NAME VERSION STATUS ISSUES IAMROLE aws-ebs-csi-driver v1.10.0-eksbuild.1 ACTIVE 0 (IAMロールのARN)
サンプルアプリケーションで確認する
では、Pod から EBS ボリュームにアクセスできるかをサンプルアプリケーションを使って試していきます。
まず、サンプルアプリケーションを取得します。
git clone https://github.com/kubernetes-sigs/aws-ebs-csi-driver.git
今回は、動的に EBS ボリュームをプロビジョニングするサンプルを動かしていきます。
次を実行することで、Storage Class、Persistent Volume Claim、それを指定するサンプルの Pod が作成され、さらに Persistent Volume として EBS ボリュームも動的に作成されます。
cd aws-ebs-csi-driver/examples/kubernetes/dynamic-provisioning/ kubectl apply -f manifests/
Storage Class の情報を表示してみます。NAME に ebs-sc 、PROVISONER に ebs.csi.aws.com の Storage Class が表示されることを確認します。
kubectl get sc
Persistent Volume Claim、Persistent Volumeは、STATUS が Bound になっていることを確認します。
kubectl get pv kubectl get pvc
次のコマンドを実行し、このサンプルアプリケーションの Pod のマニフェストをみてみます。
cat manifests/pod.yaml
次のように、Persistent Volume Claim を指定し、/data というパスにボリュームをマウントしています。
そして、echo コマンドを使用し、/data/out.txt に日時を繰り返し書き込んでいます。
apiVersion: v1 kind: Pod metadata: name: app spec: containers: - name: app image: centos command: ["/bin/sh"] args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"] volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim: claimName: ebs-claim
では、この Pod が EBS ボリュームに書き込み出来ているかを確認してみましょう。
kubectl exec -it app -- cat /data/out.txt
次のような表示が確認できれば OK です。
出力例
Thu Sep 1 01:59:12 UTC 2022 Thu Sep 1 01:59:17 UTC 2022 Thu Sep 1 01:59:22 UTC 2022 Thu Sep 1 01:59:27 UTC 2022 Thu Sep 1 01:59:32 UTC 2022 Thu Sep 1 01:59:37 UTC 2022 Thu Sep 1 01:59:42 UTC 2022
ここで、このPod だけを削除してみます。
kubectl delete pod app
Pod を削除しても、Persistent Volume Claim が削除されない限り、EBS ボリュームは残っています。
その後、他の Pod を起動し、この EBSボリュームにマウントしてみます。
次のマニフェストを作成して、nginx.yaml
として保存します。
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx volumeMounts: - name: persistent-storage mountPath: /data volumes: - name: persistent-storage persistentVolumeClaim: claimName: ebs-claim
この Pod を作成します。
kubectl create -f nginx.yaml
作成した Pod のシェルに接続してみます。
kubectl exec -it nginx -- /bin/bash
次のコマンドを実行し、削除した 前の Pod が書き込んだファイルを参照できることを確認します。
cat /data/out.txt
出力例
Thu Sep 1 01:59:12 UTC 2022 Thu Sep 1 01:59:17 UTC 2022 Thu Sep 1 01:59:22 UTC 2022 Thu Sep 1 01:59:27 UTC 2022 Thu Sep 1 01:59:32 UTC 2022 Thu Sep 1 01:59:37 UTC 2022 Thu Sep 1 01:59:42 UTC 2022
確認出来たら、シェルを終了します。
exit
サンプルアプリケーションを停止する場合は、次を実行します。
これで、EBS ボリュームも削除されます。
app という Pod はすでに削除していますので、NotFoundのエラーが出ても無視して下さい。
kubectl delete po nginx
kubectl delete -f manifests/
最後に
Amazon EKS を触りだして間もないころは、Amazon EBS CSI ドライバーの構成方法はドキュメントをみてもよくわからなかたったり、上手くいかなかったりしたのですが、今回ようやくサンプルアプリケーションを動作させる手順をまとめることができました。 次は、Amazon EFS CSI ドライバーの構成方法の記事を書きたいと思います。