Będziemy używać Gitlab CI oraz ręcznego GitOps do wdrożenia i wykorzystania Canary Deployment w Kubernetes.

Artykuły z tego cyklu:
- (ten artykuł)
- Canary Deployment przy pomocy Istio
- Canary Deployment przy pomocy Jenkins-X Istio Flagger
Canary deployment będziemy realizować ręcznie poprzez GitOps i tworzenie/zmienianie podstawowych zasobów Kubernetes. Artykuł ten jest przede wszystkim przeznaczony do zapoznania się z tym, jak działa Canary deployment w Kubernetes, ponieważ istnieją bardziej efektywne sposoby automatyzacji, które omówimy w następnych artykułach.

Canary Deployment
W strategii Canary najpierw aktualizacje są stosowane wyłącznie do części użytkowników. Poprzez monitorowanie, dane z logów, ręczne testowanie lub inne kanały informacji zwrotnej, wydanie jest testowane przed zastosowaniem dla wszystkich użytkowników.
Kubernetes Deployment (rolling update)
Domyślna strategia dla Kubernetes Deployment to rolling-update, gdzie uruchamiane jest określone ilość podów z nowymi wersjami obrazów. Jeśli zostały one utworzone bez problemów, pody ze starymi wersjami obrazów są kończone, a nowe pody są tworzone równolegle.
GitOps
Używamy GitOps w tym przykładzie, ponieważ:
- używamy Git jako jedynego źródła prawdy,
- używamy operacji Git do budowy i wdrożenia (nie są potrzebne żadne komendy, oprócz git tag/merge).
Przykład
Przyjmijmy dobrą praktykę — posiadanie jednego repozytorium dla kodu aplikacji i jednego dla infrastruktury.
Repozytorium dla aplikacji
To bardzo prosty interfejs API w Pythonie+Flask, który zwraca odpowiedź w formacie JSON. Zbudujemy paczkę za pomocą GitlabCI i wypchniemy wynik do Gitlab Registry. W rejestrze mamy dwie różne wersje wydań:
wuestkamp/k8s-deployment-example-app:v1wuestkamp/k8s-deployment-example-app:v2
Jedyną różnicą między nimi jest zmiana zwracanego pliku JSON. Używamy tej aplikacji do maksymalnie prostego wizualizowania, z jaką wersją mamy do czynienia.
Repozytorium infrastrukturalne
W tym repozytorium będziemy wdrażać poprzez GitlabCI w Kubernetes, .gitlab-ci.yml wygląda następująco:
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
Aby go uruchomić samodzielnie, będziesz potrzebować klastra, możesz użyć Gcloud:
gcloud container clusters create canary --num-nodes 3 --zone europe-west3-b
gcloud compute firewall-rules create incoming-80 --allow tcp:80Musisz zrobić fork i stworzyć zmienną KUBECONFIG w GitlabCI, która będzie zawierać konfigurację dostępu kubectl do twojego klastra.
O tym, jak uzyskać dane logowania do klastra (Gcloud), można przeczytać .
Infrastrukturalny Yaml
W repozytorium infrastrukturalnym mamy service:
apiVersion: v1
kind: Service
metadata:
labels:
id: app
name: app
spec:
ports:
- port: 80
protocol: TCP
targetPort: 5000
selector:
id: app
type: LoadBalancerI deployment w 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: 100MiI inny deployment w 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: 100MiZauważ, że app-deploy nie ma jeszcze zdefiniowanych replik.
Wykonywanie wstępnego deployu
Aby uruchomić początkowy deployment, możesz ręcznie uruchomić pipeline GitlabCI w gałęzi master. Po tym kubectl powinien wyświetlić następujące:

Widzimy app deployment z 10 replikami i app-canary z 0. Istnieje również LoadBalancer, do którego możemy się odwoływać przez curl przez External IP:
while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done

Widzimy, że nasza aplikacja testowa zwraca tylko “v1”.
Wykonywanie Canary deployu
Krok 1: wydać nową wersję dla części użytkowników
Ustawiliśmy liczbę replik na 1 w pliku deploy-canary.yaml i obraz nowej wersji:
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: 100MiW pliku deploy.yaml zmieniliśmy liczbę replik na 9:
kind: Deployment
metadata:
name: app
spec:
replicas: 9
selector:
matchLabels:
id: app
...Wysyłamy te zmiany do repozytorium, z którego zostanie uruchomiony deploy (przez GitlabCI) i ostatecznie widzimy:

Nasz Service będzie wskazywał na oba deploye, ponieważ oba mają selektor app. Z powodu losowego rozkładu domyślnego w Kubernetes powinniśmy zobaczyć różne odpowiedzi na ~ 10% zapytań:

Bieżący stan naszej aplikacji (GitOps, wzięty z Gita jako Single Source Of Truth) to obecność dwóch deploymentów z aktywnymi replikami, po jednym dla każdej wersji.
~10% użytkowników zapoznaje się z nową wersją i niezamierzanie ją testuje. Teraz nastał czas, aby sprawdzić obecność błędów w logach i danych monitorujących w celu wyszukania problemów.
Krok 2: wypuścić nową wersję dla wszystkich użytkowników
Zdecydowaliśmy, że wszystko przebiegło pomyślnie i teraz musimy wdrożyć nową wersję dla wszystkich użytkowników. Aby to zrobić, po prostu aktualizujemy deploy.yaml instalując nową wersję obrazu i liczba replik wynosi 10. W deploy-canary.yaml ustalamy liczbę replik z powrotem na 0. Po wdrożeniu rezultat będzie następujący:

Podsumowując
Dla mnie ręczne uruchomienie wdrożenia w ten sposób pomaga zrozumieć, jak łatwo można to skonfigurować za pomocą k8s. Ponieważ Kubernetes pozwala na aktualizację wszystkich za pośrednictwem API, te kroki można zautomatyzować za pomocą skryptów.
Jeszcze jedną rzeczą, którą należy wdrożyć, jest punkt wejścia testera (LoadBalancer lub przez Ingress), przez który można uzyskać dostęp tylko do nowej wersji. Może być używany do manualnego podglądu.
W następnych artykułach sprawdzimy inne zautomatyzowane rozwiązania, które wdrażają większość tego, co zrobiliśmy.
Przeczytaj również inne artykuły na naszym blogu:
Źródło: habr.com
