Top.Mail.Ru
поддержка 24/7
поддержка 24/7

Отказоустойчивый балансировщик c автоматическим SSL (Caddy + Consul)

Наш эксперт Михаил Сергеев подготовил подробный материал (в двух форматах: статья и видеоурок).

В рамках материала: 

  • Расскажем, что такое Caddy
  • Разберем, что такое Consul;
  • Создадим 3 ВМ;
  • Настроим на каждой ВМ Caddy+Consul с помощью Docker Compose;
  • Получим SSL-сертификат для нашего домена;
  • Отработаем отказ 2-х из 3-х ВМ и убедимся, что наше приложение по-прежнему доступно.



Что такое Caddy

Caddy web server — это веб-сервер и обратный прокси-сервер, написанные на языке программирования Go. Caddy предоставляет простой и быстрый способ настройки и развертывания веб-сайтов и веб-приложений.

Автоматический HTTPS  — Caddy автоматически создает и обновляет SSL-сертификаты для веб-сайтов, используя службу Let's Encrypt. Это упрощает процесс получения и установки SSL-сертификатов и обеспечивает безопасное соединение между клиентами и сервером.

Проксирование  —  Caddy может проксировать запросы к другим веб-серверам или приложениям, что позволяет использовать его в качестве прокси-сервера или балансировщика нагрузки.

Динамическая маршрутизация  —  Caddy позволяет настраивать маршрутизацию запросов на основе различных критериев, таких как метод запроса, путь, хост или заголовок. Это позволяет гибко настраивать веб-сайты и приложения и обеспечивает высокую производительность и отказоустойчивость.

Модульная архитектура  —  Caddy имеет модульную архитектуру, что позволяет легко добавлять новые функции и интегрировать сторонние модули. Это делает Caddy гибким и расширяемым веб-сервером.

Простой конфигурационный файл  —  Caddy использует простой конфигурационный файл в формате JSON или Caddyfile, что делает настройку и управление веб-сайтами и приложениями лёгким и интуитивным.

В целом, Caddy  —  это мощный и гибкий веб-сервер, который облегчает настройку и управление веб-сайтами и приложениями. Его официальный сайт https://caddyserver.com/

Что такое Consul

Consul — это распределенный сервис для обнаружения и конфигурации сервисов, разработанный компанией HashiCorp. Consul использует для хранения ключ-значений базу данных, которая позволяет сохранять и получать данные в формате ключ-значение.

База данных Consul является распределенной, что означает, что она может быть размещена на нескольких серверах, и данные будут автоматически реплицироваться между ними. Это обеспечивает высокую доступность и устойчивость к отказам, что делает Consul идеальным выбором для развертывания в распределенных средах.

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

Consul также предоставляет механизмы для обнаружения и регистрации сервисов, а также для мониторинга их состояния. Это позволяет упростить управление распределенными системами и обеспечить их надежную работу. Его официальный сайт https://www.consul.io/

Создание трёх виртуальных машин

А теперь перейдём к практической части. У нас есть 3 ВМ (виртуальные машины).

###### Адреса балансеров:
194.126.161.169 ru-cs24-b1
195.208.186.9 ru-cs24-b2
91.107.229.54 de-hz-b3
ru-cs24-b1 ansible_host=194.126.161.169
ru-cs24-b2 ansible_host=195.208.186.9
de-hz-b3 ansible_host=91.107.229.54
 
Рис.1 Три виртуальные машины на разных серверах. Рис.1 Три виртуальные машины на разных серверах.

Первые 2 балансировщика (виртуальных машин) мы создали в облаке Corpsoft24 в России, а третий — в облаке Хетцнер в Германии (Hetzner Cloud). Первое, что нужно сделать — это обновить их по максимуму до последней версии. Везде используется операционная система Ubuntu 22.04.2 LTS (Jammy Jellyfish). После этого необходимо туда установить докер (docker). Это можно сделать разными способами, но я рекомендую это делать через Ансибл (Ansible).

Ansible — система управления конфигурациями, написанная на языке программирования Python, с использованием декларативного языка разметки для описания конфигураций. Применяется для автоматизации настройки и развёртывания программного обеспечения.

Ansible-плейбук для Docker - скачать.

Рис.2 Внутреннее устройство Docker. Рис.2 Внутреннее устройство Docker.

Вначале docker запрашивает хосты, на которых необходимо его установить. Далее он добавляет репозиторий Юниверс и ставит дополнительные пакеты типа Курл, сертификаты и прочее. Далее он создаёт директорию, где docker хранит ключи от репозитория. Добавляет сам репозиторий и устанавливает docker - се, docker - се - cli, containerd.io и docker - compose - plugin. Потом всё это в автозапуск добавляется  и также добавляются алиасы (alias), чтобы не вводить длинные команды.

