+
В данной заметке хочу рассказать о некоторых приемах решений задач по связке ansible + amazon, может кому-то будет полезно или кто-то подскажет решения лучше. О установке/настройке ansible информации уже много, так что её я пропущу. О работе с amazon тоже ничего оригинального добавить не смогу. Итак, приступим.
Попросили помочь с разовой настройкой проекта, конкретно часть ansible + amazon, а так же конфигурация серверов на базе ubuntu и сервисов. Требования к проекты были выставлены такие:
Заказчик пожелал, что не нужно вносить правки на уже работающие сервера, если надо что-то поменять — меняют скрипты создания, сносят старое и создают новое… Хозяин — барин.
Для большинства задач можно использовать модуль ec2. Модуль замечательный :), с большим количеством “подмодулей” почитать их описание можно тут: /usr/share/ansible/cloud (для ubuntu/debian).
В инвентарный файл ansible (hosts) нужно прописать всего 1 хост:
Я начал с самого простого, с windows server. Приведу пример playbook:
Тут все просто, ansible используя ваши aws_access_key и aws_secret_key посылает запрос в amazon на создание машинки с именем hostname=”Windows” типа instance_type=«t2.micro» из ранее созданого образа image=«ami-xxxxxxxx» в регионе region=«us-west-2» и присваивает sequrity group group=«launch-wizard-1» и больше ничего.
Далее сложнее, будем делать бэкенды nginx. Для начала все то же самое, создаем машину, но нужно с ней работать в этом же плэйбуке.
Создадим в кабинете amazon keypair, назовем его, например, aws_ansible. Скачиваем ключик и копируем его в ~/.ssh/id_rsa пользователя из под которого запускаете плэйбуки.
Приведу в пример плэйбук создания бэкенда:
Теперь, что поменялось:
Мы указали, что для этой машинки использовать наш ключ keypair: «aws_ansible»
Указали образ чистой ubuntu image: «ami-33db9803».
С помощью registr и debug мы получили public_ip новой машинки и записали её во временную инвентаризацию в группу ec2hosts, записывать в hosts файл из плэйбука нельзя ( я не нашел как).
Следующим действием “wait for instances to listen on port:22” ждем когда станет доступен ssh.
И после всего этого выполняем обычные сценарии с обычным сервером, в моем случае установка/настройка nginx и nodejs
Еще я добавил Tag «Group»:«nginx_backend», это нужно для того что бы работать со всеми бэкендами сразу. Как? Есть скрипт подходящий для инвентаризации серверов amazon в ansible. Почитать о нем, а так же скачать его можно тут docs.ansible.com/intro_dynamic_inventory.html#id6.
Отлично, но у меня ситуация не много иная, мне нужно сделать upstream в nginx с неизвестным заранее количеством бэкендов. Побороздив просторы документации по ansible, не нашел как делать динамические списки. То есть подставлять динамически ip бэкенда — пожалуйста, а вот их количество менять… Как всегда на выручку пришел старый способ, написал велосипед ан python. не большой скрипт который вызывается из плэйбука до настройки nginx и генерирует конфиг с upstream.
Листинг:
Еще одна проблема была с redis master, его ip нужно было прописывать на каждый слэйв. Решил сделать с помощью include_vars.
При создании мастера до проверки доступности ssh делаю так:
В переменных указал:
Сам файл изначально должен быть и выглядит примерно так:
Затем в плейбуке настройки redis slave добавляем:
Используем переменную {{ master }} в шаблоне.
Sequrity group создается просто, используем модуль ec2_group:
Сложнее оказалось с очередями, модуля для них не нашлось, пытался даже доделать чьи-то попытки его написать. Но быстро опомнился и сделал через cloudformation.
Так выглядит плэйбук:
Популярность облачных решений и систем управления конфигурациями растет, но я потратил порядочно времени выискивая варианты того или иного решения, собирая информацию и тд. Отсюда и родилась идея написать эту статью.
Автор: Бурнашев Роман, главный системный администратор компании centos-admin.ru
В данной заметке хочу рассказать о некоторых приемах решений задач по связке ansible + amazon, может кому-то будет полезно или кто-то подскажет решения лучше. О установке/настройке ansible информации уже много, так что её я пропущу. О работе с amazon тоже ничего оригинального добавить не смогу. Итак, приступим.
Введение
Попросили помочь с разовой настройкой проекта, конкретно часть ansible + amazon, а так же конфигурация серверов на базе ubuntu и сервисов. Требования к проекты были выставлены такие:
- Сервера балансировщики на nginx
- N-е количество бэкендов nginx + nodejs
- Сервер redis master
- N-е количество redis slave
- N-е количество windows servers ( что-то для криптографии, с условием готового шаблона)
- Создавать очереди SQS
- Создавать security groups
Примечание
Заказчик пожелал, что не нужно вносить правки на уже работающие сервера, если надо что-то поменять — меняют скрипты создания, сносят старое и создают новое… Хозяин — барин.
Работаем
Для большинства задач можно использовать модуль ec2. Модуль замечательный :), с большим количеством “подмодулей” почитать их описание можно тут: /usr/share/ansible/cloud (для ubuntu/debian).
В инвентарный файл ansible (hosts) нужно прописать всего 1 хост:
[local]
localhost
Я начал с самого простого, с windows server. Приведу пример playbook:
- hosts: localhost
connection: local
gather_facts: False
vars:
hostname: Windows
ec2_access_key: "Secret"
ec2_secret_key: "Secret_key”
instance_type: "t2.micro"
image: "ami-xxxxxxxx"
group: "launch-wizard-1"
region: "us-west-2"
tasks:
- name: make one instance
ec2: image={{ image }}
instance_type={{ instance_type }}
aws_access_key={{ ec2_access_key }}
aws_secret_key={{ ec2_secret_key }}
instance_tags='{ "Name":"{{ hostname }}" }'
region={{ region }}
group={{ group }}
wait=true
Тут все просто, ansible используя ваши aws_access_key и aws_secret_key посылает запрос в amazon на создание машинки с именем hostname=”Windows” типа instance_type=«t2.micro» из ранее созданого образа image=«ami-xxxxxxxx» в регионе region=«us-west-2» и присваивает sequrity group group=«launch-wizard-1» и больше ничего.
Далее сложнее, будем делать бэкенды nginx. Для начала все то же самое, создаем машину, но нужно с ней работать в этом же плэйбуке.
Создадим в кабинете amazon keypair, назовем его, например, aws_ansible. Скачиваем ключик и копируем его в ~/.ssh/id_rsa пользователя из под которого запускаете плэйбуки.
Приведу в пример плэйбук создания бэкенда:
- hosts: localhost
connection: local
gather_facts: False
vars:
hostname: Nginx_nodejs
ec2_access_key: “Secret"
ec2_secret_key: "Secret_key"
keypair: "aws_ansible"
instance_type: "t2.micro"
image: "ami-33db9803"
group: "launch-wizard-1"
region: "us-west-2"
tasks:
- name: make one instance
ec2: image={{ image }}
instance_type={{ instance_type }}
aws_access_key={{ ec2_access_key }}
aws_secret_key={{ ec2_secret_key }}
keypair={{ keypair }}
instance_tags='{ "Name":"{{ hostname }}" , "Group":"nginx_backend" }'
region={{ region }}
group={{ group }}
wait=true
register: ec2_info
- debug: var=ec2_info
- debug: var=item
with_items: ec2_info.instance_ids
- add_host: hostname={{ item.public_ip }} groupname=ec2hosts
with_items: ec2_info.instances
- name: wait for instances to listen on port:22
wait_for:
state=started
host={{ item.public_dns_name }}
port=22
with_items: ec2_info.instances
- hosts: ec2hosts
gather_facts: True
user: ubuntu
sudo: True
vars:
connections : "4096"
tasks:
- include: nginx/tasks/setup.yml
handlers:
- name: restart nginx
action: service name=nginx state=restarted
- hosts: ec2hosts
gather_facts: True
user: ubuntu
sudo: True
tasks:
- include: nodejs/tasks/setup.yml
Теперь, что поменялось:
Мы указали, что для этой машинки использовать наш ключ keypair: «aws_ansible»
Указали образ чистой ubuntu image: «ami-33db9803».
С помощью registr и debug мы получили public_ip новой машинки и записали её во временную инвентаризацию в группу ec2hosts, записывать в hosts файл из плэйбука нельзя ( я не нашел как).
Следующим действием “wait for instances to listen on port:22” ждем когда станет доступен ssh.
И после всего этого выполняем обычные сценарии с обычным сервером, в моем случае установка/настройка nginx и nodejs
Еще я добавил Tag «Group»:«nginx_backend», это нужно для того что бы работать со всеми бэкендами сразу. Как? Есть скрипт подходящий для инвентаризации серверов amazon в ansible. Почитать о нем, а так же скачать его можно тут docs.ansible.com/intro_dynamic_inventory.html#id6.
Отлично, но у меня ситуация не много иная, мне нужно сделать upstream в nginx с неизвестным заранее количеством бэкендов. Побороздив просторы документации по ansible, не нашел как делать динамические списки. То есть подставлять динамически ip бэкенда — пожалуйста, а вот их количество менять… Как всегда на выручку пришел старый способ, написал велосипед ан python. не большой скрипт который вызывается из плэйбука до настройки nginx и генерирует конфиг с upstream.
Листинг:
#!/usr/bin/env python
import sys, os
from commands import *
group = '"tag_Group_nginx_backend": ['
template = "/etc/ansible/playbooks/nginx/templates/balance.conf.j2"
list_ip = []
#Create ec2_list
data = getoutput("/etc/ansible/ec2.py --refresh-cache")
flag = 0
for line in data.split("\n"):
if flag:
if line.strip() != "],":
list_ip.append(line.strip().strip(",").strip("\""))
else:
break
if line.strip() == group:
flag = 1
f = open(template, 'w')
f.write('''# upstream list
upstream backend {''')
f.close()
for ip in list_ip:
f = open(template, 'a')
f.write('''
server '''+ip+''':80 weight=3 fail_timeout=15s;''')
f.close()
f = open(template, 'a')
f.write('''
}''')
f.close()
Еще одна проблема была с redis master, его ip нужно было прописывать на каждый слэйв. Решил сделать с помощью include_vars.
При создании мастера до проверки доступности ssh делаю так:
- replace: dest={{ redis_master_ip }} regexp='^(\s+)(master\:)\s(.*)$' replace='\1\2 {{ item.public_ip }}'
with_items: ec2_info.instances
В переменных указал:
redis_master_ip: "/etc/ansible/playbooks/redis/files/master_ip.yml"
Сам файл изначально должен быть и выглядит примерно так:
master: 1.2.3.4
Затем в плейбуке настройки redis slave добавляем:
- name: Get master IP
include_vars: "{{ redis_master_ip }}"
Используем переменную {{ master }} в шаблоне.
Sequrity group создается просто, используем модуль ec2_group:
- hosts: localhost
connection: local
tasks:
- name: nginx ec2 group
local_action:
module: ec2_group
name: nginx
description: an nginx EC2 group
region: us-west-2
aws_secret_key: "Secret"
aws_access_key: "Secret"
rules:
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 192.168.0.0/24
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: 0.0.0.0/0
rules_egress:
- proto: all
cidr_ip: 0.0.0.0/0
Сложнее оказалось с очередями, модуля для них не нашлось, пытался даже доделать чьи-то попытки его написать. Но быстро опомнился и сделал через cloudformation.
Так выглядит плэйбук:
- hosts: localhost
connection: local
gather_facts: False
vars:
sqs_access_key: “Secret"
sqs_secret_key: "Secret"
region: "us-west-2”
tasks:
- name: launch some aws services
cloudformation: >
stack_name="TEST"
region={{ region }}
template=files/cloudformation.json
<\code>
А так template:
<code>
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation SQS”
"Resources" : {
"MyQueue" : {
"Type" : "AWS::SQS::Queue"
}
},
"Outputs" : {
"QueueURL" : {
"Description" : "URL of newly created SQS Queue",
"Value" : { "Ref" : "MyQueue" }
},
"QueueARN" : {
"Description" : "ARN of newly created SQS Queue",
"Value" : { "Fn::GetAtt" : ["MyQueue", "Arn"]}
}
}
}
Резюме
Популярность облачных решений и систем управления конфигурациями растет, но я потратил порядочно времени выискивая варианты того или иного решения, собирая информацию и тд. Отсюда и родилась идея написать эту статью.
Автор: Бурнашев Роман, главный системный администратор компании centos-admin.ru