
Terraform Cloudを活用したECSデプロイとインフラ管理の実践
の2日目の記事です。
はじめに
こんにちは、Hubble の SRE エンジニアの佐藤慎吾です。
今回は、私たちの会社で行っているインフラの管理とアプリケーションのデプロイ方法について紹介します。
Terraform と Terraform Cloud を活用し、シンプルで透過性の高いデプロイを実現しています。
Hubble では、インフラ管理の効率的に安全に進めるために、
Terraform と Terraform Cloud を使用しています。
特に、コンテナのオーケストレーションツールには AWS の
ECS(Elastic Container Service)
を利用しており、ECS のタスク定義やサービス自体も Terraform で管理しています。
デプロイの流れ
デプロイプロセスは以下の手順で行っています。
GitHub Actions で変更を検知:リポジトリに変更が加わると、自動的にワークフローがトリガーされます。
Docker イメージのビルドと Push:変更内容を反映した Docker イメージをビルドし、AWS の**ECR(Elastic Container Registry)**に Push します。
Terraform Cloud の変数更新:Terraform Cloud の API を使用して、該当するワークスペースの変数 image_tag を新しい Docker イメージのタグに更新します。
Terraform Apply の実行:Terraform Cloud で terraform apply を実行し、ECS のタスク定義を新しい Docker イメージで更新します。
ポイント
image_tag を variables として管理
ECS のタスク定義で使用する Docker イメージのタグを variables として管理することで、その値を変えて、Terraform Apply するだけで、簡単にアプリのバージョンの更新ができます。
Terraform Cloud の活用
Terraform Cloud の API とワークスペースを活用し、自動化されたデプロイフローを構築しています。
ワークスペースの分離
ワークスペースを分離することで、ECS 関連の変更のみを迅速に適用でき、デプロイ時間を短縮できます。
ワークスペースの分離
デプロイに関しては Terraform Cloud で、以下の 2 つのワークスペースを用意しています。
アプリを動かす上で必要な前提リソース用のワークスペース
VPC、データベース、サブネット、セキュリティグループなどのインフラリソースを管理。
デプロイ時に必要な情報は output で出力しておき、ECS 関連のワークスペースでtfe_outputsを使って取得します。
ECS 関連のデプロイ時のみ必要なリソース用のワークスペース
ECS のタスク定義や ECS サービス等を管理。
なぜ分離するのか
ワークスペースを分離することで、以下のメリットがあります。
複雑な条件分岐の排除
Terraform コードがシンプルになり、可読性と保守性が向上します。ワークスペースを一緒にしていると、条件分岐が必須になったり、アプリの実態がない(イメージがない)にもかかわらず、タスク定義やサービス等を定義せねばならない場合もあり、直感的ではなくなります。可読性も下がると考えています。ただし、まずアプリがあって、インフラはそのアプリのためのものであるという思想の場合は、まず先行してイメージがビルドされていると思うので、その場合はワークスペースを分離せずにまとめても、条件分岐等が発生することはなく、自然に管理できるかもしれません。
デプロイ速度の向上
ECS 関連の変更のみを迅速に適用でき、デプロイ時間を短縮できます。Terraform Plan / Apply はリソースが増えれば増えるほど時間がかかるため、ワークスペースを分離することで、ECS 関連のリソースのみを管理することができ、デプロイ時間を短縮できます。
安全性の確保
重要なインフラリソースへの影響を最小限に抑えることができます。
そもそも、なぜ Terraform でタスク定義や ECS を管理するのか
メリット
下記のようなメリットがあると考えています。
Terraform と Terraform Cloud を組み合わせて使うことにより、圧倒的に簡単にデプロイの自動化が実現できる。
デプロイ前に data block を使って、依存関係にあるリソースの存在チェックが簡単にできる。
ほぼ全ての AWS 関連のリソースを Terraform で管理できるという一貫性のあるインフラ管理ができる。
module 化すれば、似たようなタスク定義やサービスを作る時に、簡単に構築できる。for_each で大量生産も可能。
デメリット
下記のようなデメリットがあると考えています。
複雑なデプロイ手法に対応できない。
Terraform で ECS サービスを更新する場合、必然的にローリングアップデートになる。
Terraform でテクニカルなことをやろうとすると、コードが複雑になる。
同時実行数に制限があり、デプロイが始まるまでに時間がかかる可能性がある。
Terraform Cloud の有料プランは、同時に Plan や Apply できるワークスペースの上限数が決まっています。(Enterprise プランではその限りではないと思うが)そのため、デプロイ対象のサービスやデプロイ回数が多いような組織では、適していない可能性がある。
対して、AWS CodePipeline 等の CICD に特化したサービスはスケーラビリティが高いので、その点は気にならない。
さいごに
今回は、Terraform と Terraform Cloud を活用した ECS デプロイとインフラ管理の実践について紹介しました。
これが最適だとは限らないので、あくまで参考程度にしていただければ幸いです。
技術とは関係ないですが、僕の84歳のおばあちゃんが、
Microsoft Surfaceでイラスト描いて、LINEスタンプとしてリリースしているので、
よければチェックしてみてください。
また、Hubbleでは、一緒に働く仲間を絶賛募集中です!
気になる方は採用情報をチェックチェック!
明日のHubbleのQiita Advent Calendarの記事を担当するのは
バックエンドエンジニアのoaktomeさんです!