Ansible:尝试一次性在多个区域中创建多个EC2实例

Hen*_*ang 6 amazon-ec2 ansible ansible-playbook

我正在尝试创建一个AWS EC2 ansible playbook:

1)首先在三个区域分配一个VPC:us-west-1,ap-northeast-1和eu-west-1.

2)找到每个区域的最新ubuntu AMI(ec2_ami_search),

3)然后使用1)和2)中发现的结果,使用最新的ubuntu AMI(针对该地区)为每个区域创建一个EC2实例,其中包含可用区域us-west-1a,ap-northeast-1a和eu-west-1a , 分别.

使用Ansible,我对步骤1)和2)没有任何问题,这简单地说:

> 

  tasks:
  - name: create a vpc
    ec2_vpc:
      state: present
      region: "{{ item.region }}"
      internet_gateway: True
      resource_tags: { env: production}
      cidr_block: 10.0.0.0/16
      subnets:
        - cidr: 10.0.0.0/24
          az: "{{ item.az }}"
          resource_tags:
            env: production
            tier: public
      route_tables:
        - subnets:
          - 10.0.0.0/24
          routes:
          - dest: 0.0.0.0/0
            gw: igw
    with_items:
      - region: us-west-1
        az: us-west-1a
      - region: ap-northeast-1
        az: ap-northeast-1a
      - region: eu-west-1
        az: eu-west-1a
...
  - name: Get the ubuntu trusty AMI
    ec2_ami_search: distro=ubuntu release=trusty virt=hvm region={{ item }}
    with_items:
      - us-west-1
      - ap-northeast-1
      - eu-west-1
    register: ubuntu_image
...
>
Run Code Online (Sandbox Code Playgroud)

并使用调试模块输出ubuntu_image变量:

TASK: [print out ubuntu images] *********************************************** 
ok: [localhost] => {
    "ubuntu_image": {
        "changed": false, 
        "msg": "All items completed", 
        "results": [
            {
                "aki": null, 
                "ami": "ami-b33dccf7", 
                "ari": null, 
                "changed": false, 
                "invocation": {
                    "module_args": "distro=ubuntu release=trusty virt=hvm region=us-west-1", 
                    "module_name": "ec2_ami_search"
                }, 
                "item": "us-west-1", 
                "serial": "20150629", 
                "tag": "release"
            }, 
            {
                "aki": null, 
                "ami": "ami-9e5cff9e", 
                "ari": null, 
                "changed": false, 
                "invocation": {
                    "module_args": "distro=ubuntu release=trusty virt=hvm region=ap-northeast-1", 
                    "module_name": "ec2_ami_search"
                }, 
                "item": "ap-northeast-1", 
                "serial": "20150629", 
                "tag": "release"
            }, 
            {
                "aki": null, 
                "ami": "ami-7c4b0a0b", 
                "ari": null, 
                "changed": false, 
                "invocation": {
                    "module_args": "distro=ubuntu release=trusty virt=hvm region=eu-west-1", 
                    "module_name": "ec2_ami_search"
                }, 
                "item": "eu-west-1", 
                "serial": "20150629", 
                "tag": "release"
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我无法弄清楚如何使步骤3)从ubuntu_image寄存器变量中获取结果,然后确定给定EC2实例所属的3个AMI和子网中的哪一个.请参阅下面的解决方法,我手动硬编码了ami和子网值,我只是从上面的ubuntu_image打印输出中打印出来的:

  - name: start the instances
    ec2:
      image: "{{ item.ami }}"  # MANUALLY HARDCODED
      region: "{{ item.region }}"
      instance_type: "{{ instance_type }}"
      assign_public_ip: True
      key_name: "{{ item.name }}"
      group: ["http deployment", "ssh deployment", "outbound deployment"]
      instance_tags: { Name: "{{ item.name }}", type: ss, env: production}
      exact_count: "{{ count }}"
      count_tag: {  Name: "{{ item.name }}" }
      vpc_subnet_id: "{{ item.subnet }}" #MANUALLY HARDCODED
      wait: yes
    register: ec2
    with_items:
      - region: us-west-1
        name: ss12
        ami: ami-b33dccf7  # MANUALLY HARDCODED
        subnet: subnet-35a22550  # MANUALLY HARDCODED
      - region: ap-northeast-1
        name: ss21
        ami: ami-9e5cff9e  # MANUALLY HARDCODED
        subnet: subnet-88c47dff  # MANUALLY HARDCODED
      - region: eu-west-1
        name: ss32
        ami: ami-7c4b0a0b  # MANUALLY HARDCODED
        subnet: subnet-23f59554  # MANUALLY HARDCODED
Run Code Online (Sandbox Code Playgroud)

虽然硬编码ami /子网工作,你能想到一个解决方案让我避免ami /子网的这种硬编码吗?我试着弄乱set_fact无济于事,因为我无法让它成为"region to ami"值映射的字典

Vor*_*Vor 5

请记住,这Ansible是一个"可插拔"的系统,所以很容易为自己定制它.有时,它比使用"本机"模块找到解决方法更容易,更快捷.

在您的情况下,您可以轻松编写自己的自定义lookup_plugin搜索正确的自定义subnet.

例如:

  1. 创建lookup_plugins在主文件夹中调用的文件夹.
  2. 创建一个名为(如果没有的话)的文件 ansible.cfg
[defaults]
lookup_plugins = lookup_plugins
Run Code Online (Sandbox Code Playgroud)

lookup_plugins被叫中创建一个文件subnets.py

import boto.vpc
class LookupModule(object):
    def __init__(self, basedir=None, **kwargs):
        self.basedir = basedir
        self.plugin_name = 'subnets'
    def run(self, regions, variable=None, **kwargs):
        if not isinstance(regions, list):
            regions = [regions]
        for region in regions:
            return [boto.vpc.connect_to_region(region).get_all_subnets()[0].id]
Run Code Online (Sandbox Code Playgroud)

上面的简单代码将查找给定区域中的子网.当然,您可以根据需要自定义它.

然后在你的playbook中引用这个插件来找到正确的子网:

例:

- hosts: localhost
  gather_facts: no
  tasks:
    - name: Start instance
      debug: msg="Starting instance {{ item.ami }} in {{ item.region }} in {{ item.subnet }}"
      with_items:
        - region: us-west-1
          name: ss12
          ami: ami-b33dccf7  
          subnet: "{{ lookup('subnets', 'us-west-1') }}"
        - region: ap-northeast-1
          name: ss21
          ami: ami-9e5cff9e  
          subnet: "{{ lookup('subnets', 'ap-northeast-1') }}"
        - region: eu-west-1
          name: ss32
          ami: ami-7c4b0a0b 
          subnet: "{{ lookup('subnets', 'ap-northeast-1') }}"
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您可能需要引用正确AMI和关联Region.