この記事は、Ansible Advent Calendar 2023 の3日目のエントリです。
はじめに
気になっていた Terraform Provider for Ansible をこの機に触ってみました。
Terraform Provider for Ansible のまとめ
- Terrafromの定義ファイルに
resource "ansible_host"
を追加する
- Ansibleのインベントリファイルに
cloud.terraformプラグイン
を指定する
- インベントリファイルがtfstateの該当箇所を読み込む
環境
Ubuntu 22.04.3に構築しています。
- Ansible環境
- Ansible core : 2.15.6
- Python : 3.10.12
- cloud.terraform : 2.0.0
- Terraform環境
環境の準備
Ansibleコレクションにて、cloud.terraform をインストールします。
$ ansible-galaxy collection install cloud.terraform
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/cloud-terraform-2.0.0.tar.gz to /home/ubuntu/.ansible/tmp/ansible-local-12661qsgjsrrt/tmpzhqh3nnq/cloud-terraform-2.0.0-a_5loo9d
Installing 'cloud.terraform:2.0.0' to '/home/ubuntu/.ansible/collections/ansible_collections/cloud/terraform'
cloud.terraform:2.0.0 was installed successfully
$
$
$ ansible-galaxy collection list
Collection Version
----------------------------- -------
cloud.terraform 2.0.0
(略)
$
次に、terraformのansibleプラグインをインストールします。
ただしterrafrom initでインストールされるため、準備では割愛します。
3台のEC2インスタンスを構築します。
定義ファイルの作成
鍵はあらかじめ作成してあるものを流用、セキュリティグループはSSHのみ開けています。
terraform {
required_providers {
ansible = {
version = "~> 1.1.0"
source = "ansible/ansible"
}
}
}
### ansible host details 今回のメイン。後述のtfstateに記載される。
resource "ansible_host" "inventory" {
for_each = var.instance
name = aws_instance.server[each.value.name].public_dns
groups = ["test_group"]
variables = {
ansible_user = "ec2-user",
ansible_ssh_private_key_file = "~/.ssh/xxx.pem", # Terraformのkey指定と違い、ファイル名なので拡張子も必要。
}
}
provider "aws" {
region = "ap-northeast-1"
}
variable instance {
type = map
default = {
mito = { name = "mito" },
mito-ec2 = { name = "mito-ec2" },
mito-ec22 = { name = "mito-ec22" },
}
}
resource "aws_instance" "server" {
for_each = var.instance
ami = "ami-012261b9035f8f938"
instance_type = "t2.micro"
key_name = "xxx"
associate_public_ip_address = "true"
vpc_security_group_ids = [aws_security_group.blog_sg.id]
tags = {
Name = each.value.name
}
}
resource "aws_security_group" "blog_sg" {
name = "blog_sg"
description = "blog_sg"
dynamic "ingress" {
for_each = [22]
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
EC2インスタンス作成のほか、tfstateには以下のように resource "ansible_host"
の結果が記載されます。
"resources": [
{
"mode": "managed",
"type": "ansible_host",
"name": "inventory",
"provider": "provider[\"registry.terraform.io/ansible/ansible\"]",
"instances": [
{
"index_key": "mito",
"schema_version": 0,
"attributes": {
"groups": [
"test_group"
],
"id": "ec2-13-114-117-20.ap-northeast-1.compute.amazonaws.com",
"name": "ec2-13-114-117-20.ap-northeast-1.compute.amazonaws.com",
"variables": {
"ansible_ssh_private_key_file": "~/.ssh/xxx.pem",
"ansible_user": "ec2-user"
}
},
Ansibleのansible-inventoryコマンドを実行する
まずは、resource "ansible_host"
の結果がどう反映されるか確認するため、ansible-inventoryコマンドを実行します。
インベントリファイルの作成
cloud.terraformプラグインを指定します。
---
plugin: cloud.terraform.terraform_provider
ansible-inventoryコマンドの実行結果
無事に、ホスト情報が出力されました。
$ ansible-inventory -i inventory.yml --graph --vars
@all:
|--@ungrouped:
|--@test_group:
| |--ec2-13-114-117-20.ap-northeast-1.compute.amazonaws.com
| | |--{ansible_ssh_private_key_file = ~/.ssh/xxx.pem}
| | |--{ansible_user = ec2-user}
| |--ec2-35-78-213-104.ap-northeast-1.compute.amazonaws.com
| | |--{ansible_ssh_private_key_file = ~/.ssh/xxx.pem}
| | |--{ansible_user = ec2-user}
| |--ec2-13-231-192-241.ap-northeast-1.compute.amazonaws.com
| | |--{ansible_ssh_private_key_file = ~/.ssh/xxx.pem}
| | |--{ansible_user = ec2-user}
$
Ansibleのplaybookを実行する
インベントリファイルを指定して、簡単なPlaybookを実行し、動作を確認してみます。
playbookの作成
gitのみインストールします。
---
- hosts: all
gather_facts: no
become: yes
tasks:
- name: install git
ansible.builtin.yum:
name: git
state: present
ansible.cfgの作成
Fingerprintのチェックを無効にしておきます。
[defaults]
host_key_checking = False
playbookの実行結果
Terraform Provider for Ansibleを指定したインベントリファイルで、正常にPlaybookが実行できました。
$ ansible-playbook -i inventory.yml playbook.yml
PLAY [all] *************************************************************************************************
TASK [install git] *****************************************************************************************
changed: [ec2-13-114-117-20.ap-northeast-1.compute.amazonaws.com]
changed: [ec2-35-78-213-104.ap-northeast-1.compute.amazonaws.com]
changed: [ec2-13-231-192-241.ap-northeast-1.compute.amazonaws.com]
PLAY RECAP ************************************************************************************************
ec2-13-114-117-20.ap-northeast-1.compute.amazonaws.com : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ec2-13-231-192-241.ap-northeast-1.compute.amazonaws.com : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ec2-35-78-213-104.ap-northeast-1.compute.amazonaws.com : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$
終わりに
インベントリーファイルに、フィルターを組み合わせて使う感じで良さそう。