🔖

自動テスト可能なインフラプロジェクトのための学習メモ 【令和6年6月改良最新版】

2024/01/29に公開

アプリ開発などに比べてテストがしづらいインフラ開発において、テストを容易にするためのプロジェクトのプロトタイプ版がようやく最近完成したが、これまでに調べたツールやフレームワーク、参考資料、設計の大枠レベルで有益だった情報をこの記事で簡潔にまとめてみる。

CHANGELOG

CHANGELOG

2024/06/02追記

2024/05/04追記

  • TerraformのStyle Guideの説明を新規追加
  • Linterの説明にHashiCorpのスタイルガイド採用について追記
  • CI/CDの説明欄を新規追加
  • Regalの説明を新規追加

2024/03/03追記

IaC Tool (Terraform)

現在開発中のインフラプロジェクト(以後infra-testing-google-sample)はTerraformでのインフラリソースの管理を前提としている。

Terraformのライセンス変更の問題などもあり、Pulumiも選択肢として十分あり得るような状況になり始めている気はしているが、やはり使い慣れている人数という点においては未だにTerraformの方が有利であることから、細かい問題には目をつぶってTerraformで行くことにする。

Terraform (公式ドキュメント)

https://developer.hashicorp.com/terraform

まず真っ先に紹介しなければいけないドキュメントはTerraformの公式ドキュメントである。

当たり前すぎて、なぜ紹介するのかと感じる人もいるとは思うが、Terraform関係無く初めて利用するツールやプログラム言語、ライブラリおよびフレームワーク、AWSやGCPのサービスなどはまず最初に公式ドキュメントを全部読むことで、その後の学習効率が段違いになる。

そもそも公式ドキュメントが提供する情報以上に正確かつ網羅度の高いドキュメントはほとんどのケースにおいて存在しないのだから、それ一つを読むだけでも十分過ぎる基礎学習となる。

(出来れば数ヶ月後の自分が有益な情報をすぐに思い出せるよう、メモを取りながら読むと尚良い)

新しい技術を公式ドキュメントで学習して、あとは実際に実装してみて問題が発生したらStack Overflowや技術サイト等で調べるだけで、実装だけでなく運用まで問題なく行えるようになると、個人的には確信に近いものを以って言える。

大抵のツールやフレームワーク、クラウドサービスの公式ドキュメントは、仮に全文英語であっても、そこそこ程度に英語のReadingが出来れば、1つにつき10時間前後ですべて読み終えられる。

もし英語が得意でなくても、昨今はDeepLなどで質の良い翻訳が可能なので、多少時間はかかるが翻訳ツールを使いながら読み進めることも出来るはず。

(自分も英文を読むのに疲れてくると、DeepLに適当に英文を放り込み始める)

この作業は工数にするとせいぜい1~2営業日程度であるのに対して、その後のシステム開発の品質レベルは段違いとなる。

そもそもシステムのアーキテクチャは、たった一文程度の情報を知っている/知らないの差だけで、天地の差が生まれるような世界であるため、そのような環境下にあってシステムローンチの最終局面で後悔をしないためにも、使用する技術の公式ドキュメントは全部読むことを繰り返し強くおすすめしたい。

以上、説教がましい話になったが、実際のところTerraformの公式ドキュメントは全ページ読もうとするとかなりの量があり、自分の見積りではおそらく最低でも30時間~程度はかかる気がしている。

よって、普段からTerraformを運用している、過去にTerraformを運用していた人は、追従できていない差分の機能に関するドキュメントだけを読んだ方がいい気もしている。

Terraform を使用するためのベスト プラクティス

https://cloud.google.com/docs/terraform/best-practices-for-terraform?hl=ja

Googleが推奨するTerraformを運用する上でのベストプラクティスがまとめられているページ。

自分は0.xバージョンの頃から実務的にインフラ作業から遠ざかっていたため、最近のTerraformの運用をどうするべきか調査していたところにこのページを見つけて、情報の体系化と設計の方針決めに大きく役立った。

ただ、実際に自動テスト可能なインフラプロジェクトを設計してみると、一部不都合が発生するものもあったりしたので、要件に応じて情報の取捨選択が必要にはなる。

Google Cloud の Terraform ブループリントとモジュール

https://cloud.google.com/docs/terraform/blueprints/terraform-blueprints?hl=ja

上記ベストプラクティスの中に"ブループリント"という気になる単語が出てくるが、これは特定の用途に必要なTerraformのモジュールやリソース群を1つに束ねたものをあらわすキーワードらしい。