Alias (лат. alias — иначе) —  короткое, удобное для запоминания имя, использующееся вместо более длинного и сложного имени. Наиболее часто используется в приложениях электронной почты. Также известно как «никнейм».

Настройка на каждой ВМ Caddy+Consul с помощью Docker Compose

Давайте попробуем установить на 3 наших хоста (host) docker. 

Хост — любое устройство, предоставляющее сервисы формата «клиент-сервер» в режиме сервера по каким-либо интерфейсам и уникально определённое на этих интерфейсах. В более широком смысле под хостом могут понимать любой компьютер, подключённый к локальной или глобальной сети.
Рис.3 Опрос наших хостов. Рис.3 Опрос наших хостов.

Строки, выделенные оранжевым, показывают изменения, а зелёным — что ничего не произошло (когда директория уже есть и создавать её не требуется).

Рис.4 Установка пакетов с помощью Docker Compose.Рис.4 Установка пакетов с помощью Docker Compose.

После сообщения об успешной установке проверяем установку Docker на каждый из 3 хостов.

Теперь нужно на каждую из машин установить фаервол (firewall) для закрытия лишних портов и ограничения доступа не авторизованным пользователям. Установим uf firewall, который просто работает поверх iptables и разрешает определённые адреса, все остальные блокируя.

Uncomplicated Firewall (ufw) («незамысловатый межсетевой экран») —  представляет собой утилиту для конфигурирования межсетевого экрана Netfilter.

iptables — утилита командной строки, является стандартным интерфейсом управления работой межсетевого экрана netfilter для ядер Linux, начиная с версии 2.4. Для использования утилиты iptables требуются привилегии суперпользователя.

