Ansible: модуль cloudformation

Автор: | 25/05/2018
 

Для 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 для EC2
  • KeyName: EC2 Key Pair для доступа в систему
  • AllowLocation: IP, которому будет разрешён SSH
  • EC2AvailabilityZone: в какой 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]

Всё работает, как ожидалось.

Готово.