AWS CloudFormation 雑感

AWS CloudFormation(以下CloudFormation)は、AWS上でInfrastructure as Code(以下IaC)を実現する為にAWSが提供しているソリューション。
競合するプロダクトとしてはHashiCorpが提供しているTerraformが有名だと思う。

AWSでIaCしたい。となった場合どちらかが候補になることが多いと思う。
今回初めてCloudFormationを初めて書いたので特徴や雑感などを書いておく。
Terraformまだ未経験なので比較などはできていない。

ベンダーロックイン

CloudFormationとTerraformの一番の違いはこれになるだろう。
CloudFormationは、当然AWSに最適化されAWSにのみ適応可能なツール。
それに対してTerraformはサードパーティらしくAWS,GCP,Azureなどのクラウドサービスに対応している。

AWS以外の選択肢が存在するならばTerraformを選択するのが無難だろう。

AWS CloudFormation コンソール(GUI)の設定可能

CloudFormationではMetadataセクションが存在しておりその中にAWS::CloudFormation::Interfaceというグループを設定できる。
これはWebブラウザから操作するAWS CloudFormation コンソール上での振舞いを定義するグループで、
主にスタックのパラメータをCloudFormation コンソールから設定するときの表示順、ラベル名を設定することができる。

これを実現できることこそ、クラウドベンダーがIaCツールをリリースしていることの(ベンダー側の)利点であると思う。
個人的にはこの概念を理解するまでに多少の混乱があった。わざわざIaCをしてCUIベースに移行できたのにGUIにも関連を持つの?と
ちょっと理解した状態だとClougFormation コンソールでパラメータを設定する場合には、確かに設定されていたほうが優しいかもな?と少し思うときもある。

リソース作成後コード生成可能

正確に言うとこれはCloudFormationに限った話ではない。
というのも、以前AWSはCloudFormerという作成済みのリソースからCloudFormationのコードを生成するツールをβ版として公開していた。
だが、今利用しようとするとそもそも利用可能なテンプレートにCloudFormerが見当たらなかった。

Q: 永遠にベータのCloudFormerはいつアップデートされるんですか?
A: よく聞いてくれたね笑 残念ながらCloudFormarがこれからアップデートされることはありません。サードパーティ製のFormer2というWebベースのサービスがあるのですが、これが非常によくできているのでそれを使ってください。

[レポート]What’s New in AWS CloudFormation #reinvent #DOP408 | Developers.IO

公式なリリースは見つけられなかったがこういう記事も目に入ってきたのでFormer2を利用するというのが良いのだろう。
そのFormer2は当然CloudFormationのコードを生成することもできるし、Terraformのコードを生成することもできる。

その為、前述のベンダーロックインについてもそんなにリスクにはならないのではないだろうか(CloudFormationで作ったリソースのコードをFormer2でTerraformで吐けばよさそう)。

Ansibleを使ったとき自分が感じていたのは、基本的にコードが元で生成物がリソースという図式で、それが頭にこびりついていたので先にリソース作ってから生成可能という概念を頭に取り込めたのは収穫。

全リソースには対応していない

これはちょっと残念。遭遇した部分でいうとFormer2で生成したコードをCloudFormationにする際はインポートを行う。
既存のリソースとCloudFormationのスタックを関連づける物だが、このインポート時に関連づけたいリソースに非対応のものがあった。
Former2はそこのサポートもしてくれていて、対応リソースのみコード生成してくれるのはとても良い...(親切に対応してないから生成しませんでしたと注意もしてくれる)
が、非対応なリソースもあることが頭にないと少し戸惑うかもしれない。

まとめ

まず大前提として、IaCできていたほうがいいことは間違い無いと思っている。
その上で、TerraformではなくCloudFormationを選択することについては別に二者択一なわけではないのであまり気にしなくて良いかなと思う。

Alpine LinuxではAWS CLI v2は使用できない

原因は、下記参考サイトの通りでAWS CLI v2は「glibc」を必要とするが、Alpine Linuxでは「musl libc」を使用しており「musl libc」ではAWS CLI v2が動作しないということでした。

