[Terraform+Docker(+NewRelic)] 推荐的环境变量设置方法

用中文将该文章用三行来概述:

    • ①Gitに載せられないセンシティブな環境変数(API KEYとか)はローカルで設定しコンテナに渡す設定にする

 

    • ②Gitに載せられるような環境変数は *.tfvars ファイルに記載

 

    ③各環境ごとのディレクトリを作り、そのディレクトリでTerraformコマンドを叩くことで同一ソースを複数環境でデプロイしよう

条件

    次の過去記事で構築した環境を前提としています

Terraform和Docker环境设置 – Qiita

    NewRelicをTerraformでIaC(Infrastructure as Code)化するプロジェクトを想定しています

环境

    • macOS Big Sur v11.6.1(Intel)

 

    • Docker for Mac v4.3.1

Docker v20.10.11
docker-compose v1.29.2

這個問題

目录结构

---- terraform
   │   └ src
   │   │   └ environment
   │   │   │   └ prod
   │   │   │   │   └ prod.tf
   │   │   │   └ dev
   │   │   │       └ dev.tf
   │   │   └ main
   │   │   │   └ main.tf
   │   │   │   └ その他もろもろ // Terraform関連ソース(docker-composeでマウントする)
   │   └ home
   │   │   └ entrypoint.sh // TerraformコンテナのENTRYPOINTに指定するシェルコマンド
   │   └ root
   │   │   └ .bashrc // bashのエイリアスなどをここに記載
   │   └ Dockerfile
   └ docker-compose.yaml

将无法上传到Git上的敏感环境变量(如API密钥等)设定在本地,并将其传递给容器的设置。

    • ここでの環境変数は環境間で変更する必要はない想定で話を進めます

変更の必要がある場合、この章に記載されているやり方でローカルの環境変数を変更した上で各環境のコンテナを立ち上げる必要があるかと思います

上でも挙げた、下記の過去記事に記載がありますが、改めて要点を記載しておきます

使用Terraform和Docker进行环境构建- Qiita

docker-compose.yml的意思是什么?

environmentでローカルで設定された環境変数をコンテナ環境内に反映させる

version: "3.8"

services:
  terraform:
    container_name: tf
    build: ./terraform
    environment: // コンテナ内の環境変数を指定する => 導入するプロバイダーや求める環境次第
      - NEW_RELIC_API_KEY=${NEW_RELIC_API_KEY}
      - NEW_RELIC_ACCOUNT_ID=${NEW_RELIC_ACCOUNT_ID}
      - NEW_RELIC_REGION=US
    volumes:
      - ./terraform/src:/terraform/src

在本地设置环境变量

    CLIで設定する場合
$ NEW_RELIC_API_KEY=xxxx-xxxxxxxxxxxxxxxxxxxxxxx \
   && echo ${NEW_RELIC_API_KEY}

xxxx-xxxxxxxxxxxxxxxxxxxxxxx
    .zshenvで設定する場合
export NEW_RELIC_API_KEY=xxxx-xxxxxxxxxxxxxxxxxxxxxxx

请重新打开终端,并确认环境变量已正确设置。

echo ${NEW_RELIC_API_KEY}

xxxx-xxxxxxxxxxxxxxxxxxxxxxx

把可以上传到Git的环境变量写在*.tfvars文件中。

    ここについては、実際のTerraform開発時の流れにのって紹介していきます

terraform/home/entrypoint.sh → Terraform的主目录/入口脚本.sh

我突然插一句嘴,但在这里进行terraform init是一个很好的选择,所以我把它放在这里。

#!/bin/bash
echo -e '\n\n//===========================================';
echo -e '// START_[$ terraform init(prod)]';
echo -e '//===========================================';

cd terraform/src/environment/prod;
terraform init;
cd ../../../..

echo -e '\n\n//===========================================';
echo -e '// START_[$ terraform init(stg2)]';
echo -e '//===========================================';

cd terraform/src/environment/stg2;
terraform init;
cd ../../../..

echo -e '\n\n//===========================================';
echo -e '// SHOW_environment';
echo -e '//===========================================';

echo '$NEW_RELIC_API_KEY=' $NEW_RELIC_API_KEY;
echo '$NEW_RELIC_REGION=' $NEW_RELIC_REGION;
echo '$NEW_RELIC_ACCOUNT_ID=' $NEW_RELIC_ACCOUNT_ID;

tail -f /dev/null
    • DockerfileのENTRYPOINTに指定しているファイルです

(今回の構成に合わせて書き換えてますが、仕組みなどについてはこれも過去記事を参照してください)

