Developer's Blog

AWS「CloudFormation」で役に立つ Tips

Fenrir Advent Calendar 2016

この記事は「Fenrir Advent Calendar 2016」 の2日目の記事です

こんにちは。エンジニアの友村です。

今年「アマゾン ウェブ サービス」のAPN コンサルティングパートナーに認定され、AWS 上でのシステムの構築・運用に積極的に取り組んでいます。

今回は、AWS を用いた環境構築の観点から特にグッときている「CloudFormation」を用いた環境構築に役立つ Tips を紹介します。

参考: CloudFormation とは?

CloudFormation」とは、テンプレートと呼ばれるファイルを用いて AWS の各種リソースのプロビジョニングを行うことができるサービスです。

テンプレートは「JSON」または「YAML」で記述することができるほか、「CloudFormation Designer」を用いて視覚的にリソースを定義することが出来ます。

結果的にファイルで AWS リソースの構成管理を行うことができるようになり、手順書による環境構築コストの軽減、再利用性の向上など様々なメリットがあります。

Tips

私が「CloudFormation」を使用してきた中で特にグッときた、「役に立つ Tips」を紹介していきます。

「CloudFormation」の使い方やテンプレートの基本的な作成方法は解説いたしませんので、ご了承下さい。

1. ベストプラクティス

公式ドキュメント内に「CloudFormation」を使用するうえでのベストプラクティスが紹介されています。
なにはともあれ、公式に推奨さている事項なので必ず目を通しておきたいドキュメントです。

2. テンプレートスニペット

「CloudFormation」のドキュメントに様々なパターンのテンプレートスニペットが用意されています。
困ったときや、パターン別サンプルとして活用していけばテンプレートを記述していく際の手助けになります。

3. AWS 固有パラメータタイプ

パラメータのタイプを全て「String」にしていませんか?AWS固有パラメータを使用すれば少し幸せになれる時があるかもしれません。

– 「AWS::EC2::KeyPair::KeyName」

  キーペア名の値をドロップダウンで入力をすることが出来ます。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-16-13-44-03

– 「AWS::EC2::Subnet::Id」

  サブネットの ID をドロップダウンで入力することが出来ます。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-11-16-14-04-08

AWS 固有パラメータにつきましてはまだまだ種類がありますのでこちらを参照してみて下さい。

4. 改行を含む文字列の表現

「AWS::EC2::Instance」のプロパティである「UserData」のような複数行に渡る記述は、「Fn::Join」を使用します。

「Fn::Join」はパラメータで区切り記号を受け取ることができるので、「\n」を区切り文字を指定することにより実現できます。

"UserData": { "Fn::Base64": { "Fn::Join": ["\n", [
  "#!/bin/bash -xe",
  "yum update -y",
  "yum install -y httpd"
]]}}

JSON では表現することが難しい改行を含む文字列を、少し分かりやすく表現することができました。

5. 文字列内での変数の置換

文字列内に関数で取得した値を展開して、一つの文字列を作成したい。そんなときは「Fn::Sub」を使用します。

ここでは2パターン紹介します。

– 「論理 ID 指定」

参照したい論理 ID を直接指定することができます。この場合は「Ref」関数を使用した場合の値に置換されます。

{ "Fn::Sub": "www.${DomainName}" }

– 「マッピング方式」

明示的に置き換える値を指定します。

{ "Fn::Sub": [ "www.${Domain}", { "Domain": {"Ref" : "DomainName" }} ]}

「Fn::Sub」は比較的新しい関数で、それまでは「Fn::Join」を用いて文字の連結を行い実現していました。

「AWS::EC2::Instance」のプロパティである「UserData」のような複数行に渡る記述は、可読性を考慮して「Fn::Join」と組み合わせて表現するといいでしょう。

"UserData": { "Fn::Base64": { "Fn::Join": ["\n", [
  "#!/bin/bash -xe",
  "yum update -y",
  { "Fn::Sub": "su - www-data ${InitScriptPath}" }
]]}}

6. DeletionPolicy 属性

デフォルトでは、作成した「Stack」を削除すると設定されたリソースは全て削除されてしまいます。

S3 のバケットや DB のデータなど、「Stack」削除後にも残しておきたいリソースは「DeletionPolicy」を利用してリソースを保持させます。

{
  "ServerLogBucket": {
    "Type": "AWS::S3::Bucket",
    "DeletionPolicy": "Retain"
  }
}

このように、S3 のバケットリソースを保持させるためには「Retain」を指定します。

「Stack」を削除すると「Stack」自身の状態は「Delete_Complete」になりますが、「Retain」が指定された S3 バケットは削除されません。

その他にもスナップショットをサポートするサービスでは、スナップショットの作成を行うこともできるので是非活用してみて下さい。

DeletionPolicy 属性リファレンス

7. テンプレートの分割

AWS CloudFormation のベストプラクティスでも紹介されている、スタックのネストを用いてテンプレートを分割します。

ネストされたスタックを作成するには「AWS::CloudFormation::Stack」リソースを使用します。

{
  "Type": "AWS::CloudFormation::Stack",
  "Properties": {
    "Parameters": "指定したテンプレートに渡すパラメータ",
    "TemplateURL": "S3 に保存されているテンプレートの URL"
  }
}

「AWS::CloudFormation::Stack」プロパティの「TemplateURL」に分割したテンプレートをしめす URL を指定します。

これにより、ネストされたスタックごとに新たにスタックが作成され、テンプレート及びスタックを分割することが出来ます。テンプレートを適切に分割して管理することにより再利用性の高いテンプレートを作成することができるようになります。

注意点としては、分割されたテンプレートは S3 のバケットに保存されている必要があります。

最後に

「CloudFormation」を使いこなせている方からすれば基本的なところだったのではないでしょうか。ある程度の基本を抑えておけば公式ドキュメントを読みながら AWS のリソースをプロビジョニングすることが可能になるはずです。

また、「CloudFormation」からプロビジョニング出来ないサービスもあるので公式ドキュメントとにらめっこしながら進めていくことが重要です。

「CloudFormation」を利用したことが無いという方は、AWS CloudFormation の使用開始というウォークスルーから確認してみてはいかがでしょうか。

参考

CloudFormation ユーザーガイド
フェンリル × AWS

フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!

Copyright © 2018 Fenrir Inc. All rights reserved.