目次
こんにちは。BeeXの粥川です。
皆さんあるある話だとは思いますが、最近複数の案件で既に構築済みのProduction環境からStaging環境をすぐ作って!PerformanceTest環境もよろしく!という話が多数ありました。プラットフォームはどれもAWSなので、最初からCloudFormationやTerraformでデプロイしてるからすぐできます!なら楽なのですが、実際のプロジェクトだとGUI、CLIで構築しているケースはまだまだ多く、パパっとデプロイできない・・・一からGUIで作るか・・・と地道な作業となることも。
ただ今後もさらに複製環境が増える場合や、一度作って削除してを繰り返す場合も考えられます。そこで、本記事ではインフラ構成管理ツールであるTerraform+terraformingでProduction環境をインポート、コード化して複製したStaging環境を提供してみます。
実際に作業する前に
少し用語の説明を。
Terraformとは
HashiCorp社が開発している、インフラ構成管理ツールです。
ググればいろんな方が説明されているので、ポイントだけ。
・構築するインフラの定義ファイル(.tfファイル)を記述していく。
・定義ファイルを記述後、いざデプロイすると記述通りのインフラが出来上がる。
・構築されたインフラの状態は、状態ファイル(tfstateファイル)に記述されている。
terraformingとは
dtan4さんがメンテナンスされている、Terraformの定義ファイル(.tfファイル)を自動で作成してくれるツールです。
なぜterraformingを使うのか
実は、Terraformには公式で提供するimportというコマンドがあります。importコマンドを使うことで、既に構築済みのインフラをimportしTerraformの管理対象とすることが可能です。しかしここで問題なのが、importコマンドは定義ファイル(.tfファイル)を作成してくれないということです。importコマンドは状態ファイル(tfstateファイル)に現在の状態を記述してくれるのですが、そこから定義ファイルを作成する部分が手動になってしまいます。そこで、定義ファイルも自動で作成してくれるterraformingの出番!ということですね。
事前準備
Production環境の複製を始める前に、作業環境を整えます。
Terraform、terraformingのインストール
Terraformのパッケージマネージャーであるtfenvを使ってインストールします。今回はバージョン0.12.6をインストールしています。
$ brew
install
tfenv
$ tfenv
install
0.12.6
terraformingをgemでインストールします。
$ gem
install
terraforming
ここで、作業ディレクトリも作成しておきます。Production環境とStaging環境でフォルダを分けました。まずProduction環境のインポートを行うので、prodディレクトリに移動します。
$
mkdir
-p tfdemo
/prod
$
mkdir
-p tfdemo
/stg
$
cd
tfdemo
/prod
Credentialsの指定
AWSのAPIをコールするため、Credentialsを環境変数にセットします。
今回はAdministratorAccess権限をもったIAMユーザを使用しています。
リージョンはフランクフルトを指定しました。
$
export
AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX
$
export
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
$
export
AWS_DEFAULT_REGION=eu-central-1
構築済みインフラ環境の確認
インポート作業をする前に、インポートする環境(仮想のProduction環境)を構築しておきます。作業手順は割愛しますが、下記環境を構築しました。
ALBでhttpsアクセスを受けてEC2上の静的コンテンツを返すだけのWebサイトです。1VPCにPublic、Private Subnetがそれぞれ2つずつ、Public Subnet内のALBからPrivate SubnetのEC2にhttpでルーティングする構成になっています。
ただのテキストですが、、アクセスするとこんなページが表示されます。
Production環境のインポート
それでは、事前準備が終わりましたので、terraformingでProduction環境をインポートし、.tfファイルを作成します。
terraforming実行
初めにvpcを指定してインポートしてみます。
terraformingでは以下のようにサービスを指定すると、リージョン内の情報を一括で定義ファイル(.tfファイル)形式で出力します。
$ terraforming vpc
resource
"aws_vpc"
"vpc-prod"
{
cidr_block =
"172.20.0.0/16"
enable_dns_hostnames =
true
enable_dns_support =
true
instance_tenancy =
"default"
tags {
"Name"
=
"vpc-prod"
}
}
resource
"aws_vpc"
"vpc-331efa5a"
{
cidr_block =
"172.31.0.0/16"
enable_dns_hostnames =
true
enable_dns_support =
true
instance_tenancy =
"default"
tags {
}
}
同じようにSubnetやSecurityGroupも定義ファイル化し、作業ディレクトリ配下はこのようになりました。
prod
├── alb.tf
├── ec2.tf
├── eip.tf
├── igw.tf
├── nacl.tf
├── natgw.tf
├── route53.tf
├── rt.tf
├── sg.tf
├── subnet.tf
└── vpc.tf
上記で元となる.tfファイルの作成が完了しました。今回Production環境はTerraform管理下におかず、複製環境のみコード化します。Staging環境用のフォルダに上記ファイルを全てコピーします。
$
cp
-p prod/* stg/
$
cd
stg
Staging環境のデプロイ
Staging環境用に..tfファイルを修正し、Terraformでデプロイします。
TFSTATEファイルの管理場所指定
.tfファイルを修正する前に、tfstateファイルの管理場所を指定しておきます。tfstateファイルをローカル管理にしてしまうと、複数人で共有することができなくなります。そこで今回はS3バケットを指定しました。
# config.tf
provider
"aws"
{
region =
"eu-central-1"
}
terraform {
backend
"s3"
{
bucket =
"tfconf.example.com"
key =
"stg.tfstate"
region =
"eu-central-1"
}
}
作業ディレクトリ直下に上記ファイルを作成後、以下コマンドを実行し、tfstateファイルの保管先を認識させます。
$ terraform init
Terraform has been successfully initialized! と表示されれば完了です。
.tfファイルの修正
terraformingで作成した.tfファイルは、Production環境の各リソースid等ユニークな値が入っています。そこで、それらを変数に修正しました。例としてsubnet.tfファイルを以下のように修正しています。
# subnet.tf
resource
"aws_subnet"
"vpc-stg-pub-sub02"
{
vpc_id =
"${aws_vpc.vpc-stg.id}"
cidr_block =
"172.21.102.0/24"
availability_zone =
"eu-central-1c"
map_public_ip_on_launch =
false
tags = {
Name =
"vpc-stg-pub-sub02"
}
}
resource
"aws_subnet"
"vpc-stg-pri-web-sub02"
{
vpc_id =
"${aws_vpc.vpc-stg.id}"
cidr_block =
"172.21.2.0/24"
availability_zone =
"eu-central-1c"
map_public_ip_on_launch =
false
tags = {
Name =
"vpc-stg-pri-web-sub02"
}
}
resource
"aws_subnet"
"vpc-stg-pub-sub01"
{
vpc_id =
"${aws_vpc.vpc-stg.id}"
cidr_block =
"172.21.101.0/24"
availability_zone =
"eu-central-1a"
map_public_ip_on_launch =
false
tags = {
Name =
"vpc-stg-pub-sub01"
}
}
resource
"aws_subnet"
"vpc-stg-pri-web-sub01"
{
vpc_id =
"${aws_vpc.vpc-stg.id}"
cidr_block =
"172.21.1.0/24"
availability_zone =
"eu-central-1a"
map_public_ip_on_launch =
false
tags = {
Name =
"vpc-stg-pri-web-sub01"
}
}
他のリソースも同様に修正します。Staging環境のデプロイが完了すると同時に、stg-www.example.comへアクセスできるよう、route53.tfファイルでALIASレコードを追加しています。
# route53.tf
resource
"aws_route53_record"
"stg-www"
{
name =
"stg-www"
type
=
"A"
zone_id =
"XXXXXXXXXXXXXX"
alias
{
evaluate_target_health =
false
name =
"${aws_alb.stg-alb-web01.dns_name}"
zone_id =
"${aws_alb.stg-alb-web01.zone_id}"
}
}
実行計画の確認
他の.tfファイルの修正が完了したら、デプロイする前に実行計画を確認します。
新たにStaging環境用のリソースを作成するため、全て+ createになっています。
$ terraform plan
Refreshing Terraform state
in
-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to
local
or remote state storage.
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_alb.stg-alb-web01 will be created
+ resource
"aws_alb"
"stg-alb-web01"
{
+ arn = (known after apply)
+ arn_suffix = (known after apply)
+ dns_name = (known after apply)
+ enable_deletion_protection =
false
+ enable_http2 =
true
+
id
= (known after apply)
+ idle_timeout = 60
+ internal =
false
+ ip_address_type = (known after apply)
+ load_balancer_type =
"application"
+ name =
"stg-alb-web01"
+ security_groups = (known after apply)
+ subnets = (known after apply)
+ tags = {
+
"Name"
=
"stg-alb-web01"
}
+ vpc_id = (known after apply)
+ zone_id = (known after apply)
+ subnet_mapping {
+ allocation_id = (known after apply)
+ subnet_id = (known after apply)
}
}
・
・
・
Plan: 25 to add, 0 to change, 0 to destroy.
デプロイ実行
実行計画を確認しましたので、デプロイを実行します。
$ terraform apply
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_alb.stg-alb-web01 will be created
+ resource
"aws_alb"
"stg-alb-web01"
{
+ arn = (known after apply)
+ arn_suffix = (known after apply)
・
・
・
Apply complete! Resources: 25 added, 0 changed, 0 destroyed.
デプロイが無事完了しました!では、stg-www.example.comへアクセスしてみます。
想定通り、ページが表示されました!デプロイするEC2のuserdataで、コンテンツを差し替えていたので、ページの内容もStaging環境用に変更されています。
Subnet等も、もちろん自動で作成されています。
今回デプロイしたStaging環境を図示すると、下記のようになります。
赤枠部分がデプロイした箇所です。
まとめ
Terraform+terraformingを使って既存のProduction環境からStaging環境をデプロイしました。複製する環境用に一から.tfファイルを書いてもよいのですが、terraformingを使うことで、.tfファイルの作成を短縮化しました。
一度作成してしまえば、今後同様に他の環境を作りたい!となったときも、少し修正するだけですぐにデプロイできてしまいますね。
また、デプロイした環境は terraform destroy を実行すれば一式削除できますので、デプロイ&削除を繰り替えすような環境にも最適です。
今回はTerraformを使用しましたが、AWSではいえばCloudFormationもありますし、最近リリースされたAWS CDKもあります。既存環境のインポートなんかはAWS CDKを使えば自作できそうなので、今後検証してみます。
- カテゴリー