みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

Terraform: Up and Running を読了した

読んで重要だと感じた内容を列挙します.

サンプルなどソースコードは,以下のレポジトリに MIT license で公開されています.

GitHub - brikis98/terraform-up-and-running-code: Code samples for the book "Terraform: Up & Running" by Yevgeniy Brikman

1. Why Terraform

Terraformの特徴は以下の通り.

  • provisioning tool (状態を監視する)
  • declarative language (宣言型言語,何度実行しても同じ結果になる) (対義語: procedural language)
  • Masterless (master server が不要)
  • Agentless (監視対象にagentをインストールしなくてよい)
  • 比較的新しい言語

必要なリソースを.tfファイルに記述していくだけで管理をすべてやってくれる便利なソフトウェアである.テキストファイルなので,gitなどバージョン管理システムでインフラストラクチャの構成を管理できる.

2. Getting Started with Terraform

terraformはGo言語で記述されているので,コンパイル済みのバイナリ実行ファイルをダウンロードするだけで使用可能.

大まかに使うコマンドはinitplanapplydestroy の流れ.

3. How to Manage Terraform State

サーバーの状態を記述したtfstateファイル (JSON形式) をbackendで指定した場所に保存する.

ローカルファイルの場合は複数人で使用するのが困難なので,Amazon S3などに保存しておくとよい.

中身にはパスワードなどの機密情報が平文で記載される可能性があるので,扱いに注意する.

本番環境とテスト環境など,環境を分ける場合はworkspacesを使用してもよいが,ディレクトリやプロジェクトなどで分割するほうがよい.

tfstateな直接編集しないこと.代わりにstateimportを使用する.

4. How to Create Reusable Infrastructure with Terraform Modules

汎用のプログラム言語における関数に相当するterraformの機能がmoduleである.

通常の.tfファイルと同様,variable (関数の引数),resource (関数本体),output (関数の返り値) を使用した一連の.tfファイルを同じディレクトリに保存しておけばmoduleと認識される.関数内部で使用するだけの変数はlocals で定義する.これらを外部から使用するには,moduleを使用する.

inline block を使用してもよいが,リソースは別に記述したほうが変更しやすい.

5. Terraform Tips and Tricks: Loops, If-Statements, Deployment, and Gotchas

  • count: resourceやmoduleを繰り返すために使用する.
  • for_each: resource,inline block,moduleを繰り返すために使用する.
  • for expression: listやmapを繰り返すために使用する.
  • for string derective: 文字列の中のloopやmapを繰り返すために使用する.

countの場合は,リソースの識別がインデックスになるので,意図しないリソースが削除される場合があるので,なるべくfor_eachを使用するのが直感的な動作となる.

zero-downtime deploymentを実現するために,lifecyclecreate_before_destroy に設定するなど工夫することも可能ではあるが,そもそもAWS には instance refresh という機能があるので,こちらを使用するのがよい.

汎用的なプログラム言語ではリファクタリングは簡単だが,terraform の場合は変数名を変更したり,名前を変えるだけでリソースが意図せず編集されてしまう場合があるので,注意する.

6. Managing Secrets with Terraform

データベースのパスワードなどの機密情報を平文で保存してはいけない.バージョン管理システムに直接書いてはいけない.

機密情報の種類が,インフラストラクチャ,個人,顧客,のどれなのかを判断して,適切なサービスを使用する.

インフラストラクチャならば,HashiCorp Vault, AWS Secrets Manager, Google Secrets Manager, git-secretなどを使用する.

個人情報ならば,LastPassMacOS keychainWindows Credential Managerなどを使用する.

顧客情報ならば,顧客のパスワードはハッシュ値を保存するか,Auth0Active Directory などを使用する.

terraform を使用するには,ユーザーならばAWS access key, secret access key を環境変数に設定し,ツールならばIAM rolesを設定する.

GitHub Actionsならば,Open ID Connect (OIDC) を利用した認証が可能であり,便利である.

このように適切なしくみで機密情報を管理したとしても,Terraform state ファイルや plan ファイルには機密情報が平文で保存されてしまう.暗号化に対応したクラウドストレージ (S3, GCSなど) に保存するのが次善策だが,未だに適切な答えば出ていない.

7. Working with Multiple Providers

  • Core: Terraform の本体
  • Provider: Core の Plugin で,AWS や Azure のインフラストラクチャをネットワークを通じて操作する

provider オプションの活用,リージョンの選択やデータベースのレプリカ設定などが可能.ただし,データベースを multi-region で管理するには,単一のwriterを設定してレイテンシを許容するか,複数のwriterを設定して競合を回避するかなど,実際かなり難しい問題が発生するので,単にTerraform に複数のproviderを設定して完了するような簡単な問題ではない.

複数の AWS account を利用することで,検証環境と本番環境を区別したり,一部の操作のみを許可するアカウントを使用することでセキュリティを向上させることが可能である.GCP ならば project という用語を使用する.

複数のクラウド業者を利用してサービスを提供する (multi-cloud) ことで,ベンダーロックインやコスト削減,耐障害性の向上が見込まれるような気がしてしまうが,実際はデメリットが多く勧めない.単一のクラウド業者の環境でサービスを稼働させることはすでにとても複雑なことであり,これを複数の環境で実現するのは多くの企業にとって困難であることが多い.

Kubernates を利用することで,ある程度インフラストラクチャを抽象化することが可能であるが,サービスの内容が複雑になっていくに従って困難な問題も生じる場合があるし,Kubernates それ自身が複雑なシステムである.

