AnsibleからTerraformを呼び出すAnsible Collection cloud.terraform があることを知りました。
Ansibleのワークフローの中でクラウドリソースの作成だけTerraformに任せたい場合に便利そうなので試してみます。
Terraform collection for Ansible とは
- 名前の通りAnsibleのPlaybookからTerraformを呼び出すためのAnsible Collection。
- Ansible Galaxyからダウンロード可能です。
- 2つのモジュールが含まれています。
cloud.terraform.terraform...terraform [plan | apply | destroy]相当cloud.terraform.terraform_output...terraform output相当
Collectionを使ってみる
検証環境情報
以下の環境、バージョンで検証します。
- 開発マシン: macOS Ventura (13.5) Intel版
- Python: 3.11.4
- Ansible Core: 2.15.3
- Terraform CLI 1.5.5
- Terraform collection for Ansible: 1.1.1
本記事で試すこと
Ansible PlaybookからTerraformの実行と実行ログの出力、TerraformではAWSにVPCとSubnetを作成してみます。
また、最終系のディレクトリ構成は次の通りです。
Terraformのファイル群は terraform ディレクトリ、ログファイルの出力先は out ディレクトリとします。
.
├── ansible.cfg
├── inventories
│ └── demo.yml
├── out
│ ├── YYYYmmddTHHMMSS_terraform_apply.log
│ └── YYYYmmddTHHMMSS_terraform_apply.log
├── playbook.yml
├── requirements.txt
├── requirements.yml
└── terraform
├── main.tf
├── outputs.tf
└── variables.tf
Collectionのインストール
ansible-galaxy コマンドでTerraform collectionをインストールします。
ansible-galaxy collection install cloud.terraform
Terraformリソース定義
terraform ディレクトリの下にAWSリソースを作成するtfファイルを作成します。
main.tfにAWSリソースの作成処理、入力変数定義を variables.tf 、そして出力変数定義を outputs.tf を記述します。
main.tf
# main.tf terraform { required_providers { aws = { source = "hashicorp/aws" version = "5.12.0" } } } provider "aws" { region = var.region default_tags { tags = { ManagedBy : "Terraform" } } } resource "aws_vpc" "demo" { cidr_block = "10.23.0.0/16" } resource "aws_subnet" "demo1" { cidr_block = "10.23.45.0/24" vpc_id = aws_vpc.demo.id }
variables.tf
# variables.tf variable "region" { type = string description = "AWS Region" default = "ap-northeast-1" }
outputs.tf
# outputs.tf output "vpc_id" { value = aws_vpc.demo.id description = "VPC ID" }
Playbook定義
Terraformを呼び出すAnsible Playbookを記述します。記述例は次のとおりです。
--- - name: Terraform Demo hosts: localhost tasks: - name: Provisioning infrastructure cloud.terraform.terraform: project_path: "{{ playbook_dir }}/terraform" state: present force_init: true register: ret_tf - name: Write provisioning log ansible.builtin.copy: content: "{{ ret_tf.stdout }}" dest: "{{ playbook_dir }}/out/{{ ansible_date_time.iso8601_basic_short }}_terraform_apply.log" mode: "0644"
cloud.terraform.terraform モジュールで特定のディレクトリ配下のtfファイルを適用します。ディレクトリは project_path で指定しますが、絶対パスで指定しましょう。相対パスだとエラーとなりました。
state パラメータは present だと terraform apply 、absent を指定すると terraform destroy と同じ挙動をします。 terraform plan だけトリッキーで present を指定しつつ ansible-playbook コマンドをチェックモードで実行します。
1点注意すべき点として、Terraform実行途中のログは標準出力に表示されません。Terraformの実行ログはモジュールの stdout 変数に格納されるので ansible.builtin.copy モジュールなどでファイルに出力しておきます。Terraformの処理が中断されたらどこまで適用されたか分からないのは不便ですね。今後の改善に期待です。
いざ実行
ansible-playbook コマンドで Terraform collection を含むPlaybookを実行します。
ansible-playbook -i inventories/demo.yml playbook.yml
Terraformを実行するタスクは処理成功時に changed と表示するはずです。
PLAY [Terraform Demo] **************************************************************************************************** TASK [Gathering Facts] *************************************************************************************************** ok: [localhost] TASK [Provisioning infrastructure] *************************************************************************************** changed: [localhost] TASK [Write provisioning log] ******************************************************************************************** changed: [localhost] PLAY RECAP *************************************************************************************************************** localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Terraformの実行ログ output/YYYYmmddTHHMMSS_terraform_apply.log を参照すると、Terraform CLIと同じような実行ログが出力されていますね。
aws_vpc.demo: Creating... aws_vpc.demo: Creation complete after 1s [id=vpc-000000000000] aws_subnet.demo1: Creating... aws_subnet.demo1: Creation complete after 0s [id=subnet-123412341234] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: vpc_id = "vpc-000000000000"
試しに同じPlaybookを再実行するとTerraformモジュールのタスクが ok に変わります。Terraformの冪等性がAnsible Collectionにも反映されていますね。
PLAY [Terraform Demo] **************************************************************************************************** TASK [Gathering Facts] *************************************************************************************************** ok: [localhost] TASK [Provisioning infrastructure] *************************************************************************************** ok: [localhost] TASK [Write provisioning log] ******************************************************************************************** changed: [localhost] PLAY RECAP *************************************************************************************************************** localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
所管
利用できそうなユースケース
Terraform collectionは次のユースケースで使えそうです。
- TerraformをAnsibleのワークフローに組み込む
- Terraformの前後処理をAnsibleで実行する
- 複数のTerraform stateがあるプロジェクト間の依存解決する
以上。