AWS CloudFormation の YAML テンプレートを書くためのノウハウ

最近はがっつり AWS の CloudFormation で Infrastructure As Code してた。だいぶ要領を得てきたと思うので、思いつく限りまとめてみる。

YAML で書く

JSON よりも YAML の方が人間に優しい。持論だが JSON と YAML は、HTML と Markdown くらいの差があると思っている。

エディタのパワーに頼る

コードハイライトやアウトラインなど、エディタの力は出来るだけ借りたい。Visual Studio Code 等が使える環境下なら何の問題もないが、そうじゃない場合は適宜設定を頑張る必要がある。これは頑張った方が良い。YAML は割とすぐに何百行となってしまうが、何の力も無いと辛い。

私は秀丸エディタ使いなので、以下その前提で書く。

コードハイライトする

テンプレートが長くなると Key: やら Key: Value といった行がずらりずらりになって見づらくなるので、見易くハイライトしてあげた方が良い。

  • 単一行の Key-Value
  • 複数行の Key-Value の Key
  • 文字定数 "..."
  • コメント # ...

Visual Studio Code 等が使える環境下なら何の問題もないが、そうじゃない場合はハイライト設定を頑張る必要がある。私は秀丸エディタ使いなので自分でハイライト設定をつくった。

設定ファイルは Gist にアップしてみた。

秀丸エディタ YAML 強調定義ファイル

単語補完する

テンプレートをつくる時は !Ref やら !FindInMap やらで(ファイル中に書かれた名前を)指定することが多いので、ファイル内の単語補完が効いていると楽。

秀丸エディタなら以下。

  • ファイルタイプ別の設定 > その他 > 単語補完
  • 単語補完の自動表示
  • 自動表示にチェック入れる、表示方法はリスト

アウトライン(シンボル)を認識させる

エディタによっては関数やクラス単位で目次を表示する機能があるが、これを Key-Value に対して適用できるとすこぶる便利。

リファレンスを読む

テンプレートの書き方はリファレンスが詳しい。

というか how to ... やら ... not working やらでググってもあまり見つからないので、まずは熟読した方が良さそう。

GitHub でコード例を検索する

リファレンス見てもピンとこない場合は、実例を探す。GitHub が役立つ。

まあたまにポンコツコードにぶち上がって「んだよ動かねえじゃん」になるけど。

関連するリソースは近くにまとめて書く

たとえば AWS::EC2::Volume と AWS::EC2::VolumeAttachment とか、AWS::IAM::InstanceProfile と AWS::IAM::Role など、セットで使うリソースは固めて書いた方が見通しが良い。

関連するリソースをコメントで区切る

たとえば以下のように、関連リソースを区切るコメントがあると読みやすい。

  # ======== Instances ======== ★区切り

  # ここに AWS::EC2::Instance の定義がずらずら
  # ...

  # ======== IAM ======== ★区切り

  # ここに AWS::EC2::InstanceProfile やら AWS::IAM::Role やらの定義がずらずら
  # ...

  # ...

このようなコメントを嫌うエンジニアもいるかもしれないけど、テンプレート作成はプログラミングというよりは「リソース XXXX をつくるために XXXX の定義を書く」という感じで「XXXX の定義」単位で書く、探す、修正する、並び替えるゲーになるから、愚直にコメントを工夫して見通しを良くするのが楽だと思う。

わかりづらい定義や設定には適宜コメントを書く

「なんでこんな書き方してるの?」とならないように、読み取れない部分には適宜コメントを入れておく。

例:

  • EBS に DependsOn を付けてアタッチ順をコントロールしているのはなぜか?
  • EBS のデバイス名の命名規則はなぜこのようにしているのか?

Name タグはちゃんと設定する

しばしば管理コンソール上にいろんなリソースが散らばっていて「テンプレートでつくったのどれだ」となっちゃうので、一意に検索できるよう Name タグを入れておく。

私は以下のように「Name タグの Suffix を毎回指定させる」「そしたら projA-vpc-(Suffix) みたいな Name タグがつく」方式にした。

Parameters:
  NameTagSuffix:
    Description: Name tag suffix.
    Default: xxxxx
    Type: String

Resources:
  VPC1:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      InstanceTenancy: default
      Tags:
      - Key: Name
        Value: !Join [ "-", ["projA", "vpc", "Ref":"NameTagSuffix"] ]

たとえば Suffix を stakirantest にすれば、検索時も stakirantest とか stak とかで絞り込める。

AWSCLI でローカルでテンプレート検証できるようにする

書いたテンプレートの検証は、管理コンソールのデザイナーからも行えるが、いちいちコピペするのがだるい。ローカルでコマンド叩いてできた方が楽。

AWS CloudFormation テンプレートの検証をローカルで行えるようにした(AWSCLI使用) - stamemo

バージョン管理する

Infrastructure As Code の恩恵はバージョン管理してこそ。

GitHub や GitLab に入れて管理する。きりのいいところでタグ付けてリリースする。課題は Issue で管理する。

CloudFormation で自動化に取り組む際はちゃんと時間を取る

間違っても「普段忙しいのに加えて」この自動化も頑張る、みたいなことはしちゃいけない。以下のように、やることは意外と多いので、ちゃんとしたテンプレートをつくるのは意外と時間がかかる。

  • YAML の書き方を把握する(手を動かしながら)
  • 自動化したい環境を、どうやってコードで表現するかの考える(管理コンソールでこうなってるのをテンプレートで書くと?の答え探し)
  • 書いたテンプレートが動くかを流して確認(上記規模だと作成も削除も数分くらいかかる)
  • 環境組んだ後の 各サーバーの設定(ログインしてあれこれ)とその後の動作確認
    • ここは手作業
    • ここが本質的に時間かかるならテンプレートの動作確認も結局時間かかる
  • ……

私が取り組んだのは 1-vpc、4-subnet、3-route-table、5-server、6-ebs くらいの規模のテンプレートだったが、これでも丸々一週間近くかかってる。