Автор: Михаил Волынов
Эта статья поможет вам развернуть кластер Kubernetes и настроить на нем Canary Deployment при помощи Nginx Ingress Annotations
Canary Deployment — это способ развертывания сетевых приложений и онлайн-сервисов для некоторого множества пользователей или серверов. Его часто используют для постепенного развертывания новых версий приложений с целью раннего выявления ошибок. Canary Deployment особенно полезен при проведении A/B-тестирований или настройки Blue/Green-развертывания приложений
Рассмотрим пример с тестовым приложением. Выполним сценарий Canary Deployment для простого echo-сервера и убедимся, что трафик распределяется в соответствии с конфигурационным файлом
Ingress – это набор правил внутри вашего кластера. Эти правила предназначены для того, чтобы входящие подключения могли достичь сервисов (Services) ваших приложений
Ingress решает следующие основные задачи:
- Организация для ваших приложений URL, доступных из-вне
- Обеспечение балансировки трафика
- Терминация SSL
- Виртуальный хостинг на основе имен
Ingress Controller — это то, что позволяет набору правил Ingress работать. Если кратко, Ingress Controller представляет собой одну центральную точку в виде контейнера, который используется для проксирования всего трафика
В Nginx доступны следующие типы Canary-аннотаций:
nginx.ingress.kubernetes.io/canary-by-header — позволяет перенаправлять на Сanary-версию только запросы с определенным http-заголовком
nginx.ingress.kubernetes.io/canary-by-cookie — позволяет перенаправлять на Сanary-версию только запросы с определенным cookie
nginx.ingress.kubernetes.io/canary-weight — позволяет напрямую указать, сколько процентов запросов будет уходить на нашу Сanary-версию приложения. В нашем примере выполним балансировку по этому принципу
Схема стенда
Ingress — это ресурс (объект), который содержит инструкции маршрутизации трафика в кластере, обычно используя HTTP. В данном случае Current и Canary являются конфигурациями Ingress для версий приложений, для которых мы настраиваем Canary Deployment.
Ingress Controller отвечает за выполнение правил Ingress, как правило, с помощью балансировщика нагрузки, встроенного в K8S.
Создание кластера Kubernetes в MCS
Чтобы создать кластер Kubernets:
- В боковом меню выберите раздел Контейнеры
- Нажмите кнопку Подключить
- В боковом меню выберите раздел Кластеры Kubernetes
- Нажмите кнопку Добавить и выберите подходящие настройки
Нажмите кнопку Следующий шаг и выберите подходящую конфигурацию машин
Нажмите кнопку Создать кластер и дождитесь завершения операции. Создание кластера может занять от 5 до 20 минут, в зависимости от его размеров
По завершении создания кластера загрузится архив, содержащий файлы, необходимые для безопасного подключения к панели управления Kubernetes. Не закрывайте страницу с информацией о новом кластере, она понадобиться для входа в Kubernetes Dashboard
- Чтобы можно было подключаться к кластеру по kubectl, распакуйте архив, найдите файл config, который требуется для работы утилиты kubectl, и задайте переменную окружения KUBECONFIG:
export KUBECONFIG=<путь до файла config>
Создание приложения в production
Создадим приложение и покажем для этого приложения балансировку с помощью Nginx Canary. Для этого:
- Создайте production namespace для проекта:
kubectl create ns echo-production < namespace "echo-production" created
- Разверните приложение. Мы используем пример из репозитория Kubernetes. Подключимся к кластеру и развернем тестовый echo-сервер в созданном namespace:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/docs/examples/http-svc.yaml -n echo-production < deployment.extensions "http-svc" created < service "http-svc" created
- Создайте файл конфигурации Ingress и примените его к namespace echo-production:
http-svc.ingress apiVersion: extensions/v1beta1 kind: Ingress metadata: name: http-svc annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: echo.com http: paths: - backend: serviceName: http-svc servicePort: 80
В результате сервер будет реагировать на все запросы от хоста echo.com (serviceName — название сервиса, созданного на предыдущем шаге)
kubectl apply -f http-svc.ingress -n echo-production < ingress.extensions "http-svc" created
Создание тестовой копии приложения
Создадим копию приложения, на которую будем направлять часть запросов. Для этого:
- Создайте Canary-версию namespace приложения:
kubectl create ns echo-canary < namespace "echo-canary" created
- Разверните Canary-версию приложения:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/docs/examples/http-svc.yaml -n echo-canary < deployment.extensions "http-svc" created < service "http-svc" created
- Создайте Canary-версию файла конфигурации Ingress и примените его к namespace echo-canary:
http-svc.ingress.canary apiVersion: extensions/v1beta1 kind: Ingress metadata: name: http-svc annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "10" spec: rules: - host: echo.com http: paths: - backend: serviceName: http-svc servicePort: 80
- Примените изменения:
kubectl apply -f http-svc.ingress.canary -n echo-canary < ingress.extensions "http-svc" created
Проверка, что все работает
Зайдите Kubernetes Dashboard, используя токен, полученный после создания кластера:
Чтобы просмотреть доступные Namespaces, в боковом меню нажмите соответствующую кнопку:
Чтобы просмотреть список активных Ingress и получить их внешний IP-адрес, переключите текущий Namespace на All namespaces:
Затем в нижней части бокового меню выберите Ingresses:
В результате на экране отобразится список всех доступных Ingresses. У Canary и Production должен быть один IP-адрес:
Проверим, что запросы распределяются в соответствии с конфигурационным файлом. Для этого возьмем скрипт на Ruby:
count.rb counts = Hash.new(0) 1000.times do output = `curl -s -H "Host: echo.com" http://<внешний_ip_адрес> | grep 'pod namespace'` counts[output.strip.split.last] += 1 end puts counts
И выполним его:
ruby count.rb
Результат должен быть близок к следующему:
{"echo-production"=>896, "echo-canary"=>104}