mito’s blog

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

[Ansible] Terraformモジュールを使う際に気を付けるポイント

はじめに

AnsibleでTerraformモジュールを使った際に、気を付けるポイントを書き留めておきます。
以下にはまりました。

  1. Terraformのoutputの変数名にハイフンを使用していたため、Ansibleで呼び出せずエラーになった。
    • 原因はTerraformでは変数名にハイフンを使えるが、Ansibleでは使えないため。
  2. terraformモジュール実行後、次のタスクが失敗することがあった。
    • 原因はsshサービスが起動する前に次のタスクが走っていたため。
    • remote-execはインスタンスの起動待ちを気にしなくていいが、Playbookでは起動完了までwaitをいれたほうが安全。


解決策

以下で解決しました。

  1. outputの変数名をハイフンからアンダースコアに修正しました。
    • Terraform全体では、ハイフンとアンダースコアが混ざっている状態なのでちょっともやもや。
    • OSSを連携させるときに、こういった仕様も確認しなくては。
  2. shellモジュールを用いて、起動するまで待つステータスチェックのAWSコマンドを使用しました。
    • awsモジュールで実現したかったけど、見つけられませんでした。


環境

  • Ubuntu: 22.04.1
  • ansible core: 2.13.6
  • terraform: 1.3.4
  • community.general: 6.0.0
  • aws cli: 1.22.34


terraformで構築するインスタンス

outputの変数名はアンダースコアに修正済みです。
インスタンスIDはAWSコマンドの引数として使用するため、outputで出力しています。

provider "aws" {
    region = "ap-northeast-1"
    access_key = "XXXXX"
    secret_key = "XXXXX"
}

resource "aws_instance" "mito-ec2" {
    ami           = "ami-03f4fa076d2981b45"
    instance_type = "t2.micro"
    associate_public_ip_address = "true"
    vpc_security_group_ids = ["XXXXX"]
    key_name = "XXXXX"
    tags = {
        Name = "mito-ec2"
    }
}

output "ec2_id"{
    value = aws_instance.mito-ec2.id
}


実行するPlaybook

インスタンスの起動完了待ちは、aws ec2 wait instance-status-okコマンドを使用します。
引数に、outputで出力したインスタンスIDを指定します。

---
- hosts: localhost
  gather_facts: no

  tasks:
  - name: terraform apply
    community.general.terraform:
      project_path: 'terraform/'
      force_init: yes
      state: present
    register: result

  - name: wait instance_status_ok
    shell:
      cmd: "aws ec2 wait instance-status-ok --instance-ids {{ result.outputs.ec2_id.value }}"

  - name: get instance_status
    shell:
      cmd: "aws ec2 describe-instance-status --instance-ids {{ result.outputs.ec2_id.value }}"
    register: result_instance_status

  - name: debug
    debug:
      msg: "{{ result_instance_status.stdout_lines }}"


実行ログ

Playbookを実行します。
aws ec2 describe-instance-statusの実行結果で、起動完了が確認できます。

$ ansible-playbook terraform_module.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the 
implicit localhost does not match 'all'

PLAY [localhost] **************************************************************

TASK [terraform apply] ********************************************************
changed: [localhost]

TASK [wait instance_status_ok] ************************************************
changed: [localhost]

TASK [get instance_status] ****************************************************
changed: [localhost]

TASK [debug] *****************************************************************
ok: [localhost] => {
    "msg": [
        "{",
        "    "InstanceStatuses": [",
        "        {",
        "            "AvailabilityZone": "ap-northeast-1c",",
        "            "InstanceId": "i-0080415c81f9dd541",",
        "            "InstanceState": {",
        "                "Code": 16,",
        "                "Name": "running"",
        "            },",
        "            "InstanceStatus": {",
        "                "Details": [",
        "                    {",
        "                        "Name": "reachability",",
        "                        "Status": "passed"",
        "                    }",
        "                ],",
        "                "Status": "ok"",
        "            },",
        "            "SystemStatus": {",
        "                "Details": [",
        "                    {",
        "                        "Name": "reachability",",
        "                        "Status": "passed"",
        "                    }",
        "                ],",
        "                "Status": "ok"",
        "            }",
        "        }",
        "    ]",
        "}"
    ]
}

PLAY RECAP *******************************************************************
localhost: ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0   

$ 


エラーメッセージ

outputの変数にハイフンを使った場合のエラーで、ec2-idとしています。
リソースは作成されますが、waitで失敗します。

$ ansible-playbook terraform_module.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the 
implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************

TASK [terraform apply] *********************************************************
changed: [localhost]

TASK [wait instance_status_ok] *************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined 
variable. The error was: 'dict object' has no attribute 'ec2'\n\nThe error appears to 
be in '/home/ubuntu/test/terraform_module.yml': line 13, column 5, but may\nbe 
elsewhere in the file depending on the exact syntax problem.\n\nThe offending line 
appears to be:\n\n\n  - name: wait instance_status_ok\n    ^ here\n"}

PLAY RECAP *********************************************************************
localhost: ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0   

$