Commit learning environment for using Ansible with AWS

Add Ansible configuration, Ansible inventory, dynamic inventory script, and Ansible playbooks for a learning environment that shows how to manage AWS infrastructure using Ansible.

Signed-off-by: Scott S. Lowe <scott.lowe@scottlowe.org>
This commit is contained in:
Scott S. Lowe 2016-10-23 10:09:49 -06:00
parent 916242a569
commit b0a8f6de59
7 changed files with 1818 additions and 0 deletions

37
ansible-aws/README.md Normal file
View file

@ -0,0 +1,37 @@
# Using Ansible to Orchestrate AWS
These files provide an example of how to use Ansible to orchestrate actions on Amazon Web Services (AWS). These files were tested using Ansible 2.1.1 on macOS 10.11.5.
## Contents
* **ansible.cfg**: This file tells Ansible where to find the default inventory file (the file `inventory` in the same directory).
* **create.yml**: This Ansible playbook creates infrastructure on AWS. Be sure to edit this file to specify the values listed in the `vars` section at the top of the file.
* **delete.yml**: This Ansible playbook leverages the `ec2.py` dynamic inventory script to tear down (delete) AWS infrastructure. Be sure to edit this file to specify the values in the `vars` sections (one at the top and one farther down).
* **ec2.ini**: This file is the configuration file for the dynamic inventory script. Edit the `regions=` line in this file to specify the AWS regions where instances may be running.
* **ec2.py**: This is a dynamic inventory script to query AWS APIs and generate an inventory that Ansible can use. No edits are needed to this file.
* **inventory**: This is a simple Ansible inventory file that points to the local host. It includes a definition of "ansible_python_interpreter" to help work around Python virtualenv issues.
* **README.md**: The file you're currently reading.
## Instructions
These instructions assume that you have an AWS account, that you know your AWS access key ID and secret access key, and that Ansible is installed and working on your system.
1. Place the files from the `ansible-aws` directory of this GitHub repository into a directory on your local system. You can clone the entire "learning-tools" repository (using `git clone`) or just download the specific files from the `ansible-aws` folder.
2. Edit `create.yml` and `delete.yml` to specify the values listed in the `vars` section of each file. Note that there are _two_ `vars` sections in `delete.yml` because there are two plays in the playbook.
3. To create AWS infrastructure using ansible, run `ansible-playbook create.yml`.
4. To delete the infrastructure created in step 3, run `ansible-playbook -i ./ec2.py delete.yml`.
Enjoy!
## License
This content is licensed under the MIT License.

2
ansible-aws/ansible.cfg Normal file
View file

@ -0,0 +1,2 @@
[defaults]
inventory = ./inventory

41
ansible-aws/create.yml Normal file
View file

@ -0,0 +1,41 @@
---
- hosts: "localhost"
connection: "local"
gather_facts: false
vars:
ami: "<insert AMI ID here>"
region: "<insert AWS region here>"
type: "t2.micro"
sshkey: "<insert SSH keypair name here>"
vpcid: "<insert VPC ID here>"
tasks:
- name: "Create a new security group"
ec2_group:
name: "ansible-sec-group"
description: "New SG for Ansible-created instances"
region: "{{ region }}"
vpc_id: "{{ vpcid }}"
rules:
- proto: "tcp"
from_port: 22
to_port: 22
cidr_ip: "0.0.0.0/0"
rules_egress:
- proto: "all"
cidr_ip: "0.0.0.0/0"
register: secgrp
- name: "Provision an EC2 instance"
ec2:
key_name: "{{ sshkey }}"
group_id: "{{ secgrp.group_id }}"
instance_type: "{{ type }}"
ec2_region: "{{ region }}"
image: "{{ ami }}"
wait: true
count: 1
instance_tags:
tool: "ansible"
env: "test"
register: ec2instance

37
ansible-aws/delete.yml Normal file
View file

