[SOA] Service Oriented Ansible

в 12:52, , рубрики: Ansible, deploy, системное администрирование

Доброго дня. Сегодня мы будем говорить об Ansible и сервисах, можно конечно использовать и другие запчасти для SOA типа Docker, Jenkins и Puppet, но сегодня у нас Ansible, сервисы и пару строчек PHP. Многие из вас видели такие картинки (картинки и символы изменены).

SOA

и читали такие статьи c картинками (первая, вторая), где упоминается SOA.

Так и ближе к делу! Cегодня мы будем

Деплоить SOA

2 nginx, 2 фронта и сервис и деплой.
Всего 7 ВМ понадобиться для разворачивания SOA песочницы.

В качестве деплой сервера будем использовать локальную машину и в том же сегменте сети у нас развернуты виртуалки с пользователем ansible#ansible. Так же нашим ВМ требуется доступ в интернет для устнавки софта. Cамый просто способ это сделать 2 сетевых интерфейса с NAT и внутренней сетью 192.168.0.032. Если переиспользовать ВМ то можно сократить это число до 4 в качестве песочницы, но не более.

Главный репозиторий который нам все это намажет на наш бутерброд из ВМ и чтобы работало.
https://github.com/dangerousvasil/ansibleServicesDeploy

Также будем использовать ещё 2 репозитория.
Они содержат в себе пару строчек PHP кода без привязки к какому либо фреймворку или проекту
https://github.com/dangerousvasil/simpleFront
https://github.com/dangerousvasil/simpleService

Задача фронта сделать запрос к сервису и отобразить его результат.

Задача сервиса ответить 3 большие буквы. Ваш Капитан очевидность. (Можно попробовать подсунуть свой репозиторий — п.с. Ваш Капитан очевидность снова).

Инвенторий

Так назвается файл в котором храниться описание структуры ВМ и их особенности hosts/prod.ini

Обзовём наши ВМ и дадим им имена.
Фронт к которому у нас обращаться пользвоатель это

nginx-front-00 ansible_host=192.168.56.102

Осноной аппликейшен который принимает запросы

php-front-00 ansible_host=192.168.56.103
php-front-01 ansible_host=192.168.56.101

Один маленький балансер который обслуживает наши сервисы

nginx-balance-00 ansible_host=192.168.56.104

Один маленький сервис который горовит слово из 3х букв

service-sign-00 ansible_host=192.168.56.101
service-sign-01 ansible_host=192.168.56.103

Как видете я переиспользую ВМы для сервиса и для форонта, но давйте будем думать что это разные ВМ который находяться на разных железных серверах для отказоустойчивости.

Структура инвентория

Мы обозвали наши хосты, теперь софрмируем из них группы, а сами группы разделим на несколько частей
первая группа груп это группы сервисов.

Группа сервисы

[nginx-front]
nginx-front-00

[front_app]
php-front-00
php-front-01

[nginx-balancer]
nginx-balance-00

[sign]
service-sign-00
service-sign-01

[deploy]
deploy

Группы Софт

Мы сгруппировали наши хосты в группы и теперь надо указать какой софт необходим каждоый группе для этого необходима ещё одна группа груп.

[php-cli:children]
front_app

[php-fpm:children]
front_app
sign

[git:children]
front_app

[hg:children]

[nginx:children]
nginx-front
nginx-balancer

Добавление группы в группу подскажет нашему деплою что на данную группу необходимо установить соответвуютщее програмное обеспечение.
для хостов входящих в группу php-cli установить консольный вариант PHP для крон заданий например.
п.с. Ваш Капитан очевидность

Группа Сервисы

Следующая группа групп =)

[services:children]
sign

Группирует наши сервисы как сервисы.

Особенность Сервисов

Особенность сервисов состоит в том что сушествуют 2 точки входа

// server_name {{ service_name }}
api/index.php

// server_name {{ service_name }}_web
web/index.php

Зачем эту необходимо?
Если вы хотите сделать административную панель сервиса то ненадо делать для неё дополнительный сервис можно использовать эти же ВМ и обрашаться к ним как {{service_name}}_web
через ифрайм или курл запросом.
Сервисы могут меняться и заменятся таким образом код администрирования сервисов будет обновляться вместе с сервисом.

Ключи

Каждый раз ипользовать пароли не очень удобно поэтому давайте разбросаем ключи на наши ВМ

ansible-playbook -i hosts/prod.ini task/system/authorized_key.yml  -k --ask-sudo-pass

специально для вас я уже сгенерировал ключи в папке roles/authorized_key/keys, но вы обязаныможете сделать свои.

Добавим приватный ключ на ключе хранилище

cp roles/authorized_key/keys/id_rsa ~/.ssh/id_rsa_deploy && chmod 700 ~/.ssh/id_rsa_deploy && ssh-add ~/.ssh/id_rsa_deploy

ВАЖНО: после перезагрузки машины ключ надо добавить заново

Или прописать его в конфигурациях например в файл /etc/ssh/ssh_config добавить строчку

IdentityFile /etc/ssh/ssh_hg_deploy_key

Софт

Установим необходимый софт на ВМ

ansible-playbook -i hosts/prod.ini task/system/soft-install.yml

Это поставит нам необходимый софт на наши Группы Софт
Мы можем добавлять или удалять группы из групп чтобы на каждой ВМ стоял только необходимый набор программного обеспечения.
В случае если ВМ переиспользуеться в другом сервисе или происходить большой изменения сервиса то проше ВМ уничтожить и развернуть заново.

Мы установили php-cli,php-fpm,git:children,nginx на ниши машинки что же дальше…

FRONT

