如何使用 Ansible 和 Terraform 进行配置管理

作者选择了 自由和开源基金作为 写给捐款计划的一部分接受捐款。

介绍

Ansible是一个配置管理工具,执行 playbooks,这是在指定目标服务器上以YAML编写的可定制操作列表。它可以执行所有启动操作,如安装和更新软件,创建和删除用户,并配置系统服务。

Ansible和Terraform不是竞争的解决方案,因为它们解决了基础设施和软件部署的不同阶段。Terraform允许您定义和创建您的系统的基础设施,包括您的应用程序将运行的硬件。反过来,Ansible通过在提供的服务器实例上执行其播放簿来配置和部署软件。在创建后直接提供的Terraform资源上运行Ansible允许您更快地将资源用于您的使用案例。它还允许更轻松的维护和故障排除,因为所有部署的服务器将对它们执行相同的操作。

在本教程中,您将使用Terraform部署Dropplets,然后在创建后立即启动Dropplets使用Ansible。当资源部署时,您将直接从Terraform召唤Ansible。

前提条件

您可以通过DigitalOcean控制面板创建一个DigitalOcean个人访问代码。 您可以在DigitalOcean产品文档中找到指示, How to Create a Personal Access Token

  • Terraform安装在您的本地机器上,并与DigitalOcean提供商一起创建一个项目。 完成DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean如何使用DigitalOcean

<$>[注] **注:**本教程已被特定的测试与Terraform 1.0.2 <$>

步骤1 - 定义滴滴

在此步骤中,您将定义Dropplets,您将在其后运行一个Ansible播放簿,该书将设置Apache Web 服务器。

假设你是在terraform-ansible目录中,你创建了作为前提的一部分,你将定义一个Droplet资源,通过指定,创建三个副本,并输出他们的IP地址,你将存储定义在名为droplets.tf的文件中。

1nano droplets.tf

添加以下几行:

 1[label ~/terraform-ansible/droplets.tf]
 2resource "digitalocean_droplet" "web" {
 3  count  = 3
 4  image  = "ubuntu-18-04-x64"
 5  name   = "web-${count.index}"
 6  region = "fra1"
 7  size   = "s-1vcpu-1gb"
 8
 9  ssh_keys = [
10      data.digitalocean_ssh_key.terraform.id
11  ]
12}
13
14output "droplet_ip_addresses" {
15  value = {
16    for droplet in digitalocean_droplet.web:
17    droplet.name => droplet.ipv4_address
18  }
19}

