Zenn
Open15

Terraform関連のコマンドを実行するのが面倒なのでラッパーコマンドが欲しい

anfangdanfangd

Golang を使って terraformtfupdatetfenv などをラップするコマンドを作って、コマンド実行時にいちいちディレクトリ移動したり、セットで実行したいコマンドの実行の手間を減らすための試行錯誤。

Summary

tfhq というコマンドを作る。

課題感

terraformコードをモノレポで管理しているとディレクトリ移動が面倒くさいので簡単に制御できるようにしたい。
なんなら、理想のディレクトリ構成をサクッと作成出来るようにして欲しい。

解決方法

  • シェルスクリプト
    • シェルスクリプトで書いたことがあって、それはいい感じに使えてたけど多機能なのでコードの見通しが悪かった。
    • シェルスクリプトの場合はコードの中身を誰でもデバッグ・変更できるのでそれはそれで良い。
  • 専用コマンド
    • 作ってみたい。ついでに実装の見直ししたい。
Pros Cons
シェルスクリプト - 中身を確認できる。
- カスタムしやすい。
- Unix/Linux/Windows(WSL)であれば実行可能
- デバッグの難易度が高い
コマンド - デバッグしやすい(テストコードが書ける)
- 多機能に作り込みしやすい
- インストールが必要
- GitHub Actions などでもインストールが必要

Specification

# 初期設定
my-cli init

# コンポーネントの追加
my-cli generate
my-cli generate system
my-cli generate env
my-cli generate component

# 対象システムで terraform plan の実行
# `.my-cli/` が存在するディレクトリ配下であれば実行可能
my-cli terraform plan --system system-A --env dev --component setup
my-cli terraform plan -s system-A -e dev -c setup

my-cli tfenv list -s system-A - dev -c setup
my-cli tflint -s system-A - dev -c setup

# 対象システムで terraform plan の実行(非推奨)
my-cli terraform plan --path custom/pash

Sub Commands

  1. init : 初期設定
  2. generate : system/env/componentを追加
  3. terraform : terraform コマンドを実行
  4. tenv : tfenv コマンドを実行
  5. tflint : tflint コマンドを実行
  6. tfupdate : tfupdate コマンドを実行
  7. aqua : aqua コマンドを実行
  8. plan
    1. Commands: terraform fmt/validate/plan, tflint, tfsec
    2. Option: all components, specific component
  9. apply
    1. Commands: terraform fmt/validate/apply, tflint, tfsec
    2. Option: all components, specific component
  10. show
    1. Commands: terraform fmt/validate/show, tflint, tfsec
    2. Option: specific component
  11. import
    1. Commands: terraform fmt/validate/import, tflint, tfsec
    2. Option: specific component
  12. test
    1. Commands: terraform fmt/validate/test, tflint, tfsec
    2. Option: all components, specific component
  13. tfstate
    1. Commands: aws s3 create-bucket

Directory

Basic Constructure

src/
  └── terraform/
      ├── .my-cli/
      ├── system-A/    # カテゴライズも可能
      │   ├── envs.yaml     # システムAの環境メタ情報 (AWSアカウント名、バケット名など)
      │   └── envs/
      │       ├── prod/
      │       │   ├── dependencies.yaml    # コンポーネントの依存関係を定義
      │       │   ├── setup/
      │       │   │   ├── main.tf
      │       │   │   ├── .terraform-version
      │       │   │   ├── variables.tf
      │       │   │   ├── outputs.tf
      │       │   │   ├── README.md
      │       │   │   ├── terraform.tfvars
      │       │   │   ├── providers.tf
      │       │   │   ├── versions.tf
      │       │   │   └── backend.tf
      │       │   ├── network/
      │       │   ├── security/
      │       │   ├── datastore/
      │       │   └── app/
      │       ├── stg/
      │       └── dev/
      ├── system-B/
      │   ├── ...
      ├── scripts/
      │   ├── init.sh
      │   ├── apply.sh
      │   ├── destroy.sh
      │   ├── tflint.sh
      │   ├── tfupdate.sh
      │   └── aqua.th
      └── modules/          # 共通モジュール
# 例: system-A/envs.yaml
environments:
  dev:
    aws_account_name: "my-dev-account"
    region: "us-east-1"
    bucket_name: "my-dev-tfstate-bucket"
  stg:
    aws_account_name: "my-staging-account"
    region: "us-east-1"
    bucket_name: "my-stg-tfstate-bucket"
  prod:
    aws_account_name: "my-prod-account"
    region: "us-east-1"
    bucket_name: "my-prod-tfstate-bucket"

