Свій хмарний хостинг за 5 хвилин. Частина 2: Service Discovery

Cloud hosting

Привіт Хабр! попередній статті я розповів як побудувати свій хмарний хостинг за 5 хвилин, використовуючи Ansible, Docker Docker Swarm. У цій частині я розповім про те, як сервіси, запущені в хмарі, знаходять один одного, як відбувається балансування навантаження між ними і забезпечується їх відмовостійкість.

Це вступна стаття, тут ми зосередимося на огляді інструментів, які будуть вирішувати проблему «виявлення сервісів» в нашому хмарі. У наступній частині ми приступимо до практики, тому я вирішив дати вам час по ближче ознайомитися з ними.

Проблема

Давайте розберемо найбільш типову проблему і її поширене рішення – у нас є веб-додаток і ми повинні забезпечити балансування навантаження та його відмовостійкість.

Ми можемо запустити кілька копій нашого веб-додатки, які буде моніторити Supervisor. Supervisor буде перезапускати наш веб-додаток, якщо виникнуть якісь помилки, а також буде додавати такі події в журнал. Проблему балансування навантаження вирішить установка Nginx. Конфігурація Nginx буде виглядати приблизно так:

upstream app {
server 192.168.1.2:8080 max_fails=3 fail_timeout=5s;
server 192.168.1.2:8081 max_fails=3 fail_timeout=5s;
server 192.168.1.2:8082 max_fails=3 fail_timeout=5s;
}

server {
location / {
proxy_pass http://app;
health_check;
}
}

Працювати зазначена конфігурація буде так – якщо протягом 5 секунд число невдалих спроб при зверненні до одного з веб-додатків досягне 3-ох, то такий додаток відзначиться як непрацездатний на 5 секунд (якщо воно впало з помилкою, то Supervisor перезапустить його). Таким чином все навантаження рівномірно розподілитися тільки між робочими копіями додатків.

Недоліки

Насправді це хороша конфігурація і якщо у вас небагато додатків і навантаження більш-менш рівномірна, тоді краще використовувати саме її.

Але ми будуємо хмара, де буде запущено той чи інший додаток – ми не знаємо. Навантаження у нас може змінюватися для різних сайтів/веб-додатків по різному, тому непогано б мати можливість міняти кількість запущених копій наших програм залежно від ситуації. Іншими словами – ми не можемо заздалегідь налаштуватиNginx/Apache/etc на таку конфігурацію.

Було б круто, якщо б Nginx та інші наші сервіси пристосувалися до динамічної природи нашого хмари. Вирішенням саме цієї задачі ми і займемося в цій статті.

Вимоги

Нам потрібно місце, де наші сервіси зможуть реєструвати себе і отримувати інформацію один про одного. Docker Swarm, який ми почали використовувати в попередній статті, «з коробки» вміє працювати etcd Consul і Zookeeper.

Нам необхідно, що б наші сервіси автоматично реєструвалися і віддалялися з вищевказаних систем (ми ж не будемо навчати цьому кожний додаток). Для цих цілей ми використовуємо Registrator (нижче розглянемо його більш докладно), який «з коробки» працює з Consul, etcd і SkyDNS 2 (підтримка Zookeeper у планах).

Наші сервіси повинні мати можливість знаходити один одного за допомогою DNS запитів. Це завдання можуть вирішити Consul і SkyDNS 2, , який працює в парі з etcd).

Моніторинг здоров'я сервісів нам теж необхідний. Він доступний нам в Consul (який ми і будемо використовувати) «з коробки» і його підтримує Registrator (він повинен передавати інформацію про те, як повинен відбуватися моніторинг того або іншого сервісу).

Останнє, але не менш важливе – потрібен сервіс для автоматичної конфігурації наших складових. Якщо ми запустили 10 копій одного веб-додатки та 20 копій іншого, він повинен розуміти і негайно реагувати на це (змінюючи конфігурацію Nginx, наприклад). Виконувати цю роль буде Consul Template (нижче розглянемо його більш докладно).

ПриміткаЯк ви бачите, є різні варіанти вирішення нашої проблеми. Перш, ніж написати цю статтю, я попрацював на своїй конфігурації трохи більше місяця і не зустрів ніяких проблем.


Consul

Consul

З перерахованих вище варіантів (Consul Zookeeper etcd), Consul є найбільш самостійним проектом, який в змозі вирішити нашу проблему виявлення сервісів «з коробки».

Не дивлячись на те, що Consul, Zookeeper etcd розташовані тут в одному ряду, я б не став їх порівнювати між собою. Всі 3 проекту реалізують розподілене key/value сховище і на цьому їх загальні риси закінчуються.

Consul нас забезпечить DNS сервером, якого немає в Zookeeper etcd (можна додати за допомогою SkyDNS 2). Більш того, Consul дасть нам моніторинг здоров'я (яким не можуть похвалитися ні etcd, ні Zookeeper), що також необхідно для повноцінного Service Discovery.

У навантаження Consul ми отримаємо Web UI (демо якого можна глянути вже зараз) і якісну офіційну документацію.

ПриміткаНавіть якщо ви плануєте використовувати таку ж конфігурацію, яку я описую і використання Zookeeper і SkyDNS 2 у ваші плани не входить, я б все одно ознайомився з цими проектами.


Registrator

Registrator

Registrator отримує інформацію від Docker'а про запуску/зупинки контейнерів (через сокет-з'єднання, за допомогою Docker API) і додає/вилучає їх в/зConsul'a.

