NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

絵で覚える!!! CloudFront Continuous Deployment ~ API 操作編 ~

最近はにわかに寒さが厳しくなってきましたが皆さんいかがお過ごしでしょうか。西です。

さて、前回の記事では Amazon CloudFront (CloudFront) の Continuous Deployment 機能についてご紹介しました。

tech.nri-net.com

今回も引き続き Continuous Deployment についてお伝えしていきます。 Continuous Deployment では検証用の Distribution (Staging) の設定を本番環境に影響を与えることなく確認 / テストすることができ、その設定をそのまま本番環境の Distribution (Primary) の設定として昇格させることもできます。 DNS レコードの操作や Distribution ID /ARN 変更による修正を行わずに動作確認ができ、かつ安全な動作確認の後でデプロイが実現できるとてもありがたい機能です。

とても便利な Continuous Deployment ですが、CLI 経由等の API を使って自動化をしたい場合は要素の紐付きが少しだけ複雑で扱いにクセがあるものになっています。 また、これは CloudFront を API で操作する時全般に言えるかもしれませんが、Continuous Deployment を扱う際も操作時のパラメータがやや厳格に要求されます。

そこで今日は Continuous Deployment を API を扱う際の流れや注意点について、Continuous Deployment のライフサイクルを絵を交えつつご紹介できればと思います。

Continuous Deployment 構成要素おさらい

ここから構成要素だけ取り出すと、以下の図のように 3 つの構成要素から成り立つことがわかります。 Continuous deployment policy を使って、リクエストを適切な Distribution に割り振る構図です。

Continuous Deployment の構成要素

これだけ見れば直感的でとてもシンプルに見えます。

では早速、Continuous Deployment のライフサイクルについても見ていきましょう。

ライフサイクル

では Continuous Deployment の policy 作成から削除までのライフサイクルについて整理していきます。 ここからは絵と共に AWS CLI の対応するコマンドを添えて進めていきますので、実際のデプロイでの利用をイメージしていただければと思います。

Staging distribution と Continuous deployment policy の作成まで

まずは Primary distribution の設定をコピーして Staging distribution を作成します。

aws cloudfront copy-distribution --staging\
--primary-distribution-id {Primary distribution の Distribution ID}\
--if-match {Primary distribution の ETag}\
--caller-reference {リソースを作成するリクエストを一意に識別する値 (ここでは任意の値を設定する)} 

Staging distribution の作成

CopyDistribution API で Distribution が複製できます。 ちなみに、これ以降でも同様なのですが CloudFront の CLI 操作では --if-match オプションと --caller-reference オプションがとても曲者です。

まず --if-match についてです。このオプションは Distribution ID と共にほとんどの API で都度引数に設定せねばならないオプションです。 そして、ここで引数として渡すのは Distribution の ETag と呼ばれる値です。 ETag は Distribution のバージョン識別子なのですが、以降の操作の中で Distribution に変更がかかるたびに更新されるため、都度取得する必要があります。

次に --caller-reference についてです。 これは誤って同一のリクエストを再送信した場合にCloudFrontが重複したリソースを作成するのを防ぐのに利用される値なのですが API によっては引数として渡す必要があり、忘れないようにする必要があります。 API 実行時にたくさんのオプションで適切な値を渡してあげないと Distribution に対する操作ができないのは CloudFront の CLI 操作の難しさではないかと思います。 稼働中の Distribution にどんな値が設定されているかは、いずれも GetDistribution API および GetDistributionConfig API で取得可能です。

さて、脱線しましたが、次に進みます。

次は Primary を複製して作成した Staging の設定を変更したい内容に更新する必要があります。

aws cloudfront update-distribution --id {Staging distribution の Distribution ID}\
--if-match {Staging distribution の ETag}\
--distribution-config file://{staging 用の設定を定義した json ファイル}

Staging distribution の更新