公開方法

  • GitHub (Source, Binary)
  • Homebrew

Support

  • Unix
  • Linux
  • Windows

Inspired From

anfangdanfangd

シェルスクリプトの方がシンプルだし、基本のディレクトリ構成が欲しいなら GitHub でそれぞれのパターンを用意しておいてコピる方が楽な気もする。

anfangdanfangd

terraformコンポーネントのファイル構成

1. シンプルな構成(小規模プロジェクト)

  • 目的: 小規模プロジェクトや単一コンポーネントに適した構成。
  • 利点: シンプルで分かりやすい。
terraform/
├── main.tf         # 主なリソース定義
├── variables.tf    # 入力変数の定義
├── outputs.tf      # 出力値の定義
├── terraform.tfvars# 変数の値(オプション、環境ごとに異なる値を設定可能)
├── providers.tf    # プロバイダー設定(AWS, GCPなど)
└── versions.tf     # Terraformのバージョンやプロバイダーのバージョンをロック

2. モジュールを使った構成(中~大規模プロジェクト)

  • 目的: 再利用性の高いモジュール化を目指した構成。
  • 利点:
    • モジュールを使い回すことで効率的なリソース管理が可能。
    • 環境ごとに設定を分離し、デプロイの衝突を防止。
terraform/
├── modules/                        # モジュールを格納
│   ├── network/                    # ネットワーク関連リソース
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   └── README.md
│   ├── compute/                    # コンピュートリソース関連
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   └── README.md
├── environments/                   # 環境ごとの設定
│   ├── dev/                        # 開発環境
│   │   ├── main.tf
│   │   ├── terraform.tfvars        # 環境固有の変数
│   │   └── backend.tf              # S3やリモートバックエンド設定
│   ├── prod/                       # 本番環境
│   │   ├── main.tf
│   │   ├── terraform.tfvars
│   │   └── backend.tf
├── main.tf                         # モジュール呼び出し
├── variables.tf                    # 共通変数
├── outputs.tf                      # 共通出力
├── providers.tf                    # プロバイダー設定
└── versions.tf                     # バージョン管理

3. 高度に組織化された構成(大規模プロジェクトや複雑なインフラ)

  • 目的: 大規模チームやマルチクラウド環境での運用。
  • 利点:
    • 環境ごと、コンポーネントごとに厳密に分離。
    • 複数チームが同時並行で作業しやすい。
terraform/
├── modules/                        # モジュール
│   ├── network/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   ├── outputs.tf
│   │   └── README.md
│   ├── compute/
├── environments/                   # 環境ごとの設定
│   ├── dev/
│   │   ├── network/
│   │   │   ├── main.tf             # モジュール呼び出し
│   │   │   └── terraform.tfvars
│   │   ├── compute/
│   │   │   ├── main.tf
│   │   │   └── terraform.tfvars
│   ├── prod/
│       ├── network/
│       │   ├── main.tf
│       │   └── terraform.tfvars
├── shared/                         # 共有設定やポリシー
│   ├── variables.tf
│   ├── outputs.tf
│   └── providers.tf
├── main.tf                         # 環境ごとのモジュール呼び出し
├── README.md                       # ドキュメント
└── scripts/                        # 補助スクリプト
    ├── init.sh
    ├── apply.sh
    └── destroy.sh

各ファイルの役割

  1. main.tf:
    • リソースやモジュールの定義を記述。
  2. variables.tf:
    • 入力変数の定義。
  3. outputs.tf:
    • 外部に出力する値(例: VPC ID、EC2 IPなど)。
  4. terraform.tfvars:
    • 環境固有の変数値を記述。
  5. providers.tf:
    • 使用するクラウドプロバイダーの設定(例: AWS, GCP)。
  6. versions.tf:
    • Terraformのバージョンやプロバイダーのバージョンをロック。
  7. backend.tf:
    • Terraformのリモート状態(例: S3)を設定。
  8. README.md:
    • 使用方法や注意事項を記載。

重要なポイント

  1. リモートバックエンドの利用:
    • S3やGCSを使ってTerraformの状態ファイル(terraform.tfstate)をリモート管理するのが推奨されます。
  2. モジュールの再利用性:
    • よく使うリソース(ネットワークやIAM)をモジュール化し、コードの重複を減らします。
  3. 環境ごとの分離:
    • dev, staging, prod などの環境を明確に分離して管理。
