Използване на Istio+Kiali за стартиране и визуализация на Canary деплоймента

Статии от този цикъл
- (тази статия)
- Canary Deployment с Jenkins-X Istio Flagger
Canary разгръщане
Надяваме се, че сте прочели , където кратко обяснихме какво представляват Canary deployments и показахме как да ги реализираме с помощта на стандартни ресурси в Kubernetes.
Istio
И предполагаме, че като четете тази статия, вече знаете какво е Istio. Ако не, можете да прочетете за него .
Приложение за тестове

Всеки под съдържа два контейнера: нашето приложение и istio-proxy.
Ще използваме просто тестово приложение с подове frontend-nginx и backend на Python. Подът с nginx просто ще пренасочва всяко запитване към пода с backend и ще работи като прокси. Подробности можете да видите в следните yamls:
Стартиране на тестовото приложение самостоятелно
Ако искате да последвате примера ми и да използвате това тестово приложение самостоятелно, вижте .
Начален 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 (повече информация вижте ). Следователно можем да използваме Kiali чрез:
istioctl dashboard kiali # admin:admin

Kiali визуализира текущия трафик през Mesh
Както виждаме, 100% от трафика попада на frontend service, след това на пода на фронтенда с етикет v1, тъй като използваме прост nginx-прокси, който пренасочва запитванията към backend service, който от своя страна ги пренасочва към backend подовете с етикет v1.
Kiali работи отлично заедно с Istio и предоставя готово решение за визуализация на Mesh. Прекрасно.
Canary разгръщане
Нашият бекенд вече има два k8s deployments, един за v1 и един за v2. Сега просто трябва да кажем на Istio да пренасочва определен процент от запитванията към v2.
Стъпка 1: 10%
И всичко, което трябва да направим, е да регулираме теглото на VirtualService в :
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
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/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
...
- 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 разгръщането може да се счита за завършено и целият трафик се пренаправя към v2:

Ръчно тестване на Canary
Да предположим, че в момента изпращаме 10% от всички заявки към бекенда v2. Какво, ако искаме ръчно да тестваме v2, за да сме сигурни, че всичко работи, както очакваме?
Можем да добавим специално правило за съвпадение, базирано на HTTP заглавия:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
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/v1alpha3
kind: VirtualService
metadata:
name: backend
namespace: default
spec:
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 аналитика.
Източник: habr.com