GCPではモジュールとブループリントを以下のように定義している。

モジュールとは、Terraform リソースの論理的な要約を作成する、再利用可能な一連の Terraform 構成ファイルのことです。

ブループリントは、独自のソリューションを実装するためのモジュールとポリシーが文書化されたパッケージです。

GCPを利用している人であれば、環境を構築する際、まずはブループリントの方から探してみるといいのかもしれない。

実際にinfra-testing-google-sampleでも実装でnetworkモジュールやsql-dbモジュールを使用していて十分に実用に耐えられそうだが、一方でthree-tier-web-appのような汎用性に問題があるものもあるため、利用の際には中身の調査が必須となる。

詳解 Terraform 第3版

https://www.oreilly.co.jp/books/9784814400522/

公式ドキュメントを読むことが一番良い基礎学習方法とは上に書いたが、やはり1つのテーマに対する体系化された知識を獲得するという点においては、本を読む方が効果的ではある。

Terraformは開発中のインフラプロジェクトの中心技術となるため、自分の場合は念の為に本でも学習することにした。

(個人的にO'reillyのファンであるため、まず欲しい技術本がO'reillyの日本語版にあればそれを読むようにしている)

ちなみに著者はTerratestの開発元であるGruntworkの関係者らしい。

内容としては、Terraformの基本構文を延々と紹介といったような一般的な入門本とは異なり、Terraformの実際の運用に役立つ知識を詰め込んだ一冊となっている。

特に9章 Terraformコードをテストするは、テスタブルなインフラを構築する上でかなり参考になった。

ただ過去記事でも書いたように、この本で紹介されているテストフレームワークTerratestはTeraformのライセンス変更の問題で、現在はTerraformとの併用が不可能に近い状態となっているので、この問題の回避策を追加で考える必要があった。

https://zenn.dev/erueru_tech/articles/c17bad1d0630f4

https://zenn.dev/erueru_tech/articles/203d76860c7af3

Style Guide

https://developer.hashicorp.com/terraform/language/style

HashiCorp社が提供するHCLコードのスタイルガイド。

infra-testing-google-sampleでは設計上のメリットがある場合は一部のスタイルを無視しているものの、その他に理由がなければ基本的に準拠している。

Test Framework

自動テスト可能なインフラプロジェクトを作るのだから、アプリケーションのソースコードに対してテストコードが出来るように、Terraformのコードに対してテストコードを実行できるようにする必要がある。

以下ではテストフレームワークやテストに役立つ記事を紹介。

Terraform Tests

https://developer.hashicorp.com/terraform/language/tests

自動テスト可能なインフラプロジェクトを作ろうとしたきっかけとなった機能。

インフラのコード(Terraformのresource等)もアプリケーションのテストコード同様にテスト可能な機能がついに誕生したとテンション高めで設計を始めたのだが、Terratestの誕生年などを考えると、やろうと思えばもっと昔から出来たのではと今では思う。

実装については、まだうまく体系化できていないため、出来次第記事を書きたいと考えている。

blueprint-test

https://pkg.go.dev/github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test

上記、Terraform を使用するためのベスト プラクティスでも紹介されている、Terraformのテスト用フレームワーク。

最終的にはterraform-execをインフラコードのテストフレームワークとして採用することにはなったが、テスタブルなTerraformプロジェクトのフォルダ構成を考えていた時期に出会って、その後の設計で影響を受けたページではあった。

ただblueprint-testフレームワーク自体については、テスト設計やフォルダ構成などへの制約が強めなのと、GCP寄りのフレームワークなのが、採用にあたってマイナスポイントにはなった。

またドキュメントはほとんどなく、実際に利用する場合にはソースコードを読む事になると考えた方がいい。

Terratest

https://terratest.gruntwork.io/docs/

Terraformのライセンス変更問題に気づくまでは、自動テスト可能なインフラプロジェクトを実現するためのファーストチョイスだったが、現在はterraform-execにその座を譲ってしまった。

一応Terratestをまだ諦めない人向けに多少言及すると、公式ドキュメントを読むのにそこまで時間かからないが、全部読んだところで正直使い方があまり分からないフレームワークとなっている。

利用にあたっては、Terratest自体のソースコードを参考にしながら、実装していくスタイルになる。

terraform-exec

https://github.com/hashicorp/terraform-exec

HashiCorpが自前で提供する、terraformコマンドをGo経由で実行するためのフレームワーク。

