0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS CloudFormation】Express modeとStandard modeをCloudFrontで比べてみる

0
Posted at

はじめに

こんばんは、mirukyです。

CloudFormationのExpress modeは、リソースへ設定を適用した時点でスタック操作を完了します。リソースが利用可能になるまで待つStandard modeとは、完了の意味が異なるんですよね〜。

今回は同じCloudFrontテンプレートを両モードで作成し、CloudFormationがCREATE_COMPLETEを返すまでの秒数と、その時点のCloudFrontの状態をAWS CLIだけで比べてみます。

目次

  1. Express modeの完了条件
  2. ハンズオンの準備
  3. 検証用テンプレートの作成
  4. Standard modeの計測
  5. Express modeの計測
  6. CloudFrontの準備完了を待つ
  7. 計測結果の比較
  8. 後片付け

1. Express modeの完了条件

Standard modeは、リソースがトラフィックを処理できる状態までCloudFormationが待ってから操作を完了します。Express modeはリソースへ設定が適用されると完了し、リソース側の準備はバックグラウンドで続きます。

有効化はテンプレートではなく、作成、更新、削除といった操作単位です。AWS CLIでは--deployment-config 'Mode=EXPRESS'を付けます。

Express modeはロールバックを既定で無効にします。失敗した状態を残して修正しやすくする動作ですが、自動ロールバックが必要なら--deployment-config 'Mode=EXPRESS,DisableRollback=false'と明示します。

2. ハンズオンの準備

AWS CLI v2で認証済みの環境と、cfn-lintを用意してください。操作先のCloudFormationスタックは東京リージョン、CloudFront Distributionはグローバルリソースです。CloudFormationとCloudFrontの作成、参照、削除に必要なIAM権限も使います。

CloudFrontはデータ転送やHTTPリクエストなどで課金されます。今回のDistributionはEnabled: falseで作成し、リクエストは送りません。それでも実行前に料金ページとアカウントの利用状況を確認してください。

既存のAWS設定を変更しないように、リージョンとページャーはこのターミナル内の変数だけで指定します。以降は同じターミナルで続けてください。

# 検証専用の作業場所と固有名を作ります。
START_DIR=$(pwd)
WORK_DIR=$(mktemp -d)
cd "$WORK_DIR"

AWS_REGION=ap-northeast-1
AWS_PAGER=""
RUN_ID=$(date +%Y%m%d%H%M%S)

STANDARD_STACK="qiita-cfn-standard-${RUN_ID}"
EXPRESS_STACK="qiita-cfn-express-${RUN_ID}"

RUN_IDを付けるのは、同じアカウントで動く別の処理や過去のスタックと名前が重ならないようにするためです。

3. 検証用テンプレートの作成

nanoでtemplate.yamlを開きます。

# 新しいテンプレートファイルを開きます。
nano template.yaml

次の内容を貼り付け、Ctrl+O、Enterで保存し、Ctrl+Xで閉じます。配信は無効のままにし、CloudFrontの状態遷移だけを扱います。

# 配信を無効にしたCloudFront Distributionを作ります。
AWSTemplateFormatVersion: "2010-09-09"
Description: Compare CloudFormation standard and express modes with CloudFront

Resources:
  Distribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Comment: Qiita CloudFormation express mode hands-on
        Enabled: false
        Origins:
          - DomainName: example.com
            Id: example-origin
            CustomOriginConfig:
              OriginProtocolPolicy: https-only
        DefaultCacheBehavior:
          AllowedMethods:
            - GET
            - HEAD
          CachedMethods:
            - GET
            - HEAD
          TargetOriginId: example-origin
          ViewerProtocolPolicy: redirect-to-https
          ForwardedValues:
            QueryString: false
            Cookies:
              Forward: none
      Tags:
        - Key: Purpose
          Value: qiita-cfn-express

ローカル検査とAWS側の構文検証を続けて実行します。どちらかがエラーを返した場合は作成へ進まず、行番号とメッセージを基にテンプレートを直してください。

# ローカル検査の後にAWS側でも構文を確認します。
cfn-lint template.yaml

