CommandRunner を触ってみる
これいいんじゃない?
CDK とか serverless framework とかでだいぶ CloudFormation もデプロイが簡単になってきた昨今、個人的に嬉しい機能が CloudFormation でできるようになっていました。
それが CommandRunner です。
正式な機能ではないため、サポートされていませんが、CloudFormation のデプロイ前後にBashコマンドを実行することができます。なので例えば、CloudFormationのデプロイ後に Lambda を実行したいといったニーズに答えてくれます。
ちなみに仕組みは Amazon Linux 2 を動かしているだけなので、コマンドの自由度は高いです。なお、Lambdaじゃない理由は、Lambda が Bash の使用をネイティブにサポートしていないからだそうです。
実際に使ってみる
Install
git clone https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner.git
cd aws-cloudformation-resource-providers-awsutilities-commandrunner
curl -LO https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-awsutilities-commandrunner/releases/latest/download/awsutility-cloudformation-commandrunner.zip
./scripts/register.sh --set-default
Github に記載の通りに上記コマンドを実行します。
--set-default
こちらのオプションの部分で、AWS CLIのユーザーを指定しています。なおこのスクリプト、AWS SSOユーザーには対応していなかったので、CommandRunner用のIAMユーザーを用意してもいいのかもしれません(SSOユーザーとIAMユーザーは、/.aws
ディレクトリ配下にある認証情報の場所が違うことが原因かと思います)。
このスクリプトを実行すると、CommandRunner に必要なIAMロールが作成されます。
そのあとに CommandRunner が利用する ec2.amazonaws.com
を信頼関係としたIAMロールを作成します。このIAMロールは CommandRunner が立ち上げたEC2インスタンスにて使用されるロールのため、テンプレートのロール部分にはこちらのARNを記載します。
なおこの IAMロール には以下のポリシーが必要です。
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:PutLogEvents"
これで準備完了です。
実際に使ってみる
Serverless Framework を使ってデプロイしてみました。
service: commandrunner-demo
frameworkVersion: '2'
provider:
name: aws
region: ap-northeast-1
resources:
Resources:
MySNSTopic:
# リソースの前にコマンドを実行する場合はここに DependsOn を追記する
# DependsOn: Command
Type: AWS::SNS::Topic
Properties:
TopicName: "SampleTopic"
Command:
# リソースの後にコマンドを実行する場合はここに DependsOn を追記する
# DependsOn: MySNSTopic
Type: AWSUtility::CloudFormation::CommandRunner
Properties:
Command: 'aws sns list-topics --region ap-northeast-1 > /command-output.txt'
Role: arn:aws:iam::${AWS_ACCOUNT_ID}:role/CommandRunnerRole
Outputs:
Output:
Description: The output of the CommandRunner.
Value: !GetAtt Command.Output
Role
の部分はインストール時にデプロイされたIAMロールを使用してください。
実際に sls deploy
コマンドを実行してデプロイすると、CommandRunnerが実行されます。
以下、わかったことや特徴をまとめています。
- AWS CLIコマンドの実行は
--region
オプションを使用してください。S3のようなグローバルサービスはなくてもいいです。 - ロググループやサブネット、セキュリティグループがオプションで指定することができます。
- デプロイしたスタックとは別に、CommandRunner用のスタックが起動します。
- CommandRunner用のスタックは、EC2作ったりいろいろしたりしているので1行のコマンドでも実行完了までが長い。
- サブネットを指定しなければ、デフォルトのVPCにEC2が使用されます。
- サブネットを指定する場合は、セキュリティグループも指定しなければなりません。
Output
Resources:
Command:
Type: AWSUtility::CloudFormation::CommandRunner
Properties:
Command: aws s3 ls > /command-output.txt
Role: String
Outputs:
Output:
Description: The output of the CommandRunner.
Value: !GetAtt Command.Output
コマンドの結果は、上記のように /command-output.txt
を出力先にすることで、CloudFormation の出力部分に残すことができます。
上記のやつをデプロイしてみると、なぜか以下のエラーが出ます。
WaitCondition timed out. Received 0 conditions when expecting 1
CommandRunner がEC2を作成できていないみたいです。なぜでしょうか。
飽きたので終わり