2015-07-20 9 views
6

che sto cercando di creare un playbook ansible AWS EC2 che:Ansible: Cercando di creare più istanze EC2 in più regioni in un solo colpo

1) prima assegna un VPC ciascuno su tre Regioni che sono: noi- West-1, ap-northeast-1 e eu-west-1.

2) trova l'ultima Ubuntu AMI per ogni regione (ec2_ami_search),

3) poi con i risultati rilevati dal 1) e 2), creare un'istanza EC2 per regione con la più recente ubuntu AMI (per la regione) con le zone di disponibilità us-west-1a, ap-northeast-1a e eu-west-1a, rispettivamente.

Con Ansible, ho avuto nessun problema con il passaggio 1) e 2), che era semplicemente:

> 

    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 
... 
> 

e la outputted per la variabile ubuntu_image con modulo di debug:

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" 
      } 
     ] 
    } 
} 

Tuttavia, non è stato possibile capire come eseguire il passaggio 3) prendere il risultato dalla variabile di registro ubuntu_image e quindi determinare quale delle 3 AMI e subnet apparteneva all'istanza EC2 fornita. Vedi sotto dove come una soluzione ho hardcoded manualmente il valore ami e la sottorete che ho semplicemente preso dalla stampa da quanto sopra ubuntu_image stampa:

- 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 

Mentre hardcoding opere/sottorete AMI, si può pensare a una soluzione per io per evitare questo hardcoding dell'ami/subnet? Ho provato scherzi con set_fact senza alcun risultato come non ho potuto farlo diventare un dizionario di "regione a ami" mappature valore

risposta

4

Tenete a mente che Ansible è un sistema "plugable", quindi è davvero facile da personalizzare per te stesso. A volte è ancora più semplice e veloce che cercare di trovare una soluzione alternativa usando i moduli "nativi".

Nel tuo caso puoi scrivere facilmente la tua personalizzata lookup_plugin che cercherebbe un subnet corretto.

Ad esempio:

  1. Creare una cartella denominata lookup_plugins nella cartella principale.
  2. Creare un file (se non ne avete uno) chiamato ansible.cfg
[defaults] 
lookup_plugins = lookup_plugins 

creare un file in lookup_plugins chiamato 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] 

Il codice semplice di cui sopra sarebbe cercare una sottorete in una determinata regione. Ovviamente puoi personalizzarlo come vuoi.

Poi, nel vostro riferimento playbook questo plugin per trovare corretta sottorete:

Esempio:

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

Nel tuo caso si sarebbe probabilmente necessario fare riferimento alla corretta AMI e associato Region.

0

se si vuole ancora fare questo senza l'aiuto di un altro modulo si può calcolare il modulo '%' dei server e la lunghezza sottoreti:

"{{subnets[item.0 | int % subnets | length | int].aws_ec2_subnets}}" 

esempio di codice

Vars:

subnets: 
    - {zone: "us-east-1a", aws_ec2_subnets: 'subnet-123'} 
    - {zone: "us-east-1b", aws_ec2_subnets: 'subnet-456'} 
    - {zone: "us-east-1d", aws_ec2_subnets: 'subnet-789'} 

server_list: 
    - server1 
    - server2 
    - server3 

compito:

- name: Create new ec2 instance 
    ec2: 
    profile: "{{aws_profile}}" 
    key_name: "{{aws_key_name}}" 
    group_id: "{{aws_security_group}}" 
    instance_type: "{{aws_instance_type}}" 
    image: "{{aws_ami}}" 
    region: "{{region}}" 
    exact_count: "1" 
    #instance_profile_name: none 
    wait: yes 
    wait_timeout: 500 
    volumes: "{{volumes}}" 
    monitoring: no 
    vpc_subnet_id: "{{subnets[item.0 | int % subnets | length | int].aws_ec2_subnets}}" 
    assign_public_ip: no 
    tenancy: default 
    termination_protection: yes 
    instance_tags: 
     App: "{{app_name}}" 
     Environment: "{{environment_type}}" 
     Platform: "{{platform_name}}" 
     Name: "{{item.1}}" 
    count_tag: 
     App: "{{app_name}}" 
     Environment: "{{environment_type}}" 
     Platform: "{{platform_name}}" 
     Name: "{{item.1}}" 
    register: ec2_new_instance 
    with_indexed_items: 
    - "{{server_list}}"