aws cloudformation validate-template \
  --template-body file://template.yaml \
  --region "$AWS_REGION" \
  --query 'Description' \
  --output text \
  --no-cli-pager

成功すると、cfn-lintは何も表示せず、AWS CLIはDescriptionを返します。

Compare CloudFormation standard and express modes with CloudFront

1秒間隔でスタック状態を確認する関数も作ります。AWS CLIの標準waiterは確認間隔が長いため、今回の秒数比較では同じ短い間隔を両モードへ使います。

# 両モードを同じ間隔で計測する関数です。
wait_stack_terminal() {
  local stack_name="$1"
  local stack_status

  while true
  do
    stack_status=$(aws cloudformation describe-stacks \
      --stack-name "$stack_name" \
      --region "$AWS_REGION" \
      --query 'Stacks[0].StackStatus' \
      --output text \
      --no-cli-pager)

    case "$stack_status" in
      *_COMPLETE|*_FAILED)
        printf '%s\n' "$stack_status"
        return
        ;;
    esac

    sleep 1
  done
}

4. Standard modeの計測

最初は--deployment-configを付けず、既定のStandard modeで作成します。開始時刻から終端状態までの秒数を計算します。

# Standard modeで作成時間を計測します。
STANDARD_START=$(date +%s)

aws cloudformation create-stack \
  --stack-name "$STANDARD_STACK" \
  --template-body file://template.yaml \
  --region "$AWS_REGION" \
  --no-cli-pager >/dev/null

STANDARD_STATUS=$(wait_stack_terminal "$STANDARD_STACK")
STANDARD_SECONDS=$(($(date +%s)-STANDARD_START))

printf 'StackStatus=%s\n' "$STANDARD_STATUS"
printf 'ElapsedSeconds=%s\n' "$STANDARD_SECONDS"

if [ "$STANDARD_STATUS" != "CREATE_COMPLETE" ]
then
  printf 'Standard stackの作成に失敗しました。\n' >&2
  exit 1
fi

手元では171秒で完了しました。秒数はリージョンやサービスの状態で変わるので注意ですね。

StackStatus=CREATE_COMPLETE
ElapsedSeconds=171

CloudFormationが作ったDistribution IDを取得し、CloudFront側の状態を確認します。

# Standard modeが完了した時点のCloudFrontを確認します。
STANDARD_DISTRIBUTION_ID=$(aws cloudformation describe-stack-resource \
  --stack-name "$STANDARD_STACK" \
  --logical-resource-id Distribution \
  --region "$AWS_REGION" \
  --query 'StackResourceDetail.PhysicalResourceId' \
  --output text \
  --no-cli-pager)

aws cloudfront get-distribution \
  --id "$STANDARD_DISTRIBUTION_ID" \
  --query 'Distribution.{Status:Status,Enabled:DistributionConfig.Enabled}' \
  --output json \
  --no-cli-pager

Standard modeの完了時点では、CloudFrontもDeployedでした。EnabledはテンプレートどおりFalseです。

{
  "Status": "Deployed",
  "Enabled": false
}

5. Express modeの計測

同じテンプレートへMode=EXPRESSだけを追加します。リソース構成は変えません。

# Express modeで同じテンプレートを作成します。
EXPRESS_START=$(date +%s)

aws cloudformation create-stack \
  --stack-name "$EXPRESS_STACK" \
  --template-body file://template.yaml \
  --deployment-config 'Mode=EXPRESS' \
  --region "$AWS_REGION" \
  --no-cli-pager >/dev/null

EXPRESS_STATUS=$(wait_stack_terminal "$EXPRESS_STACK")
EXPRESS_SECONDS=$(($(date +%s)-EXPRESS_START))

printf 'StackStatus=%s\n' "$EXPRESS_STATUS"
printf 'ElapsedSeconds=%s\n' "$EXPRESS_SECONDS"

if [ "$EXPRESS_STATUS" != "CREATE_COMPLETE" ]
then
  printf 'Express stackの作成に失敗しました。\n' >&2
  exit 1