参考サイト

様々な理由があって「ruby:2.2-alpine」を使っていて、試しに参考サイトからリンクのあったStack Overflowの対応は行ってみましたが
glibc-binで失敗したので断念しました。Alpineに拘る必要は特になかったのでDebianのイメージに変更しました。

Amazon ECSでのFarGate設定について簡単にまとめておく

Amazon ECS(以下ECS)は、AWS上で展開されているコンテナオーケストレーションサービス。
コンテナを動作させる為の選択肢としてEC2とFarGateが用意されているが今回はFarGateの話。

ただ、基本的にECS上の設定を変更すればEC2とFarGateで同じコンテナを使って動作させることもできる。

Amazon ECR

ECSでは、コンテナレジストリからコンテナイメージのPullを行って動作させる。
その為、コンテナレジストリが必要なるがAWSではAmazon ECR(以下ECR)というレジストリを用意している。
ECRはECSに統合されている為、ECRにイメージをPushしておけば簡単にECSからイメージを利用できる。

手元のマシンからECRへイメージをPushする方法については下記ドキュメント
https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html

AWS CLIを使った方法で前半はAWS CLIのセットアップ。あとはDockerイメージをビルドして、タグをつけて、Pushするだけ。

Amazon ECS

ECSでは大きく3つのリソースをセットアップすることになる。

  1. クラスター
  2. タスク定義
  3. サービス
クラスター

クラスターはFarGate用とEC2用で作成する際に必要なパラメータがとても異なる。
EC2クラスターはEC2を使用するのでEC2の設定が必要になる。例えばインスタンスタイプとかだ。
それに対してFarGateは配置するVPCを選択or作成するだけで完了する。

タスク定義

ECSでコンテナを実行するにはタスクを実行する必要がある。そのタスクの定義を行うのがタスク定義。

  • タスク名
  • 実行ロール
  • ネットワークモード
  • タスクメモリ
  • タスクCPU
  • コンテナ定義
  • ボリューム

などの設定を行う。
注意すべき点としてはFarGateではネットワークモードがawsvpc固定となる。
EC2の場合はbridgeなどいくつか選択肢が与えられ選択することができる。

awsvpcはタスクごとにENI(Elastic Network Interface)を割り当てて通信を行うもの。
各タスクごとに独立したネットワークインターフェースを持つということ。

その為、ネットワークモードがawsvpcのタスク定義を実行する場合には実行するVPCとサブネット、セキュリティグループの指定が必要になる。

もう1つパブリックIPを付与するかどうかの設定がある。
自分はよく忘れがちでCannotPullContainerErrorを出しがちなのだが、ECRからコンテナイメージをPullするにはパブリックIPが必要なる為それを意識して設定すること。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ecs-pull-container-api-error-ecr/

コンテナの定義では主に下記を設定する。

  • イメージURI
  • ポートマッピング
  • 環境変数
  • ストレージ

docker-composeを触っていれば何を指しているかはすぐイメージできると思う。
環境変数については直接値を記述することもできるしAWS Systems Manager パラメータストアから値を参照することもできる。

ボリュームを設定する場合は
タスク定義でボリュームの設定をしてから、コンテナ定義でマウントを設定する必要があることは注意したい。

サービス

タスク定義を作ったらタスク実行することができるようになる。
タスクをただ実行することももちろんできるが、主に永続的に動作させることが目的のタスクの場合はサービスを併用する。

大雑把に言えばタスクとロードバランサーを関連づけるのがサービスという理解でいいのではないだろうか。

有効なサービスでタスクの数が1に設定されているならば、常に1つタスクが実行される状態になる。
例えばタスクを故意に終了してもサービスがタスク数が1に保たれるよう働く為新しいタスクが立ち上げられやがて1つのタスクが動作する状態に戻る。

まとめ

用語がたくさんでてくるがECSにおいてはクラスター、タスク定義、サービスがそれぞれ何を担っているかを理解できれば容易に扱うことができるようになると思う。