【Terraform】環境ごとにリソースの数が異なる場合の設定方法(同じtfファイルを利用する場合)

Terraform でインフラ環境を構築していると、当然のごとく prod 環境(本番環境)、stg 環境(ステージング環境)、dev 環境(開発環境)の複数環境が出てきます。

今回は同じ tf ファイルを使い、且つ環境ごとにリソースの数が異なる場合の設定方法について解説します。

 

環境ごとに構成を変える場合にどうするか?

prod 環境(本番環境)、stg 環境(ステージング環境)、dev 環境(開発環境)で設定が異なるのは当然です。

 

環境ごとに tf ファイルを作成する

一番簡単なのは、以下のようにディレクトリを分けてそれぞれに tf ファイルを作ることです。

 

■一番簡単に環境を分ける例

$ tree 

└── env 
    ├── dev 
    │   └── main.tf 
    ├── prod 
    │   └── main.tf 
    └── stg 
        └── main.tf 

 

この場合は環境ごとに差分がいくらあろうが、各環境が独立をしているのでリソースの数が異なろうが特に問題になることはありません。

ただし折角 Terraform でインフラ構成をコード化しているのにこの構成はもったいないと言えます。

 

それと検証環境で問題なかったので同じように本番環境でデプロイしたが、実は気が付かない部分で本番環境の tf ファイルと検証環境の tf ファイルに差分があり障害が発生するという可能性も出てきます。

 

tf ファイルを共通化して変数を使って環境ごとに設定を分ける

例えば以下のように設計して、同じ tf ファイルを使用するが環境変数を利用して環境ごとに設定を分ける(例:CIDRブロックやIP、EC2インスタンスタイプ、名前など)ことが出来ます。

 

■ファイル一覧

ls 
dev.tfvars       main.tf         variables.tf 
dev.tfbackend    prod.tfvars     vpc.tf

 

 

■variables.tf ファイル

$ cat variables.tf  
#—————————————- 
#  Common  
#—————————————- 
variable “env” {} 
 
#—————————————- 
#  AWSアカウント  
#—————————————- 
variable “aws_account” {} 
 
#—————————————- 
#  VPC  
#—————————————- 
variable “vpc_cidr_block” {} 

 

 

■dev.tfvars

cat dev.tfvars  
env                                = “dev” 
aws_account                        = “1111111111” 
vpc_cidr_block                     = “10.1.0.0/16”

 

 

■prod.tfvars 

cat prod.tfvars  
env                     = “prod” 
aws_account             = “222222222222” 
vpc_cidr_block          = “10.2.0.0/16”

 

 

■vpc.tf

