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



Простой канареечный деплой в Kubernetes включает в себя два ключевых ресурса: сам сервис и инструмент развертывания. Канареечный деплой работает через одну службу, которая взаимодействует с двумя разными ресурсами, обслуживающими трафик обновления. Один из этих ресурсов будет работать с «канареечной» версией, а второй — со стабильной. В этой ситуации мы можем регулировать количество канареечных версий для того, чтобы снизить объем необходимого к обслуживанию трафика. Если, к примеру, вы предпочитаете использовать Yaml, то выглядеть в Kubernetes это будет следующим образом:

kind: Deployment
metadata:
  name: app-canary
  labels:
    app: app
spec:
  replicas: 1
  ...
    image: myapp:canary
---
kind: Deployment
metadata:
  name: app
  labels:
    app: app
spec:
  replicas: 5
  ...
    image: myapp:stable
---
kind: Service
selector:
  app: app # Selector will route traffic to both deployments.

Еще проще представить такой вариант можно на kubectl, а в документации по Kubernetes даже есть полноценный туториал по этому сценарий. Но главный вопрос этого поста заключается в том, как мы собираемся автоматизировать этот процесс, используя Helm.

Автоматизация канареечного деплоя


Прежде всего нам понадобится карта чартов Helm, в которую уже внесены обсуждаемые нами выше ресурсы. Выглядеть она должна быть примерно так:

~/charts/app
+-- Chart.yaml
+-- README.md
+-- templates
¦   +-- NOTES.txt
¦   +-- _helpers.tpl
¦   +-- deployment.yaml
¦   L-- service.yaml
L-- values.yaml

Основа концепции Helm — управление мультиверсиями релизов. Stable-версия — это наша основная стабильная ветка кода проекта. Но с помощью Helm мы можем развернуть канареечный релиз с нашим экспериментальным кодом. Главное — сохранить обмен трафиком между стабильной версией и канареечным релизом. Управлять всем этим мы будем с помощью специального селектора:

selector:
  app.kubernetes.io/name: myapp

Наши как «канареечные», так и stable-ресурсы деплоя будут указывать эту метку на модулях. Если все настроить правильно, то во время деплоя канареечной версии нашей карты чартов Helm мы увидим, что трафик будет направляться на свежеразвернутые модули. Стабильная версия этой команды будет выглядеть так:

helm upgrade
  --install myapp   --namespace default   --set app.name=myapp \      # Goes into app.kubernetes.io/name
  --set app.version=v1 \      # Goes into app.kubernetes.io/version
  --set image.tag=stable   --set replicaCount=5

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

helm upgrade
  --install myapp-canary   --namespace default   --set app.name=myapp \      # Goes into app.kubernetes.io/name
  --set app.version=v2 \      # Goes into app.kubernetes.io/version
  --set image.tag=canary   --set replicaCount=1

Вот, собственно, и все! Если пингануть службу, то можно увидеть, что канареечное обновление маршрутизирует трафик только часть времени.



Если вы ищите инструменты автоматизации деплоя, которые включают в себя описанную логику, то обратите внимание на Deliverybot и на инструменты автоматизации Helm на GitHub. Чарты Helm, используемые для реализации описанного выше способа лежат на Github, вот тут. Вообще, это был теоретический обзор того, как реализовать автоматизацию деплоя канареечных версий на практике, с конкретными концепциями и примерами.

Комментарии (7)


  1. gecube
    19.09.2019 14:09

    А чем вас привекла именно эта методика канареечного релиза?
    Почему, например, не через Istio?
    И статья не говорит как сделать полноценный канареечный деплой от 0% до 100% новой версии.


    Ссылка https://github.com/deliverybot/helm/charts — ведет на 404 :-(


    1. ProFfeSsoRr
      20.09.2019 07:41

      Ставить Istio только ради канареечных релизов наверное не очень, а Helm у них видимо уже был.


    1. Macbet
      20.09.2019 14:38

      видимо это очень " бюджетный" вариант, istio все-таки довольно дорого по ресурсам запускать


    1. ITSumma
      23.09.2019 14:03

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


  1. evg_krsk
    20.09.2019 04:25

    Сервис не пингуется :-)


  1. zloichel
    20.09.2019 14:38

    Переключать трафик, меняя не объект service, а label — мне это в свое время в голову не пришло 8)
    Жаль что helm не позволяет менять объект service, созданный в другом релизе — и в итоге вместо двух релизов blue\green с общим svc пришлось делать третий, который содержит только объект service, и переключать blue->green приходиться через helm upgrade релиза с service, меняя в нем selector…


  1. LuckySB
    20.09.2019 19:03

    ну такоэ…

    основная трамблема, если мне надо отправить 1% трафика на канарейку, то надо будет поднимать 99 стейбл-реплик на один канареечный.
    что не самое удобное решение )))

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