Terratestの機能の8割はterraformコマンドの実行であると前の記事でも書いたが、このterraform-execはその機能を持つため、テストに便利な機能面等でTerratestに比べて若干劣るが、代替足りうるというのが現在の評価。

そして、ここまで紹介したフレームワーク同様、ドキュメントがREADME.mdしか存在しないため、基本ソースコードやテストコードを見ながら実装することになる。

Testing HashiCorp Terraform

https://www.hashicorp.com/blog/testing-hashicorp-terraform

HashiCorpがインフラのテスト手法について言及している記事。

Terraform Tests & Mockを使用したテストをメインのテストフレームワークに据える場合はかなり参考になるはず。

その他

Terraformのコードのテストフレームワークには他にもKitchen-TerraformというRubyベースのものがある。

Linter

アプリのプロジェクトでは最低限パッケージ管理、リンタ、フォーマッタ、テストコードさえ入っていれば体を成す(と個人的には思ってる)ことから、インフラのコード開発でもリンタを入れたい。

そして、Terraformのリンタで最も有名なのがTFLintだった。

なお2024年3月に公開されたHCLのスタイルガイドでもこのツールについて触れられているためTerratestとは異なり、おそらくは今後もライセンス変更の影響を受けずに開発継続される可能性が高い。

TFLint User Guide

https://github.com/terraform-linters/tflint/blob/master/docs/user-guide/

上記フォルダ内のドキュメントは全部読むのにほとんど時間はかからないので、もちろん全部読むことをおすすめしたい。

またフォルダ内のドキュメントの他にもソースコードを調べると、ルールセット一覧のような重要な情報も見つかるので、少しコード探索してみるといい気がしている。

User Guide以外にも、自作のルールセットを開発する人向けのDeveloper Guideもあるが、こちらはTFLintをデフォルト設定で使うだけならそこまで読む必要は無かった。

CI/CD

infra-testing-google-sampleではCI/CDツールとしてGithub Actionsを採用している。

GitHub Actions ドキュメント

https://docs.github.com/ja/actions

Github Actionsを扱うためには公式ドキュメントを読み込むのが一番良いが、Terraformのドキュメント並みに量が多い。

そのためまったくの初学者である場合は最低限Github Actionsがどのようなものかを上記ページで簡単に掴んだ後で、あとはinfra-testing-google-sampleで実際に動いているコード解説記事を先に読んだ方が短期間で習得しやすい気がしている。

社内用GitHub Actionsのセキュリティガイドラインを公開します

https://engineering.mercari.com/blog/entry/20230609-github-actions-guideline/

以前Codecovを踏み台にした不正アクセス攻撃を受けたメルカリ社だが、おそらくはその対策方法をテックブログの記事で紹介してくれている。

これまでプライベートリポジトリでGithub Actionsを稼働させていただけなのでそこまでセキュリティを意識してこなかったが、オープンソースプロジェクトでGithub Actionsを稼働させるにあたって、セキュリティ対策が課題となっていた際にこの記事を見つけることが出来た。

網羅度が非常に高く、infra-testing-google-sampleのワークフロー実装はこの記事に大きな影響を受けている。

Github Actionsを使用して開発する人には是非一度読むことをおすすめしたい。

Github OIDC Simple Example

https://github.com/terraform-google-modules/terraform-google-github-actions-runners/blob/master/examples/oidc-simple/

infra-testing-google-sampleでは基本的にGoogle公式が提供するTerraformモジュールを使用してほとんどのHCLコードの実装を行なっているが、Github ActionsからGCPに接続する際に必要なWorkload Identity連携についても同様にgh-oidcモジュールを使用していて、上記サンプルコードを参考にながら実装を行なった。

実際に実装したモジュールはこちら

そもそもWorkload Identity連携とは?について知りたい方は、Googleの記事を参照。

slack-github-action

https://github.com/slackapi/slack-github-action

infra-testing-google-sampleのGithub Actionsのワークフローでは実行が完了すると正常/異常終了問わず、Slackのチャネルにその実行結果をメッセージで通知している。

このアクションはSlack社から提供されているもので、Slackチャネルの作成とWebhook URLの発行をこちらの記事を参考に行えば、あとはREADME.mdに記載されている方法でアクションを使用すればSlackにメッセージを通知することが出来る。

Compliance Test

infra-testing-google-sampleを開発していて、初めて知ったのがPolicy as Code(以後PaC)という単語。

ざっくり説明すると、あるプロダクトの状態がセキュリティルールや組織の方針に従っているかをテストする、といった領域で出てくるキーワードである。