$ cat vpc.tf  
#—————————————– 
# VPC の作成 
#—————————————– 
resource “aws_vpc” “vpc” { 
  cidr_block = var.vpc_cidr_block 
 
  tags = { 
    Name = “system-${var.env}-vpc” ← 環境ごとに異なる値を使う場合はこのように ${var.env} で値(devかprod)を持ってきます。
  } 

 

 

実際に terraform コマンドを実行する場合は以下のように変数のファイルを引数として与えます。

 

■terraform init コマンドを実行(開発環境)

$ terraform init -var-file=dev.tfvars

 

■terraform init コマンドを実行(本番環境)

$ terraform init -var-file=prod.tfvars

 

■terraform plan コマンドを実行(開発環境)

$ terraform plan -var-file=dev.tfvars

 

■terraform plan コマンドを実行(本番環境)

$ terraform plan -var-file=prod.tfvars

 

■terraform apply コマンドを実行(開発環境)

$ terraform apply -var-file=dev.tfvars

 

■terraform apply コマンドを実行(本番環境)

$ terraform apply -var-file=prod.tfvars

 

上記のように環境変数の値が入っているファイル(この例では dev.tfvars や prod.tfvars)を指定することで、開発環境や本番環境を構築できます。

そして一番のメリットは、「本番環境と開発環境で同じ tf ファイルを利用するので本番環境と開発環境で環境が異ならないことを担保できる」ということです。

これは障害の発生を抑制出来たり運用を楽にしてサービスの品質を上げることが出来ます。

「開発環境の tf ファイルを修正したので、同じように本番環境の tf ファイルを修正しなければいけない。。面倒だな~」と思ってくると将来の障害発生が予測できてしまいますが、この場合は「そもそも tf ファイルが同じ」なのでこの観点での障害は発生しようがないですよね。

 

 

本題:同じ tf ファイルで環境ごとにリソースの数が異なる場合の設定方法

いよいよ本断です。

開発環境と本番環境が全く一緒の構成なら何の問題もありません。

一番理想的な状態と言えます。

しかし運用していく中でいろいろな追加・変更・修正が発生してきます。

どうしようもない理由で開発環境だけ●●を追加する。本番環境だけ●●の設定を追加する、などの差分が発生してきます。

これはしょうがないです。可能な限り本番環境と開発環境を同一にしたくても限界があります。

 

その場合、どうすればいいのでしょうか?

 

例えば、以下のケースを考えてみました。

  • 本番環境:セキュリティグループのルールが1つ
  • 開発環境:セキュリティグループのルールが3つ

 

理由は、開発環境の場合は様々なベンダーが絡んできてどうしても開発環境だけセキュリティグループで開発ベンダーの開発・検証・動確の為にルールを追加してポートを開放しなければいけないということが発生すると思われるからです。

 

では、実際に設定をしてみます。

 

count関数を利用して三項演算子でルールを作る・作らないを決める(if文のような使い方)

本番環境ではセキュリティグループのルールは1つだけでいい。しかし開発環境は3つルールを作る必要がある。

つまりあらかじめルールを3つ作っておき、本番環境の場合はスキップをすればいいのです。

そこで「Terraform に if 文のようなものはないかな~」と思って探してみたところありました。

count関数を利用して三項演算子で本番環境の場合は count を 0 に設定して、開発環境の場合は count を 1 に設定すれば行けるのでは?と考えて調査してみました。

以下のようなイメージです。

 

■三項演算子のイメージ

count = “${var.env == “prod” ? “0” : “1”}”

 

何となく眺めているだけで理解できると思いますが、env が prod の場合は count に 0 が入ります。つまり、スキップされます。

env が dev の場合は count に 1 が入ります。つまり、実行されます。

 

 

まずは単純に terraform でリソースを定義して、count を 0 にしてスキップされるのか確認してみました。

 

■securitygroup.tf ファイル(まずは直接 count に 0 を入れてみてスキップされるか動作確認)

$ cat securitygroup.tf  
#—————————————– 
# セキュリティグループの作成 
#—————————————– 
resource “aws_security_group” “securitygroup” { 
  name = “system-${var.env}-securitygroup” 
  description = “Terraform Security Group Test” 
  vpc_id = aws_vpc.vpc.id 
 
  tags = { 
    Name = “system-${var.env}-securitygroup” 
  } 

 
resource “aws_security_group_rule” “ingress_https_test1” { 
  description       = “HTTP Rule 1” 
  from_port         = “443” 
  to_port           = “443” 
  protocol          = “tcp” 
  security_group_id = aws_security_group.securitygroup.id 
  type              = “ingress” 
  cidr_blocks       = [“${var.source_ip1}”] 

 
resource “aws_security_group_rule” “ingress_https_test2” { 
  count             = 0 ← count を追加する。直接 0 を入れてみる。 
  description       = “HTTP Rule 2 Only Dev” 
  from_port         = “443” 
  to_port           = “443” 
  protocol          = “tcp” 
  security_group_id = aws_security_group.securitygroup.id 
  type              = “ingress” 
  cidr_blocks       = [“${var.source_ip2}”] 

 
resource “aws_security_group_rule” “ingress_https_test3” { 
  count             = 0 ← count を追加する。直接 0 を入れてみる。  
  description       = “HTTP Rule 3 Only Dev” 
  from_port         = “443” 
  to_port           = “443” 
  protocol          = “tcp” 
  security_group_id = aws_security_group.securitygroup.id 
  type              = “ingress” 
  cidr_blocks       = [“${var.source_ip3}”] 

 

動作確認をしたところ、問題なくスキップされました。

 

では次に三項演算子を設定します。

 

 

■securitygroup.tf ファイル(三項演算子を設定して環境ごとに実行されるかスキップされるようにする)

$ cat securitygroup.tf  
#—————————————– 
# セキュリティグループの作成 
#—————————————– 
resource “aws_security_group” “securitygroup” { 
  name = “system-${var.env}-securitygroup” 
  description = “Terraform Security Group Test” 
  vpc_id = aws_vpc.vpc.id 
 
  tags = { 
    Name = “system-${var.env}-securitygroup” 
  } 

 
resource “aws_security_group_rule” “ingress_https_test1” { 
  description       = “HTTP Rule 1” 
  from_port         = “443” 
  to_port           = “443” 
  protocol          = “tcp” 
  security_group_id = aws_security_group.securitygroup.id 
  type              = “ingress” 
  cidr_blocks       = [“${var.source_ip1}”] 

 
resource “aws_security_group_rule” “ingress_https_test2” { 
  count             = “${var.env == “prod” ? “0” : “1”}”  ← 三項演算子を入れて prod はスキップ、dev は実行されるようにする。
  description       = “HTTP Rule 2 Only Dev” 
  from_port         = “443” 
  to_port           = “443” 
  protocol          = “tcp” 
  security_group_id = aws_security_group.securitygroup.id 
  type              = “ingress” 
  cidr_blocks       = [“${var.source_ip2}”] 

 
resource “aws_security_group_rule” “ingress_https_test3” { 
  count             = “${var.env == “prod” ? “0” : “1”}”  ← 三項演算子を入れて prod はスキップ、dev は実行されるようにする。
  description       = “HTTP Rule 3 Only Dev” 
  from_port         = “443” 
  to_port           = “443” 
  protocol          = “tcp” 
  security_group_id = aws_security_group.securitygroup.id 
  type              = “ingress” 
  cidr_blocks       = [“${var.source_ip3}”] 

 

 

設定したら以下のように各環境で terraform plan を実行します。

 

■terraform plan コマンドを実行(開発環境)

$ terraform plan -var-file=dev.tfvars

 

■terraform plan コマンドを実行(本番環境)

$ terraform plan -var-file=prod.tfvars

 

 

これで各環境で同じ tf ファイルを利用していてリソースの数が異なっても運用できるようになりました。

 

 

 

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

AlphaOmega Captcha Medica  –  What Do You See?
     
 

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください