AWSで最初からCloudFormationでインフラを管理する方法を考えてみる
AWSで最初からCloudFormationを使ってインフラを管理していく方法について考えてみました。
個人でサービスを作ろうと思い、あまりお金もかけたくなかったのでサービス選定は
項 | サービス名 |
---|---|
クラウドサービス | AWS |
ソースコード管理 | Bitbucket |
CI/CD | CircleCI |
といった感じです。
参考にしたサイトです。
CloudFormation と CI の組み合わせをする上で必要な物
- IAMユーザー
- S3 Bucket
今回だとCircleCIからAWSへアクセスする為のIAMユーザーが必要になります。
また、CloudFormationのテンプレートを分割して管理する場合は、S3 Bucketも必要になります。
導入手順
先に今回の内容をコード化したものがコチラです。 github.com
導入手順としては
- 全サービスにアクセスできるIAMユーザーを作る
- 自分が作成したいサービス向けのIAMユーザーを作る
という流れにしようと思いました。
悩ましいのが、どうしても最初はWebのAWSコンソールからIAMユーザーとS3 bucketの作成が必要になることでした。
いろいろ考えて納得できる方法としては
- 手作業でAWSコンソールのCloudFormationから
setup/cfn.template.yml
を指定して awscli 用のIAMとCloudFormationのテンプレートを一時的に置くS3 bucket を作成します。 - 作成されたIAMユーザーのkey, secretを作成してAWS CLIにアカウントをセットアップします。
- AWS CLI でcloudformationのスタックを作成して新規作成するサービス向けのインフラを構築するための準備をします。
という手順です。
- の作成に使うテンプレートだけは別管理にした方がわかりやすいかなと思いました。
CloudFormationのスタックが2つに分かれてしまいますが、管理しやすくて良いかなと思いました。
- スタック1(setupディレクトリ配下)
- awscli用のIAMユーザーとテンプレートなどを保存するためのs3 bucketを管理するテンプレート
- スタック2(srcディレクトリ配下)
- 各サービスを管理するためのユーザーを管理するテンプレート
の形にCloudFormationのスタックを分けることでができるので良いかなと思いました。
理想としては1つのスタックで完結させたいです。
ディレクトリツリーで見るとこんな感じです。
要は全てのIAMを src/iam.template.yml
で管理したいです。
├── src │ ├── bucket.template.yml │ ├── cfn.template.yml │ └── iam.template.yml
ですが、 最初はWebのAWSコンソールからIAMユーザーとS3 bucketの作成 をしないといけないので
├── setup │ └── cfn.template.yml ├── src │ ├── bucket.template.yml │ ├── cfn.template.yml │ └── iam.template.yml
と分け
├── setup │ └── cfn.template.yml
ここで、最初のユーザーを管理します。
AWS CLI からのスタック作成について
デプロイするテンプレートは管理しやすくするために分割してます。
├── src │ ├── cfn.template.yml │ └── iam.template.yml
実際のところは下の様に実行すればCloudFormationで実行可能なテンプレートを作成することができる。
$ aws cloudformation package \ --template-file src/cfn.template.yml \ --s3-bucket artifact \ --output-template-file .cfn/packaged.yml \ --s3-prefix template
このコマンドでしていることは、 --s3-bucket
で指定したバケットの --s3-prefix
で指定したディレクトリ配下に src/cfn.template.yml
以外のテンプレートファイルをアップロードします。
--output-template-file .cfn/packaged.yml
で指定している部分に出力されるファイルは、 src/cfn.template.yml
の参照している他テンプレートファイルを指定するパスが追加されています。
TemplateURL: /path/to/bucket/fc2e4965584e9309b667bf9a6c1eb6f4.template
の様な物が追加されています。
.cfn/packaged.yml
が作成されたら、create-stack
や update-stack
を使って更新していきます。
ここまでやるとiam.template.yml
で作成したIAMユーザーをCircleCIに設定することで自動更新ができるようになります。
あとは、新しく作りたいサービスがでたらそのサービス向けに権限を絞ったIAMユーザーを作ることができます。 そうすることで、CIなどを使った際に誤操作で別サービスのデータを消してしまうなどが防げるのではないかと思いました。
課題
今回の構成で自動デプロイできるようにはなってますが、課題もあります。
update-stack
実行後のCloudFormationの状態を監視していないのでCircleCIでは Success になるが CloudFormation では失敗してロールバックする可能性がある- 連続でデプロイしたとき、現在のスタックの状態を確認していないため、スタックが更新中の場合不具合が起きる可能性がある
備考
テンプレートの検証に cfn-lint
を使っていて気づいたけど、 Type: AWS::CloudFormation::Stack
を使ってテンプレートを分けた場合は、子テンプレートまでチェックしてくれるわけではないみたい。
あくまで引数に渡したテンプレートファイル単体のテストをしてくれるツールみたい