具体的には、S3やGCSのバケットが外部公開される設定になっていないかをチェックしたり、データベースにprevent_destroy = trueの設定がされているか等をポリシーとして定義してチェックを行う。

そしてPaCを実現するためのランタイム/プログラム言語がOPA/Regoとなる。

(間違っている可能性もあるが、JavaでいうところのOPAがJREで、RegoがJavaみたいに認識している)

Terraformに対してOPAでポリシーチェックを行う場合、こちらのサンプルが参考になるが、やっていることは

入力値(terraform planコマンドなどを使用してJSON出力したプロダクトの状態)
↓
入力値がRegoで定義されたポリシーに合致した値となっているかテスト
↓
テスト結果(この値を元にCIのエラー終了など次の制御を決定)

のように抽象化出来る。

つまりJSONで状態を表現さえ出来れば、システム領域だけでなく、ありとあらゆる事象に対してooはxxでなければならないを定義できるはずである。

そしてポリシーはREST APIとして社内で一元管理して公開することも出来るため、すべてのプロジェクトに対してCIでこのポリシーサーバーでテストを行うことを義務付けることで、組織の方針を強制的に適用することが出来るようになる。

(融通の効かない人間の思考をAPI化出来るような所にロマンを感じる)

OPA/Rego入門

https://zenn.dev/mizutani/books/d2f1440cfbba94

基本的に新技術の調査は、ほとんどのケースにおいて英文の公式ドキュメントを読むところから始まるのだが、OPAに関してはこのZenn本のおかげで日本語で入門出来る。

やはり、ある程度の事前知識があった方が、英文のドキュメントをいきなり読むのに比べて、理解しやすい気がしている。

余談だが、O RLY Cover Generatorを使用した表紙のおかげで、本気でO'reillyの本のサンプルみたいなものだと思って読んでいた。

Open Policy Agent

https://www.openpolicyagent.org/docs/latest/

公式ドキュメント。

infra-testing-google-sample設計当初はOPAネイティブな実行環境でポリシーテストの実装や実行を行おうと考えていたが、後述するConftestの方が簡単にポリシーテストを実現できそうというのが現在の感想。

Conftestで対応しきれなくなる場面では、やはり必要になりそうな気もしている。

Sentinel (Terraform Cloud)

https://developer.hashicorp.com/terraform/cloud-docs/policy-enforcement

Terraform Cloudを使用することで、利用可能となるポリシーテストの機能。

Terraform Cloud調査の記事でも書いたが、実質有料の機能であるにも関わらず、HashiCorp製品限定のプログラム言語であるSentinelを覚えなければいけないため、より幅広く利用されているOPAを使ってポリシーテストを行った方がよいというのが個人的な感想。

そして何より次に紹介するConftestがポリシーテストのツールとして、自分の環境では一番優れているので必要とはならなかった。

Conftest

https://www.conftest.dev/

Conftestの紹介記事で実践的な利用方法を詳しく書いたが、TerraformのHCLファイルに限らず、Kubernetes、Dockerfile、その他各種設定ファイルのポリシーテストを簡単に行うことが出来る、かなりおすすめのツール。

そもそもこのツールはOPA自身から提供されているものなので、ポリシーはもちろんOPAで実装することになる。

infra-testing-google-sampleではConftestをポリシーテスト役として採用した。

Regal

https://docs.styra.com/regal

OPAの開発元であるStyra社が提供するスタイルガイドに準じたコードを実装するためのRegoのリンタ。

Regoは一般的に有名なプログラム言語の記法とはかなり異なるため、事前にバグになりそうなコードをチェックしてくれるのは助かる。

Security Test

インフラプロジェクトではたった少しの設定ミスで不正アクセスや情報漏洩が発生する危険性があるため、自動でのセキュリティテストは確実に入れておきたい。

調査では以下の2つのツールが見つかった。

terrascan

https://runterrascan.io/docs

決して悪くないツールで導入してもよいが、保守コストが増える割にあまりメリットを教授できない気がするという印象を受けた。

具体的にはGCPを利用している場合、こちらで列挙されているチェックを行なってくれる。

firewallの設定を厚めにチェックしてくれているので、他のツールでセキュリティテストを行なっていて、その辺りが弱いなら併用の選択肢も出てくるのかもしれない。

ただ、実際に試してみて、再帰スキャンの挙動などで作り込みの甘さを感じるなど、不満に思うことが何度かあった。

何より以下で紹介するTrivyの方が明らかに高性能なので、自分の設計では導入見送りとなった。

Trivy

https://aquasecurity.github.io/trivy/latest/docs

