この記事は、Ansible Advent Calendar 2022 の2日目のエントリです。
はじめに
今回はAnsibleのTerraformモジュールを使うのではなく、TerraformでEC2インスタンスを作成し、local-execでPlaybookを実行してパッケージをインストールします。
AnsibleのAmazonEC2のインベントリプラグインは使わず、出来る限りTerraformで実装してみます。
Provisioner: local-exec | Terraform | HashiCorp Developer
結論
Playbookを更新しても一度それを実行するnull_resourceが成功していれば、terraform applyでは差異なしと判断され、null_resource(Playbook)は再実行されません。
また、Terrafromが出力するPlaybookのログがきれいに表示されないので、AnsibleからTerraformを呼び出したほうが便利そうです。
環境
用意するファイル
- main.tf
- main.yml
- 実装内容
- gitのインストール
- 実装内容
- ansible.cfg
- 実装内容
- host_key_checkingの無効
- 実装内容
main.tf
provider "aws" { region = "ap-northeast-1" access_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" secret_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" } # EC2インスタンスの作成 resource "aws_instance" "mito_ec2" { ami = "ami-072bfb8ae2c884cc4" # Amazon Linux 2 instance_type = "t2.micro" associate_public_ip_address = "true" key_name = aws_key_pair.deployer.key_name vpc_security_group_ids = [aws_security_group.sg_mito.id] tags = { Name = "mito_ec2" } } # キーペアの作成 resource "tls_private_key" "rsa_4096" { algorithm = "RSA" rsa_bits = 4096 } resource "aws_key_pair" "deployer" { key_name = "mito_key" public_key = tls_private_key.rsa_4096.public_key_openssh lifecycle { ignore_changes = [key_name] } } resource "local_file" "private_key_pem" { content = tls_private_key.rsa_4096.private_key_pem filename = "/home/ubuntu/.ssh/mito_key.pem" # ログインユーザに合わせる } # セキュリティグループの作成 resource "aws_security_group" "sg_mito" { name = "sg_mito" description = "sg_mito" ingress { description = "SSH" from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["${chomp(data.http.myip.response_body)}/32"] # ホストのパブリックIPを許可する } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "sg_mito" } } # 返り値でホストのパブリックIPを取得する data "http" "myip" { url = "http://ipv4.icanhazip.com" } # 対象ノードのプライベートIPが記載されたinventory.iniを作成する resource "local_file" "inventory" { content = aws_instance.mito_ec2.public_ip filename = "./inventory.ini" file_permission = "0644" } # Playbookの実行 resource "null_resource" "playbook" { depends_on = [ aws_instance.mito_ec2 # インスタンス作成後に実行 ] # 対象ノードの起動を待ち、Playbookを実行する provisioner "local-exec" { interpreter = ["/usr/bin/bash", "-c"] command = <<-EOT chmod 600 ${local_file.private_key_pem.filename} aws ec2 wait instance-status-ok --instance-ids ${aws_instance.mito_ec2.id} ansible-playbook main.yml -i inventory.ini -u ec2-user --private-key=${local_file.private_key_pem.filename} EOT } }
main.yml
--- - hosts: all gather_facts: no become: yes tasks: - name: install git yum: name: git state: present
ansible.cfg
[defaults] host_key_checking = False
実行ログ
99行目からPlaybookのログが表示されていますが、ログの順番が変わっています。
$ terraform init Initializing the backend... Initializing provider plugins... - Reusing previous version of hashicorp/null from the dependency lock file - Reusing previous version of hashicorp/tls from the dependency lock file - Finding latest version of hashicorp/http... - Reusing previous version of hashicorp/aws from the dependency lock file - Reusing previous version of hashicorp/local from the dependency lock file - Using previously-installed hashicorp/null v3.2.1 - Using previously-installed hashicorp/tls v4.0.4 - Installing hashicorp/http v3.2.1... - Installed hashicorp/http v3.2.1 (signed by HashiCorp) - Using previously-installed hashicorp/aws v4.43.0 - Using previously-installed hashicorp/local v2.2.3 (略) $ $ $ terraform apply data.http.myip: Reading... data.http.myip: Read complete after 0s [id=http://ipv4.icanhazip.com] 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: # aws_instance.mito_ec2 will be created + resource "aws_instance" "mito_ec2" { + ami = "ami-072bfb8ae2c884cc4" + arn = (known after apply) + associate_public_ip_address = true + availability_zone = (known after apply) (略) # local_file.inventory will be created + resource "local_file" "inventory" { + content = (known after apply) + directory_permission = "0777" + file_permission = "0644" + filename = "./inventory.ini" + id = (known after apply) } # local_file.private_key_pem will be created + resource "local_file" "private_key_pem" { + content = (sensitive) + directory_permission = "0777" + file_permission = "0777" + filename = "/home/ubuntu/.ssh/mito_key.pem" + id = (known after apply) } # null_resource.playbook will be created + resource "null_resource" "playbook" { + id = (known after apply) } (略) Plan: 7 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 tls_private_key.rsa_4096: Creating... aws_security_group.sg_mito: Creating... tls_private_key.rsa_4096: Creation complete after 1s [id=6d5549db0XXXXXXXXXXXXXXXXX] local_file.private_key_pem: Creating... aws_key_pair.deployer: Creating... local_file.private_key_pem: Creation complete after 0s [id=9f5e11483XXXXXXXXXXXXXXXXXXXX] aws_key_pair.deployer: Creation complete after 0s [id=mito_key] aws_security_group.sg_mito: Creation complete after 3s [id=sg-091fbXXXXXXXXXXXX] aws_instance.mito_ec2: Creating... aws_instance.mito_ec2: Still creating... [10s elapsed] aws_instance.mito_ec2: Still creating... [20s elapsed] aws_instance.mito_ec2: Creation complete after 21s [id=i-02fb1XXXXXXXXXXXX] local_file.inventory: Creating... null_resource.playbook: Creating... local_file.inventory: Creation complete after 0s [id=fecdbeXXXXXXXXXXXXXXXXXXXXXXXXXXXXX] null_resource.playbook: Provisioning with 'local-exec'... null_resource.playbook (local-exec): Executing: ["/usr/bin/bash" "-c" "chmod 600 /home/ubuntu/.ssh/mito_key.pem\naws ec2 wait instance-status-ok --instance-ids i-02fb1149af69d72ce\nansible-playbook main.yml -i inventory.ini -u ec2-user --private-key=/home/ubuntu/.ssh/mito_key.pem\n"] null_resource.playbook: Still creating... [10s elapsed] null_resource.playbook: Still creating... [20s elapsed] null_resource.playbook: Still creating... [30s elapsed] null_resource.playbook: Still creating... [40s elapsed] null_resource.playbook: Still creating... [50s elapsed] null_resource.playbook: Still creating... [1m0s elapsed] null_resource.playbook: Still creating... [1m10s elapsed] null_resource.playbook: Still creating... [1m20s elapsed] null_resource.playbook: Still creating... [1m30s elapsed] null_resource.playbook: Still creating... [1m40s elapsed] null_resource.playbook (local-exec): PLAY [all] ********************************************************************* null_resource.playbook (local-exec): TASK [install git] ************************************************************* null_resource.playbook: Still creating... [1m50s elapsed] null_resource.playbook (local-exec): [WARNING]: Platform linux on host xx.xx.xx.xx is using the discovered Python null_resource.playbook (local-exec): interpreter at /usr/bin/python3.7, but future installation of another Python null_resource.playbook (local-exec): interpreter could change the meaning of that path. See null_resource.playbook (local-exec): https://docs.ansible.com/ansible- null_resource.playbook (local-exec): core/2.13/reference_appendices/interpreter_discovery.html for more information. null_resource.playbook (local-exec): changed: [xx.xx.xx.xx] null_resource.playbook (local-exec): PLAY RECAP ********************************************************************* null_resource.playbook (local-exec): xx.xx.xx.xx : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 null_resource.playbook: Creation complete after 1m54s [id=6559XXXXXXXXXXXXXX] Apply complete! Resources: 7 added, 0 changed, 0 destroyed. $