序章

Ansible は、 playbooks を実行する構成管理ツールです。これは、指定されたターゲットサーバー上でYAMLで記述されたカスタマイズ可能なアクションのリストです。 ソフトウェアのインストールと更新、ユーザーの作成と削除、システムサービスの構成など、すべてのブートストラップ操作を実行できます。 そのため、デフォルトで空白で作成されるTerraformを使用してデプロイするサーバーを起動するのに適しています。

AnsibleとTerraformは、インフラストラクチャとソフトウェアの展開のさまざまなフェーズを解決するため、競合するソリューションではありません。 Terraformを使用すると、アプリケーションを実行するハードウェアを含む、システムのインフラストラクチャを定義および作成できます。 逆に、Ansibleは、提供されたサーバーインスタンスでプレイブックを実行することにより、ソフトウェアを構成およびデプロイします。 作成直後にプロビジョニングされたリソースTerraformでAnsibleを実行すると、リソースをユースケースで使用できるようにすることができます。 また、デプロイされたすべてのサーバーに同じアクションが適用されるため、メンテナンスとトラブルシューティングが容易になります。

このチュートリアルでは、Terraformを使用してドロップレットをデプロイし、作成直後にAnsibleを使用してドロップレットをブートストラップします。 リソースがデプロイされるときに、Terraformから直接Ansibleを呼び出します。 また、Terraformを使用して競合状態を導入することも避けます。 remote-execlocal-exec 構成内のプロビジョナー。これにより、セットアップを開始する前にDropletの展開が完全に完了することが保証されます。

前提条件

  • DigitalOceanパーソナルアクセストークン。DigitalOceanコントロールパネルから作成できます。 手順については、DigitalOcean製品ドキュメントパーソナルアクセストークンの作成方法を参照してください。

  • ローカルマシンにインストールされたTerraformと、DigitalOceanプロバイダーでセットアップされたプロジェクト。 DigitalOcean チュートリアルでTerraformを使用する方法のステップ1およびステップ2を完了し、プロジェクトフォルダーに名前を付けてください terraform-ansible、 それ以外の loadbalance.

  • Ansibleがマシンにインストールされています。 Ubuntu 20.04の場合は、 Ubuntu20.04チュートリアルにAnsibleをインストールして構成する方法の最初のステップを完了します。 Ansibleの詳細については、このAnsibleを使用した構成管理の概要の記事をお読みください。

注:このチュートリアルはTerraformで特別にテストされています 1.0.2.

ステップ1—液滴を定義する

このステップでは、後でAnsibleプレイブックを実行するドロップレットを定義します。これにより、ApacheWebサーバーがセットアップされます。

あなたがにいると仮定して terraform-ansible 前提条件の一部として作成したディレクトリで、Dropletリソースを定義し、次のように指定してそのコピーを3つ作成します。 count、およびそれらのIPアドレスを出力します。 定義をという名前のファイルに保存します droplets.tf. 次のコマンドを実行して、編集用に作成して開きます。

  1. nano droplets.tf

次の行を追加します。

〜/ terraform-ansible / droplets.tf
resource "digitalocean_droplet" "web" {
  count  = 3
  image  = "ubuntu-18-04-x64"
  name   = "web-${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"

  ssh_keys = [
      data.digitalocean_ssh_key.terraform.id
  ]
}

output "droplet_ip_addresses" {
  value = {
    for droplet in digitalocean_droplet.web:
    droplet.name => droplet.ipv4_address
  }
}

ここでは、リージョンのCPUコアに1GBのRAMを搭載したUbuntu18.04を実行するDropletリソースを定義します。 fra1. Terraformは、前提条件で定義したSSHキーをアカウントからプルし、指定された一意のID listelementが渡されたプロビジョニングされたドロップレットに追加します。 ssh_keys. Terraformは、ドロップレットを3回展開します。 count パラメータが設定されています。 その後の出力ブロックには、3つのドロップレットのIPアドレスが表示されます。 loop はドロップレットのリストをトラバースし、インスタンスごとに、その名前とIPアドレスをペアにして、結果のマップに追加します。

完了したら、ファイルを保存して閉じます。

これで、Terraformが展開するドロップレットが定義されました。 次のステップでは、デプロイされた3つのドロップレットのそれぞれで実行され、ApacheWebサーバーをデプロイするAnsibleプレイブックを作成します。 後でTerraformコードに戻り、Ansibleとの統合を追加します。

ステップ2—AnsiblePlaybookを作成する

