検索
連載

AnsibleとTerraformを連携させてAWS環境の構築を自動化してみようスキマ時間にこっそり学ぶ「Ansible」入門(終)

Ansibleのユースケースを紹介しながら、Ansibleの魅力をお伝えする本連載。最終回はAnsibleとTerraform を連携させてAWS環境の構築を自動化する方法を紹介します。

PC用表示
Share
Tweet
LINE
Hatena

 Ansibleのユースケースを紹介しながら、Ansibleの魅力をお伝えする本連載は、今回で最終回となります。最後を飾る今回は、インフラ自動構築ツールの一つである「Terraform」をAnsibleと組み合わせて、インフラの構築からシステムの設定まで、一連の構築作業を全て自動化する手法を紹介します。

Terraformとは

 Terraformは、HashiCorpが開発したインフラ自動構築ツールです。Amazon Web Services(AWS)やGoogle Cloud Platform(GCP)などのクラウド環境において構築するリソースをコードで表現し、コマンドを実行することで自動で環境を構築できます。

 TerraformはAWSやGCPの他にも、Microsoft AzureやマネージドのKubernetesサービスなどにも対応しています。Terraformには「プロバイダー」と呼ばれる仕組みがあり、構築可能なクラウドサービスの設定はプロバイダーを利用することになります。プロバイダーの一覧についてはこちらを参照してください。

 まずTerraformがどのようなものなのかを体験するために、早速手元の環境にTerraformをインストールしましょう。TerraformはそれぞれのLinuxディストリビューション向けにリポジトリを提供していますので、そのリポジトリを登録した上でインストールすることが可能です。インストール方法は以下の通りです。

$ sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
$ sudo dnf -y install terraform
Rocky Linuxでのインストール方法
$ wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
$ sudo apt update && sudo apt install terraform
Ubuntuでのインストール方法

 正しくインストールされたかどうかを確認するために、以下のようなコマンドを実行してバージョン情報が出力されることを確認してください。

$ terraform -version
Terraform v1.3.7
on linux_amd64

 次に、TerraformでAWS環境を操作するためにはAWS CLIのインストールも必要ですので、以下の手順でインストールします。

$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install

 併せて、AWSを操作するIAMアカウントでアクセスキーを作成し、発行されたアクセスキー IDとシークレットアクセスキーを以下の手順で登録しておきます。

$ aws configure
AWS Access Key ID [None]: (アクセスキーIDを入力)
AWS Secret Access Key [None]: (シークレットアクセスキーを入力)
Default region name [None]: (何も入力せずエンター)
Default output format [None]: (何も入力せずエンター)

 これでTerraformからAWSを操作する準備が整いましたので、早速Terraformを使ってAmazon EC2インスタンスを作成しようと思います。以降のAnsibleとの連携でも使用するため、本連載で作成したAnsible Playbookを格納しているディレクトリ上に、terraformというディレクトリを作成します。その中に、EC2 インスタンスを構築するTerraformの設定ファイルmain.tfを作成します。ディレクトリ/ファイル構成は以下のようになります。

ansible-example
├(前回までに作成したファイル群)
└terraform
 └main.tf

 次に、main.tfに以下の内容を入力します。<キーペア名>と<セキュリティグループID>は、ご自身の環境に合わせて適宜変更してください。なお、ここで指定しているAMIは、Amazon Linux 2のものです。

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}
provider "aws" {
  region = "ap-northeast-1"
}
resource "aws_instance" "example" {
  ami                    = "ami-0bba69335379e17f8"
  instance_type          = "t3.micro"
  key_name               = "<キーペア名>"
  vpc_security_group_ids = ["<セキュリティグループID>"]
  tags = {
    Name = "ansible-example"
  }
}

 main.tfが作成できたら、以下のコマンドを実行して初期化します。

$ terraform init
Initializing the backend...
Initializing provider plugins...
(中略)
Terraform has been successfully initialized!

 上記のようなメッセージが出力されれば初期化が成功しています。それでは早速、以下のコマンドを実行してAWS上にEC2インスタンスを作成します。

$ 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:
(どのような構成でリソースを作成するか表示される)
Plan: 1 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 (←「yes」と入力する)
aws_instance.example: Creating...
aws_instance.example: Still creating... [10s elapsed]
aws_instance.example: Creation complete after 13s [id=i-xxxxxxxxxxxxxxxxx]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

 実行完了後、AWSマネジメントコンソールを確認すると、ansible-exampleという名前の付いたEC2インスタンスが作成されていることが確認できます。次項のAnsibleとの連携で再度インスタンスの作成を試みたいので、いったん作成したインスタンスを削除します。Terraformを使用していれば、Terraform管理下のリソースの削除もコマンドを1回実行するだけで可能です。

$ terraform destroy
aws_instance.example: Refreshing state... [id=i-xxxxxxxxxxxxxxxxx]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy
Terraform will perform the following actions:
(削除対象のリソース情報が表示される)
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.
  Enter a value: yes (←「yes」と入力する)
aws_instance.example: Destroying... [id=i-xxxxxxxxxxxxxxxxx]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 10s elapsed]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 20s elapsed]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 30s elapsed]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 40s elapsed]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 50s elapsed]
aws_instance.example: Still destroying... [id=i-xxxxxxxxxxxxxxxxx, 1m0s elapsed]
aws_instance.example: Destruction complete after 1m0s
Destroy complete! Resources: 1 destroyed.

