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

1) 首先在三个 Region 上各分配一个 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
...
>

以及带有调试模块的 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"
            }
        ]
    }
}

但是,我不知道如何进行第 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

虽然硬编码 ami/subnet 有效,你能想出一个解决方案来避免这种硬编码 ami/subnet 吗?
我尝试弄乱 set_fact 无济于事,因为我无法让它成为“区域到 ami”值映射的字典

最佳答案

请记住,Ansible 是一个“可插入”系统,因此为您自己定制它真的很容易。有时,它比尝试使用“ native ”模块寻找解决方法更容易、更快捷。

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

例如:

  • 在主文件夹中创建一个名为 lookup_plugins 的文件夹。
  • 创建一个名为 ansible.cfg
  • 的文件(如果你没有)



    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]
    

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

    然后在您的剧本中引用此插件以找到正确的子网:

    例子:
    - 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') }}"
    

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

    关于amazon-ec2 - Ansible:尝试一次性在多个区域创建多个 EC2 实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31523682/

    10-12 18:00