次に、新しいユーザーの作成やインストールされたパッケージのアップグレードなど、サーバーの初期セットアップタスクを実行するAnsibleプレイブックを作成します。 ターゲットホストで実行されるアクションの単位であるtasksを記述して、Ansibleに何をすべきかを指示します。 タスクは、組み込み関数を使用することも、実行するカスタムコマンドを指定することもできます。 初期設定のタスクに加えて、Apache Webサーバーをインストールして、そのサーバーを有効にします。 mod_rewrite モジュール。

プレイブックを作成する前に、DigitalOceanアカウントのSSHキーに対応する公開SSHキーと秘密SSHキーが、TerraformとAnsibleを実行しているマシンで使用可能でアクセス可能であることを確認してください。 Linuxに保存するための一般的な場所は次のとおりです。 ~/.ssh (他の場所に保存することもできますが)。

注: Linuxでは、秘密鍵ファイルに適切な権限があることを確認する必要があります。 次のコマンドを実行して設定できます。

  1. chmod 600 your_private_key_location

秘密鍵の変数はすでに定義されているため、公開鍵の場所に1つ追加するだけで済みます。

開ける provider.tf 実行による編集の場合:

  1. nano provider.tf

次の行を追加します。

〜/ terraform-ansible / Provider.tf
terraform {
  required_providers {
    digitalocean = {
      source = "digitalocean/digitalocean"
      version = "~> 2.0"
    }
  }
}

variable "do_token" {}
variable "pvt_key" {}
variable "pub_key" {}

provider "digitalocean" {
  token = var.do_token
}

data "digitalocean_ssh_key" "terraform" {
  name = "terraform"
}

完了したら、ファイルを保存して閉じます。

とともに pub_key 変数が定義されたら、Ansibleプレイブックの作成を開始します。 次のファイルに保存します apache-install.yml. 編集のために作成して開きます。

  1. nano apache-install.yml

徐々にプレイブックを作成していきます。 まず、プレイブックを実行するホスト、その名前、およびタスクをrootとして実行するかどうかを定義する必要があります。 次の行を追加します。

〜/ terraform-ansible / apache-install.yml
- become: yes
  hosts: all
  name: apache-install

設定することにより becomeyes、スーパーユーザーとしてコマンドを実行するようにAnsibleに指示し、次のように指定します all 為に hosts、Ansibleが任意のサーバーでタスクを実行できるようにします。Terraformのように、コマンドラインから渡されたサーバーでも実行できます。

追加する最初のタスクは、root以外の新しいユーザーを作成します。 次のタスク定義をプレイブックに追加します。

〜/ terraform-ansible / apache-install.yml
  tasks:
    - name: Add the user 'sammy' and add it to 'sudo'
      user:
        name: sammy
        group: sudo

最初にタスクのリストを定義してから、それにタスクを追加します。 sammy という名前のユーザーを作成し、を使用してスーパーユーザーアクセスを許可します。 sudo それらを適切なグループに追加します。

次のタスクでは、公開SSHキーをユーザーに追加するため、後で接続できるようになります。

〜/ terraform-ansible / apache-install.yml
    - name: Add SSH key to 'sammy'
      authorized_key:
        user: sammy
        state: present
        key: "{{ lookup('file', pub_key) }}"

このタスクにより、ローカルファイルから検索される公開SSHキーが present ターゲット上。 の値を指定します pub_key 次のステップでTerraformから変数。

これで、Apacheとのインストールを注文できます。 mod_rewrite 次のタスクを追加してモジュールを作成します。

〜/ terraform-ansible / apache-install.yml
    - name: Wait for apt to unlock
      become: yes
      shell:  while sudo fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 5; done;
      
    - name: Install apache2
      apt:        
        name: apache2
        update_cache: yes
        state: latest
        
    - name: Enable mod_rewrite
      apache2_module:
        name: rewrite
        state: present
      notify:
        - Restart apache2

  handlers:
    - name: Restart apache2
      service:
      name: apache2
      state: restarted

最初のタスクは、を使用して以前のパッケージがインストールされるまで待機します apt パッケージマネージャーが完成しました。 2番目のタスクが実行されます apt Apacheをインストールします。 次に、3番目のものは mod_rewrite モジュールは present. 有効にした後、Apacheを再起動する必要があります。これは、タスク自体から構成することはできません。 これを解決するには、ハンドラーを呼び出して再起動を発行します。

この時点で、プレイブックは次のようになります。

