Canary Deployment у Kubernetes #1: Gitlab CI

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

Canary Deployment у Kubernetes #1: Gitlab CI

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

Виконувати Canary-деплой ми будемо руками через GitOps та створення/зміну основних ресурсів Kubernetes. Ця стаття призначена насамперед для знайомства з тим, як працює в Kubernetes Canary деплою, тому що є більш ефективні способи автоматизації, які ми розглянемо в наступних статтях.


Canary Deployment у Kubernetes #1: Gitlab CI

https://www.norberteder.com/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-docker

before_script:
   - printenv
   - kubectl version

stages:
 - deploy

deploy 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-b

gcloud 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: v1
kind: Service
metadata:
 labels:
   id: app
 name: app
spec:
 ports:
 - port: 80
   protocol: TCP
   targetPort: 5000
 selector:
   id: app
 type: LoadBalancer

І deployment у deploy.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: app
spec:
 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: Deployment
metadata:
 name: app-canary
spec:
 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 повинен вивести наступне:

Canary Deployment у Kubernetes #1: Gitlab CI

Ми бачимо 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

Canary Deployment у Kubernetes #1: Gitlab CI

Ми бачимо, що наш тестовий додаток повертає лише “v1”.

Виконання Canary деплою

Крок 1: випустити нову версію частини користувачів

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

kind: Deployment
metadata:
 name: app-canary
spec:
 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: Deployment
metadata:
 name: app
spec:
 replicas: 9
 selector:
   matchLabels:
     id: app
...

Ми пушимо ці зміни до репозиторію, з якого запуститься деплою (через GitlabCI) і бачимо в результаті:

Canary Deployment у Kubernetes #1: Gitlab CI

Наш Service буде вказувати на обидва деплої, так як у обох є селектор app. Через випадковий розподіл за замовчуванням у Kubernetes ми повинні побачити різні відповіді на ~ 10% запитів:

Canary Deployment у Kubernetes #1: Gitlab CI

Поточний стан нашої програми (GitOps, взятий з Git як із Single Source Of Truth) це наявність двох deployments з активними репліками, по одному для кожної версії.

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

Крок 2: випустити нову версію для всіх користувачів

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

Canary Deployment у Kubernetes #1: Gitlab CI

Підводячи підсумок

Для мене запуск деплою вручну таким чином допомагає зрозуміти, як легко він може бути налаштований за допомогою k8s. Оскільки Kubernetes дозволяє оновлювати все через API, ці кроки можна автоматизувати через скрипти.

Ще одна річ, яку потрібно реалізувати - це точка входу тестувальника (LoadBalancer або через Ingress), через яку можна отримати доступ лише до нової версії. Вона може бути використана для перегляду вручну.

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

Також читайте інші статті у нашому блозі:

Джерело: habr.com

Додати коментар або відгук