☔️

Cloudformationツール:rainの便利なコマンドと記法

2024/09/26に公開

概要

rainで利用できる、「あまり存在を知られていなそうだけど便利なコマンドや記法」について一部紹介します。

rainの基本的な使い方については触れません。以下の記事が大変わかりやすいです。
rain: CloudFormation を便利に操作しちゃおう - kakakakakku blog

rainについて

rainは、AWS CloudFormationのテンプレート作成やデプロイを簡素化するためのコマンドラインツールです。
テンプレートの検証、フォーマット、デプロイを効率的に行うことができます。
https://github.com/aws-cloudformation/rain

コマンド

今回利用するCloudformationテンプレート

template.yaml
AWSTemplateFormatVersion: 2010-09-09

Description: Generated by rain

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: kagamirror-2024-09-26

ls

通常 rain deploy の際に、以下のようにスタックの差分を確認することができますが、これだと「S3バケットに何らかの変更がある」ことは分かっても、「S3バケットにどんな変更があったか」までは分かりません。

そこで、ls --changesetを使うことで差分の詳細を確認することができます。

# --no-execでチェンジセットの作成までに留めておく
output=$(rain deploy template.yaml kagamirror-test --no-exec --yes)

# チェンジセットIDを取得
changeset_id=$(echo "$output" | grep 'not executed: ' | awk -F ': ' '{print $2}')

# チェンジセットを確認
rain ls -c kagamirror-test ${changeset_id}

before/afterが表示され、プロパティレベルで差分を確認することができました。

差分が問題なければ、rain deploy --changesetでスタックをデプロイすればOK

forecast

デプロイ失敗の可能性に関する警告を出力してくれるコマンドです。

同じテンプレートでスタック名だけ変えてデプロイしてみます。

> rain forecast --experimental template.yaml kagamirror-test-2

Stormy weather ahead! 🌪

1 checks failed out of 1 total checks
FG001 FAIL on line 6: AWS::S3::Bucket Bucket - Resource with this name already exists

すでに存在するS3バケット名でデプロイしようとしたので、デプロイ前にエラーを検知してくれました。
この程度であればわざわざforecastするまでもないですが、デプロイに時間のかかるテンプレートの場合などは役立ちそうなコマンドです。

logs

rain logs はスタックのイベントログを出力するコマンドです

❯ rain logs kagamirror-test --all

Sep 26 08:17:36 kagamirror-test/Bucket (AWS::S3::Bucket) CREATE_COMPLETE
Sep 26 08:17:36 kagamirror-test/kagamirror-test (AWS::CloudFormation::Stack) CREATE_COMPLETE
Sep 26 08:17:23 kagamirror-test/Bucket (AWS::S3::Bucket) CREATE_IN_PROGRESS "Resource creation Initiated"
Sep 26 08:17:21 kagamirror-test/Bucket (AWS::S3::Bucket) CREATE_IN_PROGRESS
Sep 26 08:17:19 kagamirror-test/kagamirror-test (AWS::CloudFormation::Stack) CREATE_IN_PROGRESS "User Initiated"
Sep 26 08:12:28 kagamirror-test/kagamirror-test (AWS::CloudFormation::Stack) REVIEW_IN_PROGRESS "User Initiated"

--chartオプションをつけることで、スタックの各リソースのデプロイにかかった時間をガントチャートで表示することができます。

rain logs --chart kagamirror-test > gantchart.html

記法

!Rain::Embed

テンプレートに別ファイルの内容を文字列として埋め込むことの出来るディレクティブです。

テンプレートと同じ階層にindex.pyを作成して以下のように記述することで埋め込みができます。

.
├ index.py
└ template.yaml
index.py
def handler_name(event, context): 
    print("Hello World")
    return "ok"
template.yaml
AWSTemplateFormatVersion: 2010-09-09

Description: Generated by rain

Resources:
  TestLambda:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: test-lambda
      Role: arn:aws:iam::xxxxxxxxxxx:role/AWSLambdaBasicExecutionRole
      Runtime: python3.12
      Handler: index.lambda_handler
      Code:
        ZipFile: !Rain::Embed index.py

!Rain::Include

テンプレートに別のyamlをincludeすることのできるディレクティブです。
肥大化したテンプレート等で適切な粒度でファイルを分けると見通しが良くなりそうです。

以下のように使います。

.
├ s3.yaml
├ lambda.yaml
├ index.py
└ template.yaml
s3.yaml
Type: AWS::S3::Bucket
Properties:
  BucketName: kagamirror-2024-09-26
lambda.yaml
Type: AWS::Lambda::Function
Properties:
  FunctionName: test-lambda
  Role: arn:aws:iam::xxxxxxxxxxx:role/AWSLambdaBasicExecutionRole
  Runtime: python3.12
  Handler: index.lambda_handler
  Code:
    ZipFile: !Rain::Embed index.py
template.yaml
AWSTemplateFormatVersion: 2010-09-09

Description: Generated by rain

Resources:
  TestS3:
    !Rain::Include s3.yaml
  TestLambda:
    !Rain::Include lambda.yaml

!Rain::S3Http / !Rain:S3

このディレクティブを使用すると、CloudFormation テンプレート内で指定されたローカルファイルが Rain CLI によって自動的に S3 にアップロードされ、その HTTPS URL をテンプレート内で使用できます。
アップロード先のS3のことを考えなくてよいので非常に便利です。

アップロード先の S3 バケットは rain によって自動的に作成されるバケットです。(rain-artifacts-<AWSアカウントID>-<AWSリージョン>という規則で作成されます。)

ディレクティブの違い

  • !Rain::S3Http : https://から始まるURLが返ってくる
  • !Rain:S3 : s3:://から始まるS3URLが返ってくる

単純に指定する場合

S3Httpを使用する例
Resources:
  NestedStack:
    Type: AWS::CloudFormation::Stack
    Properties:
      TemplateURL: !Rain::S3Http templates/child-stack.yaml
S3を使用する例
Resources:
  MySageMakerModel:
    Type: AWS::SageMaker::Model
    Properties:
      PrimaryContainer:
        Image: <ECR Image URI>
        ModelDataUrl: !Rain::S3 model/model.tar.gz

バケットやキーを分けて指定する必要がある場合

以下は、API Gateway をデプロイする例です。
バケット名とキー名をそれぞれ個別に指定する必要のあるリソースでは、以下のようにPath, Zip, BucketProperty, KeyPropertyに分解して書く必要があるようです。

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: '!Rain::S3Http を使用した API Gateway の例'

Resources:
  MyApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: MyAPI
      BodyS3Location: !Rain::S3
        Path: api-definition.yaml
        Zip: false
        BucketProperty: Bucket
        KeyProperty: Key
rain deploy --debug で確認できる展開後のyaml
AWSTemplateFormatVersion: "2010-09-09"

Description: '!Rain::S3Http を使用した API Gateway の例'

Resources:
  MyApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: MyAPI
      BodyS3Location:
        Bucket: rain-artifacts-xxxxxxxxxxxxxx-us-west-2
        Key: 2944a86b8861de0ae0c1f7exxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Parameters / Tags

rainでは別ファイルのyamlに定義したParametersTagsをデプロイの際に読み込むことが出来る。

環境ごとに読み込ませたいparameters.yamlを切り替えることで柔軟な運用が可能になる。

parameters.dev.yaml
Parameters:
  ParamA: aaa
  ParamB: bbb

Tags:
  Environment: dev
rain deploy template.yaml <stack_name> --config parameters.dev.yaml
GitHubで編集を提案

Discussion