構成管理のためにTerraformでAnsibleを使用する方法
序章
Ansible は、 playbooks を実行する構成管理ツールです。これは、指定されたターゲットサーバー上でYAMLで記述されたカスタマイズ可能なアクションのリストです。 ソフトウェアのインストールと更新、ユーザーの作成と削除、システムサービスの構成など、すべてのブートストラップ操作を実行できます。 そのため、デフォルトで空白で作成されるTerraformを使用してデプロイするサーバーを起動するのに適しています。
AnsibleとTerraformは、インフラストラクチャとソフトウェアの展開のさまざまなフェーズを解決するため、競合するソリューションではありません。 Terraformを使用すると、アプリケーションを実行するハードウェアを含む、システムのインフラストラクチャを定義および作成できます。 逆に、Ansibleは、提供されたサーバーインスタンスでプレイブックを実行することにより、ソフトウェアを構成およびデプロイします。 作成直後にプロビジョニングされたリソースTerraformでAnsibleを実行すると、リソースをユースケースで使用できるようにすることができます。 また、デプロイされたすべてのサーバーに同じアクションが適用されるため、メンテナンスとトラブルシューティングが容易になります。
このチュートリアルでは、Terraformを使用してドロップレットをデプロイし、作成直後にAnsibleを使用してドロップレットをブートストラップします。 リソースがデプロイされるときに、Terraformから直接Ansibleを呼び出します。 また、Terraformを使用して競合状態を導入することも避けます。 remote-exec
と local-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
. 次のコマンドを実行して、編集用に作成して開きます。
- nano 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では、秘密鍵ファイルに適切な権限があることを確認する必要があります。 次のコマンドを実行して設定できます。
- chmod 600 your_private_key_location
秘密鍵の変数はすでに定義されているため、公開鍵の場所に1つ追加するだけで済みます。
開ける provider.tf
実行による編集の場合:
- nano 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
. 編集のために作成して開きます。
- nano apache-install.yml
徐々にプレイブックを作成していきます。 まず、プレイブックを実行するホスト、その名前、およびタスクをrootとして実行するかどうかを定義する必要があります。 次の行を追加します。
- become: yes
hosts: all
name: apache-install
設定することにより become
に yes
、スーパーユーザーとしてコマンドを実行するようにAnsibleに指示し、次のように指定します all
為に hosts
、Ansibleが任意のサーバーでタスクを実行できるようにします。Terraformのように、コマンドラインから渡されたサーバーでも実行できます。
追加する最初のタスクは、root以外の新しいユーザーを作成します。 次のタスク定義をプレイブックに追加します。
tasks:
- name: Add the user 'sammy' and add it to 'sudo'
user:
name: sammy
group: sudo
最初にタスクのリストを定義してから、それにタスクを追加します。 sammy という名前のユーザーを作成し、を使用してスーパーユーザーアクセスを許可します。 sudo
それらを適切なグループに追加します。
次のタスクでは、公開SSHキーをユーザーに追加するため、後で接続できるようになります。
- 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
次のタスクを追加してモジュールを作成します。
- 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を再起動する必要があります。これは、タスク自体から構成することはできません。 これを解決するには、ハンドラーを呼び出して再起動を発行します。
この時点で、プレイブックは次のようになります。
- 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-exec
と remote-exec
、それぞれローカルまたはリモート(ターゲット上)でコマンドを実行します。 remote-exec
タイプやアクセスキーなどの接続データが必要ですが、 local-exec
Terraformが実行されているマシンですべてを実行するため、接続情報は必要ありません。 注意することが重要です local-exec
定義したリソースのプロビジョニングが完了した直後に実行されます。 したがって、リソースが実際に起動するのを待つことはありません。 クラウドプラットフォームがシステム内での存在を確認した後に実行されます。
ドロップレットにプロビジョナー定義を追加して、デプロイ後にAnsibleを実行します。 開ける droplets.tf
編集用:
- nano 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_location
と public_key_location
それぞれ秘密鍵と公開鍵の場所を使用して:
- 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アドレスのリストが表示されます。
Outputdroplet_ip_addresses = {
"web-0" = "..."
"web-1" = "..."
"web-2" = "..."
}
これで、ブラウザのIPアドレスの1つに移動できます。 デフォルトのApacheウェルカムページが表示され、Webサーバーが正常にインストールされたことを示します。
これは、Terraformがサーバーをプロビジョニングし、Ansibleプレイブックがサーバー上で正常に実行されたことを意味します。
SSHキーがプロビジョニングされたドロップレットのsammyに正しく追加されたことを確認するには、次のコマンドを使用してそれらの1つに接続します。
- ssh -i private_key_location sammy@droplet_ip_address
Terraform出力にあるプロビジョニングされたドロップレットの1つの秘密鍵の場所とIPアドレスを忘れずに入力してください。
出力は次のようになります。
OutputWelcome 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
プロンプトが表示されたら:
- 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コンテンツリソースを見つけることができます。