├── 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 }}" --------------------------------------------------------------------------------