TerraformとAnsibleを連携させる

 先ほどまではTerraformをコマンドで実行していましたが、今度はAnsibleと連携してAnsible側からTerraformを実行してみましょう。先ほど作成したTerraformの設定ファイルを保存しているディレクトリの親ディレクトリ上にterraform.ymlという名前でAnsible Playbookを作成します。

ansible-example
├(前回までに作成したファイル群)
├terraform.yml
└terraform
 └main.tf

 AnsibleからTerraformを実行するモジュールはcommunity.general.terraformです。これを使って、terraform.ymlに以下の内容を入力します。

- hosts: localhost
  tasks:
    - name: Terraform を実行する
      community.general.terraform:
        project_path: 'terraform/'
        state: present

 内容としては非常にシンプルです。localhostを対象にterraformディレクトリ内にある設定ファイルを使ってTerraformの実行を定義しています。このPlaybookを実行すると以下のようになります。

$ ansible-playbook terraform.yml
PLAY [localhost] ****************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************
ok: [localhost]
TASK [Terraform を実行する] *****************************************************************************************
changed: [localhost]
PLAY RECAP **********************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

 実行が完了すると、先ほどと同様にEC2インスタンスが作成されているはずです。

TerraformとAnsibleを使ったAWS環境の自動構築例

 それでは最後に、Ansibleを使ってTerraformを実行し、EC2インスタンスを作成した後に、EC2インスタンスに対してAnsibleからタスクを実行する所まで自動化してみましょう。

 まず、TerraformでEC2インスタンスを作成するため、実際に実行しないと作成したインスタンスの接続先IPアドレスを知ることができません。それでも、作成から環境構築までを自動化するために、Ansibleのダイナミックインベントリという機能を利用します。

 ダイナミックインベントリは、クラウド環境のように実行対象のIPアドレスが変わる可能性がある場合に、柔軟にインベントリ情報を用意するための機能です。今回はAWSの環境で使用するため、amazon.aws.aws_ec2というプラグインを使用します。aws_ec2.ymlというファイルを作成して、以下の内容を入力します。

plugin: amazon.aws.aws_ec2
regions:
  - ap-northeast-1
keyed_groups:
  - prefix: tag
    key: tags

 これで、EC2インスタンスのタグ「Name」に設定された文字列を使って「tag_Name_<名前>」でAnsibleから接続できるようになります。次に、先ほど作成したterraform.ymlの内容を以下のように変更します。

- hosts: localhost
  tasks:
    - name: Terraform を実行する
      community.general.terraform:
        project_path: 'terraform/'
        state: present
    - name: 作成した EC2 インスタンスをインベントリに反映させる
      ansible.builtin.meta: refresh_inventory
- hosts: tag_Name_ansible_example
  remote_user: ec2-user
  become: yes
  gather_facts: no
  tasks:
    - name: SSH 接続できるまで待つ
      ansible.builtin.wait_for_connection:
    - name: ホストの情報を取得する
      ansible.builtin.setup:
    - name: Apache HTTPD をインストールする
      ansible.builtin.yum:
        name: httpd
        state: present
    - name: Apache HTTPD を起動する
      ansible.builtin.systemd:
        name: httpd.service
        enabled: yes
        state: started

 このPlaybookでは、Terraformを実行した後にインベントリ情報のリフレッシュを実行しています。これによって、Terraformで作成したインスタンス情報がインベントリに反映されます。続いて、作成したインスタンスに対して操作を実行しますが、EC2インスタンスの作成直後は、SSH接続が可能になるまで時間がかかるため、接続できるまで待ちます。そのため、最初にホスト情報の取得を無効化するgather_facts: noという設定をしています。接続できるようになったらホスト情報を取得し、Apacheをインストールして起動するまでの処理を記述しています。

 このPlaybookを以下のコマンドで実行すると、環境の構築が完了します。

$ ansible-playbook -i aws_ec2.yml terraform.yml
PLAY [localhost] ****************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************
ok: [localhost]
TASK [Terraform を実行する] *****************************************************************************************
changed: [localhost]
TASK [作成した EC2 インスタンスをインベントリに反映させる] **********************************************************
PLAY [tag_Name_ansible_example] *************************************************************************************
TASK [SSH 接続できるまで待つ] ***************************************************************************************
ok: [ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com]
TASK [ホストの情報を取得する] ***************************************************************************************
ok: [ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com]
TASK [Apache HTTPD をインストールする] ******************************************************************************
changed: [ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com]
TASK [Apache HTTPD を起動する] **************************************************************************************
changed: [ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com]
PLAY RECAP **********************************************************************************************************
ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

 全4回にわたってAnsibleの魅力を紹介しましたが、いかがでしたでしょうか。Ansibleのモジュールは非常にたくさんの種類が存在しますので、本連載記事で紹介できなかったものの中にもとても便利なモジュールが存在します。本連載をご覧になったことをきっかけに、読者の皆さまがインフラ自動化を実現し、効率的に業務が遂行できるようになることを願っています。最後までお読みいただき、ありがとうございました。

筆者紹介

鎌田啓佑

サイオステクノロジー所属。OSS よろず相談室でサポート対応をしているテクニカルサポートエンジニア。Ansible に出会ってから自動化に取り憑かれ、自身の業務やプライベートであらゆるものの自動化に取り組む。プライベートでは Java でちょっとしたツールの開発を趣味にしている。

サイオス OSS よろず相談室

サイオステクノロジーエンジニアブログ

サイオステクノロジーエンジニア YouTube チャンネル


Copyright © ITmedia, Inc. All Rights Reserved.

[an error occurred while processing this directive]
ページトップに戻る