基盤構築とAMI作成の自動化 (ただいま移行PJ進行中)

某国産クラウドを捨ててAWSに移行するというプロジェクトをやっています。
現在の弊社インフラの状況を眺めてみると、
(僕の知らない、おそらくだいぶ○○な歴史的経緯)でかなり辛いところがあって、
そう遠くないうちに運用が頓挫、破綻するのが目に見えていたので、
移行のタイミングでもうちょっとモダンな運用環境を整備していかねば、と決心しました。
弊社にはインフラ要員が僕だけ(かつ今後も獲得できる見通し薄)なので、

  1. インフラ作業に不要な労力をかけず
  2. 自分自身の壊滅的な記憶力に頼らず
  3. なるべく鮮度の高い状態を維持する

を念頭において、インフラを構築する手段を試行錯誤してます。
メモ書き程度ですが、どんな感じにしているかを書いてみました。

Terraform

AWSマネージドな基盤部分の構成(ネットワーク, ALB, CloudFrontなど)は、Terraformを使うことにしました。
正直言ってこの類のIaCなツールを本格的に使うのは初めてだったんですが、
AWSの管理コンソールでチコチコやらないで済む&自分の記憶に頼らなくて済むのは、
精神衛生にかなり優しい〜というのが感想です。
ただ、全部を全部Terraformで管理するとなると、それはそれで辛いです。
特にサービスの可用性に直接関連し、なおかつ設定値が頻繁に変わる可能性があるようなところの管理は向いてない気がします。
なんか設定値変えようと思ったらリソースの再作成が必要になった、とかなると心が折れそうな気がして...
どこまでTerraformに任せて、どこからは手作業でやるかの匙加減が難しいです。今なお試行錯誤中。

Packer + Ansible

マシンイメージの作成はPacker + Ansibleでやっています。
PackerにはProvisionerって機能があって、Ansibleを利用する(SSH, ローカルともに実行可)Provisionerもあって便利だもんで、
最初はPackerのレポジトリ内にAnsibleのPlaybook(とAMI内に配置する設定ファイル諸々)を同居させてやろうかとやってたんですが、
ユーザ追加とかミドルウェアのアップデートとかを任意のタイミングで走らせたいと考えたときに、
PackerとAnsibleが密に結合しているのは不便だなぁという事に気づき、結局のところこれらのレポジトリを分割しました。 今のところ、どういう流れで構築しているかというと、

  1. Packerのbuilderでベースのインスタンスを立ち上げる
  2. Shell ProvisionerでGit, Ansibleなど最小限のパッケージをインストールする
  3. Shell ProvisionerでAnsibleのレポジトリを落としてきてインスタンス上でansible-playbook 〜を実行する

という形でAMIのビルドを実施しています。
現在の弊社基盤だと、ロールごとにインスタンスの構成が異なるのですが、
それぞれに重複する工程があり(必須ミドルウェアのインストール、ユーザ追加などなど)、
AMIごとに同じ作業を繰り返すのは全く無駄なので、

の2段構えにすることで、AMI再構築時の時間の無駄をなるべく省くような作りにしています。

AMIのテスト

AMIが目論見通り作られているとか、Packer(およびAnsible)の設定変更に伴い不具合が出ていないか、などの確認のため、
Testinfraを使ってインフラテストも自動化しています。
PackerのShell Provisionerを利用してテストケースの入ったレポジトリを持ってきてテスト実行…みたいな感じにしています。
Packer構築のときだけでなく、Ansible実行のときはTestinfraを対で実行させる仕組みを作らないとなー。

不要なAMIのガベージ

AMIのビルドを繰り返すたびに古いイメージが量産されてしまうので、PackerのPost Processorを利用して、
指定された世代数のAMIのみを残して残りは削除する運用にしています。

その他

AMIからインスタンスを作成するときに、ドメイン名とホスト名をタグに入れておくと、
ブート時にRoute53のPrivateHostedZoneに自動的にレコードを登録(して結果をSlackに通知)する仕組みを入れてます。
こういうチマチマした自動化はインパクトあまりないんですが、定形作業と確認が減って、
設定漏れないかなーとか確認漏れないかなーとかそういうことに気を揉まなくて済むようになるのでいいです。

次の目標

CodeBuildを利用して、Ansibleの設定変更をhookして最新のAMIを自動的に作るとか、
週に1回はミドルウェア等々最新化されたAMIを作るとかそういう運用を目指していきたいと思ってます。
ついでにアプリケーションもmasterを自動的にpullしてステージング環境でテスト、
寝てる間にインフラもアプリも完全に構成されテストされてて後は本番を差し替えるだけ…みたいなのが理想なんですが。