fi

こちらは62秒でした。Standard modeの171秒に対し、CloudFormationの完了通知まで約2.8倍短い結果です。

StackStatus=CREATE_COMPLETE
ElapsedSeconds=62

適用されたモードとロールバック設定を取得します。

# 適用されたモードとロールバック設定を取得します。
aws cloudformation describe-stacks \
  --stack-name "$EXPRESS_STACK" \
  --region "$AWS_REGION" \
  --query 'Stacks[0].{Mode:DeploymentConfig.Mode,DisableRollback:DisableRollback}' \
  --output json \
  --no-cli-pager

ModeはEXPRESS、DisableRollbackはTrueです。Express modeではロールバックが既定で無効になることも、スタック情報から確認できます。

{
  "Mode": "EXPRESS",
  "DisableRollback": true
}

Standard modeと同じ方法でDistribution IDを取得し、すぐにCloudFrontを確認します。

# Express modeが完了した直後のCloudFrontを確認します。
EXPRESS_DISTRIBUTION_ID=$(aws cloudformation describe-stack-resource \
  --stack-name "$EXPRESS_STACK" \
  --logical-resource-id Distribution \
  --region "$AWS_REGION" \
  --query 'StackResourceDetail.PhysicalResourceId' \
  --output text \
  --no-cli-pager)

aws cloudfront get-distribution \
  --id "$EXPRESS_DISTRIBUTION_ID" \
  --query 'Distribution.{Status:Status,Enabled:DistributionConfig.Enabled}' \
  --output json \
  --no-cli-pager

CloudFormationはCREATE_COMPLETEですが、CloudFrontはInProgressでした。Express modeの完了を、そのままアプリケーションの利用開始合図にしない理由がここにあります。

{
  "Status": "InProgress",
  "Enabled": false
}

6. CloudFrontの準備完了を待つ

CloudFrontを次の処理で使うなら、サービス側の準備完了を別途待ちます。CloudFront用のwaiterを実行し、待機後の状態を再確認します。

# CloudFront自身がDeployedになるまで待ちます。
BACKGROUND_START=$(date +%s)

aws cloudfront wait distribution-deployed \
  --id "$EXPRESS_DISTRIBUTION_ID" \
  --no-cli-pager

BACKGROUND_SECONDS=$(($(date +%s)-BACKGROUND_START))
printf 'BackgroundWaitSeconds=%s\n' "$BACKGROUND_SECONDS"

aws cloudfront get-distribution \
  --id "$EXPRESS_DISTRIBUTION_ID" \
  --query 'Distribution.{Status:Status,Enabled:DistributionConfig.Enabled}' \
  --output json \
  --no-cli-pager

追加で124秒待つとDeployedになりました。Express modeは待ち時間を消すのではなく、CloudFormationの完了通知とリソースの準備完了を分けます。

BackgroundWaitSeconds=124

{
  "Status": "Deployed",
  "Enabled": false
}

7. 計測結果の比較

今回の結果をまとめます。

確認対象 Standard mode Express mode
CloudFormation完了 171秒 62秒
完了直後のCloudFront Deployed InProgress
CloudFrontの追加待機 不要 124秒
既定のロールバック 有効 無効

Express modeは、開発中にCloudFormationの完了通知を手っ取り早く受け取りたい場面へ向きます。一方、デプロイ直後にCloudFrontへ依存する処理を動かすなら、distribution-deployedのようなサービス別の確認が必要です。

今回はOutputsを使っていません。公式ドキュメントでは、リソース属性をOutputsで参照すると、その値を取得できるまでExpress modeでも待つ場合があると説明されています。比較時はテンプレートの出力条件も同じにしてください。

おわりに

ここまでお付き合いいただきありがとうございます。

同じCloudFrontテンプレートでも、Standard modeはDeployedまで待ち、Express modeはInProgressの段階でCloudFormationを完了しました。短くなった待ち時間の先でリソースがどの状態にあるかまで確認して、次の処理を設計する必要があります。

ではまた、お会いしましょう。

参考リンク

AWS公式ドキュメント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?