Інформацію про те чи іншому сервісі Registrator автоматично отримує на основі опублікованих портів і змінних оточення Docker контейнера. Іншими словами – це працює з будь-якими контейнерами, які у вас є і вимагає додаткового конфігурування тільки в тому випадку, якщо необхідно перевизначити параметри отримані автоматично.

І раз всі наші сервіси працюють виключно в Docker контейнерах (і сам Registrator в тому числі, Consul'е завжди буде інформація про всіх запущених сервісах нашого хмари.

Це все звичайно круто, але ще крутіше те, що Registrator може розповісти Consul'у, як перевіряти здоров'я наших сервісів. Робиться це за допомогою тих же змінних оточення.

ПриміткаConsul вміє перевіряти здоров'я сервісів, якщо для збереження інформації про них використовується Consul Service Catalog (який ми і залучаємо).

Якщо ж використовується Consul Key-value Store (який теж підтримується Registrator'ом і використовує, наприклад, Docker Swarm для збереження інформації про Docker ноди), такої функції немає.

Давайте розглянемо приклад:

$ docker run-d --name nginx.0-p 4443:443-p 8000:80 \
-e "SERVICE_443_NAME=https" \
-e "SERVICE_443_CHECK_SCRIPT=curl --silent --fail https://our-https-site.com" \
-e "SERVICE_443_CHECK_INTERVAL=5s" \
-e "SERVICE_80_NAME=http" \
-e"SERVICE_80_CHECK_HTTP=/health/endpoint/path" \
-e "SERVICE_80_CHECK_INTERVAL=15s" \
-e "SERVICE_80_CHECK_TIMEOUT=3s" \
-e "SERVICE_TAGS=www" nginx

Після подібного запуску, список наших сервісів у Consul'а буде виглядати наступним чином:

{
"services": [
{
"id":"hostname:nginx.0:443",
"name": "https",
"tags": [
"www"
],
"address": "192.168.1.102",
"порту": 4443,
"checks": [
{
"script" : "curl --silent --fail https://our-https-site.com",
"interval": "5s"
}
]
},
{
"id":"hostname:nginx.0:80",
"name": "http",
"tags": [
"www"
],
"address": "192.168.1.102",
"порту": 8000,
"checks": [
{
"http":"/health/endpoint/path",
"interval": "15s",
"timeout": "3s"
}
]
},
...
]
}

Як ви бачите, на основі опублікованих портів Registrator зробив висновок, що треба зареєструвати 2 сервісу (http і https). Більш того, у Consul'a тепер є вся необхідна інформація про те, як перевіряти здоров'я цих сервісів.

У першому випадку буде виконуватися команда "curl --silent --fail our-https-site.com" кожні 5 секунд і результат перевірки буде залежати від коду виходу даної команди.

У другому випадку – кожні 15 секунд Consul буде смикати переданий нами URL. Якщо код відповіді сервера буде 2xx, то наш сервіс «здоровий», якщо 429 Too Many Requests, то в «екстреному стані», якщо все інше, то «земля йому пухом».

Більше прикладів та більш детальну інформацію ви може почерпнути з офіційній документації.

Consul Template

Consul Template
Ми вирішили де зберігати інформацію про всіх сервісах нашого хмари, а також як вона буде туди потрапляти і автоматично там оновлюватися. Але ми ще не розібралися, як же будемо отримувати інформацію від туди і як, надалі, будемо її передавати нашим сервісам. Саме цим і буде займатися Consul Template.

Для цього треба взяти конфігураційний файл нашого додатка (яке ми хочемо налаштувати) і зробити з нього шаблон, згідно з правилами HashiCorp Configuration Language.

Давайте розглянемо простий приклад з конфігураційним файломNginx:

upstream app {
least_conn;
# list of all services healthy
{{range service"tag1.cool-app" "passing"}}server{{.Address}}:{{.Port}} max_fails=3 fail_timeout=60s weight=1;
{{else}}server 127.0.0.1:65535; # force a 502{{end}}
}
...

Після того, як ми пояснимо Consul Template де знаходиться даний шаблон, куди покласти результат і яку подану команду виконати (він це теж вміє) при його зміні (в даному випадку перезавантажити Nginx), почнеться магія. В даному випадку Consul Template отримає адреси і номери портів всіх копій додатки"cool-app", позначені тегом"tag1" і знаходяться в «здорове» стан і додасть їх у конфігураційний файл. Якщо таких додатків немає, тоді, як ви вже здогадалися, залишиться все, що знаходиться після{{else}}.

При кожному додаванні і видаленні сервісу"cool-app" з тегом"tag1" конфігураційний файл буде перезаписуватися, а після цього Nginx буде перезавантажений. Все це відбувається автоматично і не вимагає втручання, ми просто запускаємо потрібну кількість копій нашого додатка і не про що не турбуємося.

Більше прикладів ви можете знайти на офіційній документації.

Висновок

На сьогоднішній день існує достатня кількість інструментів для вирішення проблеми виявлення сервісів, але не так багато коштів, які могли б вирішити дану проблему «з коробки» і відразу забезпечити нас усім необхідним.

В наступній частині, яка буде зовсім скоро, я опублікую набір сценаріїв для Ansible, які сконфигурируют за нас всі вищеописані інструменти і ми зможемо приступити в практиці.

На цьому все. Всім дякую за увагу. Стабільних вам хмар і удачі!

P. S. Я шукаю дизайнера, backend та frontend програмістів в стартап, подробиці у мене в профілі.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.