在这里,您定义了运行 Ubuntu 18.04 的 Droplet 资源,在fra1区域内的 CPU 核心上具有 1GB RAM。Terraform 将从您的帐户中提取您在前提条件中定义的 SSH 密钥,并将其添加到提供的 Droplet 中,指定的独特 ID(列表元素)(https://andsky.com/tech/tutorials/how-to-improve-flexibility-using-terraform-variables-dependencies-and-conditionals#data-types-in-hcl)传入ssh_keys。Terraform 将部署 Droplet 三次,因为设置了计数参数。 随后的输出块将显示三个 Droplets 的 IP 地址。 loop通过 Droplets 的列表,并在每个例子中将其名称与 IP 地址并附加到结果的地图上。

保存并关闭文件,当你完成。

您现在已经定义了Terraform将部署的Droplets。在下一步,您将编写一个Ansible播放簿,它将在三个部署的Droplets中执行,并部署ApacheWeb服务器。

步骤 2 - 写一个可理解的剧本

您现在将创建一个Ansible播放簿,执行初始服务器设置任务,例如创建新用户和升级已安装的包。您将指示Ansible写 tasks,这是在目标主机上执行的操作单元。

在写本之前,请确保您的公共和私人SSH密钥,这与您的DigitalOcean帐户中的密钥相匹配,在您运行Terraform和Ansible的机器上可用和可访问。

<$>[note] 注: 在 Linux 上,您需要确保私钥文件具有适当的权限。

1chmod 600 your_private_key_location

美元

您已经为私钥定义了变量,因此您只需要为公共密钥位置添加一个变量。

打开provider.tf进行编辑:

1nano provider.tf

添加下列行:

 1[label ~/terraform-ansible/provider.tf]
 2terraform {
 3  required_providers {
 4    digitalocean = {
 5      source = "digitalocean/digitalocean"
 6      version = "~> 2.0"
 7    }
 8  }
 9}
10
11variable "do_token" {}
12variable "pvt_key" {}
13variable "pub_key" {}
14
15provider "digitalocean" {
16  token = var.do_token
17}
18
19data "digitalocean_ssh_key" "terraform" {
20  name = "terraform"
21}

完成后,保存并关闭文件。

现在定义了pub_key变量,您将开始写 Ansible 播放簿,将其存储在名为apache-install.yml的文件中。

1nano apache-install.yml

您将逐步构建播放簿. 首先,您需要定义在哪个主机上播放簿将运行,其名称,以及任务是否应该作为 root运行。

1[label ~/terraform-ansible/apache-install.yml]
2- become: yes
3  hosts: all
4  name: apache-install

通过将成为设置为,您指示Ansible作为超级用户运行命令,并指定所有主机,您允许Ansible在任何特定服务器上运行任务 - 即使是通过命令行传输的任务,就像Terraform一样。

您将添加的第一个任务将创建一个新的非根用户。

1[label ~/terraform-ansible/apache-install.yml]
2  tasks:
3    - name: Add the user 'sammy' and add it to 'sudo'
4      user:
5        name: sammy
6        group: sudo

它将创建一个名为 sammy的用户,并通过将其添加到相应的组授予他们使用sudo的超级用户访问权限。

下一个任务将为用户添加您的公共 SSH 密钥,因此您可以在稍后连接到它:

1[label ~/terraform-ansible/apache-install.yml]
2    - name: Add SSH key to 'sammy'
3      authorized_key:
4        user: sammy
5        state: present
6        key: "{{ lookup('file', pub_key) }}"

此任务将确保从本地文件中搜索到的公共 SSH 密钥在目标中存在,您将在下一步提供 Terraform 的pub_key变量值。

您现在可以通过附加以下任务来命令安装Apache和mod_rewrite模块:

 1[label ~/terraform-ansible/apache-install.yml]
 2    - name: Wait for apt to unlock
 3      become: yes
 4      shell:  while sudo fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 5; done;
 5
 6    - name: Install apache2
 7      apt:        
 8        name: apache2
 9        update_cache: yes
10        state: latest
11
12    - name: Enable mod_rewrite
13      apache2_module:
14        name: rewrite
15        state: present
16      notify:
17        - Restart apache2
18
19  handlers:
20    - name: Restart apache2
21      service:
22      name: apache2
23      state: restarted

第一个任务将等到使用apt包管理器的任何之前的包安装完成。第二个任务将运行apt来安装Apache。然后,第三个任务将确保mod_rewrite模块存在。在启用后,您需要确保您重新启动Apache,您无法从任务本身配置。

在这一点上,你的剧本将看起来如下:

 1[label ~/terraform-ansible/apache-install.yml]
 2- become: yes
 3  hosts: all
 4  name: apache-install
 5  tasks:
 6    - name: Add the user 'sammy' and add it to 'sudo'
 7      user:
 8        name: sammy
 9        group: sudo
10
11    - name: Add SSH key to 'sammy'
12      authorized_key:
13        user: sammy
14        state: present
15        key: "{{ lookup('file', pub_key) }}"
16
17    - name: Wait for apt to unlock
18      become: yes
19      shell:  while sudo fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 5; done;
20
21    - name: Install apache2
22      apt:
23        name: apache2
24        update_cache: yes
25        state: latest
26
27    - name: Enable mod_rewrite
28      apache2_module:
29        name: rewrite 
30        state: present
31      notify:
32        - Restart apache2
33
34  handlers:
35    - name: Restart apache2
36      service:
37        name: apache2
38        state: restarted

完成后,请检查所有 YAML 元素的插头是否正确,并匹配上面所示的内容。这就是您在 Ansible 侧面上需要定义的全部,所以保存并关闭播放簿。

步骤 3 – 在部署的滴滴上运行 Ansible

现在你已经定义了Ansible将在目标服务器上执行的操作,你将修改Terraform配置以在Droplet创建时运行它。

Terraform 提供两个执行命令的供应商:本地执行远程执行,分别在本地或远程执行命令(针对目标)。远程执行需要连接数据,如类型和访问密钥,而本地执行可以执行Terraform计算机上的所有操作,因此不需要连接信息。

现在,您将向您的 Droplet 添加提供者定义,以便在部署后运行 Ansible。

1nano droplets.tf

添加突出的线条:

 1[label ~/terraform-ansible/droplets.tf]
 2resource "digitalocean_droplet" "web" {
 3  count  = 3
 4  image  = "ubuntu-18-04-x64"
 5  name   = "web-${count.index}"
 6  region = "fra1"
 7  size   = "s-1vcpu-1gb"
 8
 9  ssh_keys = [
10      data.digitalocean_ssh_key.terraform.id
11  ]
12
13  provisioner "remote-exec" {
14    inline = ["sudo apt update", "sudo apt install python3 -y", "echo Done!"]
15
16    connection {
17      host        = self.ipv4_address
18      type        = "ssh"
19      user        = "root"
20      private_key = file(var.pvt_key)
21    }
22  }
23
24  provisioner "local-exec" {
25    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"
26  }
27}
28
29output "droplet_ip_addresses" {
30  value = {
31    for droplet in digitalocean_droplet.web:
32    droplet.name => droplet.ipv4_address
33  }
34}

与Terraform一样,Ansible在本地运行,并通过SSH连接到目标服务器。要运行它,您在Droplet定义中定义了一个本地执行提供器,它运行了ansible-playbook命令。这会传输到用户名(root),当前Droplet的IP(用${self.ipv4_address)恢复,SSH的公共和私人密钥,并指定要运行的播放簿文件(apache-install.yml).通过将ANSIBLE_HOST_KEY_CHECKING环境变量设置为False,您会忽略检查服务器是否已连接到。

如前所述,本地exec提供器在不等待Droplet的可用性下运行,因此播放本的执行可能先于Droplet的实际可用性。 为了修复此问题,你将远程exec提供器定义为包含在目标服务器上执行的命令。 为了远程exec执行,目标服务器必须可用。 由于远程exec本地exec之前运行,服务器将在呼吁 Ansible时完全初始化。

完成更改后,保存并关闭文件。

然后,运行下面的命令来部署 Droplets. 请记住将private_key_locationpublic_key_location替换为您的私钥和公共钥匙的位置:

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

您的 Droplets 将提供,然后将与每一个建立连接。接下来,远程执行器将执行并安装 Python3:

 1[secondary_label Output]
 2...
 3digitalocean_droplet.web[1] (remote-exec): Connecting to remote host via SSH...
 4digitalocean_droplet.web[1] (remote-exec):   Host: ...
 5digitalocean_droplet.web[1] (remote-exec):   User: root
 6digitalocean_droplet.web[1] (remote-exec):   Password: false
 7digitalocean_droplet.web[1] (remote-exec):   Private key: true
 8digitalocean_droplet.web[1] (remote-exec):   Certificate: false
 9digitalocean_droplet.web[1] (remote-exec):   SSH Agent: false
10digitalocean_droplet.web[1] (remote-exec):   Checking Host Key: false
11digitalocean_droplet.web[1] (remote-exec): Connected!
12...

之后,Terraform将为每一个Dropplets运行本地执行程序,该程序执行 Ansible。

 1[secondary_label Output]
 2...
 3digitalocean_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"]
 4
 5digitalocean_droplet.web[2] (local-exec): PLAY [apache-install] **********************************************************
 6
 7digitalocean_droplet.web[2] (local-exec): TASK [Gathering Facts] *********************************************************
 8digitalocean_droplet.web[2] (local-exec): ok: [ip_address]
 9
10digitalocean_droplet.web[2] (local-exec): TASK [Add the user 'sammy' and add it to 'sudo'] *******************************
11digitalocean_droplet.web[2] (local-exec): changed: [ip_address]
12
13digitalocean_droplet.web[2] (local-exec): TASK [Add SSH key to 'sammy''] *******************************
14digitalocean_droplet.web[2] (local-exec): changed: [ip_address]
15
16digitalocean_droplet.web[2] (local-exec): TASK [Update all packages] *****************************************************
17digitalocean_droplet.web[2] (local-exec): changed: [ip_address]
18
19digitalocean_droplet.web[2] (local-exec): TASK [Install apache2] *********************************************************
20digitalocean_droplet.web[2] (local-exec): changed: [ip_address]
21
22digitalocean_droplet.web[2] (local-exec): TASK [Enable mod_rewrite] ******************************************************
23digitalocean_droplet.web[2] (local-exec): changed: [ip_address]
24
25digitalocean_droplet.web[2] (local-exec): RUNNING HANDLER [Restart apache2] **********************************************
26digitalocean_droplet.web[2] (local-exec): changed: [ip_address]
27
28digitalocean_droplet.web[2] (local-exec): PLAY RECAP *********************************************************************
29digitalocean_droplet.web[2] (local-exec): [ip_address]             : ok=7 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
30
31...

在输出结束时,您将收到三个Dropplets及其IP地址的列表:

1[secondary_label Output]
2droplet_ip_addresses = {
3  "web-0" = "..."
4  "web-1" = "..."
5  "web-2" = "..."
6}

您现在可以导航到您的浏览器中的IP地址之一,您将到达默认的Apache欢迎页面,表示成功安装Web服务器。

Apache Welcome Page

这意味着Terraform提供您的服务器和您的Ansible播放簿在其上成功执行。

要检查提供的 Droplets 上 SSH 密钥是否正确添加到 sammy,请使用以下命令连接到其中一个:

1ssh -i private_key_location sammy@droplet_ip_address

请记住输入私钥位置和提供的 Droplets 中的一个 IP 地址,您可以在您的 Terraform 输出中找到。

结果将类似于以下:

 1[secondary_label Output]
 2Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-121-generic x86_64)
 3
 4 * Documentation:  https://help.ubuntu.com
 5 * Management:     https://landscape.canonical.com
 6 * Support:        https://ubuntu.com/advantage
 7
 8  System information as of ...
 9
10  System load:  0.0 Processes:           88
11  Usage of /:   6.4% of 24.06GB Users logged in:     0
12  Memory usage: 20%               IP address for eth0: ip_address
13  Swap usage:   0%                IP address for eth1: ip_address
14
150 packages can be updated.
160 updates are security updates.
17
18New release '20.04.1 LTS' available.
19Run 'do-release-upgrade' to upgrade to it.
20
21*** System restart required ***
22Last login: ...
23...

您已成功连接到目标并为 sammy 用户获得壳存取,这确认 SSH 密钥对该用户进行了正确配置。

您可以通过运行以下命令来摧毁部署的 Droplets,当被提示时输入:

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

在此步骤中,您已在您的 Droplet 定义中添加了 Ansible 播放本执行程序作为一个本地执行程序提供程序. 为了确保服务器可供连接,您已包括了远程执行程序提供程序,它可以用于安装python3的前提条件,然后 Ansible 将运行。

结论

Terraform 和 Ansible 一起构成一个灵活的工作流程,可以将服务器与所需的软件和硬件配置进行旋转,直接运行 Ansible 作为 Terraform 部署流程的一部分,可让您更快地为您的开发工作和应用程序启动和启动服务器。

本教程是《如何使用Terraform管理基础设施》系列的一部分,该系列涵盖了许多Terraform主题,从首次安装Terraform到管理复杂项目。

您还可以在我们的 Ansible 主题页面上找到其他 Ansible 内容资源。

Published At
Categories with 技术
comments powered by Disqus