はじめに

本技術ブログは、さまざまな小規模ウェブサービスのインフラを構築できるTerraformスクリプトを試作した経験をまとめたものです。Terraformスクリプトを作成される方への参考を目的にしています。

要約

  • さまざまな小規模ウェブサービスのインフラを構築するというコンセプトを決めた
  • 独自概念”Component”を導入しこれの組み合わせでインフラを構築した
  • Componentの実装や管理で改善の必要はあるがおおむねコンセプトを実現できた

想定読者

Terraformの基礎的な使い方を把握されている方を想定しています。

以下は本ブログの範囲外とします。

背景

2019年度に行ったスタートアップとのサービス開発でいくつか課題が挙がりました。 その課題解決策の1つに、Infrastructure as Code(IaC)を採用する、がありました。

IaC作成ツールにはデファクトスタンダードとなっているTerraformを利用することはすぐに決まりました。今後のスタートアップとのサービス開発を想定すると、各サービス向けの専用のインフラコードを書くのではなく、さまざまなインフラを構築できる汎用的なコードを書くと開発効率があがります。これを試作のコンセプトにしました。このコードで実現したいインフラの初回の目標としてよくある小さいウェブサービスにしました。

ウェブサービスサンプルインフラ図

クラウドやTerraformの開発経験が少ない方でもインフラを素早く構築できれば、クラウドやTerraformの学習コストの工数が抑えられるだろうと思い、コンセプトに追加しました。

コンセプト

背景をもとに、試作で実現したいコンセプトを以下にしました。

  1. さまざまな小規模ウェブサービスのインフラを構築できる
  2. クラウドやTerraformの開発経験が少なくてもインフラを素早く構築できる

設計

独自概念 “Component”

ResourceとModuleを組み合わせ、ある特定機能を提供するものを”Component”とし、これらが互いに依存関係を持つように設計しました。下記にComponentの一部例を紹介します。図中の青線内が対象のComponentを表します。青線外のものは対象のComponentが依存している他のComponentを表します。

Component名 説明 依存関係
network component AWS VPC, VPC NAT, Public subnet, Private subnetを構築します 他Componentへの依存はありません
alb component Application Load Balancer(alb)機能を提供します network componentに依存します
ecs component AWS ECS機能を提供します alb componentに依存します
ssh_key component 公開鍵情報をAWSへ格納します 他Componentへの依存はありません
ecs_on_ec2 component auto scalingで管理されるEC2上でECSコンテナーを動作させます network component, alb component, ecs component, ssh_key componentに依存します

このComponent群を組み合わせてインフラを構築できるように設計しました。 あるComponentを選択すると、それに必要な他のComponentが依存関係から明らかになるので、インフラ設計の助けになります。しかし、依存関係が構築できるインフラの種類を制限します。依存関係に関する課題については後述します。

Componentをstateの単位にする

Terraformを使ったインフラ運用で、インフラ全体でstateファイルを1つにすることがあります。こうすると、インフラのごく一部の変更であったとしてもインフラ全体の状態がチェックされます。チェック時間はチェックの対象数に比例するため、インフラ全体のチェックは一般的に時間がかかります。Componentの組み合わせでインフラを構築する本試作では、Componentがstateの単位になることでチェック時間が短くなります。しかし、これには課題もあり対策が必要でした。課題と対策については後述します。

Componentの課題

Componentの依存関係の課題

コンセプトにあるユーザーが素早くインフラを構築できることを優先した結果、Component同士の依存関係をあらかじめ固定する必要がありました。
たとえばecs_on_ec2 componentはalb componentに依存します。これを依存する・しないを選べるようにできればインフラの構築できるパターンが増えます。しかし、このような選択を行えるComponentの実装をTerraformスクリプトで実現できませんでした。
回避的な実装として、alb componentに依存するecs_on_ec2 componentと依存しないecs_on_ec2 componentを用意する方法があります。 けれども、この方法では似たようなComponentをいくつも実装する必要があります。その結果、ユーザーがインフラ構築時に数多くのComponentを選択することが必要になってしまいます。
以上のことより、コンセプトを満たすようComponent同士の依存関係をあらかじめ固定しました。

Componentの更新の伝搬を明示的に行う必要がある

Terraformではインフラ更新時に、コンフィギュレーションとtfstateをチェックして差分を検出し、変更する予定の箇所とします。この箇所を参照している他の箇所も検出し、変更する予定の箇所として追加します。さらにこの追加された箇所を参照している他の箇所も検出し…と再帰的に変更する箇所を検出します。このようにして最終的に変更するすべての箇所を決定します。
インフラをComponent単位のtfstateを分割すると、このような変更点の再帰的な検知ができません。そのため、これに対処するスクリプトを用意することにしました。

検証

コンセプトをもとに試作を実装しました。
試作を検証するため、こちらで用意したサンプル手順をテストユーザーに実行していただいて、インフラを構築していただきました。おおむねスムーズに構築されていました。
テストユーザーのみなさまは、コンセプトやこれを実現するための独自概念のComponentの必要性を納得いただけました。しかし、このComponentの管理についてはシェルスクリプトを用いており、この管理が煩雑であるという意見を多くいただきました。実装者の私自身も感じており、改善の必要な点としました。

本試作を実プロジェクトで使用

本試作を社内プロジェクトで利用していただく機会がありました。 社内プロジェクトで構築したインフラは下図です。

このインフラではウェブサービスサンプルインフラとは違う点がいくつかあります。 ECSコンテナーを稼働させるEC2とは別のEC2が稼働しています。このEC2へデータを投入するためのサービスがいくつか稼働しています。また、EC2へのSSH踏み台(bastion)サーバーを用意しています。

社内プロジェクトの担当者は、AWSの経験はありましたがTerraformは未経験でした。担当者が試作を利用してインフラを構築していく途中で、Componentに渡す設定の変更だけでは対処できない、Componentの実装の変更が必要になる場面がありました。今回の試作では、コンセプトの実証を優先してComponentの実装方法をユーザーに提供しませんでしたが、次の試作の際にはユーザーが簡単にComponentを実装できる手段の提供の必要性を感じました。
構築を終えた担当者から次の評価を頂きました。マイナス評価点は、テストユーザーでの検証でもありました、シェルスクリプトによるComponentの管理が煩雑である点でした。 プラス評価点は、Terraformの学習やTerraformスクリプトとコンフィグレーションを1から用意するよりずいぶん楽にインフラを構築できた、という点でした。
本試作の結果は、課題点がいくつか残りましたがコンセプトをおおむね実現できました。

まとめ

背景からコンセプトを決め、これを実現するための独自概念”Component”を試作しました。

一部に課題が残りましたがインフラ構築を素早く行う方法の1つを実証できました。
この試作の改善の必要な点は、ユーザーがComponentを簡単に実装・管理できることです。次の試作の時にはこの実現を目指します。

今後は、今回の試作で得た知見を他プロジェクトで活かしていく予定です。


本コンテンツはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。