Русский
Русский
English
Статистика
Реклама

Canary

Перевод Canary Deployment в Kubernetes 3 Istio

03.08.2020 14:12:05 | Автор: admin

Использование Istio+Kiali для запуска и визуализации Canary деплоя





Статьи этого цикла


  1. Canary Deployment в Kubernetes #1: Gitlab CI
  2. Canary Deployment в Kubernetes #2: Argo Rollouts
  3. (эта статья)
  4. Canary Deployment используя Jenkins-X Istio Flagger

Canary Deployment


Надеемся, что вы читали первую часть, где мы кратко объясняли что такое Canary deployments и показывали как его реализовать при помощи стандартных ресурсов Kubernetes.


Istio


И мы предполагаем, что читая эту статью, вы уже знаете что такое Istio. Если нет, то вы можете почитать о нем здесь.


Приложение для тестов



Каждый под содержит два контейнера: наше приложение и istio-proxy.


Мы будем использовать простое тестовое приложение с подами frontend-nginx и backend на python. Под с nginx будет просто перенаправлять каждый запрос на под с backend и работать как прокси. Детали можно посмотреть подробнее в следующих yamls:



Запуск тестового приложения самостоятельно


Если вы хотите последовать моему примеру и использовать данное тестовое приложение самостоятельно, см. readme проекта.


Начальный Deployment


При запуске первого Deployment видим, что поды нашего приложения имеют всего по 2 контейнера, то есть Istio sidecar пока только внедряется:





И также видим Istio Gateway Loadbalancer в namespace istio-system:



Создание трафика


Мы будем использовать следующий IP, что бы сгенерировать трафик, который будет принят frontend подами и перенаправлен на backend поды:


while true; do curl -s --resolve 'frontend.istio-test:80:35.242.202.152' frontend.istio-test; sleep 0.1; done


Мы так же добавим frontend.istio-test в наш hosts файл.


Просмотр Mesh через Kiali


Мы установили тестовое приложение и Istio вместе с Tracing, Grafana, Prometheus и Kiali (подробнее см. readme проекта). Следовательно, мы можем использовать Kiali через:


istioctl dashboard kiali # admin:admin



Kiali визуализирует текущий трафик через Mesh


Как мы видим, 100% трафика попадает на frontend service, затем на под фронтенда с label v1, так как мы используем простой nginx-прокси, который перенаправляет запросы на backend service, который в свою очередь перенаправляет их на backend поды с label v1.


Kiali работает отлично вместе с Istio и предоставляет коробочное решение для визуализации Mesh. Просто прекрасно.


Canary Deployment


Наш бекенд уже имеет два k8s deployments, один для v1 и один для v2. Теперь нам нужно просто сказать Istio перенаправлять определенный процент запросов на v2.


Шаг 1: 10%


И все что нам нужно сделать это отрегулировать вес VirtualService в istio.yaml:


apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: backend  namespace: defaultspec:  gateways: []  hosts:  - "backend.default.svc.cluster.local"  http:  - match:    - {}    route:    - destination:        host: backend.default.svc.cluster.local        subset: v1        port:          number: 80      weight: 90    - destination:        host: backend.default.svc.cluster.local        subset: v2        port:          number: 80      weight: 10




Мы видим, что 10% запросов перенаправлено на v2.


Шаг 2: 50%


И теперь достаточно просто увеличить его до 50%:


apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: backend  namespace: defaultspec:...    - destination:        host: backend.default.svc.cluster.local        subset: v1        port:          number: 80      weight: 50    - destination:        host: backend.default.svc.cluster.local        subset: v2        port:          number: 80      weight: 50




Шаг 3: 100%


Теперь Canary deployment может считаться завершенным и весь трафик перенаправляется на v2:





Тестирование Canary вручную


Допустим, сейчас мы отправляем на бэкэнд v2 10% от всех запросов. Что, если мы хотим вручную протестировать v2, чтобы убедиться, что все работает как мы ожидаем?


Мы можем добавить специальное соответствующее правило, основанное на HTTP заголовках:


apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: backend  namespace: defaultspec:  gateways: []  hosts:  - "backend.default.svc.cluster.local"  http:  - match:    - headers:        canary:          exact: "canary-tester"    route:    - destination:        host: backend.default.svc.cluster.local        subset: v2        port:          number: 80      weight: 100  - match:    - {}    route:    - destination:        host: backend.default.svc.cluster.local        subset: v1        port:          number: 80      weight: 90    - destination:        host: backend.default.svc.cluster.local        subset: v2        port:          number: 80      weight: 10