8. Production-Grade Terraform Code

問題を解決するために問題が発生することが何度も繰り返される状況をヤクの毛刈り (yak shaving) と呼ぶが,これにより production-grade のサービスを作るには想像するよりも時間がかかる.例えば以下のようなチェックリストを確認する必要がある.

  • Install: ソフトウェアをインストールし,依存関係を解決する
  • Configure: 実行環境のための設定をする.ポートの設定,TLS証明書,Service Discoveryなど.
  • Provision: インフラストラクチャを用意する.サーバー,ロードバランサー,ネットワーク設定,ファイアウォール設定,アクセス権限の設定など.
  • Deploy: インフラストラクチャにサーバーを展開する.ダウンタイムなしで更新を適応する.blue-green, rolling, canary deployment などの方法を使用する.
  • High availability: それぞれのプロセス,サーバー,サービス,データセンター,リージョンの機能停止から持ちこたえる.
  • Scalability: 負荷に応じてスケールアップ/ダウンする.水平方向への拡張 (サーバーの台数)と垂直方向への拡張(大きなサーバー)がある.
  • Performance: CPU, memory, ディスク,ネットワーク,GPUの使用率を最適化する.クエリーを最適化したり,ベンチマークを取得したり,負荷テストを実施したり,プロファイルを取得する.
  • Networking: 静的・動的なIPアドレス,ポート,service discovery,ファイアウォール,DNS,SSH,VPNを設定する.
  • Security: データ通信とディスクの暗号化,認証,承認,シークレット管理など.
  • Metrics: 可用性の指標,ビジネスの指標,アプリケーションの指標,サーバーの指標,イベント,可観測性,トレース,アラートなど.
  • Logs: ディスクのログのローテーション,中央のロケーションにログデータを集約する.
  • Backup and Restore: データベース,キャッシュなどのデータをスケジュール管理でバックアップする.別のリージョンやアカウントに複製する.
  • Cost optimization: 適切なインスタンスの種類を選択し,スポットインスタンス,リザーブドインスタンスを使用する.自動スケールを有効にする.使用していないリソースを削除する.
  • Documentation: コード,アーキテクチャ,業務を文書化する.インシデントに対応するための作戦帳を作成する.
  • Test: インフラストラクチャの自動化テストを作成する.コミットする度にテストを実行する.

インフラストラクチャをモジュール単位で管理する.モジュールは1個のことを正しくできる単位で作成し,これらを集約するように設計する.モジュール単位のテストを作成する.モジュールの依存関係のバージョンを固定し,モジュール自身のバージョンを管理することで,いつ実行しても同じ結果が得られるようにする.

Terraform の provisioner で,ローカルやリモートでスクリプトを実行したり (loca-exec, remote-exec),リモートにファイルをコピーする (file) .null_resource は,実際のリソースとは関係なく使用できる.

9. How to Test Terraform Code

インフラストラクチャーに関するテストを作成するために,最終的には terraform で実際の環境にデプロイするしかないので,以下の作業を繰り返す.

  1. 単体で動く汎用性が高いモジュールを作成する.
  2. 簡単にデプロイ可能な例を作成する.
  3. terraform apply コマンドで実際の環境にデプロイする.
  4. デプロイしたものの動作確認をするテストを作成する.
  5. terraform destroy コマンドで削除する.

実際には,インフラストラクチャの作成・変更・削除には時間がかかるので,テスト専用の環境を用意するのがおすすめである.

単体テスト < 結合テスト < E2Eテスト の順番に複雑になり,実行時間が長くなるので,この順番にテスト数を少なくする.

静的コード解析により実行せずコードを簡単に検証できる.例えば,tfsec, tflint, Terrascan などがある.また,terraform validate コマンドは terraform に含まれているので,簡単に使用できる.なお,実際に実行するわけではないため,これらのツールでエラーがないからといって実行可能とは限らない.

terraform plan コマンドの結果を検証する方法もある.例えば,Terratest, Open Policy Agent (OPA), HashiCorp Sentinel, Chekhov, terraform-compliance などがある.policy as code と呼ばれ,ルールを規定することで未然に間違いを防ぐ.実際の環境の読み取り結果 plan を利用するため,静的コード解析より実行に時間がかかる.

サーバーの属性を検証する方法もある.inspec, serverspec, goss などのツールがある.実際にデプロイしたサーバーに対して検証するため,実行に時間がかかる.

これらの方法にはそれぞれ長所と短所が存在するため,適切に組み合わせて使用する.

10. How to Use Terraform as a Team

実際のソフトウェア開発・運用はチームで行うため,terraform がチームで使用できるよう,上司を説得し,物事を小さい単位に分割して徐々に変化させ (一度に変化させない),構成員が勉強する時間を確保するのが重要である.プロジェクトが大きくなると時間がかかり難易度が上昇する.

インフラストラクチャのデプロイ作業は以下のような流れになる.

  1. バージョン管理システムを導入する.
  2. ローカル環境で実行可能にする.
  3. コードを変更する.
  4. コードの変更箇所をレビューする.
  5. 自動化したテストを実行する.
  6. マージしてリリースする.
  7. デプロイする.

感想

terraform はとても使いやすいですが,高品質なWebサービスを長期間運用するとなると難易度が高い印象がありましたが,この本を読んで注意するべきことが網羅されていたので勉強になりました.また,terraform に関連する便利なツールが紹介されていたので,取り入れていこうと思いました.