← Kubernetes: рабочие нагрузки
7 мин · средне · Урок 10 из 11

Blue-Green деплой

Два контура и один Service-переключатель: как получить мгновенный откат и чем за это платят.

Что такое Blue-Green

Blue-Green - стратегия деплоя без простоя с мгновенным откатом. В проде держат два независимых контура. Один контур называют blue, он принимает весь трафик. Второй называют green, он развёрнут и готов, но трафика не получает.

Когда green готов, трафик переключают на него. Если что-то сломалось, трафик переключают обратно на blue. Blue всё это время жив, поэтому откат происходит мгновенно.

В Kubernetes роль переключателя играет Service. Service - объект, который раздаёт трафик на набор Pod, отобранных по меткам. Метка (label) - пара ключ-значение на объекте. selector - набор меток, по которым Service выбирает Pod.

Меняешь selector с color=blue на color=green, и endpoints перестраиваются. endpoints - список IP-адресов Pod, на которые Service шлёт трафик. kube-proxy (компонент на каждой ноде, который держит правила сети для Service) обновляет правила, и трафик переезжает за секунду.

Главный плюс - откат идёт той же скоростью, что и выкатка. Один patch возвращает selector обратно. За это платишь ресурсами: в окне переключения в кластере живут обе версии сразу. Pod на 500 МБ RAM в 5 репликах держит лишние 5 ГБ. Для критичных сервисов страховка оправдана. Небольшим микросервисам с частой выкаткой такой расход ресурсов обходится дороже, чем стоит.

Минимальная конструкция

Нужны два Deployment с разными значениями метки color. Deployment - объект, который держит нужное число одинаковых Pod.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-blue
spec:
  selector:
    matchLabels: {app: app, color: blue}
  template:
    metadata:
      labels: {app: app, color: blue}
    spec:
      containers:
        - name: app
          image: nginxinc/nginx-unprivileged:1.21

Второй Deployment такой же, но с color: green и образом nginxinc/nginx-unprivileged:1.25.

Один Service с явным color в selector:

apiVersion: v1
kind: Service
metadata:
  name: app
spec:
  selector:
    app: app
    color: blue       # переключаем blue/green здесь
  ports:
    - port: 80
      targetPort: 8080

Как переключают трафик

kubectl patch svc app \
  -p '{"spec":{"selector":{"app":"app","color":"green"}}}'

kubectl patch записывает в spec.selector новый цвет. Контроллер endpoints замечает изменение, перебирает Pod в namespace и складывает в endpoints те, что подходят под новый selector. kube-proxy на каждой ноде следит за изменением endpoints и обновляет правила сети.

Если в selector Service нет ключа color, он поймает и blue, и green сразу. Трафик размажется по обеим версиям, а переключать будет нечего.

Соединения, открытые до переключения, доживают на blue. Новые соединения идут на green.

Откат

kubectl patch svc app \
  -p '{"spec":{"selector":{"app":"app","color":"blue"}}}'

Blue Deployment всё это время жив, его Pod готовы. Откат проходит за секунду.

Связанные команды

kubectl get deploy
kubectl get svc app -o jsonpath='{.spec.selector}'
kubectl get endpoints app
kubectl get pods -l color=green -o wide
kubectl rollout status deploy/app-green

Объект v1 Endpoints deprecated с 1.33, и kubectl get endpoints печатает про это предупреждение. Тот же список адресов через актуальный объект:

kubectl get endpointslice -l kubernetes.io/service-name=app

Что часто ломается

Когда не подходит Blue-Green

Домашка

Теорию закрепляет задание на своём кластере: 2 шага с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.

./run.sh start k8s-blue-green     # развернуть стартовое состояние
./run.sh verify k8s-blue-green    # проверить текущий шаг

Коротко

Прошли материал до конца? Отметьте урок пройденным.