@ -0,0 +1,37 @@
---
- hosts: "tag_tool_ansible"
connection: "local"
gather_facts: false
vars:
region: "<insert AWS region here>"
tasks:
- name: "Remove tagged EC2 instances from security group"
ec2:
state: "running"
region: "{{ region }}"
instance_ids: "{{ ec2_id }}"
group_id: ""
delegate_to: "localhost"
- name: "Terminate tagged EC2 instances"
ec2:
state: "absent"
region: "{{ region }}"
instance_ids: "{{ ec2_id }}"
wait: true
delegate_to: "localhost"
- hosts: "localhost"
connection: "local"
gather_facts: false
vars:
region: "<insert AWS region here>"
tasks:
- name: "Remove security group"
ec2_group:
name: "ansible-sec-group"
description: "New SG for Ansible-created instances"
region: "{{ region }}"
state: "absent"

189
ansible-aws/ec2.ini Normal file
View file

@ -0,0 +1,189 @@
# Ansible EC2 external inventory script settings
#
[ec2]
# to talk to a private eucalyptus instance uncomment these lines
# and edit edit eucalyptus_host to be the host name of your cloud controller
#eucalyptus = True
#eucalyptus_host = clc.cloud.domain.org
# AWS regions to make calls to. Set this to 'all' to make request to all regions
# in AWS and merge the results together. Alternatively, set this to a comma
# separated list of regions. E.g. 'us-east-1,us-west-1,us-west-2'
regions = us-west-2
regions_exclude = us-gov-west-1,cn-north-1
# When generating inventory, Ansible needs to know how to address a server.
# Each EC2 instance has a lot of variables associated with it. Here is the list:
# http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance
# Below are 2 variables that are used as the address of a server:
# - destination_variable
# - vpc_destination_variable
# This is the normal destination variable to use. If you are running Ansible
# from outside EC2, then 'public_dns_name' makes the most sense. If you are
# running Ansible from within EC2, then perhaps you want to use the internal
# address, and should set this to 'private_dns_name'. The key of an EC2 tag
# may optionally be used; however the boto instance variables hold precedence
# in the event of a collision.
destination_variable = public_dns_name
# This allows you to override the inventory_name with an ec2 variable, instead
# of using the destination_variable above. Addressing (aka ansible_ssh_host)
# will still use destination_variable. Tags should be written as 'tag_TAGNAME'.
#hostname_variable = tag_Name
# For server inside a VPC, using DNS names may not make sense. When an instance
# has 'subnet_id' set, this variable is used. If the subnet is public, setting
# this to 'ip_address' will return the public IP address. For instances in a
# private subnet, this should be set to 'private_ip_address', and Ansible must
# be run from within EC2. The key of an EC2 tag may optionally be used; however
# the boto instance variables hold precedence in the event of a collision.
# WARNING: - instances that are in the private vpc, _without_ public ip address
# will not be listed in the inventory until You set:
# vpc_destination_variable = private_ip_address
vpc_destination_variable = ip_address
# The following two settings allow flexible ansible host naming based on a
# python format string and a comma-separated list of ec2 tags. Note that:
#
# 1) If the tags referenced are not present for some instances, empty strings
# will be substituted in the format string.
# 2) This overrides both destination_variable and vpc_destination_variable.
#
#destination_format = {0}.{1}.example.com
#destination_format_tags = Name,environment
# To tag instances on EC2 with the resource records that point to them from
# Route53, uncomment and set 'route53' to True.
route53 = False
# To exclude RDS instances from the inventory, uncomment and set to False.
#rds = False
# To exclude ElastiCache instances from the inventory, uncomment and set to False.
#elasticache = False
# Additionally, you can specify the list of zones to exclude looking up in
# 'route53_excluded_zones' as a comma-separated list.
# route53_excluded_zones = samplezone1.com, samplezone2.com
# By default, only EC2 instances in the 'running' state are returned. Set
# 'all_instances' to True to return all instances regardless of state.
all_instances = False
# By default, only EC2 instances in the 'running' state are returned. Specify
# EC2 instance states to return as a comma-separated list. This
# option is overriden when 'all_instances' is True.
# instance_states = pending, running, shutting-down, terminated, stopping, stopped
# By default, only RDS instances in the 'available' state are returned. Set
# 'all_rds_instances' to True return all RDS instances regardless of state.
all_rds_instances = False
# Include RDS cluster information (Aurora etc.)
include_rds_clusters = False
# By default, only ElastiCache clusters and nodes in the 'available' state
# are returned. Set 'all_elasticache_clusters' and/or 'all_elastic_nodes'
# to True return all ElastiCache clusters and nodes, regardless of state.
#
# Note that all_elasticache_nodes only applies to listed clusters. That means
# if you set all_elastic_clusters to false, no node will be return from
# unavailable clusters, regardless of the state and to what you set for
# all_elasticache_nodes.
all_elasticache_replication_groups = False
all_elasticache_clusters = False
all_elasticache_nodes = False
# API calls to EC2 are slow. For this reason, we cache the results of an API
# call. Set this to the path you want cache files to be written to. Two files
# will be written to this directory:
# - ansible-ec2.cache
# - ansible-ec2.index
cache_path = ~/.ansible/tmp
# The number of seconds a cache file is considered valid. After this many
# seconds, a new API call will be made, and the cache file will be updated.
# To disable the cache, set this value to 0
cache_max_age = 300
# Organize groups into a nested/hierarchy instead of a flat namespace.
nested_groups = False
# Replace - tags when creating groups to avoid issues with ansible
replace_dash_in_groups = True
# If set to true, any tag of the form "a,b,c" is expanded into a list
# and the results are used to create additional tag_* inventory groups.
expand_csv_tags = False
# The EC2 inventory output can become very large. To manage its size,
# configure which groups should be created.
group_by_instance_id = True
group_by_region = True
group_by_availability_zone = True
group_by_ami_id = True
group_by_instance_type = True
group_by_key_pair = True
group_by_vpc_id = True
group_by_security_group = True
group_by_tag_keys = True
group_by_tag_none = True
group_by_route53_names = True
group_by_rds_engine = True
group_by_rds_parameter_group = True
group_by_elasticache_engine = True
group_by_elasticache_cluster = True
group_by_elasticache_parameter_group = True
group_by_elasticache_replication_group = True
# If you only want to include hosts that match a certain regular expression
# pattern_include = staging-*
# If you want to exclude any hosts that match a certain regular expression
# pattern_exclude = staging-*
# Instance filters can be used to control which instances are retrieved for
# inventory. For the full list of possible filters, please read the EC2 API
# docs: http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html#query-DescribeInstances-filters
# Filters are key/value pairs separated by '=', to list multiple filters use
# a list separated by commas. See examples below.
# Retrieve only instances with (key=value) env=staging tag
# instance_filters = tag:env=staging
# Retrieve only instances with role=webservers OR role=dbservers tag
# instance_filters = tag:role=webservers,tag:role=dbservers
# Retrieve only t1.micro instances OR instances with tag env=staging
# instance_filters = instance-type=t1.micro,tag:env=staging
# You can use wildcards in filter values also. Below will list instances which
# tag Name value matches webservers1*
# (ex. webservers15, webservers1a, webservers123 etc)
# instance_filters = tag:Name=webservers1*
# A boto configuration profile may be used to separate out credentials
# see http://boto.readthedocs.org/en/latest/boto_config_tut.html
# boto_profile = some-boto-profile-name
[credentials]
# The AWS credentials can optionally be specified here. Credentials specified
# here are ignored if the environment variable AWS_ACCESS_KEY_ID or
# AWS_PROFILE is set, or if the boto_profile property above is set.
#
# Supplying AWS credentials here is not recommended, as it introduces
# non-trivial security concerns. When going down this route, please make sure
# to set access permissions for this file correctly, e.g. handle it the same
# way as you would a private SSH key.
#
# Unlike the boto and AWS configure files, this section does not support
# profiles.
#
# aws_access_key_id = AXXXXXXXXXXXXXX
# aws_secret_access_key = XXXXXXXXXXXXXXXXXXX
# aws_security_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXX

1510
ansible-aws/ec2.py Executable file

File diff suppressed because it is too large Load diff

2
ansible-aws/inventory Normal file
View file

@ -0,0 +1,2 @@
[local]
localhost ansible_python_interpreter=python