ここで利用する設定用の json ファイルの内容は Distribution の設定を記載する必要があります。 Primary に対して GetDistributionConfig API を実行し、変更したい箇所を手直しして作成するのが良いかと思います。 むしろゼロから生成はつらい。

さて、次はいよいよ Continuous deployment policy を作成していきます。

aws cloudfront create-continuous-deployment-policy --continuous-deployment-policy-config file://{continuous deployment policy の設定を定義した json}

Continuous deployment policy の作成

ここで渡す json ファイルでは Continuous deployment policy の設定を定義します。 作成時には Staging として利用する Distribution の DomainName ({ランダム文字列}.cloudfront.net) が必要なので新しく作成した Distribution のそれを設定しましょう。 Continuous Deployment では Staging へリクエストをルーティングするポリシーを以下の 2 種類のポリシーから選択します。

  • Header-based: 特定のヘッダーが付与されたリクエストを Staging へルーティングするポリシー
  • Weighted-based: 設定した一定の割合のリクエストを Staging へルーティングするポリシー

ここでは Header-based の例を載せます、Distribution そのものの設定と比べればとてもコンパクトです。

{
  "StagingDistributionDnsNames": {
    "Quantity": 1,
    "Items": ["{staging の ドメイン名 (*.cloudfront.net)"]
  },
  "Enabled": true,
  "TrafficConfig": {
    "SingleHeaderConfig": {
      "Header": "aws-cf-cd-staging",
      "Value": "true"
    },
    "Type": "SingleHeader"
  }
}

では作成した Continuous deployment policy を Primary に関連付けます。

aws cloudfront update-distribution --primary-distribution-id {Primary distribution の Distribution ID}\
--if-match {Primary distribution の ETag}\
--distribution-config file://{Continuous deployment policy を関連付ける設定を入れた Primary の設定定義 json ファイル}

Primary distribution に Continuous deployment policy を関連付ける

ここでは Primary の設定定義 json の中の ContinuousDeploymentPolicyId というキーに作成した Continuous deployment policy の ID を記載して Primary を更新します。

これで Staging に対して動作確認を実施できる状態となります。 今回の紹介内容では Header-based の例を挙げましたので、CloudFront の CNAME に対して設定した Header と値を付与して curl 等でリクエストを実行すれば動作確認が可能です。 想定通りの挙動が確認できればいよいよ Staging の設定を Primary の設定に Promote (昇格) させます。

aws cloudfront update-distribution-with-staging-config  --id ${Primary distribution の Distribution ID}\
--staging-distribution-id ${Staging distribution の Distribution ID}\
--if-match '${Primary distribution の ETag}, ${Staging distribution の ETag}'

Staging の設定を Primary の設定として Promote (昇格) させる

Primary と Staging の Distribution ID を一緒に使って専用の API である UpdateDistributionWithStagingConfig を利用します。 かなり変則的なコマンド操作ですね。 最後の --if-match の引数はクォーテーションで包むことを忘れないようにして下さい。

Staging distribution の Promote (昇格) から後掃除まで

さて、ここまでで Staging の動作確認と Promote までを紹介しました。

Staging の設定を Primary に反映したところですので、次は要らなくなった Staging や continuous deployment policy の削除を考えていきましょう。 というわけでここからは、後掃除として Promote 後の Staging と Continuous deployment policy の削除までの流れをご紹介をしていきます。 実はここまでのコマンドは公式ドキュメントでも紹介されているのですが、2023 年 11 月現在ではここから先の削除手順は同ページでは見つけられませんでした。

docs.aws.amazon.com

Staging と Continuous deployment policy の削除は自分で触っている中で少々の試行錯誤を繰り返した点なので、その辺りの点を中心にお伝えしていこうと思います。

後掃除ですが、直感的には「Staging や Continuous deployment policy の削除用 API を実行して終わりじゃん」と思われるのではないでしょうか。 少なくとも僕はそう思っていましたが、話はそう簡単ではなく一手間挟まないといけない仕様でした。

