mtyson
mtyson

Reputation: 8580

Ansible EC2 - Perform operation on set of instances

This is probably obvious, but how do you execute an operation against a set of servers in Ansible (this is with the EC2 plugin)?

I can create my instances:

---
- hosts: 127.0.0.1
  connection: local
 - name: Launch instances
      local_action:
        module: ec2
        region: us-west-1
        group: cassandra
        keypair: cassandra
        instance_type: t2.micro
        image: ami-4b6f650e
        count: 1
        wait: yes
      register: cass_ec2

And I can put the instances into a tag:

   - name: Add tag to instances
      local_action: ec2_tag resource={{ item.id }} region=us-west-1 state=present
      with_items: cass_ec2.instances
      args:
        tags:
          Name: cassandra

Now, let's say I want to run an operation on each server:

# This does not work - It runs the command on localhost
- name: TEST - touch file
  file: path=/test.txt state=touch
  with_items: cass_ec2.instances

How to run the command against the remote instances just created?

Upvotes: 4

Views: 4453

Answers (2)

Arbab Nazar
Arbab Nazar

Reputation: 23811

Please use the following playbook pattern to perform the both operations in a single playbook (means lauch an ec2 instance(s) and perform the certain tasks on it/them ) at the same time.

Here is the working playbook, that perform the following task, this playbook suppose that you have the hosts file in this same directory, where you are running the playbook:

---
  - name: Provision an EC2 Instance
    hosts: local
    connection: local
    gather_facts: False
    tags: provisioning
    # Necessary Variables for creating/provisioning the EC2 Instance
    vars:
      instance_type: t1.micro
      security_group: cassandra
      image: ami-4b6f650e
      region: us-west-1
      keypair: cassandra
      count: 1

    # Task that will be used to Launch/Create an EC2 Instance
    tasks:

      - name: Launch the new EC2 Instance
        local_action: ec2 
                      group={{ security_group }} 
                      instance_type={{ instance_type}} 
                      image={{ image }} 
                      wait=true 
                      region={{ region }} 
                      keypair={{ keypair }}
                      count={{count}}
        register: ec2

      - name: Add the newly created EC2 instance(s) to the local host group (located inside the directory)
        local_action: lineinfile 
                      dest="./hosts" 
                      regexp={{ item.public_ip }} 
                      insertafter="[cassandra]" line={{ item.public_ip }}
        with_items: ec2.instances


      - name: Wait for SSH to come up
        local_action: wait_for 
                      host={{ item.public_ip }} 
                      port=22 
                      state=started
        with_items: ec2.instances

      - name: Add tag to Instance(s)
        local_action: ec2_tag resource={{ item.id }} region={{ region }} state=present
        with_items: ec2.instances
        args:
          tags:
            Name: cassandra

      - name: SSH to the EC2 Instance(s)
        add_host: hostname={{ item.public_ip }} groupname=cassandra
        with_items: ec2.instances

  - name: Install these things on Newly created EC2 Instance(s)
    hosts: cassandra
    sudo: True 
    remote_user: ubuntu # Please change the username here,like root or ec2-user, as I am supposing that you are lauching ubuntu instance
    gather_facts: True
    # Run these tasks  
    tasks:
      - name: TEST - touch file
        file: path=/test.txt state=touch

Your hosts file should be look like this:

[local]
localhost

[cassandra]

Now you can run this playbook like this:

ansible-playbook -i hosts ec2_launch.yml

Upvotes: 1

keba
keba

Reputation: 2127

For running against just the newly created servers, I use a temporary group name and do something like the following by using a second play in the same playbook:

- hosts: localhost
  tasks:
    - name: run your ec2 create a server code here
      ...
      register: cass_ec2

    - name: add host to inventory
      add_host: name={{ item.private_ip }} groups=newinstances
      with_items: cas_ec2.instances

- hosts: newinstances
  tasks:
    - name: do some fun stuff on the new instances here

Alternatively if you have consistently tagged all your servers (and with multiple tags if you also have to differentiate between production and development; and you are also using the ec2.py as the dynamic inventory script; and you are running this against all the servers in a second playbook run, then you can easily do something like the following:

- hosts: tag_Name_cassandra
  tasks:
    - name: run your cassandra specific tasks here

Personally I use a mode tag (tag_mode_production vs tag_mode_development) as well in the above and force Ansible to only run on servers of a specific type (in your case Name=cassandra) in a specific mode (development). This looks like the following:

- hosts: tag_Name_cassandra:&tag_mode_development

Just make sure you specify the tag name and value correctly - it is case sensitive...

Upvotes: 7

Related Questions