〜/ terraform-ansible / apache-install.yml
- become: yes
  hosts: all
  name: apache-install
  tasks:
    - name: Add the user 'sammy' and add it to 'sudo'
      user:
        name: sammy
        group: sudo
        
    - name: Add SSH key to 'sammy'
      authorized_key:
        user: sammy
        state: present
        key: "{{ lookup('file', pub_key) }}"
        
    - name: Wait for apt to unlock
      become: yes
      shell:  while sudo fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 5; done;
      
    - name: Install apache2
      apt:
        name: apache2
        update_cache: yes
        state: latest
      
    - name: Enable mod_rewrite
      apache2_module:
        name: rewrite 
        state: present
      notify:
        - Restart apache2

  handlers:
    - name: Restart apache2
      service:
        name: apache2
        state: restarted

完了したら、すべてのYAML要素のインデントが正しく、上記のインデントと一致していることを確認します。 Ansible側で定義する必要があるのはこれだけなので、プレイブックを保存して閉じます。 ドロップレットのプロビジョニングが完了したときにこのプレイブックを実行するように、ドロップレット展開コードを変更します。

ステップ3—デプロイされたドロップレットでAnsibleを実行する

Ansibleがターゲットサーバーで実行するアクションを定義したので、Dropletの作成時に実行するようにTerraform構成を変更します。

Terraformは、コマンドを実行する2つのプロビジョナーを提供します。 local-execremote-exec、それぞれローカルまたはリモート(ターゲット上)でコマンドを実行します。 remote-exec タイプやアクセスキーなどの接続データが必要ですが、 local-exec Terraformが実行されているマシンですべてを実行するため、接続情報は必要ありません。 注意することが重要です local-exec 定義したリソースのプロビジョニングが完了した直後に実行されます。 したがって、リソースが実際に起動するのを待つことはありません。 クラウドプラットフォームがシステム内での存在を確認した後に実行されます。

ドロップレットにプロビジョナー定義を追加して、デプロイ後にAnsibleを実行します。 開ける droplets.tf 編集用:

  1. nano droplets.tf

強調表示された行を追加します。

〜/ terraform-ansible / droplets.tf
resource "digitalocean_droplet" "web" {
  count  = 3
  image  = "ubuntu-18-04-x64"
  name   = "web-${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"

  ssh_keys = [
      data.digitalocean_ssh_key.terraform.id
  ]

  provisioner "remote-exec" {
    inline = ["sudo apt update", "sudo apt install python3 -y", "echo Done!"]

    connection {
      host        = self.ipv4_address
      type        = "ssh"
      user        = "root"
      private_key = file(var.pvt_key)
    }
  }

  provisioner "local-exec" {
    command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u root -i '${self.ipv4_address},' --private-key ${var.pvt_key} -e 'pub_key=${var.pub_key}' apache-install.yml"
  }
}

output "droplet_ip_addresses" {
  value = {
    for droplet in digitalocean_droplet.web:
    droplet.name => droplet.ipv4_address
  }
}

Terraformと同様に、Ansibleはローカルで実行され、SSH経由でターゲットサーバーに接続します。 それを実行するには、次のように定義します local-exec を実行するドロップレット定義のプロビジョナー ansible-playbook 指図。 これにより、ユーザー名( root )、現在のドロップレットのIP( ${self.ipv4_address})、SSH公開鍵と秘密鍵、および実行するプレイブックファイルを指定します(apache-install.yml). を設定することにより ANSIBLE_HOST_KEY_CHECKING 環境変数から False、サーバーが事前に接続されているかどうかの確認をスキップします。

述べたように、 local-exec プロビジョナーは、ドロップレットが利用可能になるのを待たずに実行されるため、プレイブックの実行は、ドロップレットが実際に利用可能になる前に実行される場合があります。 これを改善するには、次のように定義します。 remote-exec ターゲットサーバーで実行するコマンドを含むプロビジョナー。 為に remote-exec 実行するには、ターゲットサーバーが使用可能である必要があります。 以来 remote-exec 前に実行 local-exec、サーバーはAnsibleが呼び出されるまでに完全に初期化されます。 python3 Ubuntu 18.04にプリインストールされているため、必要に応じてコマンドをコメントアウトまたは削除できます。

変更が完了したら、ファイルを保存して閉じます。

次に、次のコマンドを実行してドロップレットを展開します。 交換することを忘れないでください private_key_locationpublic_key_location それぞれ秘密鍵と公開鍵の場所を使用して:

  1. terraform apply -var "do_token=${DO_PAT}" -var "pvt_key=private_key_location" -var "pub_key=public_key_location"

出力が長くなります。 ドロップレットがプロビジョニングされ、それぞれとの接続が確立されます。 次は remote-exec プロビジョナーが実行してインストールします python3:

Output
... digitalocean_droplet.web[1] (remote-exec): Connecting to remote host via SSH... digitalocean_droplet.web[1] (remote-exec): Host: ... digitalocean_droplet.web[1] (remote-exec): User: root digitalocean_droplet.web[1] (remote-exec): Password: false digitalocean_droplet.web[1] (remote-exec): Private key: true digitalocean_droplet.web[1] (remote-exec): Certificate: false digitalocean_droplet.web[1] (remote-exec): SSH Agent: false digitalocean_droplet.web[1] (remote-exec): Checking Host Key: false digitalocean_droplet.web[1] (remote-exec): Connected! ...

その後、Terraformは local-exec Ansibleを実行する各ドロップレットのプロビジョナー。 次の出力は、ドロップレットの1つについてこれを示しています。

Output
... digitalocean_droplet.web[2] (local-exec): Executing: ["/bin/sh" "-c" "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u root -i 'ip_address,' --private-key private_key_location -e 'pub_key=public_key_location' apache-install.yml"] digitalocean_droplet.web[2] (local-exec): PLAY [apache-install] ********************************************************** digitalocean_droplet.web[2] (local-exec): TASK [Gathering Facts] ********************************************************* digitalocean_droplet.web[2] (local-exec): ok: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Add the user 'sammy' and add it to 'sudo'] ******************************* digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Add SSH key to 'sammy''] ******************************* digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Update all packages] ***************************************************** digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Install apache2] ********************************************************* digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): TASK [Enable mod_rewrite] ****************************************************** digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): RUNNING HANDLER [Restart apache2] ********************************************** digitalocean_droplet.web[2] (local-exec): changed: [ip_address] digitalocean_droplet.web[2] (local-exec): PLAY RECAP ********************************************************************* digitalocean_droplet.web[2] (local-exec): [ip_address] : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 ...

出力の最後に、3つのドロップレットとそのIPアドレスのリストが表示されます。

Output
droplet_ip_addresses
= { "web-0" = "..." "web-1" = "..." "web-2" = "..." }

これで、ブラウザのIPアドレスの1つに移動できます。 デフォルトのApacheウェルカムページが表示され、Webサーバーが正常にインストールされたことを示します。

これは、Terraformがサーバーをプロビジョニングし、Ansibleプレイブックがサーバー上で正常に実行されたことを意味します。

SSHキーがプロビジョニングされたドロップレットのsammyに正しく追加されたことを確認するには、次のコマンドを使用してそれらの1つに接続します。

  1. ssh -i private_key_location sammy@droplet_ip_address

Terraform出力にあるプロビジョニングされたドロップレットの1つの秘密鍵の場所とIPアドレスを忘れずに入力してください。

出力は次のようになります。

Output
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-121-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of ... System load: 0.0 Processes: 88 Usage of /: 6.4% of 24.06GB Users logged in: 0 Memory usage: 20% IP address for eth0: ip_address Swap usage: 0% IP address for eth1: ip_address 0 packages can be updated. 0 updates are security updates. New release '20.04.1 LTS' available. Run 'do-release-upgrade' to upgrade to it. *** System restart required *** Last login: ... ...

ターゲットに正常に接続し、 sammy ユーザーのシェルアクセスを取得しました。これにより、SSHキーがそのユーザーに対して正しく構成されていることが確認されます。

次のコマンドを実行して、展開されたドロップレットを破棄できます。 yes プロンプトが表示されたら:

  1. terraform destroy -var "do_token=${DO_PAT}" -var "pvt_key=private_key_location" -var "pub_key=public_key_location"

このステップでは、Ansibleプレイブックの実行を次のように追加しました。 local-exec ドロップレット定義のプロビジョナー。 サーバーが接続に使用できることを確認するために、 remote-exec をインストールするのに役立つことができるプロビジョナー python3 前提条件。その後、Ansibleが実行されます。

結論

TerraformとAnsibleは一緒になって、必要なソフトウェアとハードウェアの構成でサーバーを起動するための柔軟なワークフローを形成します。 Terraformデプロイメントプロセスの一部としてAnsibleを直接実行すると、サーバーを起動して、開発作業とアプリケーションの依存関係をはるかに高速にブートストラップできます。

このチュートリアルは、Terraformシリーズでインフラストラクチャを管理する方法の一部です。 このシリーズでは、Terraformの初めてのインストールから複雑なプロジェクトの管理まで、Terraformの多くのトピックを取り上げています。

また、Ansibleトピックページで追加のAnsibleコンテンツリソースを見つけることができます。