Нам необходимо сконфигурировать наш фронтовой НГИНКС который находиться тут

 roles/nginx-front/templates/nginx.conf.j2

Как видимо это шаблон с минимально сконфигурированным набором параметров, даже особо не конфигурированный.
Также очень необходимый файл

 roles/nginx-front/templates/vhosts.conf.j2 

Рассмотрим его более детально

upstream php-front
{
    {% for upstream in groups["front_app"] %}
        server {{ hostvars[upstream]["ansible_host"] }}:9000;
    {% endfor %}
}

Мы конфигрурируем наш балансер простейшим способом, для более серьезной конфигурации можно добавлять переменные к хостам и дописать наш балансер с учётом дополнительных переменных.
Виртуальный хост использует upstream php-front.

  fastcgi_pass php-front;

Применим эти настройки на наш фронт

ansible-playbook -i hosts/prod.ini task/nginx/front.yml 

Теперь наш фронт начал посылать запросы на наш фронт апп но там ещё ничего нет ....

Сервисы

Наш фронт апп также является сервисом как и остальные сервисы, просто он принимает запрос из сети интернет, поэтому он конфигурируеться как и все остальный сервисы.

в папке hosts/group_vars/ в соответвии названием группы находяться файлы конфигурации группы

#hosts/group_vars/front_app.yml
service_name: front_app
deploy_via: git
repo: 'https://github.com/dangerousvasil/simpleFront'
branch: 'master'
keep_releases: 10

также общие конфигурации hosts/group_vars/all.yml

 releases_path: '/var/www'
 current_release_dir: 'www'
 application_configuration_path: '/etc/application/config.ini'
 keep_releases: 0
 apt_cache_valid_time: 86400
 www_user: 'www-data'

Здесь мы можем указать куда деплоить код приложения и файл конфигурации
и много других конфигураций который в дальнейшем вам потребуются.

Запустим задачу на обновления кода приложения

 ansible-playbook -i hosts/prod.ini task/app/code-update.yml 

Теперь наше приложение уже готово принимать первые запросы на фронт
также мы можем зайти на нашу ВМ и посмотреть где же лежит наш код по умолчанию это

{{ releases_path }}/{{ service_name }}/{{ current_release_dir }}
/var/www/front_app/www

Зайдя на машинку мы увидим что эта папка у нас являеться ссылкой которая ведёт на другую папку
releases/20171024121418Z, это сделаного для того чтобы мы всегда могли откатить изменения на прошлый успешный релиз

lrwxrwxrwx /var/www/front_app/www -> /var/www/front_app/releases/20171024121418Z

releases:
total 40
drwxr-xr-x 2  20171024121418Z
drwxr-xr-x 2  20171024120329Z
drwxr-xr-x 2  20171024112918Z
drwxr-xr-x 2  20171024104100Z
drwxr-xr-x 2  20171024102800Z
drwxr-xr-x 2  20171024102702Z
drwxr-xr-x 2  20171024102548Z
drwxr-xr-x 2  20171024102458Z
drwxr-xr-x 2  20171024095629Z
drwxr-xr-x 2  20171024094949Z

Для этого есть задача

ansible-playbook -i hosts/prod.ini task/app/code-rollback.yml 

Это передвинет нашу ссылку на прошлый релиз если он был или выдаст исключение. Если запустить задачу ещё раз то передвинет ссылку дальше пока релизы не закончаться.

Балансер

Код выложен, фронт настроен, осталось дело за малым — балансировщик сервисов.
Пока используем 1 можно добавить ещё несколько и банасировать между ними с помощью разных инструментов ddns или HAProxy или просто рандомно выбирать сервер на стороне приложения — решать вам.
Запускаем задачу

ansible-playbook -i hosts/prod.ini task/nginx/balancer.yml 

С помошью файла hosts/group_vars/nginx-balancer.yml
Создаться конфигурация балансировки указанных сервисов соответвенно тут имя сервиса совпадает с группой в файле инвентория, но может не совпадать с именем сервиса указанным в файле конфигурации сервера

with_services:
  - sign

Окружение

для того чтобы наше приложение знало что её окружает балансеры сервисы мы сгенерируем небольшой ini файл и разложим его на каждую машинку

ansible-playbook -i hosts/prod.ini task/app/app_config.yml 

$ cat /etc/application.ini 
[application]
service.host[]=192.168.56.102

теперь наше приложение знает кто отвечает за связь с сервисами, сюда можно и добавить другие настройки вашего приложения.

Тестирование

Открыв в браузере наш фронт http://192.168.56.102 мы увидим неприглядную картинку

string(14) "192.168.56.104"
string(191) "HTTP/1.1 200 OK
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 25 Oct 2017 09:51:43 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive

<h1>API</h1>"

для кого-то это кажеться полной ерундой, а кто-то увидит что наш сервис написал нам свои 3 большие буквы "API" и обрадуется.

Заключение

Если вы добавили свой проект в качестве фронта и написали там пару строчек или подключили пару бибилиотек для работы с сервисами по json-rpc, наверно вы разбираетесь в PHP и вам это сильно поможет

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://' . $serviceHost); // balancer
$header[] = "Host: service";       // необходимый сервис
@curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$output = curl_exec($ch);
var_dump($output);

Вариант с бибилиотекой fguillot/json-rpc

$client = new Client('http://' . $serviceHost); // balancer
$http = $client->getHttpClient()
        ->withHeaders(['Host: service']);  // service

То поздравляю вы окунули свой проект в самый модный и молодежный тренд сезона SOA.

Пост скриптум

Код проекта ещё требует множества доработок и конфигураций, поэтому сделаны только основные конфигурации чтобы работало.

Автор: Vasilii

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js