cloudformation
Ansible Роль: Создание стеков CloudFormation
Мотивация | Установка | Особенности | Переменные | Использование | Шаблоны | Различия | Зависимости | Требования | Лицензия
Ansible роль для преобразования произвольного количества шаблонов Jinja2 в файлы CloudFormation и развертывания любого количества стеков.
Мотивация
Эта роль преодолевает недостатки самих шаблонов CloudFormation и активно использует функции Ansible.
- Ограничения CloudFormation - Синтаксис CloudFormation довольно ограничен, когда дело доходит до программной логики, такой как условия, циклы и сложные переменные, такие как массивы или словари. Обернув свой шаблон CloudFormation в Ansible, вы сможете использовать директивы Jinja2 внутри самого шаблона CloudFormation, таким образом, имея все преимущества Ansible и все еще развертывая через стеки CloudFormation.
- Независимость от окружения - Благодаря возможности преобразовывать шаблоны CloudFormation с помощью пользовательских переменных цикла, вы сможете создавать полностью независимые от окружения шаблоны и повторно использовать их для производства, тестирования, развертывания и других окружений.
- Проверка без развертывания - Еще одно преимущество использования Ansible для развертывания ваших шаблонов CloudFormation заключается в том, что Ansible поддерживает режим проверки (
--check
) для развертываний CloudFormation (с версии Ansible 2.4). В этом режиме он создаст Change-set и сообщит вам, что изменится, если вы действительно его развернете. Таким образом, вы можете безопасно тестировать свои стеки перед их фактическим применением.
Эта роль может использоваться для генерации только ваших шаблонов с помощью cloudformation_generate_only
или также для развертывания ваших преобразованных шаблонов. Поэтому, когда у вас уже есть инфраструктура развертывания, вы все равно можете использовать эту роль, просто преобразовав шаблоны и затем вручную передав их вашей существующей инфраструктуре.
Когда шаблоны преобразованы, в каталоге роли создается временный каталог build/
. Это может либо сохраняться, либо создаваться заново каждый раз, когда выполняется эта роль. Укажите поведение с помощью cloudformation_clean_build_env
.
Установка
Используйте Ansible Galaxy для установки роли:
$ ansible-galaxy install cytopia.cloudformation
Или клонируйте репозиторий в каталог ваших ролей
$ git clone https://github.com/cytopia/ansible-role-cloudformation /path/to/ansible/roles
Особенности
- Развертывание произвольного количества шаблонов CloudFormation
- Создание шаблонов CloudFormation с использованием шаблонизатора Jinja2
- Только преобразование шаблонов и использование вашей текущей инфраструктуры для развертывания
- Режим проверки с помощью Ansible
--check
, который создаст временные Change-set (например: сообщит вам, если ресурс требует пересоздания) - Просмотр различий построчно между локальными и развернутыми шаблонами с помощью модуля cloudformation_diff
- Использование Ansible vault для хранения конфиденциальной информации в зашифрованном виде
Переменные
Обзор
Следующие переменные доступны в defaults/main.yml
и могут быть использованы для настройки вашей инфраструктуры.
Переменная | Тип | По умолчанию | Описание |
---|---|---|---|
cloudformation_clean_build_env |
bool | False |
Очистить каталог build/ с шаблонами CloudFormation, сгенерированными Jinja2, при каждом запуске. |
cloudformation_generate_only |
bool | False |
Вместо развертывания ваших шаблонов CloudFormation вы также можете только преобразовать их и сделать доступными в каталоге build/ , чтобы можно было использовать вашу текущую инфраструктуру для их развертывания.Совет: Укажите эту переменную через аргументы командной строки ansible. |
cloudformation_run_diff |
bool | False |
Эта роль поставляется с настраиваемым модулем Ansible CloudFormation cloudformation_diff. Этот модуль генерирует текстовый вывод различий между вашим локальным шаблоном cloudformation, готовым к развертыванию, и текущим развернутым шаблоном на AWS CloudFormation. Зачем это нужно? Текущий модуль cloudformation просто перечисляет наборы изменений в режиме --check, что позволит вам узнать, что изменится (например, группы безопасности), но не конкретно, что именно изменится (какие группы безопасности и их значения). Чтобы также видеть точные изменения, которые произойдут, включите модуль cloudformation_diff здесь. |
cloudformation_diff_output |
string | json |
Когда cloudformation_run_diff включен, какой вывод различий следует указать? Если вы пишете свои шаблоны cloudformation в формате json, используйте json , или если вы пишете свои шаблоны в формате yaml, используйте yaml . |
cloudformation_required |
list | [] |
Массив доступных ключей стеков cloudformation, которые вы хотите сделать обязательными вместо необязательных. Каждый элемент стека cloudformation будет проверен на соответствие заданным обязательным ключам. Если элемент стека не содержит ни одного из этих ключей, будет выдана ошибка до начала развертывания. |
cloudformation_defaults |
dict | {} |
Словарь значений по умолчанию, которые применяются ко всем стеком cloudformation. Обратите внимание, что эти значения могут быть переопределены в определении каждого стека. |
cloudformation_stacks |
list | [] |
Массив стеков cloudformation для развертывания. |
Подробности
Этот раздел содержит более подробное описание доступных ключей словарей или массивов.
cloudformation_defaults
Ключ | Тип | Обязательный | Описание |
---|---|---|---|
aws_access_key |
string | необязательный | AWS access key для использования |
aws_secret_key |
string | необязательный | AWS secret key для использования |
security_token |
string | необязательный | AWS security token для использования |
profile |
string | необязательный | AWS boto profile для использования |
notification_arns |
string | необязательный | Публикация уведомлений стеков по этим ARN |
termination_protection |
bool | необязательный | Включить или отключить защиту от завершения стека. Работает только с botocore >= 1.7.18 |
region |
string | необязательный | Регион AWS для развертывания стека |
cloudformation_stacks
Ключ | Тип | Обязательный | Описание |
---|---|---|---|
stack_name |
string | обязательный | Имя стека cloudformation |
template |
string | обязательный | Путь к шаблону cloudformation, который нужно обработать и развернуть (не нужно обрабатывать) |
aws_access_key |
string | необязательный | AWS access key для использования (перезаписывается по умолчанию) |
aws_secret_key |
string | необязательный | AWS access key для использования (перезаписывается по умолчанию) |
security_token |
string | необязательный | AWS security token для использования (перезаписывается по умолчанию) |
profile |
string | необязательный | AWS boto profile для использования (перезаписывается по умолчанию) |
notification_arns |
string | необязательный | Публикация уведомлений стеков по этим ARN (перезаписывается по умолчанию) |
termination_protection |
bool | необязательный | Включить или отключить защиту от завершения стека. Работает только с botocore >= 1.7.18 |
region |
string | необязательный | Регион AWS для развертывания стека (перезаписывается по умолчанию) |
template_parameters |
dict | необязательный | Обязательные параметры стека cloudformation |
tags |
dict | необязательный | Теги, связанные со стеком cloudformation |
Примеры
Определите значения по умолчанию, которые будут применяться ко всем стекам (если не переопределены в определении каждого стека)
# Принудите установить 'profile' для каждого элемента стека cloudformation
cloudformation_required:
- profile
cloudformation_defaults:
region: eu-central-1
Определите стеки cloudformation, которые будут обработаны и развернуты
cloudformation_stacks:
- stack_name: stack-s3
template: files/cloudformation/s3.yml.j2
profile: production
template_parameters:
bucketName: my-bucket
tags:
env: production
- stack_name: stack-lambda
template: files/cloudformation/lambda.yml.j2
profile: production
termination_protection: True
template_parameters:
lambdaFunctionName: lambda
handler: lambda.run_handler
runtime: python2.7
s3Bucket: my-bucket
s3Key: lambda.py.zip
tags:
env: production
Только преобразуйте ваши шаблоны Jinja2, но не развертывайте их в AWS. Преобразованные файлы cloudformation будут находиться в каталоге build/
этой роли.
$ ansible-playbook play.yml -e cloudformation_generate_only=True
Использование
Простое
Простой пример использования:
playbook.yml
- hosts: localhost
connection: local
roles:
- cloudformation
group_vars/all.yml
# Определите стеки Cloudformation
cloudformation_stacks:
# Первый стек
- stack_name: stack-s3
profile: testing
region: eu-central-1
template: files/cloudformation/s3.yml.j2
template_parameters:
bucketName: my-bucket
tags:
env: testing
# Второй стек
- stack_name: stack-lambda
profile: testing
termination_protection: True
region: eu-central-1
template: files/cloudformation/lambda.yml.j2
template_parameters:
lambdaFunctionName: lambda
handler: lambda.run_handler
runtime: python2.7
s3Bucket: my-bucket
s3Key: lambda.py.zip
tags:
env: testing
Продвинутое
Пример продвинутого использования, вызывающего роль независимо в разных виртуальных хостах.
inventory
[my-group]
infrastructure ansible_connection=local
application ansible_connection=local
playbook.yml
# Часть инфраструктуры
- hosts: infrastructure
roles:
- cloudformation
tags:
- infrastructure
# Часть приложения
- hosts: application
roles:
- some-role
tags:
- some-role
- application
- hosts: application
roles:
- cloudformation
tags:
- application
group_vars/my-group.yml
stack_prefix: testing
boto_profile: testing
s3_bucket: awesome-lambda
cloudformation_defaults:
profile: "{{ boto_profile }}"
region: eu-central-1
host_vars/infrastructure.yml
cloudformation_stacks:
- stack_name: "{{ stack_prefix }}-s3"
template: files/cloudformation/s3.yml.j2
template_parameters:
bucketName: "{{ s3_bucket }}"
tags:
env: "{{ stack_prefix }}"
host_vars/application.yml
cloudformation_stacks:
- stack_name: "{{ stack_prefix }}-lambda"
template: files/cloudformation/lambda.yml.j2
template_parameters:
lambdaFunctionName: lambda
handler: lambda.run_handler
runtime: python2.7
s3Bucket: "{{ s3_bucket }}"
s3Key: lambda.py.zip
tags:
env: "{{ stack_prefix }}"
Шаблоны
Этот раздел дает краткий обзор того, что можно сделать с шаблонами CloudFormation, используя директивы Jinja2.
Пример: Определения подсетей
Следующий шаблон можно развернуть в разных тестовых окружениях и он способен включать различное количество подсетей.
Переменные Ansible
---
# файл: staging.yml
vpc_subnets:
- directive: subnetA
az: a
cidr: 10.0.10.0/24
tags:
- name: Name
value: staging-subnet-a
- name: env
value: staging
- directive: subnetB
az: b
cidr: 10.0.20.0/24
tags:
- name: Name
value: staging-subnet-b
- name: env
value: staging
---
# файл: production.yml
vpc_subnets:
- directive: subnetA
az: a
cidr: 10.0.10.0/24
tags:
- name: Name
value: prod-subnet-a
- name: env
value: production
- directive: subnetB
az: b
cidr: 10.0.20.0/24
tags:
- name: Name
value: prod-subnet-b
- name: env
value: production
- directive: subnetC
az: b
cidr: 10.0.30.0/24
tags:
- name: Name
value: prod-subnet-c
- name: env
value: production
Шаблон CloudFormation
AWSTemplateFormatVersion: '2010-09-09'
Description: Шаблон VPC
Resources:
vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: {{ vpc_cidr_block }}
EnableDnsSupport: true
EnableDnsHostnames: true
{% if vpc_tags %}
Tags:
{% for tag in vpc_tags %}
- Key: {{ tag.name }}
Value: {{ tag.value }}
{% endfor %}
{% endif %}
{% for subnet in vpc_subnets %}
{{ subnet.directive }}:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: {{ subnet.az }}
CidrBlock: {{ subnet.cidr }}
VpcId: !Ref vpc
{% if subnet.tags %}
Tags:
{% for tag in subnet.tags %}
- Key: {{ tag.name }}
Value: {{ tag.value }}
{% endfor %}
{% endif %}
Пример: Группы безопасности
Определение групп безопасности с правилами, специфичными для IP, может быть очень сложным, если вы хотите сохранить независимость от окружения и все еще использовать один и тот же шаблон CloudFormation для всех окружений. Тем не менее, это можно легко преодолеть, предоставив специфичные для окружения определения массивов через Jinja2.
Переменные Ansible
---
# файл: staging.yml
# В staging все открыто, чтобы разработчики могли
# подключаться с прикрепленных VPN
security_groups:
- protocol: tcp
from_port: 3306
to_port: 3306
cidr_ip: 10.0.0.1/32
- protocol: tcp
from_port: 3306
to_port: 3306
cidr_ip: 192.168.0.15/32
- protocol: tcp
from_port: 3306
to_port: 3306
cidr_ip: 172.16.0.0/16
---
# файл: production.yml
# В производственной среде значительно меньше правил и другие
# диапазоны ip.
security_groups:
- protocol: tcp
from_port: 3306
to_port: 3306
cidr_ip: 10.0.15.1/32
Шаблон CloudFormation
AWSTemplateFormatVersion: '2010-09-09'
Description: Шаблон VPC
Resources:
rdsSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Группа безопасности RDS
{% if security_groups %}
SecurityGroupIngress:
{% for rule in security_groups %}
- IpProtocol: "{{ rule.protocol }}"
FromPort: "{{ rule.from_port }}"
ToPort: "{{ rule.to_port }}"
CidrIp: "{{ rule.cidr_ip }}"
{% endfor %}
{% endif %}
Различия
Когда вы включите cloudformation_run_diff
, вы сможете видеть построчные различия между вашим локальным (обработанным jinja2) шаблоном и тем, который в настоящее время развернут на AWS. Чтобы вам было представление о том, как это выглядит, смотрите следующий пример вывода:
Не забудьте запустить Ansible с --diff
, чтобы это работало:
$ ansible-playbook play.yml --diff
Json различия
Чтобы вывести в режиме json diff, установите cloudformation_diff_output
в json
.
TASK [cloudformation : diff cloudformation template file] *********************************************
--- before
+++ after
@@ -38,7 +38,6 @@
"Type": "AWS::S3::BucketPolicy"
},
"s3Bucket": {
- "DeletionPolicy": "Retain",
"Properties": {
"BucketName": {
"Ref": "bucketName"
Yaml различия
Чтобы выводить в режиме yaml diff, установите cloudformation_diff_output
в yaml
.
TASK [cloudformation : diff cloudformation template file] *********************************************
--- before
+++ after
@@ -14,7 +14,6 @@
Service: !Sub 'logs.${AWS::Region}.amazonaws.com'
Bucket: !Ref 's3Bucket'
s3Bucket:
- DeletionPolicy: Retain
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref 'bucketName'
Зависимости
Эта роль не зависит от других ролей.
Требования
Используйте как минимум Ansible 2.5, чтобы иметь возможность использовать режим --check
для cloudformation.
Модуль python cfn_flip
требуется при использовании постричного сравнения локальных и удаленных шаблонов CloudFormation (cloudformation_run_diff=True
). Его можно легко установить локально:
$ pip install cfn_flip
Лицензия
Copyright (c) 2017 cytopia
Ansible role to render an arbitrary number of Jinja2 templates into cloudformation files and create any number of stacks.
ansible-galaxy install cytopia/ansible-role-cloudformation