mito’s blog

IT技術メインの雑記。思い立ったが吉日。

Terraform Provider for Ansible「resource "ansible_playbook"」を試してみた

terraform Advent Calendar 2023 の11日目の記事です。

はじめに

気になっていた Terraform Provider for Ansible をこの機に試してみました。
今回の対象は resource "ansible_playbook" です。


試した感触

TerraformとAnsibleを組み合わせるなら、今のところリソースansible_hostを使って、別途Playbookを実行したほうが良さそうです。

本投稿に成功したログを残していますが、投稿の検証のためにapply/destoryを繰り返していたところ、 削除したはずのホストがインベントリに表示していたり、ansibleプラグインが読み込めなかったこともありました。
時間を見つけて調査してみようかと。

mitomito.hatenablog.jp



環境

Ubuntu 22.04.3に構築しています。

  • Terraform : 1.6.5
  • Ansible core : 2.15.6
  • Python : 3.10.12


TerraformでEC2インスタンスを構築する

tfファイル、ansible.cfg、Playbookを作成し、実行します。


Terraformの定義ファイルの作成

resource "ansible_playbook" がPlaybook実行のリソースです。

terraform {
  required_providers {
    ansible = {
      version = "~> 1.1.0"
      source  = "ansible/ansible"
    }
  }
}

provider "aws" {
    region = "ap-northeast-1"
}

### playbookのメインとなるリソース
resource "ansible_playbook" "playbook" {
    playbook                            = "playbook.yml"
    name                                = aws_instance.server.public_dns
    replayable                          = true   ### terraform applyの度に、Playbookを実行

    extra_vars = {
        ansible_user                    = "ec2-user"
        ansible_ssh_private_key_file    = "~/.ssh/xxxx.pem"
    }
}

## 確認できる4つのoutputを表示
output "args" {
  value = ansible_playbook.playbook.args
}

output "temp_inventory_file" {
  value = ansible_playbook.playbook.temp_inventory_file
}

output "playbook_stderr" {
  value = ansible_playbook.playbook.ansible_playbook_stderr
}

output "playbook_stdout" {
  value = ansible_playbook.playbook.ansible_playbook_stdout
}

resource "aws_instance" "server" {
    ami                         = "ami-012261b9035f8f938"
    instance_type               = "t2.micro"
    key_name                    = "xxxx"
    associate_public_ip_address = "true"
    vpc_security_group_ids      = [aws_security_group.blog_sg.id]

    tags = {
        Name                    = "mito-ec2"
    }
}

resource "aws_security_group" "blog_sg" {
    name        = "blog_sg2"
    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"]
    }
}


ansible.cfgの作成

ホストキーのチェックを無効にします。 ドキュメントに記載はなかったのですが、今回コンフィグファイルは読み込めたようです。

[defaults]
host_key_checking = false


AnsibleのPlaybookの作成

gitをインストールするのみのPlaybookです。

---
- hosts: all
  gather_facts: no
  become: yes

  tasks:
    - name: install git
      ansible.builtin.yum:
        name: git
        state: present


terraform applyの実行結果

terraform applyを実行します。

$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # ansible_playbook.playbook will be created
  + resource "ansible_playbook" "playbook" {
      + ansible_playbook_binary = "ansible-playbook"
      + ansible_playbook_stderr = (known after apply)
      + ansible_playbook_stdout = (known after apply)
      + args                    = (known after apply)
      + check_mode              = false
      + diff_mode               = false
      + extra_vars              = {
          + "ansible_ssh_private_key_file" = "~/.ssh/xxxx.pem"
          + "ansible_user"                 = "ec2-user"
        }
      + force_handlers          = false
      + id                      = (known after apply)
      + ignore_playbook_failure = false
      + name                    = (known after apply)
      + playbook                = "playbook.yml"
      + replayable              = true
      + temp_inventory_file     = (known after apply)
      + verbosity               = 0
    }

  # aws_instance.server will be created
()

Plan: 3 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + args                = (known after apply)
  + playbook_stderr     = (known after apply)
  + playbook_stdout     = (known after apply)
  + temp_inventory_file = (known after apply)

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

aws_security_group.blog_sg: Creating...
aws_security_group.blog_sg: Creation complete after 3s [id=sg-07168004190e490bb]
aws_instance.server: Creating...
aws_instance.server: Still creating... [10s elapsed]
aws_instance.server: Still creating... [20s elapsed]
aws_instance.server: Still creating... [30s elapsed]
aws_instance.server: Still creating... [40s elapsed]
aws_instance.server: Creation complete after 41s [id=i-0cfa9440f6cb49b9c]
ansible_playbook.playbook: Creating...
ansible_playbook.playbook: Still creating... [10s elapsed]
ansible_playbook.playbook: Still creating... [20s elapsed]
ansible_playbook.playbook: Creation complete after 23s [id=2023-12-10 18:21:34.340075309 +0000 UTC m=+44.513961043]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

args = tolist([
  "-e",
  "hostname=ec2-13-115-221-150.ap-northeast-1.compute.amazonaws.com",
  "-e",
  "ansible_ssh_private_key_file=~/.ssh/xxxx.pem",
  "-e",
  "ansible_user=ec2-user",
  "playbook.yml",
])
playbook_stderr = ""
playbook_stdout = <<EOT

PLAY [all] *********************************************************************

TASK [install git] *************************************************************
changed: [ec2-13-115-221-150.ap-northeast-1.compute.amazonaws.com]

PLAY RECAP *********************************************************************
ec2-13-115-221-150.ap-northeast-1.compute.amazonaws.com : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


EOT
temp_inventory_file = ""
$ 


インスタンスのステータスチェックをしているのか、たまたま成功したのか。。。