Terraformは、インフラリソースの構築・変更・バージョン管理を行うためのツールです。コードはTerraform Configuration File( .tf形式または .tf.json形式)で記載します。
Providers にある通り、多数のクラウドサービスに対応していますが、QiitaなどでもAWSの構築記事を見かけることが多いかと思います。
本記事は、TerraformでAzureリソースの作成・変更(複数人でのステートファイル共有)をするための手順となります。
1) Azure CLIとTerraformのインストール
実行にはAzure CLI 2.0(azコマンド)が必要となります。
Azure CLI のインストールにある通りのコマンドを実行してインストールします。以降の手順は、Ubuntu 18.04で実行した手順です。
※インストール実行※
$ which az
$ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
※出力は長いので省略※
※インストール結果の確認※
$ which az
/usr/bin/az
$ az --version
azure-cli 2.0.68
command-modules-nspkg 2.0.3
core 2.0.68
nspkg 3.0.4
telemetry 1.0.3
Python location '/opt/az/bin/python3'
Extensions directory '/home/azureuser/.azure/cliextensions'
Python (Linux) 3.6.5 (default, Jun 28 2019, 06:19:45)
[GCC 7.4.0]
Legal docs and information: aka.ms/AzureCliLegal
Your CLI is up-to-date.
terraformはダウンロード・解凍してできる単一ファイルにパスを通すだけです。Download Terraformから最新版のパスを確認して指定します。
※ダウンロード※
$ wget https://releases.hashicorp.com/terraform/0.12.3/terraform_0.12.3_linux_amd64.zip
--2019-07-05 06:15:42-- https://releases.hashicorp.com/terraform/0.12.3/terraform_0.12.3_linux_amd64.zip
Resolving releases.hashicorp.com (releases.hashicorp.com)... 151.101.77.183, 2a04:4e42:15::439
Connecting to releases.hashicorp.com (releases.hashicorp.com)|151.101.77.183|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16036886 (15M) [application/zip]
Saving to: ‘terraform_0.12.3_linux_amd64.zip’
terraform_0.12.3_linux_amd64.zip 100%[=========================================================================>] 15.29M 23.3MB/s in 0.7s
2019-07-05 06:15:43 (23.3 MB/s) - ‘terraform_0.12.3_linux_amd64.zip’ saved [16036886/16036886]
※解凍してパスを通す※
$ unzip terraform_0.12.3_linux_amd64.zip
Archive: terraform_0.12.3_linux_amd64.zip
inflating: terraform
$ sudo mkdir /opt/terraform0.12.3
$ sudo cp terraform /opt/terraform0.12.3
$ sudo ln -s /opt/terraform0.12.3/terraform /usr/local/bin/terraform
※確認※
$ which terraform
/usr/local/bin/terraform
$ terraform -v
Terraform v0.12.3
2) ステートファイル共有場所(ストレージアカウントとコンテナ)作成
Terraformでは管理しているインフラの状態をステートファイル( .tfstate)というファイルで管理してます。
ステートファイルが正しく共有できていないと、変更のつもりが同名リソースの新規作成になってしまった、といったことが発生するので注意が必要です。Azureなので、今回はBlobストレージ内に共有用のコンテナを1つ作成しておきます。
3) リソースグループを作成・変更してみる
1台目の操作(リソースグループ作成)
リソースグループ作成のための .tfファイルを作成します。ステートファイル設定のところは実行する環境に合わせて修正して下さい。
# Azure Providerの設定
provider "azurerm" {
}
# ステートファイルの設定
terraform {
backend "azurerm" {
storage_account_name = "<先ほど作成したストレージアカウント名>"
container_name = "<先ほど作成したコンテナ名>"
key = "terraform.tfstate" # ステートファイル名
resource_group_name = "<先ほど作成したストレージアカウントのリソースグループ>"
}
}
# 作成するリソースグループの設定
resource "azurerm_resource_group" "test_resource_group" {
name = "test_resource_group"
location = "Japan East"
}
Azure CLIにログイン。サブスクリプションが複数ある場合は、az account setコマンドで対象のサブスクリプションを設定しておきます。
※ログイン※
$ az login
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code GZYxxxxxxx to authenticate.
※→ 表示されたURLをブラウザで表示し、表示されたコードを入力する※
※アカウント(サブスクリプション)一覧の確認※
$ az account list --output table
Name CloudName SubscriptionId State IsDefault
------------------------------- ----------- ------------------- ------- -----------
Azure_Dev AzureCloud 939cxxxxxxx-xxxxxxx Enabled True
Visual Studio Enterprise MPN AzureCloud 0ce0xxxxxxx-xxxxxxx Enabled False
visionarts-demo-env AzureCloud 65b7xxxxxxx-xxxxxxx Enabled False
※作業対象サブスクリプションの設定※
$ az account set --subscription "visionarts-demo-env"
※IsDefaultが設定されたことの確認※
$ az account list --output table
Name CloudName SubscriptionId State IsDefault
------------------------------- ----------- ------------------- ------- -----------
Azure_Dev AzureCloud 939cxxxxxxx-xxxxxxx Enabled False
Visual Studio Enterprise MPN AzureCloud 0ce0xxxxxxx-xxxxxxx Enabled False
visionarts-demo-env AzureCloud 65b7xxxxxxx-xxxxxxx Enabled True
.tfファイルを置いたディレクトリでterraform initを実行
$ terraform init
Initializing the backend...
Successfully configured the backend "azurerm"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "azurerm" (terraform-providers/azurerm) 1.31.0...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.azurerm: version = "~> 1.31"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
terraform planを実行し、リソースグループが1つ作成(予定)と表示されることを確認する。
$ 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:
# azurerm_resource_group.test_resource_group will be created
+ resource "azurerm_resource_group" "test_resource_group" {
+ id = (known after apply)
+ location = "japaneast"
+ name = "test_resource_group"
+ tags = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
terraform applyを実行(途中確認を求められるので"yes"を入力)
$ 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:
# azurerm_resource_group.test_resource_group will be created
+ resource "azurerm_resource_group" "test_resource_group" {
+ id = (known after apply)
+ location = "japaneast"
+ name = "test_resource_group"
+ tags = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
azurerm_resource_group.test_resource_group: Creating...
azurerm_resource_group.test_resource_group: Creation complete after 2s [id=/subscriptions/65b7xxxxxxx-xxxxxxx/resourceGroups/test_resource_group]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
リソースグループが実際に作成されたことを確認します。
また、指定したコンテナ内にステートファイルが作成されていることが確認できます。
2台目の操作(リソースグループ変更)
続いて、2台目の作業です。インストールとログイン・対象サブスクリプションへの切り替え手順は、1台目と全く同じ手順を実施しておきます。
変更用の .tfファイルを作成します。差分は最後の4行で、タグを追加しています。
# Azure Providerの設定
provider "azurerm" {
}
# ステートファイルの設定
terraform {
backend "azurerm" {
storage_account_name = "<1台目で設定したのと同じストレージアカウント名>"
container_name = "<1台目で設定したのと同じコンテナ名>"
key = "terraform.tfstate" # ステートファイル名
resource_group_name = "<1台目で設定したのと同じリソースグループ名>"
}
}
# 作成するリソースグループの設定
resource "azurerm_resource_group" "test_resource_group" {
name = "test_resource_group"
location = "Japan East"
tags = {
environment = "Demo"
}
}
terraform initの実行。
$ terraform init
Initializing the backend...
Successfully configured the backend "azurerm"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "azurerm" (terraform-providers/azurerm) 1.31.0...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.azurerm: version = "~> 1.31"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
次に terraform planを実行し、リソースグループが1つ変更(予定)と表示されることを確認します。
ここで 1台目と同じ新規作成(予定)が表示される場合はステートファイルの参照に失敗しているので、ここまでの手順を再確認して下さい。
$ 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.
azurerm_resource_group.test_resource_group: Refreshing state... [id=/subscriptions/65b7xxxxxxx-xxxxxxx/resourceGroups/test_resource_group]
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# azurerm_resource_group.test_resource_group will be updated in-place
~ resource "azurerm_resource_group" "test_resource_group" {
id = "/subscriptions/65b7xxxxxxx-xxxxxxx/resourceGroups/test_resource_group"
location = "japaneast"
name = "test_resource_group"
~ tags = {
+ "environment" = "Demo"
}
}
Plan: 0 to add, 1 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
terraform applyを実行(1台目同様確認に"yes"を入力)
$ terraform apply
azurerm_resource_group.test_resource_group: Refreshing state... [id=/subscriptions/65b7xxxxxxx-xxxxxxx/resourceGroups/test_resource_group]
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# azurerm_resource_group.test_resource_group will be updated in-place
~ resource "azurerm_resource_group" "test_resource_group" {
id = "/subscriptions/65b7xxxxxxx-xxxxxxx/resourceGroups/test_resource_group"
location = "japaneast"
name = "test_resource_group"
~ tags = {
+ "environment" = "Demo"
}
}
Plan: 0 to add, 1 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
azurerm_resource_group.test_resource_group: Modifying... [id=/subscriptions/65b7xxxxxxx-xxxxxxx/resourceGroups/test_resource_group]
azurerm_resource_group.test_resource_group: Modifications complete after 3s [id=/subscriptions/65b7xxxxxxx-xxxxxxx/resourceGroups/test_resource_group]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
リソースグループにタグが付与されたことを確認します。
また、2台目の作業によってステートファイルが更新されたことが確認できます。
以上でTerraformによるAzureリソースの作成・変更(複数人でのステートファイル共有)が確認できました。