anfangdanfangd

Terraform Knowledges

Practice

Module の利用方法

HCP Terraform

HashiCorp Cloud Platform (HCP)

Open Policy Agent (OPA)

Slide

Books

anfangdanfangd

Terraform による IaC の実現で実現すべき要素

Keywords

  • GitOps
  • Format
  • Validation
  • TFLint
  • TFSec
  • Precondition
  • PostCondition
  • Open Policy Agent
  • Drift Detection

仕様

anfangdanfangd

Terraform の Style, Module そして Test

  • Style Guide - Configuration Language | Terraform | HashiCorp Developer
    • Code style
    • Code formatting
    • Code validation
    • File names
      • backend.tf: contains backend configuration
      • main.tf
      • outputs.tf
      • providers.tf: contains provider block
      • terraform.tf: contains a single terraform block which defines your required_version and required_providers.
      • variables.tf
      • locals.tf: contains local values
      • override.tf: contains override definitions
    • Linting and static code analysis
    • Resource naming
    • Resource order
      • you should define a data source before the resource that references it.
    • Variables
    • Outputs
    • Local values
    • Provider aliasing
    • Dynamic resource count
    • .gitignore
    • Workflow style
    • Version pinning
    • Module repository names: The Terraform registry requires that repositories match a naming convention for all modules that you publish to the registry. Module repositories must use this three-part name terraform-<PROVIDER>-<NAME>, where <NAME> reflects the type of infrastructure the module manages and <PROVIDER> is the main provider the module uses. The <NAME> segment can contain additional hyphens, for example, terraform-google-vault or terraform-aws-ec2-instance.
    • Module structure
    • Local module
    • Repository structure
    • Branching strategy: we recommend using the GitHub flow.
    • Multiple environments
    • State sharing
    • Secrets management
    • Integration and unit testing:
      • Terraform tests let you validate your modules and catch breaking changes. We recommend that you write tests for your Terraform modules and run them just as you run your tests for your application code, such as pre-merge check in your pull requests or as a prerequisite step in your automated CI/CD pipeline.
      • Tests differ from validation methods such as variable validation, preconditions, postconditions, and check blocks. These features focus on verifying the infrastructure deployed by your code, while tests validate the behavior and logic of your code itself. For more information, refer to the Terraform test documentation and the Write Terraform tests tutorial.
    • Policy
  • Modules Overview - Configuration Language | Terraform | HashiCorp Developer
  • Build and use a local module | Terraform | HashiCorp Developer
  • Write Terraform Tests | Terraform | HashiCorp Developer
anfangdanfangd

Architecting AWS with Terraform By Erol Kavas, December 2023

前半が良かった。

  • Part 1:Introduction to IAC and Terraform in AWS
    • Chapter 1, Understanding Patterns and Anti-Patterns of IaC and Terraform
    • Chapter 2, How Not to Use IaC and Terraform
    • Chapter 3, Building Your First Terraform Project
    • Chapter 4, Discovering Best Practices for Terraform IaC Projects
  • Part 2:Become an Expert in Terraform with AWS
    • Chapter 5, Planning and Designing Infrastructure Projects in AWS
    • Chapter 6, Making Decisions for Terraform Projects with AWS
    • Chapter 7, Implementing Terraform in Projects
    • Chapter 8, Deploying Serverless Projects with Terraform
    • Chapter 9, Deploying Containers in AWS with Terraform
  • Part 3:How to Structure and Advance Terraform in Enterprises
    • Chapter 10, Leveraging Terraform for the Enterprise
    • Chapter 11, Building Git Workflows for IaC and Terraform Projects
    • Chapter 12, Automating the Deployment of Terraform Projects
    • Chapter 13, Governing AWS with Terraform
    • Chapter 14, Building a Secure Infrastructure with AWS Terraform
    • Chapter 15, Perfecting AWS Infrastructure with Terraform

わかりやすい


Figure 1.1 – EKS deployment workflow

anfangdanfangd
  • Module creation workflow
  • Scope the requirements into appropriate modules
  • Create the module MVP
  • Explore a scoping example
  • Network module
  • Application modules
  • Database module
  • Routing module
  • Security module
  • Module creation tips
  • Nesting modules
  • Label and document module elements
  • Define and use a consistent module structure
  • Collaborate on modules
  • Use source control to track modules
  • Develop a module consumption workflow
  • Make modules easy to use
  • Clarify how teams use modules
ログインするとコメントできます