Best way to launch aws ec2 instances with ansible

2020-01-30 05:47发布

问题:

I'm trying to create an small webapp infrastructure with ansible on Amazon AWS and I want to do all the process: launch instance, configure services, etc. but I can't find a proper tool or module to deal with that from ansible. Mainly EC2 Launch.

Thanks a lot.

回答1:

This is the short answer of your question, if you want detail and fully automated role, please let me know. Thanks

Prerequisite:

  • Ansible

  • Python boto library

  • Set up the AWS access and secret keys in the environment settings
    (best is inside the ~./boto)

To Create the EC2 Instance(s):

In order to create the EC2 Instance, please modified these parameters that you can find inside the "ec2_launch.yml" file under "vars":

  • region # where is want to launch the instance(s), USA, Australia, Ireland etc
  • count # Number of instance(s), you want to create

    Once, you have mentioned these parameter, please run the following command:

ansible-playbook -i hosts ec2_launch.yml

Contents of hosts file:

[local]
localhost

[webserver]

Contents of ec2_launch.yml file:

---
  - 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: webserver # Change the security group name here
      image: ami-98aa1cf0 # Change the AMI, from which you want to launch the server
      region: us-east-1 # Change the Region
      keypair: ansible # Change the keypair name
      count: 1

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

      - name: Create a security group
        local_action: 
          module: ec2_group
          name: "{{ security_group }}"
          description: Security Group for webserver Servers
          region: "{{ region }}"
          rules:
            - proto: tcp
              type: ssh
              from_port: 22
              to_port: 22
              cidr_ip: 0.0.0.0/0
            - proto: tcp
              from_port: 80
              to_port: 80
              cidr_ip: 0.0.0.0/0
          rules_egress:
            - proto: all
              type: all
              cidr_ip: 0.0.0.0/0


      - 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="[webserver]" 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: webserver


回答2:

As others have said, the cloud module contains just about all the AWS provisioning support you'd need. That said, Ansible's paradigm makes most sense once there's an existing SSH:able machine to target and connect to. The instantiation phase, by comparison, essentially asks you to target your local machine and calls AWS API endpoints from there.

Like you, I wanted a single-shot command with a graceful transition from EC2 instantiation into its configuration. There's suggestions on how to accomplish something like this in the documentation, but it relies on the the add_host module to tweak Ansible's idea of current host inventory, and even then I couldn't find a solution that didn't feel like i was working against rather than with the system.

In the end I opted for two distinct playbooks: a provision.yml that uses the ec2, ec2_group, ec2_vol, ec2_eip and route53 modules to ensure I have the "hardware" in place, and then configure.yml, more like a traditional Ansible site.yml, which is able to treat host inventory (static in my case, but dynamic will work well) as a given and do all that good declarative state transitioning.

Both playbooks are idempotent, but it's configure.yml that's meant to be rerun over and over in the long run.



回答3:

The EC2 module was designed precisely for creating and destroying instances.

If you want the "best" way, it's hard to beat CloudFormation, which can be launched from Ansible.