いきなり Continuous deployment poilicy の削除を行おうとすると「Primary にて利用されています」という旨のエラーとなります。 よって、リソース間依存の都合でまずは Primary から Continuous deployment policy の関連付けを外すところから始めなければなりません。

aws cloudfront update-distribution --primary-distribution-id {Primary distribution の Distribution ID}\
--if-match {Primary distribution の ETag}\
--distribution-config file://{Continuous deployment policy の関連付けを外した Primary の設定定義 json ファイル}

Primary distribution から Continuous deployment policy の関連付けを外す

今度は先のステップで設定した ContinuousDeploymentPolicyId の値を "" のように空に設定して更新をかける必要があります。 ここでも適切な ETag を取得して引数に渡すことを忘れないで下さい。

さて、 Primary からの 関連付けも外せたのでいよいよ Continuous deployment policy を削除......できません!!!

先に Continuous deployment policy そのものを Disabled 状態にしないと「Staging で利用されています」という旨のエラーとなります。 ということで

  • Primary からは関連付けを外す
  • Staging だけに関連付いている状態でも Disabled 状態にせねばならない

となっており、関係している Distribution との連結を完全に切る / 機能しない状態にしないと削除できないようです。 ここでもリソース間の依存が厳密にチェックされるようですね。 というわけで Continuous deployment policy を Disabled 状態にします。

aws cloudfront update-continuous-deployment-policy
--id ${Continuous deployment policy ID}\
--if-match {Continuous deployment policy の ETag}\
--continuous-deployment-policy-config file://{Continuous deployment policy config の "Enabled" の値を false に設定した json ファイル}

Continuous deployment policy を Disabled 状態にする

ここまでくればようやく終わりが見えてきます、Continuous deployment policy を削除しましょう。

aws cloudfront delete-continuous-deployment-policy
--id ${Continuous deployment policy ID}\
--if-match {Continuous deployment policy の ETag}

Continuous deployment policy の削除

あとは Staging を Disabled にして Delete するだけです、険しい道のりでした。 まずは Disabled 状態にしましょう。

aws cloudfront update-distribution
--staging-distribution-id ${Staging distribution の Distribution ID}\
--if-match ${Staging distribution の ETag}
--distribution-config file://{Staging の設定中の "Enabled" を false に設定し、Continuous deployment policy の関連付けを外した json ファイル}

Staging distribution を Disabled 状態にする

Disabled になることを確認したらそのまま Delete Distribution API まで進めます。

aws cloudfront delete-distribution
--staging-distribution-id ${Staging distribution の Distribution ID}\
--if-match ${Staging distribution の ETag}

Staging distribution の削除

これにて Continuous Deployment の Policy 誕生から削除までのライフサイクルが終了します。 正直、この記事を書いていて「今どこまで進んだっけ」となるほどには (ちょっとだけですが) 長く複雑でした。 とはいえ、関連リソース削除に少しクセがあるだけで安全かつシームレスにデプロイが可能な点は変わらず Continuous Deployment の大きなメリットです。 せっかくの便利な機能なので後掃除するところまで使いこなしていきたいですね。

おわりに

本稿では Continuous Deployment を API (CLI) で操作するケースについて、当該コマンドとリソース状態を示した図を使ってご紹介しました。 CLI 部分は SDK など、より利用しやすい形式で応用することも可能です。 前回の記事でもお伝えした通り Continuous Deployment はせっかくの便利な機能なので、今回お伝えした注意点を考慮しつつ自動化してお手軽に活用していきたいですね。 皆さんのシステム開発において、Continuous Deployment の持つメリットを活かすための一助になれれば嬉しいです。

執筆者: 西 洋平


AWS メインのクラウドエンジニア。
ソースコードより文章書く方が好きです。
2023 Japan AWS Jr. Champion / 2023 Japan AWS All Certifications Engineer