В жизни любого DevOps-инженера возникает необходимость создать игровую площадку для команды разработчиков.
Как всегда он должен быть умным, шустрым и потреблять минимальное количество ресурсов.
В этой статье я хочу рассказать о том, как я решил проблему создания такого зверя для микросервисного приложения на kubernetes.
Входящие условия и требования
Немного о том, что это за система, для которой нужно было создать игровую площадку:- Kubernetes, кластер без ОС;
- Простой API-шлюз на базе nginx;
- MongoDB как база данных;
- Дженкинс в качестве CI-сервера;
- Git на Bitbucket;
- Два десятка микросервисов, которые могут общаться друг с другом (через API-шлюз), с базой данных и с пользователем.
Требования, которые нам удалось сформулировать в ходе активного общения с тимлидом:
- Минимизация потребления ресурсов;
- Минимизация изменений в коде сервисов для работы на игровой площадке;
- Возможность параллельной разработки нескольких сервисов;
- Возможность развития нескольких сервисов в одном пространстве;
- Возможность продемонстрировать изменения клиентам перед развертыванием на промежуточной стадии;
- Все разработанные сервисы могут работать с одной базой данных;
- Минимизация усилий разработчиков по развертыванию протестированного кода.
Размышления по теме
С самого начала было ясно, что наиболее логичным способом создания параллельных пространств в k8s является использование нативного инструмента виртуальных кластеров или, в терминологии k8s, пространств имен.Задача упрощается еще и тем, что все взаимодействия внутри кластера осуществляются с использованием коротких имен, предоставляемых kube-dns, а это означало, что структуру можно было запустить в отдельном пространстве имен без потери связности.
У этого решения есть только одна проблема — необходимость развертывания всех доступных сервисов в пространстве имен, что отнимает много времени, неудобно и потребляет большое количество ресурсов.
Пространство имен и DNS
При создании любого сервиса k8s создает DNS-запись вида ..
svc.cluster.local .
Этот механизм позволяет осуществлять связь через короткие имена в пределах одного пространства имен благодаря изменениям, внесенным в resolv.conf каждого запущенного контейнера.
В обычном состоянии это выглядит так:
То есть к службе в том же пространстве имен можно обращаться по имени , в соседних пространствах имен по имени .search <namespace-name>.
svc.cluster.local svc.cluster.local cluster.local nameserver 192.168.0.2 options ndots:5
Мы обходим систему
В этот момент на ум приходит простая мысль: База общая, за маршрутизацию запросов к сервисам отвечает API-шлюз, почему бы не сделать так, чтобы он шел сначала к сервису в его неймспейсе, а если его там нет, то по умолчанию? " Да, такое решение можно было бы организовать с помощью настроек пространства имен (мы помним, что это nginx), но такое решение вызвало бы разницу в настройках на pg и на других кластерах, что неудобно и может вызвать ряд проблем.
Итак, был выбран метод замены строки search <namespace-name>.
svc.cluster.local svc.cluster.local cluster.local
На search <namespace-name>.
svc.cluster.local svc.cluster.local cluster.local default.svc.cluster.local
Такой подход обеспечит автоматический переход к пространству имен по умолчанию, если требуемый сервис недоступен в его пространстве имен.
Аналогичного результата можно добиться в кластере следующим образом.
Kubelet добавляет в контейнер параметры поиска из разрешения.
conf хост-машины, поэтому вам просто нужно добавить следующую строку в /etc/resolv.conf каждого узла: search default.svc.cluster.local
Если вы не хотите, чтобы узлы разрешали адреса служб, вы можете использовать параметр --resolv-conf при запуске kubelet, который позволит вам указать любой другой файл вместо /etc/resolv.conf. Например, файл /etc/k8s/resolv.conf с той же строкой.
Вопрос технологии
Дальнейшее решение достаточно простое, вам просто нужно принять следующие соглашения:- Новые функции разрабатываются в отдельных ветках, таких как play/
- Для работы с несколькими сервисами в рамках одной фичи названия ветвей должны совпадать в репозиториях всех задействованных сервисов.
- Jenkins выполняет всю работу по развертыванию автоматически.
- Для тестирования ветки функций доступны по адресу .
cluster.local
настройки SSL-разгрузчика
Конфигурация Nginx для перенаправления запросов на api-gw в соответствующем пространстве имен server_name ~^(?<namespace>.
+)\.
cluster\.
local;
location / {
resolver 192.168.0.2;
proxy_pass http://api-gw.$namespace.svc.cluster.local ;
}
Дженкинс
Плагин Jenkins используется для автоматизации процесса развертывания.В настройках проекта указываем собирать только ветки, соответствующие шаблону play/* и добавляем Jenkinsfile в корень всех проектов, с которыми будет работать сборщик.
Для обработки используется заводной скрипт; Полностью приводить не буду, просто пара примеров.
В остальном развертывание принципиально ничем не отличается от обычного.
Получение имени ветки: def BranchName() {
def Name = "${env.BRANCH_NAME}" =~ "play[/]?(.
*)"
Name ? Name[0][1] : null
}
Минимальная конфигурация пространства имен требует развернутого шлюза API, поэтому мы добавляем в проект вызов, который создает пространство имен и развертывает в нем шлюз API: def K8S_NAMESPACE = BranchName()
build job: 'Create NS', parameters: [[$class: 'StringParameterValue', name: 'K8S_NAMESPACE', value: "${K8S_NAMESPACE}"]]
build job: 'Create api-gw', parameters: [[$class: 'StringParameterValue', name: 'K8S_NAMESPACE', value: "${K8S_NAMESPACE}"]]
Заключение
Серебряной пули не существует, но мне так и не удалось найти не только лучшие практики, но и описания того, как у других организованы песочницы, поэтому я решил поделиться методом, который использовал при создании песочницы на базе k8s. Возможно, это не идеальный способ, поэтому я с радостью приму комментарии или рассказы о том, как для вас решили эту проблему.Теги: #Kubernetes #DevOps #игровая площадка
-
Как Конвертировать Мтс В Avi На Mac
19 Oct, 24 -
Новые Элементы Яндекса В Вашем Браузере
19 Oct, 24 -
Delphi Xe5 + Android: Первые Впечатления
19 Oct, 24 -
Новая Версия Wefi.
19 Oct, 24