亚马逊AWS官方博客

Terraform架构实践(3)- 与Ansible集成的主要方法,实现中国区自己的“EFS”

Terraform是一个可以支持多种云环境,进行创建,更改、版本控制的工具。是一个Infra-As-Code的瑞士军刀级的工具。我们将Terraform在AWS上最佳实践架构方式和与一些其他工具进行整合的方法汇总成以下几篇文章。主要如下:

这次我们介绍一下与Ansible集成的方法,实现一套Pacemaker + DRBD + NFS来实现一个跨AZ的集群部署方案。

所以在这种框架下,我们要做到以下两件事:

1:通过Terraform创建目标账号下所需要的Infra层面的所有资源.

2:通过Terraform调用Ansible Playbook实现对所有目标主机的配置。

AWS上HA实现方案:

1:VIP

在AWS由于Subnet无法跨AZ,所以实现的方法就存在两种。Overlay的假IP,就是一个存粹的路由表指向,将这个不真实存在于VPC内的IP指向一个ENI ; 还有一种方式就是EIP,也就是拥有固定外网IP的Public IP.

2:IAM Role的权限

这个权限定义通常是集群主机内所有主机的开关机权限。然后以ec2 role的方式赋予。之所以需要这个权限,是因为系统内的HA agent会通过AWS CLI进行状态的monitor和Switch动作。所以需要这样的权限,在发生Failover后,能够正确处置后续的资源位置。

整体上HA的架构:

1:新增的EBS,通过DRBD的方式进行底层数据的同步。

2:基于DRBD所创建的文件系统PV-VG-LV,做到提供给NFS作为基本的文件系统,用于文件的分享。

3:最上层的NFS服务,构建与文件系统上,提供基础服务。

4:VIP随着DRBD的Master绑定进行切换。

而关于我们上面提到的EIP的架构图如下:

最重要的要点:

1:与Ansible的集成生成inventory

在生成所需的ec2主机后,如果构建inventory,请看如下代码:

[ec2-user@ip-172-31-22-159 withAnsible-55523423422-nx-centos]$ cat upload.tf

data "template_file" "inventory" {
  template = "${file("${path.module}/templates/hosts.tpl")}"

  vars = {
    dns01_hostname = "nfs01.liujia.com"
    dns02_hostname = "nfs02.liujia.com"
    dns01_ip = tolist(module.ec2-nfs01.private_ip)[0]
    dns02_ip = tolist(module.ec2-nfs02.private_ip)[0]
    key_path = "~/.ssh/id_rsa"
  }
}

resource "local_file" "save_inventory" {
  content  = "${data.template_file.inventory.rendered}"
  filename = "./ansible-playbook/hosts"
}

[ec2-user@ip-172-31-22-159 withAnsible-55523423422-nx-centos]$ cat templates/hosts.tpl
[master]
${nfs01_hostname} ansible_ssh_host=${nfs01_ip}

[slave]
${nfs02_hostname} ansible_ssh_host=${nfs02_ip}

[all:vars]
ansible_ssh_private_key_file = ${key_path}

在这里通过对模板inventory的定义,在通过data template_file的参数传递,最终渲染生成local_file到ansible的playbook里面生成inventory,用于最终playbook的生成。

2:完成Ansible的上传和playbook的执行

[ec2-user@ip-172-31-22-159 withAnsible-55523423422-nx-centos]$ cat upload.tf
...
resource "null_resource" "utility" {
    connection {
      timeout = "5m"
      type = "ssh"
      user = "ansible"
      host = tolist(module.ec2-utility.public_ip)[0]
      private_key = "${file("mykey.pem")}"
      }

    provisioner "local-exec" {
       command = "tar zcvf ./ansible-playbook.tgz ./ansible-playbook"
    }

    provisioner "file" {
      source = "./ansible-playbook.tgz"
      destination = "/tmp/ansible-playbook.tgz"
    }

    provisioner "remote-exec" {
      inline = [
        "tar zxvf /tmp/ansible-playbook.tgz -C /tmp",
        "cd /tmp/ansible-playbook",
        "ansible-playbook -i ./hosts site.yml",
      ]
    }
    depends_on = [local_file.save_inventory]
}

在这里通过对模板inventory的定义,在通过data template_file的参数传递,最终渲染生成local_file到ansible的playbook里面生成inventory,用于最终playbook的生成。

本篇作者

刘佳

是AWS ProServe团队云架构师。曾就职于Novell/Redhat/VMware。对于Linux和虚拟化拥有丰富的经验。具备16年的IT经验,支持过多家银行的数据中心。