Очень важный момент: Docker работает через iptables, и он работает не корректно, если добавлять различные правила. Поэтому на Github есть специальный скрипт (https://github.com/chaifeng/ufw-docker) исправляющий эту проблему. У меня он автоматически скачивается и устанавливается. Далее, если поставили разрешить определённые порты, то он их открывает. У меня это 80/443. Затем перезапускается uf.

###### добавить в фаервол:
ufw allow from
ufw route allow proto tcp from
ufw route allow proto udp from

Плюс у меня есть дополнительная защита для Линукс (Linux),  блокирующая различные сервисы /etc/hosts.allow.  

Ansible-плейбук для ufw - скачать.

Теперь запустим всё на наших хостах. Для этого через пробел указываем их адреса. Разрешаем порты 80/443.

Рис.5 Запуск firewall на наших хостах. Рис.5 Запуск firewall на наших хостах. 

Обязательно устанавливайте firewall на каждую машину. И, учитывая, что наши машины будут взаимодействовать между собой, прописываем для всех машин разрешённые адреса, позволяя им обращаться друг ко другу по любому порту. 

Также для синхронизации конфигов нам понадобится SSH, который мы прописываем для всех 3 машин.

SSH — сетевой протокол прикладного уровня, позволяющий производить удалённое управление операционной системой и туннелирование TCP-соединений. Схож по функциональности с протоколами Telnet и Rlogin, но, в отличие от них, шифрует весь трафик, включая и передаваемые пароли.

При установке Caddy+Consul нас будут спрашивать про количество необходимых серверов. Удобнее использовать нечётное количество серверов, но больше 3. Например, 3/5/7/9. Если сервер будет 1, то 1 и указываем. Для каждого сервера нужно ввести IP-адрес. Добавим наш тестовый сайт.

Для установки Caddy+Consul, на каждом сервере запускаем процесс установки. Указываем наше количество серверов, у нас их 3. И добавляем их IP-адреса.

По системным требованиям, для не сильно загруженного балансировщика не требуется много ресурсов. Хватит маломощного компьютера (с двухъядерным процессором и 4-8 Гб оперативной памяти) даже при хорошей нагрузке.

Проверяем все 3 хоста на работу Caddy+Consul, везде они запустились. Проверяем, какие порты у нас открылись. Consul открывает большое количество портов для работы. Админка у него на порте 8500. Если взять любой из разрешённых IP-адресов и этот порт, то мы можем зайти в админку Consul. В ней мы видим 3 instances (экземпляра) сonsul, и наши 3 ноды (node), для которых можно посмотреть статус и различные параметры. Среди наших нод есть лидер, отмеченный звездой и надписью Leader.

Рис.6 Наши 3 ноды и их лидер. Рис.6 Наши 3 ноды и их лидер. 

Получение SSL-сертификата для нашего домена

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

###### Скрипт для синхронизации конфигураций:
#!/bin/bash
# rsync config folder
rsync -avz -e "ssh -p 2221"  --delete --no-owner --no-group  --rsync-path="sudo rsync" /app/caddyconsul/sites /app/caddyconsul/files ms@65.109.16.84:/app/caddyconsul/ > /dev/null 2>&1
rsync -avz -e "ssh -p 2221"  --delete --no-owner --no-group  --rsync-path="sudo rsync" /app/caddyconsul/sites /app/caddyconsul/files ms@185.175.45.196:/app/caddyconsul/ > /dev/null 2>&1
rsync -avz -e "ssh -p 2221"  --delete --no-owner --no-group  --rsync-path="sudo rsync" /app/caddyconsul/sites /app/caddyconsul/files ms@109.248.33.137:/app/caddyconsul/ > /dev/null 2>&1
# reload caddy
sudo docker exec -w /etc/caddy caddy caddy reload > /dev/null 2>&1
ssh -p '2221' 'ms@65.109.16.84' sudo docker exec -w /etc/caddy caddy caddy reload > /dev/null 2>&1
ssh -p '2221' 'ms@185.175.45.196' sudo docker exec -w /etc/caddy caddy caddy reload > /dev/null 2>&1
ssh -p '2221' 'ms@109.248.33.137' sudo docker exec -w /etc/caddy caddy caddy reload > /dev/null 2>&1
echo "sync ok"

Сертификат действует до 24 июня, а потом автоматически продлится.

Отработка отказа 2-х из 3-х ВМ. Убедимся, что наше приложение по-прежнему доступно

Теперь давайте сделаем имитацию отказа одного из российских хостов. Для этого мы вручную тушим сервер. После этого представим, что у нас отобрана и вторая машина (в облаке Хетцнер в Германии (Hetzner Cloud), и теперь работающим остался лишь последний, третий хост.

Рис.7 Проверка доступности нашего сайта.Рис.7 Проверка доступности нашего сайта.

Обратите внимание, что после отключения 2 виртуальных машин  у нас остался только один IP-адрес. Браузер будет пробовать попасть по всем адресам, указанным в DNS.

DNS — компьютерная распределённая система для получения информации о доменах. Чаще всего используется для получения IP-адреса по имени хоста, получения информации о маршрутизации почты и/или обслуживающих узлах для протоколов в домене.

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

Теперь настроим наш Caddy на работу реверсивного прокси (reverse proxy).

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

##### Конфигурация для проксирования в кубер:
 {
 reverse_proxy 195.208.185.64 {
 health_uri /healthz
 health_port 80
 health_interval 10s
 health_timeout 10s
 health_status 200
 }
#####  Ингресс для кубера
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
	kubernetes.io/ingress.class: nginx
  name: caddy-test
  namespace: gitlab
spec:
  rules:
  - host: caddytest.corpsoft24.ru
	http:
  	paths:
  	- backend:
      	service:
        	name: production-auto-deploy
        	port:
          	number: 80
    	path: /
    	pathType: Prefix
…

###### Настройка хоста:
https:// {
	tls {
    	on_demand
	}
respond "corpsoft24.ru"
	}
###### Для Caddyfile:
    	on_demand_tls {
            	ask https://url
            	interval 3m
            	burst 100
    	}

Синхронизируем это на все наши балансировщики и получаем сертификат. Сертификат настраивается автоматически.

#Используемые в уроке команды:
### Docker
echo "alias d='docker compose up -d'" >> ~/.bashrc
echo "alias ds='docker compose stop'" >> ~/.bashrc
echo "alias dcd='docker compose down'" >> ~/.bashrc
echo "alias d1='docker compose up'" >> ~/.bashrc
echo "alias dr='docker compose stop && docker compose up -d'" >> ~/.bashrc
echo "alias dl='docker compose logs -f'" >> ~/.bashrc
echo "alias dc='docker compose'" >> ~/.bashrc
echo "alias de='docker exec -it'" >> ~/.bashrc
echo "alias dp='docker system prune'" >> ~/.bashrc
echo "alias dps='docker ps --format=\"table {{.Names}}\t{{.Ports}}\t{{.Status}}\"'" >> ~/.bashrc
echo "alias dff='docker compose logs -f --tail 100'" >> ~/.bashrc
echo "alias db='docker compose build'" >> ~/.bashrc
echo "alias trl='truncate -s 0 /var/lib/docker/containers/*/*-json.log'" >> ~/.bashrc
source ~/.bashrc

Разместить данные в защищенном отказоустойчивом облаке Corpsoft24⁠

Загрузка ...