やっていること

コンテナ起動時、各環境でterraform initコマンドを叩いている
ローカルで定義した環境変数をコンテナに反映している(docker-compose.ymlに記載)ので、正常に反映されているかチェックしている

terraform的根目录为/root/.bashrc

alias ll='ls -la --color' # これは便利なのでおまけ
alias tf='terraform' # これは便利なのでおまけ

# plan
alias plan:dev="cd /terraform/src/environment/dev && terraform plan -var-file ./dev.tfvars && cd ../../../.."
alias plan:prod="cd /terraform/src/environment/prod && terraform plan -var-file ./prod.tfvars && cd ../../../.."

# apply
alias apply:dev="cd /terraform/src/environment/dev && terraform apply -var-file ./dev.tfvars && cd ../../../.."
alias apply:prod="cd /terraform/src/environment/prod && terraform apply -var-file ./prod.tfvars && cd ../../../.."

# tmt
alias fmt="terraform fmt -recursive" # これは便利なのでおまけ
    • やっていること

各環境のディレクトリに移動
Terraformコマンド起動

-var-fileオプションで各環境ごとの環境変数ファイルを定義している

コンテナのルートディレクトリに移動

各環境のディレクトリへの移動は絶対パスで指定しているのでコンテナのどこにいてもコマンドは叩ける
「terraform initが必要」という旨のエラーが現れた場合

各環境のディレクトリに移動した状態でコマンドが中断されているはずなので、そこでinitをすればOK

terraform源代码环境文件夹中的prod和dev目录下的所有tfvars文件。

例如:产品

env              = "prod"
domain           = "www.example_prod.com"
    • 上記****.****bashrc内エイリアスの-var-fileオプションにて指定されている環境変数の定義ファイル

これでplan, applyしたディレクトリ内の.tfファイル内でvariableとして取得し、使用することができる

terraform/源码/环境/生产和开发/*.tf

//-------------------------------------
// variable
//-------------------------------------
variable "env" { type = string }
variable "domain" { type = string }

//-------------------------------------
// modules
//-------------------------------------
module "main" {
  source           = "../../main"
  env              = var.env
  domain           = var.domain
}

//-------------------------------------
// terraform
//-------------------------------------
terraform {
  required_version = "~> 1.0"
  required_providers {
    newrelic = {
      source = "newrelic/newrelic"
    }
  }
}
    • variableブロックで環境変数を取得している

 

    • modulesブロックで環境変数を”main”としているmoduleに渡している

あとは”main”のmoduleから使いたいところまで環境変数をパスしていく

(参考) 中文环境变量的中继方式

terraform 主文件夹下的 modules.tf

		module "urls" {
      source = "./modules/output/urls"
++    domain = var.domain
    }

请下来。
请向下走。

terraform的源代码模块中的output文件夹内的urls文件表格.tf。

      //-------------------------------------
      // variable
      //-------------------------------------
++    variable "domain" {
++      type = string
++    }
      
      //-------------------------------------
      // output
      //-------------------------------------
      output "urls" {
        value = {
--        "https://example.aaaa.com/path/to/hoge" : {
++        "https://${var.domain}:443//path/to/hoge" : {
            url_name = "ほげ"
          }
          
        }
      }
      
      //-------------------------------------
      // terraform
      //-------------------------------------
      terraform {
        required_version = "~> 1.0"
        required_providers {
          newrelic = {
            source = "newrelic/newrelic"
          }
        }
      }

通过创建各个环境的目录,并在目录中运行Terraform命令,可以在多个环境中部署相同的源代码。

直到这一点

    • 各環境ごとのディレクトリ構成ができており

 

    • それぞれの環境で環境変数を定義できていて

 

    • (terraform/src/environment/prod & dev****/.tfvars)***

 

    • それぞれの環境でTerraformコマンドを叩く準備

 

    (terraform/root/.bashrc)

能够做到

---- terraform
   │   └ src
   │   │   └ environment
   │   │   │   └ prod
   │   │   │   │   └ prod.tf
   │   │   │   └ dev
   │   │   │       └ dev.tf
︙

只需在容器内键入命令,就可以了。

$ plan:dev
$ apply:prod

结束

你能够在各个环境中成功应用资源吗?

为了写成文章,我尽量去除了尽可能多的废话,所以可能会省略掉一些必要的部分,也可能有一些我认为很自然而没有写下的事项。

如果遇到任何问题或卡住的地方,请务必在评论中告知,非常感谢!

广告
将在 10 秒后关闭
bannerAds