使用Terraform来执行Ansible的playbook

首先

你好,我是SRE工程师hayaosato。
在日常工作中,作为SRE的一部分,我正在推动基础设施即代码(Infrastructure As Code)。

Terraform和Ansible

我计划从基础设施定义到服务器配置一气呵成地执行。具体来说,在使用AWS创建服务器时,我们将使用Terraform定义基础设施,然后使用Ansible进行服务器的中间件安装等操作。此外,我们将在使用Terraform创建服务器后立即执行Ansible作为配置管理工具。以下是代码。

地球塑形

首先,在AWS上创建EC2实例。
这次创建的实例将从最新的Ubuntu18.04 AMI进行创建。
Terraform和提供者的版本如下所示。

Terraform v0.12.16
+ provider.aws v2.38.0
+ provider.local v1.4.0

不可避免的人工智能

要获取最新的AMI ID,您可以按照以下方式进行获取。

data "aws_ami" "latest-ubuntu" {
  most_recent = true
  owners      = ["679593333241"]

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

您可以使用AWS CLI的ec2 describe-images命令来确认所需获取的AMI,如果您想在其他操作系统上获取相同的最新镜像,则可以参考这个命令。总之,代码文件ec2_images.tf中还包含了获取Centos7和Amazon Linux2最新镜像的方法。

云服务器

接下来是创建EC2实例,如下所示:

resource "aws_instance" "default" {
  ami             = data.aws_ami.latest-ubuntu.id
  key_name        = var.key_name
  private_ip      = var.private_ip
  count           = 1
  security_groups = var.security_groups
  subnet_id       = var.subnet_id
  instance_type   = "t3.medium"
  tags = {
    Name = "terraform-ansible"
  }

  provisioner "remote-exec" {
    connection {
      type        = "ssh"
      user        = "ubuntu"
      host        = var.private_ip
      private_key = file("~/.ssh/${var.key_name}.pem")
    }
    inline = [
      "sudo apt install -y python"
    ]
  }

  provisioner "local-exec" {
    command = "ansible-playbook -i hosts ${var.service_name}.yml"
  }
}

希望您能查看官方文档以获取关于上述参数的详细信息。本次执行Ansible是通过provisioner完成的。在terraform中,有多种Provisioning功能可用,包括使用remote-exec和local-exec。

远程执行

为了对EC2资源进行配置,可以使用remote-exec进行远程执行,并在服务器创建后使用SSH等方式连接并执行命令或配置文件。为了执行Ansible,我们安装了Python。

现场执行

本地执行(local-exec)指定了在本地环境中执行Terraform命令的命令,我们将指定它来直接执行Ansible命令。

另外,在使用ansible指令时出现的困扰是指令的指定。

command = "ansible-playbook -i hosts ${var.service_name}.yml --private-key=~/.ssh/${var.key_name}.pem"

以这种方式运行,但偶尔在terraform fmt格式化器中。

command = "ansible-playbook -i hosts ${var.service_name}.yml --private-key = ~/.ssh/${var.key_name}.pem"

由于–private-key指定的前后加入了空格,所以最好在~/.ansible.cfg的private_key_file设置中加以处理。

[defaults]
host_key_checking = False
private_key_file = /path/to/private_key_file

一种选项是:安思富 sī fù)

现在,我认为在这一点上我们已经完成了使用Terraform创建EC2实例的定义。
接下来,我们将创建并运行实际的Ansible配置。
以下是Ansible的版本。

ansible 2.7.15

这次的任务非常简单,只需要使用apt来安装vim即可。

- name: install vim
  become: yes
  apt:
    name: vim

另外,playbook的步骤如下所示。

- hosts: service
  remote_user: ubuntu
  roles:
    - service

本次将省略对于Ansible playbook的说明。

库存文件

在这里,关于清单文件,
hosts设置只需要填写private_ip,但是只要在terraform中管理,只需重用它,
我计划在terraform中创建清单文件。
内容非常简单,如下所示。
在本地创建文件使用的是本地提供者的本地文件。

resource "local_file" "hosts_file" {
  content         = <<EOF
[${var.service_name}]
${var.private_ip}
EOF
  filename        = "hosts"
  file_permission = "0644"
}

我认为通过使用Terraform进行管理,当需要更改私有IP时,系统可以自动联动,这是很好的。

执行

最后,在运行时设置terraform的var属性。

terraform apply -var-file sample.tfvars

创建一个EC2实例,并在该服务器上执行Ansible的配置已经完成。

最后

這次的結構是為那些想使用Terraform建立實例並直接執行Ansible的人們所設計。
基本上,我認為在Ansible中已經保證了幂等性,所以並不感覺到使用上的必要性,
然而,我還是希望能夠在創建Ansible配置時提供一些可用的功能。

另外,如果对上述结构有任何“这样做更好!”之类的建议,请务必不吝赐教。谢谢!

请参考

    • 10分で理解するTerraform

 

    • Amazon EC2 AMI Locator

 

    • Terraform Documentation

 

    Ansible Documentation
bannerAds