├── README.md
├── config.yml
├── provision.yml
└── roles
├── apache
├── README.md
├── defaults
│ └── main.yml
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── tasks
│ ├── Debian.yml
│ ├── RedHat.yml
│ └── main.yml
├── templates
│ └── index.html.j2
└── vars
│ ├── Debian.yml
│ ├── RedHat.yml
│ └── main.yml
└── infra
├── README.md
├── defaults
└── main.yml
├── handlers
└── main.yml
├── meta
└── main.yml
├── tasks
└── main.yml
└── vars
└── main.yml
/README.md:
--------------------------------------------------------------------------------
1 | # Provisioning an Autoscaling Infrastructure using Ansible
2 |
3 | Please check out the article on [our blog](http://www.ansible.com/blog/autoscaling-infrastructures?utm_source=github&utm_medium=referral&utm_campaign=Blog) !
4 |
--------------------------------------------------------------------------------
/config.yml:
--------------------------------------------------------------------------------
1 | - hosts: tag_aws_autoscaling_groupName_autoscale-blog
2 | sudo: yes
3 | roles:
4 | - apache
5 |
--------------------------------------------------------------------------------
/provision.yml:
--------------------------------------------------------------------------------
1 | - hosts: localhost
2 | gather_facts: no
3 | roles:
4 | - infra
5 |
--------------------------------------------------------------------------------
/roles/apache/README.md:
--------------------------------------------------------------------------------
1 | Role Name
2 | ========
3 |
4 | A brief description of the role goes here.
5 |
6 | Requirements
7 | ------------
8 |
9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
10 |
11 | Role Variables
12 | --------------
13 |
14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
15 |
16 | Dependencies
17 | ------------
18 |
19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
20 |
21 | Example Playbook
22 | -------------------------
23 |
24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
25 |
26 | - hosts: servers
27 | roles:
28 | - { role: username.rolename, x: 42 }
29 |
30 | License
31 | -------
32 |
33 | BSD
34 |
35 | Author Information
36 | ------------------
37 |
38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed).
39 |
--------------------------------------------------------------------------------
/roles/apache/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # defaults file for apache
3 | apache_test_message: This is a test -
--------------------------------------------------------------------------------
/roles/apache/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # handlers file for apache
3 |
4 | - name: restart apache
5 | service: name={{ apache_service }} state=restarted
6 |
7 |
--------------------------------------------------------------------------------
/roles/apache/meta/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | galaxy_info:
3 | author: your name
4 | description:
5 | company: your company (optional)
6 | # Some suggested licenses:
7 | # - BSD (default)
8 | # - MIT
9 | # - GPLv2
10 | # - GPLv3
11 | # - Apache
12 | # - CC-BY
13 | license: license (GPLv2, CC-BY, etc)
14 | min_ansible_version: 1.2
15 | #
16 | # Below are all platforms currently available. Just uncomment
17 | # the ones that apply to your role. If you don't see your
18 | # platform on this list, let us know and we'll get it added!
19 | #
20 | #platforms:
21 | #- name: EL
22 | # versions:
23 | # - all
24 | # - 5
25 | # - 6
26 | # - 7
27 | #- name: GenericUNIX
28 | # versions:
29 | # - all
30 | # - any
31 | #- name: Fedora
32 | # versions:
33 | # - all
34 | # - 16
35 | # - 17
36 | # - 18
37 | # - 19
38 | # - 20
39 | #- name: opensuse
40 | # versions:
41 | # - all
42 | # - 12.1
43 | # - 12.2
44 | # - 12.3
45 | # - 13.1
46 | # - 13.2
47 | #- name: Amazon
48 | # versions:
49 | # - all
50 | # - 2013.03
51 | # - 2013.09
52 | #- name: GenericBSD
53 | # versions:
54 | # - all
55 | # - any
56 | #- name: FreeBSD
57 | # versions:
58 | # - all
59 | # - 8.0
60 | # - 8.1
61 | # - 8.2
62 | # - 8.3
63 | # - 8.4
64 | # - 9.0
65 | # - 9.1
66 | # - 9.1
67 | # - 9.2
68 | #- name: Ubuntu
69 | # versions:
70 | # - all
71 | # - lucid
72 | # - maverick
73 | # - natty
74 | # - oneiric
75 | # - precise
76 | # - quantal
77 | # - raring
78 | # - saucy
79 | # - trusty
80 | #- name: SLES
81 | # versions:
82 | # - all
83 | # - 10SP3
84 | # - 10SP4
85 | # - 11
86 | # - 11SP1
87 | # - 11SP2
88 | # - 11SP3
89 | #- name: GenericLinux
90 | # versions:
91 | # - all
92 | # - any
93 | #- name: Debian
94 | # versions:
95 | # - all
96 | # - etch
97 | # - lenny
98 | # - squeeze
99 | # - wheezy
100 | #
101 | # Below are all categories currently available. Just as with
102 | # the platforms above, uncomment those that apply to your role.
103 | #
104 | #categories:
105 | #- cloud
106 | #- cloud:ec2
107 | #- cloud:gce
108 | #- cloud:rax
109 | #- clustering
110 | #- database
111 | #- database:nosql
112 | #- database:sql
113 | #- development
114 | #- monitoring
115 | #- networking
116 | #- packaging
117 | #- system
118 | #- web
119 | dependencies: []
120 | # List your role dependencies here, one per line. Only
121 | # dependencies available via galaxy should be listed here.
122 | # Be sure to remove the '[]' above if you add dependencies
123 | # to this list.
124 |
125 |
--------------------------------------------------------------------------------
/roles/apache/tasks/Debian.yml:
--------------------------------------------------------------------------------
1 | - name: install packages (Debian)
2 | apt: name={{ item }} state=present update_cache=yes cache_valid_time=3600
3 | with_items: packages
4 | tags: package
5 |
--------------------------------------------------------------------------------
/roles/apache/tasks/RedHat.yml:
--------------------------------------------------------------------------------
1 | - name: stop iptables
2 | service: name=iptables state=stopped
3 |
4 | - name: install packages (Red Hat)
5 | yum: name={{ item }} state=present
6 | with_items: packages
7 | tags: package
--------------------------------------------------------------------------------
/roles/apache/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # tasks file for apache
3 |
4 | - name: Add the OS specific variables
5 | include_vars: "{{ ansible_os_family }}.yml"
6 |
7 | # CentOS specific package installations
8 | - include: RedHat.yml
9 | when: ansible_os_family == "RedHat"
10 |
11 | # Ubuntu specific package installations
12 | - include: Debian.yml
13 | when: ansible_os_family == "Debian"
14 |
15 | - name: copy index.html
16 | template: src=index.html.j2 dest={{ apache_docroot }}/index.html
17 |
18 | - name: start and enable apache service
19 | service: name={{ apache_service }} state=started enabled=yes
20 | tags: service
--------------------------------------------------------------------------------
/roles/apache/templates/index.html.j2:
--------------------------------------------------------------------------------
1 | {{ apache_test_message }} {{ ansible_distribution }} {{ ansible_distribution_version }}
2 | Current Host: {{ ansible_hostname }}
--------------------------------------------------------------------------------
/roles/apache/vars/Debian.yml:
--------------------------------------------------------------------------------
1 | packages:
2 | - apache2
3 | apache_service: apache2
4 | apache_docroot: /var/www
5 |
--------------------------------------------------------------------------------
/roles/apache/vars/RedHat.yml:
--------------------------------------------------------------------------------
1 | packages:
2 | - httpd
3 | - libselinux-python
4 | apache_service: httpd
5 | apache_docroot: /var/www/html
6 |
--------------------------------------------------------------------------------
/roles/apache/vars/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # vars file for apache
3 |
--------------------------------------------------------------------------------
/roles/infra/README.md:
--------------------------------------------------------------------------------
1 | Role Name
2 | ========
3 |
4 | A brief description of the role goes here.
5 |
6 | Requirements
7 | ------------
8 |
9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
10 |
11 | Role Variables
12 | --------------
13 |
14 | A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
15 |
16 | Dependencies
17 | ------------
18 |
19 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
20 |
21 | Example Playbook
22 | -------------------------
23 |
24 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
25 |
26 | - hosts: servers
27 | roles:
28 | - { role: username.rolename, x: 42 }
29 |
30 | License
31 | -------
32 |
33 | BSD
34 |
35 | Author Information
36 | ------------------
37 |
38 | An optional section for the role authors to include contact information, or a website (HTML is not allowed).
39 |
--------------------------------------------------------------------------------
/roles/infra/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # defaults file for myapp_infra
3 |
--------------------------------------------------------------------------------
/roles/infra/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # handlers file for myapp_infra
3 |
--------------------------------------------------------------------------------
/roles/infra/meta/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | galaxy_info:
3 | author: your name
4 | description:
5 | company: your company (optional)
6 | # Some suggested licenses:
7 | # - BSD (default)
8 | # - MIT
9 | # - GPLv2
10 | # - GPLv3
11 | # - Apache
12 | # - CC-BY
13 | license: license (GPLv2, CC-BY, etc)
14 | min_ansible_version: 1.2
15 | #
16 | # Below are all platforms currently available. Just uncomment
17 | # the ones that apply to your role. If you don't see your
18 | # platform on this list, let us know and we'll get it added!
19 | #
20 | #platforms:
21 | #- name: EL
22 | # versions:
23 | # - all
24 | # - 5
25 | # - 6
26 | # - 7
27 | #- name: GenericUNIX
28 | # versions:
29 | # - all
30 | # - any
31 | #- name: Fedora
32 | # versions:
33 | # - all
34 | # - 16
35 | # - 17
36 | # - 18
37 | # - 19
38 | # - 20
39 | #- name: opensuse
40 | # versions:
41 | # - all
42 | # - 12.1
43 | # - 12.2
44 | # - 12.3
45 | # - 13.1
46 | # - 13.2
47 | #- name: Amazon
48 | # versions:
49 | # - all
50 | # - 2013.03
51 | # - 2013.09
52 | #- name: GenericBSD
53 | # versions:
54 | # - all
55 | # - any
56 | #- name: FreeBSD
57 | # versions:
58 | # - all
59 | # - 8.0
60 | # - 8.1
61 | # - 8.2
62 | # - 8.3
63 | # - 8.4
64 | # - 9.0
65 | # - 9.1
66 | # - 9.1
67 | # - 9.2
68 | #- name: Ubuntu
69 | # versions:
70 | # - all
71 | # - lucid
72 | # - maverick
73 | # - natty
74 | # - oneiric
75 | # - precise
76 | # - quantal
77 | # - raring
78 | # - saucy
79 | # - trusty
80 | #- name: SLES
81 | # versions:
82 | # - all
83 | # - 10SP3
84 | # - 10SP4
85 | # - 11
86 | # - 11SP1
87 | # - 11SP2
88 | # - 11SP3
89 | #- name: GenericLinux
90 | # versions:
91 | # - all
92 | # - any
93 | #- name: Debian
94 | # versions:
95 | # - all
96 | # - etch
97 | # - lenny
98 | # - squeeze
99 | # - wheezy
100 | #
101 | # Below are all categories currently available. Just as with
102 | # the platforms above, uncomment those that apply to your role.
103 | #
104 | #categories:
105 | #- cloud
106 | #- cloud:ec2
107 | #- cloud:gce
108 | #- cloud:rax
109 | #- clustering
110 | #- database
111 | #- database:nosql
112 | #- database:sql
113 | #- development
114 | #- monitoring
115 | #- networking
116 | #- packaging
117 | #- system
118 | #- web
119 | dependencies: []
120 | # List your role dependencies here, one per line. Only
121 | # dependencies available via galaxy should be listed here.
122 | # Be sure to remove the '[]' above if you add dependencies
123 | # to this list.
124 |
125 |
--------------------------------------------------------------------------------
/roles/infra/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # tasks file for myapp_infra
3 | - name: create app security group
4 | ec2_group:
5 | name: "{{ app_name }}"
6 | description: "{{ app_name }} security group"
7 | region: "{{ region }}"
8 | rules: "{{ sec_group_rules }}"
9 | vpc_id: "{{ vpc_id }}"
10 | tags: security_groups
11 | register: app_security_group
12 |
13 |
14 | - name: launch load balancer
15 | ec2_elb_lb:
16 | name: "{{ app_name }}"
17 | region: "{{ region }}"
18 | state: present
19 | subnets: "{{ subnets | join(',') }}"
20 | security_group_ids: "{{ app_security_group.group_id }}"
21 | connection_draining_timeout: 60
22 | listeners:
23 | - protocol: http
24 | load_balancer_port: 80
25 | instance_port: 80
26 | health_check:
27 | ping_protocol: http # options are http, https, ssl, tcp
28 | ping_port: 80
29 | ping_path: "/" # not required for tcp or ssl
30 | response_timeout: 5 # seconds
31 | interval: 30 # seconds
32 | unhealthy_threshold: 5
33 | healthy_threshold: 5
34 | tags: load_balancer
35 |
36 | - name: create launch config
37 | ec2_lc:
38 | name: "{{ app_name }}"
39 | image_id: "{{ ami }}"
40 | key_name: "{{ key_name }}"
41 | region: "{{ region }}"
42 | security_groups: "{{ app_security_group.group_id }},{{ tower_callback_client_group_id }},{{ tower_client_group_id }}"
43 | instance_type: "{{ instance_size }}"
44 | user_data: "{{ user_data }}"
45 | tags: launch_config
46 |
47 | - name: create autoscale groups
48 | ec2_asg:
49 | name: "{{ app_name }}"
50 | load_balancers: "{{ app_name }}"
51 | launch_config_name: "{{ app_name }}"
52 | min_size: "{{ min_size }}"
53 | max_size: "{{ max_size }}"
54 | desired_capacity: "{{ desired_capacity }}"
55 | region: "{{ region }}"
56 | vpc_zone_identifier: "{{ subnets | join(',') }}"
57 | health_check_type: EC2
58 | health_check_period: 300
59 |
60 |
61 | - name: create scale down policy
62 | ec2_scaling_policy:
63 | state: present
64 | region: "{{ region }}"
65 | name: scale-down-policy
66 | adjustment_type: ChangeInCapacity
67 | asg_name: "{{ app_name }}"
68 | scaling_adjustment: -1
69 | min_adjustment_step: -1
70 | cooldown: 300
71 | register: scale_down_policy
72 | tags: scaling_policy
73 |
74 | - name: create scale up policy
75 | ec2_scaling_policy:
76 | state: present
77 | region: "{{ region }}"
78 | name: scale-up-policy
79 | adjustment_type: ChangeInCapacity
80 | asg_name: "{{ app_name }}"
81 | scaling_adjustment: 1
82 | min_adjustment_step: 1
83 | cooldown: 300
84 | register: scale_up_policy
85 | tags: scaling_policy
86 |
87 | - name: create scale down alarm
88 | ec2_metric_alarm:
89 | state: present
90 | region: "{{ region }}"
91 | name: "cpu-low"
92 | metric: CPUUtilization
93 | namespace: "AWS/EC2"
94 | statistic: Average
95 | comparison: "<="
96 | threshold: 5.0
97 | period: 300
98 | evaluation_periods: 3
99 | unit: "Percent"
100 | description: "This will alarm when cpu usage average is lower than 5% for 15 minutes "
101 | dimensions:
102 | AutoScalingGroupName: "{{ app_name }}"
103 | alarm_actions:
104 | - "{{ scale_down_policy.arn }}"
105 | tags: alarm
106 |
107 | - name: create scale up alarm
108 | ec2_metric_alarm:
109 | state: present
110 | region: "{{ region }}"
111 | name: "cpu-high"
112 | metric: CPUUtilization
113 | namespace: "AWS/EC2"
114 | statistic: Average
115 | comparison: "<="
116 | threshold: 90.0
117 | period: 300
118 | evaluation_periods: 3
119 | unit: "Percent"
120 | description: "This will alarm when cpu usage average is higher than 90% for 15 minutes "
121 | dimensions:
122 | AutoScalingGroupName: "{{ app_name }}"
123 | alarm_actions:
124 | - "{{ scale_up_policy.arn }}"
125 | tags: alarm
126 |
127 |
--------------------------------------------------------------------------------
/roles/infra/vars/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # vars file for myapp_infra
3 | user_data: |
4 | #!/bin/bash
5 | exec > /tmp/autoscale.log 2>&1
6 | set -x
7 | TOWER_ADDRESS={{ tower_address }}
8 | HOST_CONFIG_KEY={{ host_config_key }}
9 | TEMPLATE_ID={{ template_id }}
10 |
11 |
12 | retry_attempts=10
13 | attempt=0
14 | while [[ $attempt -lt $retry_attempts ]]
15 | do
16 | status_code=`curl -k -s -i --data "host_config_key=$HOST_CONFIG_KEY" https://$TOWER_ADDRESS/api/v1/job_templates/$TEMPLATE_ID/callback/ | head -n 1 | awk '{print $2}'`
17 | if [[ $status_code == 202 ]]
18 | then
19 | exit 0
20 | fi
21 | attempt=$(( attempt + 1 ))
22 | echo "${status_code} received... retrying in 1 minute. (Attempt ${attempt})"
23 | sleep 60
24 | done
25 | exit 1
26 |
27 | sec_group_rules:
28 | - proto: tcp
29 | from_port: 80
30 | to_port: 80
31 | cidr_ip: 0.0.0.0/0
32 | - proto: tcp
33 | from_port: 0
34 | to_port: 65535
35 | group_name: "{{ app_name }}"
36 | - proto: udp
37 | from_port: 0
38 | to_port: 65535
39 | group_name: "{{ app_name }}"
40 | - proto: icmp
41 | from_port: 0
42 | to_port: 0
43 | group_name: "{{ app_name }}"
--------------------------------------------------------------------------------