Для Ansible существует интересный модуль cloudformation, который позволяет создавать и удалять AWS CloudFormation стеки.
Его может быть полезно использовать, что бы удобно передавать различные параметрыдля стеков, например Dev и Production, через переменные самого Ansible.
Для примера возьмём шаблон ec2_simple_stack.json.
Содержание
Подготовка проекта
Создадим новые проект:
[simterm]
$ mkdir ansible_cf_example
[/simterm]
Создаём плейбук, всего одна роль — cloudformation:
- hosts:
- all
become:
true
gather_facts:
false
roles:
- role: cloudformation
Добавляем инвентори файл — hosts.ini, домены тут сейчас не играют роли, но в реальном проекте через него будем передавать параметры для создаваемых стеков Dev и Production окружений:
[all:vars] ansible_connection: local [dev-cf-example] dev-cf-example.com [dev-cf-example:vars] [production-cf-example] production-cf-example.com [production-cf-example:vars]
В переменных для Dev и Production пока пусто, добавим их по ходу создания роли cloudformation.
Роль cloudformation
Приступаем к созданию роли.
Добавляем каталоги:
[simterm]
$ mkdir -p roles/cloudformation/{tasks,files}
[/simterm]
Переменные для окружений
Есть несколько вариантов того, как можно определять параметры для Dev и Production стеков, например:
- передавать через
varsвhosts.ini - передавать через отдельные файлы переменных, которые будут подгружаться через
tasksролиcloudformation(см. пример тут>>>)
Тут для простоты параметры будем переопределять через hosts.ini, а потом использовать --limit для ansible-playbook, что бы указать на окружение, которое будем создавать.
Шаблон CloudFormation
В каталоге files создаём шаблон из файла ec2_simple_stack.json:
[simterm]
$ cp ~/Work/RTFM/Github/setevoy-aws-templates/ec2_simple_stack.json roles/cloudformation/files/
[/simterm]
В нём имеется несколько параметров:
InstanceType: тип инстанса в стекеAMIID: AMI для EC2KeyName: EC2 Key Pair для доступа в системуAllowLocation: IP, которому будет разрешён SSHEC2AvailabilityZone: в какой Availability зоне создавать инстанс
Вот их мы и будем переопределять для Dev и Production. Имеет смысл для Dev создавать инстанс поменьше, например t2.nano, а для Prod — t2.small, и использовать различные ключи, для Dev пусть будет setevoy-testing-dev, для прода — setevoy-testing-prod.
Остальные параметры будут общие, их задачим в [all:vars].
Кроме того — для Dev и Prod добавим переменную env.
Возвращаемся к hosts.ini, добавляем переменные:
[all:vars] aws_access_key="AKI***AYQ" aws_secret_key="q0I***jvj" region="eu-west-1" ansible_connection=local ami_id="ami-8a745cf3" allow_location="0.0.0.0/0" ec2_availability_zone="eu-west-1a" [dev-cf-example] dev-cf-example.com [dev-cf-example:vars] instance_type="t2.nano" key_name="setevoy-testing-dev" env="Dev" [production-cf-example] production-cf-example.com [production-cf-example:vars] instance_type="t2.small" key_name="setevoy-testing-prod" env="Production"
Задача создания стека
Теперь можно добавить задачу для создания стека.
Описываем её в файле roles/cloudformation/tasks/main.yml:
- name: "Create a {{ env }} Cloudformation stack"
cloudformation:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
region: "{{ region }}"
stack_name: "ansible-{{ env }}-cf-example"
state: "present"
disable_rollback: true
template: "roles/cloudformation/files/ec2_simple_stack.json"
template_parameters:
KeyName: "{{ key_name }}"
InstanceType: "{{ instance_type }}"
AllowLocation: "{{ allow_location }}"
tags:
Stack: "ansible-cloudformation"
Создание стека
Далее можно создавать стек.
Проверяем плейбук:
[simterm]
$ ansible-playbook -i hosts.ini --limit=dev-cf-example ansible_cf_example.yml --check PLAY [all] **** TASK [cloudformation : Create a Dev Cloudformation stack] **** changed: [dev-cf-example.com] PLAY RECAP **** dev-cf-example.com : ok=1 changed=1 unreachable=0 failed=0
[/simterm]
Создаём Dev:
[simterm]
$ ansible-playbook -i hosts.ini --limit=dev-cf-example ansible_cf_example.yml PLAY [all] **** TASK [cloudformation : Create a Dev Cloudformation stack] **** changed: [dev-cf-example.com] PLAY RECAP **** dev-cf-example.com : ok=1 changed=1 unreachable=0 failed=0
[/simterm]
Проверяем значения, которые мы передавали:
[simterm]
$ aws ec2 describe-instances --instance-ids i-027dbe988498ce5d6 --query '[Reservations[*].Instances[*].InstanceType]' --output text t2.nano
[/simterm]
ОК, создаём Production:
[simterm]
$ ansible-playbook -i hosts.ini --limit=production-cf-example ansible_cf_example.yml PLAY [all] **** TASK [cloudformation : Create a Production Cloudformation stack] **** changed: [production-cf-example.com] PLAY RECAP **** production-cf-example.com : ok=1 changed=1 unreachable=0 failed=0
[/simterm]
Проверяем:
[simterm]
$ aws ec2 describe-instances --instance-ids i-012c67879aaf0001b --query '[Reservations[*].Instances[*].InstanceType]' --output text t2.small
[/simterm]
Всё работает, как ожидалось.
Готово.
