複数の環境のための地形としてのインフラストラクチャ

12416 ワード

コード(IAC)としてインフラストラクチャでの作業は素晴らしいです.CI/CDパイプラインを含む正しいリポジトリ構造を考え出すことは、それほど単純ではありません.
これが私の2セントです.

動機

  • 変更を監査して前の状態に戻るgitを使う
  • Gitのプル要求による環境の促進( dev -> stg -> prd )
  • 環境毎の快適性維持

  • 提供構造


    生の例を調べるunfor19/terraform-multienv . このリポジトリも使用できますas a template .
    .
    ├── .github
    │   └── workflows
    │       ├── terraform-apply.yml
    │       └── terraform-plan.yml
    ├── cloudformation
    │   └── cfn-tfbackend.yml
    ├── live
    │   ├── backend.tf.tpl
    │   ├── main.tf
    │   ├── providers.tf
    │   └── variables.tf
    └── scripts
        ├── prepare-backend.sh
        ├── prepare-files-folders.sh
        └── terraform.sh
    

    仮定

  • ブランチ名は、環境名、例えばdev , stg and prd
  • CI/CDツールは変数をサポートします${BRANCH_NAME} , 例えば${DRONE_BRANCH}
  • ディレクトリ./live コードファイルとしてインフラストラクチャを含みます*.tf , *.tpl , *.json

  • 複数の環境
  • すべての環境は同じgitリポジトリで維持されます
  • 異なるAWSアカウントの環境のホスティングがサポートされます(推奨)

  • 変数
  • ${ appname name } =your-app-name
  • ${環境} =dev or stg or prd
  • リモートバックエンド


    リソースの作成


    これはAWSコンソールで手動で行うことができます.cloudposse/terraform-aws-tfstate-backend .
    最初に、私はterraformモジュールを使用しました、しかし、私は私が「チキンと卵」状況で立ち往生しているとわかりました.私はそれらのリソースの状態を保存するリソースを作成するためにTerrformを使用しています何?
    私はCloudFormationでこのタスクを実行するのが簡単であるとわかりました.そして、それは全く別々のプロセスになります、そして、それは環境につき一度行われます.
    私はスクリプトを作成しましたscripts/prepare-backend.sh , これは、状態ファイルとstate lock . スクリプトはAWS CLIを使用し、cloudformation/cfn-tfbackend.yml テンプレート.
    注意:リモートバックエンドリソースは、環境ごとに生成されます.

    環境ごとの設定


    この設定の主要な痛みポイントの一つはTerraform Remote Backend 環境ごと.それぞれの環境は独自の「バックエンド設定」を持たなければなりません、そして、値はterraform backend コードブロック.

    Only one backend may be specified, and the configuration may not contain interpolations. Terraform will validate this. Source


    この部分は、実行する前に修正されるテンプレートを作成することによって解決されましたterraform apply .
    live/backend.tf.tpl
    terraform {
      backend "s3" {
        region         = "AWS_REGION"
        bucket         = "APP_NAME-state-ENVIRONMENT"
        key            = "terraform.tfstate"
        dynamodb_table = "APP_NAME-state-lock-ENVIRONMENT"
        encrypt        = false
      }
    }
    
    修正を適用するスクリプトはscripts/prepare-files-folders.sh . それは簡単ですsed コマンドと置換AWS_REGION , APP_NAME and ENVIRONMENT . これらの変更を適用した後、ファイルbackend.tf.tplbackend.tf , そのためにTRARAFORM CLIに利用可能にすることtf 拡張.
    このスクリプトprepare-files-folders.sh より大きな目的を持っています、そして、我々は2、3の瞬間にそれに飛び込みます.

    ブランチ毎環境


    それらのすべてを支配する1つのDIR


    目標は、すべてのIACファイル(TF、JSONなど)を含む1つのディレクトリを持っているし、実行することですterraform apply このディレクトリから.そして再び.scripts/prepare-files-folders.sh 救助に来る.
    meirgabay@~/terraform-multienv (dev)$ ./scripts/prepare-files-folders.sh 
    [LOG] Prepared files and folders for the environment - dev
    total 48
    drwxr-xr-x   8 meirgabay  staff   256B Dec  9 23:06 .
    drwxr-xr-x  19 meirgabay  staff   608B Dec  9 23:06 ..
    -rw-r--r--   1 meirgabay  staff   229B Dec  9 23:06 backend.tf
    -rw-r--r--   1 meirgabay  staff   775B Dec  9 23:06 main.tf
    -rw-r--r--   1 meirgabay  staff    72B Dec  9 23:06 outputs.tf
    -rw-r--r--   1 meirgabay  staff    41B Dec  9 23:06 providers.tf
    -rw-r--r--   1 meirgabay  staff   1.2K Dec  9 23:06 variables.tf
    terraform {
      backend "s3" {
        region         = "eu-west-1"
        bucket         = "tfmultienv-state-dev"
        key            = "terraform.tfstate"
        dynamodb_table = "tfmultienv-state-lock-dev"
        encrypt        = false
      }
    }
    
    新しいディレクトリdev プロジェクトのルートディレクトリに作成され、インフラストラクチャの配置に必要なファイルが含まれます.上記の例はdev , しかし、結果は同じですstg and prd ; 本当に変更する唯一のことはリモートバックエンドの設定です.

    環境変数


    ここはどこですvariables and local values 遊びに出る.
    変数BRANCH_NAME が割り当てられるenvironment , 展開されるブランチに従ってterraform apply . ci/cdプロセスはBRANCH_NAME 私たちはそれに乗ります.
    BRANCH_NAME=dev
    $ (dev) terraform --apply -var environment="$BRANCH_NAME"
    
    live/variables.tf
    variable "environment" {
      type        = string
      description = "dev, stg, prd"
    }
    
    variable "cidr_ab" {
      type = map
      default = {
        dev = "10.1"
        stg = "10.2"
        prd = "10.3"
      }
    }
    
    locals {
      vpc_cidr = "${lookup(var.cidr_ab, var.environment)}.0.0/16"
    }
    
    live/main.tf
    module "vpc" {
      source             = "terraform-aws-modules/vpc/aws"
      cidr               = local.vpc_cidr
      # omitted arguments for brevity
    }
    
    注意:変数の代わりに、リソースやモジュールでローカル値を使う方が好きです.私もそれについて書いた.それは必須ではありませんが、私はそれが最善の練習として考えます.

    シー・シーディー


    この部分は完全にREADMEterraform-multienv . これは全体のプロセスの抽象です.
  • インフラストラクチャを展開する
  •    git checkout dev
       git add .
       git commit -m "deploy dev"
       git push --set-upstream origin dev
    

  • CI/CDサービス( Github action in my case )が起動される
  • に対してstg or prd , トリガーterraform-plan.yml
  • プッシュするdev , stg , prd , トリガーterraform-apply.yml

  • 促進するdev 環境stg
  • PRを作成するdev to stg
  • 計画stg によるコメントとして追加されますterraform-plan パイプラインはこちらan example
  • 変更をマージするstg , とチェックterraform-apply アクションタブで
  • 代替案


  • Terraform Cloud - Gitリポジトリへの統合Workspace

  • terragrunt - あなたの構成を乾燥させて、複数のterraformモジュールで働いて、遠隔状態を管理するために、余分のツールを提供します
  • 参考文献




  • 最終語


    あなたは、私が何も言及しなかったのに気がつきましたscripts/terraform.sh . あなたがこれを持っているので、あなたはそれが何を知っているに値する
  • terraform init
  • terraform plan - プランをMarkdownファイルに保存するplan.md
  • terraform apply - 計画が変更を含む場合のみ実行する
  • 私はあなたがこの便利な、そしてあなたが拍手することを忘れないでください心を共有し、お友達や同僚と共有することを忘れないでください.
    任意の質問や疑問を入手?議論を始めましょう!下記のコメントをお気軽に.
    当初公開meirg.co.il 2020年(平成20年)12月10日