Теперь используя curl мы можем принудительно запросить v2 отправив заголовок:





Запросы без заголовка все еще будут управляться соотношением 1/10:





Canary для двух зависимых версий


Теперь мы рассмотрим вариант, где у нас есть версия v2 и для frontend и для backend. Для обоих мы указали, что 10% трафика должно идти к v2:





Мы видим, что frontend v1 и v2 оба пересылают трафик в соотношении 1/10 на backend v1 и v2.


А что если бы мы нам было нужно пересылать трафик с frontend-v2 только на backend-v2, потому что он не совместим с v1? Для этого мы установим 1/10 соотношение для frontend, который контролирует какой трафик попадает на backend-v2 используя согласование по sourceLabels :


apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:  name: backend  namespace: defaultspec:  gateways: []  hosts:  - "backend.default.svc.cluster.local"  http:...  - match:    - sourceLabels:        app: frontend        version: v2    route:    - destination:        host: backend.default.svc.cluster.local        subset: v2        port:          number: 80      weight: 100

В результате получаем то, что нужно:





Отличия от ручного Canary подхода


В первой части мы выполняли Canary deployment вручную, также используя два k8s deployments. Там мы управляли соотношением запросов, изменяя количество реплик. Такой подход работает, но имеет серьезные недостатки.


Istio дает возможность определять соотношение запросов вне зависимости от количества реплик. Это значит, к примеру, что мы можем использовать HPAs (Horizontal Pod Autoscalers горизонтальное масштабирование подов) и его не нужно настраивать в соответствии с текущем состоянием Canary деплоя.


Итог


Istio работает отлично и используя его вместе с Kiali получаем очень мощную комбинацию. Следующий в моем списке интересов это комбинация Spinnaker с Istio для автоматизации и Canary-аналитики.

Подробнее..

Перевод Canary Deployment в Kubernetes 1 Gitlab CI

29.07.2020 16:12:53 | Автор: admin

Мы будем использовать Gitlab CI и ручной GitOps для внедрения и использования Canary-деплоя в Kubernetes





Статьи из этого цикла:


  • (эта статья)
  • Canary Deployment при помощи ArgoCI
  • Canary Deployment при помощи Istio
  • Canary Deployment при помощи Jenkins-X Istio Flagger

Выполнять Canary-деплой мы будем руками через GitOps и создание/изменение основных ресурсов Kubernetes. Эта статья предназначена в первую очередь для знакомства с тем, как работает в Kubernetes Canary деплой, так как есть более эффективные способы автоматизации, которые мы рассмотрим в следующих статьях.



https://www.norberteder.com/canary-deployment/


Canary Deployment


При Canary-стратегии обновления сначала применяются только для части пользователей. Через мониторинг, данные с логов, ручное тестирование или другие каналы обратной связи релиз тестируется перед его применением для всех пользователей.


Kubernetes Deployment (rolling update)


Стратегия по умолчанию для Kubernetes Deployment это rolling-update, где запускается определенное количество подов с новыми версиями образов. Если они создались без проблем, поды со старыми версиями образов завершаются, а новые поды создаются параллельно.


GitOps


Мы используем GitOps в этом примере, так как мы:


  • используем Git как единый источник истины
  • используем Git Operations для сборки и деплоя (никаких команд, кроме git tag/merge не нужно)

Пример


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


Репозиторий для приложений


Это очень простая API на Python+Flask, возвращающая ответ в виде JSON. Мы соберем пакет через GitlabCI и запушим результат в Gitlab Registry. В регистри у нас есть две разные версии релизов:


  • wuestkamp/k8s-deployment-example-app:v1
  • wuestkamp/k8s-deployment-example-app:v2

Единственная разница между ними это изменение возвращаемого JSON-файла. Мы используем это приложение для максимально простой визуализации того, с какой версией мы общаемся.


Инфраструктурный репозиторий


В этой репе мы будем деплоить через GitlabCI в Kubernetes, .gitlab-ci.yml выглядит следующим образом:


image: traherom/kustomize-dockerbefore_script:   - printenv   - kubectl versionstages: - deploydeploy test:   stage: deploy   before_script:     - echo $KUBECONFIG   script:     - kubectl get all     - kubectl apply -f i/k8s   only:     - master

Для его запуска самостоятельно вам понадобится кластер, можно использовать Gcloud:


gcloud container clusters create canary --num-nodes 3 --zone europe-west3-bgcloud compute firewall-rules create incoming-80 --allow tcp:80

Вам нужно сделать форк https://gitlab.com/wuestkamp/k8s-deployment-example-canary-infrastructure и создать переменную KUBECONFIG в GitlabCI, которая будет содержать конфиг для доступа kubectl к вашему кластеру.


О том, как получить учетные данные для кластера (Gcloud) можно почитать вот тут.


Инфраструктурный Yaml


В инфраструктурном репозитории у нас есть service:


apiVersion: v1kind: Servicemetadata: labels:   id: app name: appspec: ports: - port: 80   protocol: TCP   targetPort: 5000 selector:   id: app type: LoadBalancer

И deployment в deploy.yaml:


apiVersion: apps/v1kind: Deploymentmetadata: name: appspec: replicas: 10 selector:   matchLabels:     id: app     type: main template:   metadata:     labels:       id: app       type: main   spec:     containers:     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v1       name: app       resources:         limits:           cpu: 100m           memory: 100Mi

И другой deployment в deploy-canary.yaml:


kind: Deploymentmetadata: name: app-canaryspec: replicas: 0 selector:   matchLabels:     id: app     type: canary template:   metadata:     labels:       id: app       type: canary   spec:     containers:     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2       name: app       resources:         limits:           cpu: 100m           memory: 100Mi

Заметьте, что app-deploy пока не имеет определенных реплик.


Выполнение начального деплоя


Для запуска начального deployment вы можете запустить пайплайн GitlabCI вручную в мастер-ветке. После этого kubectl дожен вывести следующее:





Мы видим app deployment c 10 репликами и app-canary с 0. Так же есть LoadBalancer с которого мы можем обращаться через curl по External IP:


while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done





Мы видим, что наше тестовое приложение возвращает только v1.


Выполнение Canary деплоя


Шаг 1: выпустить новую версию для части пользователей


Мы установили количество реплик в 1 в файле deploy-canary.yaml и образ новой версии:


kind: Deploymentmetadata: name: app-canaryspec: replicas: 1 selector:   matchLabels:     id: app     type: canary template:   metadata:     labels:       id: app       type: canary   spec:     containers:     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2       name: app       resources:         limits:           cpu: 100m           memory: 100Mi

В файле deploy.yaml мы изменили количество реплик до 9:


kind: Deploymentmetadata: name: appspec: replicas: 9 selector:   matchLabels:     id: app...

Мы пушим эти изменения в репозиторий, из которого запустится деплой (через GitlabCI) и видим в итоге:





Наш Service будет указывать на оба деплоя, так как у обоих есть селектор app. Из-за случайного распределения по умолчанию в Kubernetes мы должны увидеть разные ответы на ~ 10% запросов:





Текущее состояние нашего приложения (GitOps, взятый с Git как с Single Source Of Truth) это наличие двух deployments c активными репликами, по одному для каждой версии.


~10% пользователей знакомятся с новой версией и ненамеренно тестируют ее. Теперь настало время проверить наличие ошибок в логах и данных мониторинга для поиска проблем.


Шаг 2: выпустить новую версию для всех пользователей


Мы решили, что все прошло хорошо и теперь нам нужно развернуть новую версию на всех пользователей. Для этого мы просто обновляем deploy.yaml устанавливая новую версию образа и количество реплик, равное 10. В deploy-canary.yaml мы устанавливаем количество реплик равное обратно 0. После деплоя результат будет следующим:





Подводя итог


Для меня запуск деплоя вручную таким образом помогает понять как легко он может быть настроен при помощи k8s. Так как Kubernetes позволяет обновлять все через API, эти шаги можно автоматизировать через скрипты.


Еще одна вещь, которую нужно реализовать это точка входа тестировщика (LoadBalancer или через Ingress), через которую можно получить доступ только к новой версии. Она может быть использована для просмотра вручную.


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


Также читайте другие статьи в нашем блоге:


Подробнее..

Категории

Последние комментарии

© 2006-2020, personeltest.ru