最初はtfsecを調査しようとしたのだが、Trivyに買収、統合されたとのこと。

はっきり言ってドキュメントは理解しづらいものだったが、ツール自体は期待以上のものだった。

Trivyでは、Terraformのコードにセキュリティ上の問題がないかのスキャン(misconfig)以外にも、認証情報が含まれていないかのチェック(secret)、アプリケーションパッケージの脆弱性検査(vuln)、ライセンス違反探索(license)などを行なってくれる。

さらにAWSで環境を構築している場合、コマンド一つでダイレクトにセキュリティスキャンを行えるらしい(GCP向けは現在は存在しない)。

そして、デフォルトで提供されているセキュリティスキャン機能を使うだけなら導入コストはかなり低い。

一方でRego(下記)で実装したカスタムポリシーを用いたスキャンもサポートしているので拡張性も高い。

Drift Detection

driftctl

https://github.com/snyk/driftctl

Terraformのstateで管理されていないリソースを検出するためのツール。

Terraform関連ツールとしては珍しくAWSだけでなくGCPにも対応していて、本来であればファーストチョイスとなるツールだった。

しかし残念ながら現在はメンテナンスモードとなっていて、将来的に問題が発生した場合への対応に懸念が残るため、採用を断念した。

とはいえ、GCPの場合Cloud Asset Inventory APIを呼び出してリソース一覧を取得して、Terraformのstateと付き合わせる処理を自前で実装することで似たような機能を実装することはできるのではないかと考えている。

Drift Detection (Terraform Cloud)

https://developer.hashicorp.com/terraform/cloud-docs/workspaces/health

Terraform Cloudではポリシーテストだけでなく、ドリフト検知の機能も提供している。

こちらもTerraform Cloudの調査で機能を調べたが、機能は劣るものの数行のコマンドで似たようなドリフト検知機能を自前で実装できそうなので不採用となった。

その他

他にもドリフト検知をCI上で行うフレームワークとしてtfactionDiggerなどがあるが、これらは既にオレオレフレームでCIを実装している自分のインフラプロジェクトとは相性が悪かったため利用を断念した。

Resource Cleanup

テスト環境で実行されるTerraformのテストコードでエラーが発生した場合、手動でリカバリを行わないとインフラリソースが削除されずに残ることになる。

またコンソールやCLIからクラウドのリソースを手動で追加してしまった後で削除を忘れると、リソースが残ったままとなりサービスによっては課金が発生することになる。

よってテスト環境で不要になったリソースが残っている場合、自動的に削除されることが望ましいが、この要件を実現するツールは一応クラウドごとに存在する。

aws-nuke

https://github.com/rebuy-de/aws-nuke

自分が把握する限り唯一実運用に耐えられるAWS向けのリソースクリーンアップツールである。

プロジェクト全体をクリーンアップすることもできれば、IAMユーザなど消してしまうとプロジェクトの復旧が完全に不可能となってしまうリソースを設定によって除外することも可能となっている。

また削除による事故対策がかなり厳重に練られていることからも、Terraformのテストコードで常時行われるdestroy対策を考える上でも役に立つものであった。

project_cleanup

https://github.com/terraform-google-modules/terraform-google-scheduled-function/tree/master/modules/project_cleanup

GCP向けのプロジェクトクリーンアップツールだが、プロジェクトの削除を行うだけでaws-nukeのようなきめ細かな削除対象リソースの指定ができないため、自分のプロジェクトでは利用を控えている。

なおaws-nukeのGCP版を自前で実装するのは流石に骨が折れるので、妥協案としてプロジェクトのコストをモニタリングして明らかにコストに異常が見られる場合にアラートを送信するような仕組みを実装すれば良いのではないかと考えている。

その他

他にもcloud-nukeというツールがあるが、こちらはドキュメントを確認する限りGCPには対応していない模様。

あとGCP向けのクリーンアップツールとして一応gcp-nukeというプロジェクトが2つ存在するが、どちらも長らく更新されないまま放置された状態となっている。

Miscellaneous Tools

tfenv

https://github.com/tfutils/tfenv

ローカルのTerraformのバージョンを簡単に切り替えられるようにするツール。

導入手順はこちらの記事でまとめている。

pre-commit

https://pre-commit.com/

Githubにコード変更をpushする前に、上記TFLintやTrivyによるチェックを自動的に行うようにするためのツール。

pre-commitについての詳細はこちらの記事でまとめている。

おわり

引き続き情報が集まり次第、情報の加筆・修正を随時行なっていきたい。

Discussion