В этом посте я собираюсь обсудить различные стратегии развертывания и способы их реализации с помощью K8 и Istio. В основном реализация всех стратегий основана на способности K8 одновременно запускать несколько версий микросервиса и на концепции, что потребители могут получить доступ к микросервису только через какую-то точку входа. В этой точке входа мы можем контролировать, на какую версию микросервиса должен направляться потребитель.
Пример приложения для этого поста будет простым приложением Spring Boot, помещенным в образ Docker. Итак, есть два изображения
superapp: old и superapp: new, представляющие старую и новую версии приложения соответственно:
docker run -d –name old -p 9001: 8080 eugeneflexagon / superapp: old
docker run -d –name new -p 9002: 8080 eugeneflexagon / superapp: new
curl http: // localhost: 9001 / version
{ «ID»: 1,»содержание»:»старый»}
curl http: // localhost: 9002 / version
{ «ID»: 1,»содержание»:»новый»}
Предположим, старая версия приложения развернута в кластере K8s, работающем на Oracle Kubernetes Engine, со следующим манифестом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
apiVersion: apps/v1beta1 kind: Deployment metadata: name: superapp spec: replicas: 3 template: metadata: labels: app: superapp spec: containers: - name: superapp image: eugeneflexagon/superapp:old ports: - containerPort: 8080 |
Таким образом, есть три копии модуля, на котором запущена старая версия приложения. Существует также сервис, направляющий трафик на эти модули:
01
02
03
04
05
06
07
08
09
10
|
apiVersion: v1 kind: Service metadata: name: superapp spec: selector: app: superapp ports: - port: 8080 targetPort: 8080 |
Rolling Update
Эта стратегия развертывания обновляет модули по мере обновления, меняя их одну за другой.
Это стратегия по умолчанию, которая обрабатывается самим кластером K8s, поэтому нам просто нужно обновить развертывание superapp со ссылкой на новый образ:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
apiVersion: apps/v1beta1 kind: Deployment metadata: name: superapp spec: replicas: 3 template: metadata: labels: app: superapp spec: containers: - name: superapp image: eugeneflexagon/superapp: new ports: - containerPort: 8080 |
Тем не менее, мы можем точно настроить алгоритм скользящего обновления , предоставив параметры для этой стратегии развертывания в файле манифеста:
1
2
3
4
5
6
7
8
9
|
spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 30 % maxUnavailable: 30 % template: ... |
Параметр maxSurge определяет максимальное количество модулей, которое может быть создано за желаемое количество модулей. Это может быть процент или абсолютное число. Значение по умолчанию составляет 25%.
Параметр maxUnavailable определяет максимальное количество модулей, которые могут быть недоступны в процессе обновления. Это может быть процент или абсолютное число. Значение по умолчанию составляет 25%.
Recreate
Эта стратегия развертывания убивает все старые модули, а затем создает новые.
1
2
3
4
5
6
|
spec: replicas: 3 strategy: type: Recreate template: ... |
Очень простой.
Цвет морской волны
Эта стратегия определяет старую версию приложения как зеленую, а новую версию — как синюю . Пользователи всегда имеют доступ только к зеленой версии.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
apiVersion: apps/v1beta1 kind: Deployment metadata: name: superapp- 01 spec: template: metadata: labels: app: superapp version: "01" ... apiVersion: v1 kind: Service metadata: name: superapp spec: selector: app: superapp version: "01" ... |
Сервис направляет трафик только на пакеты с версией «01» .
Мы внедряем «голубую» версию в кластер K8s и делаем ее доступной только для обеспечения качества или для инструмента автоматизации тестирования (через отдельный сервис или прямую переадресацию портов).
01
02
03
04
05
06
07
08
09
10
11
|
apiVersion: apps/v1beta1 kind: Deployment metadata: name: superapp- 02 spec: template: metadata: labels: app: superapp version: "02" ... |
После тестирования новой версии мы переключаем сервис на нее и уменьшаем старую версию:
1
2
3
4
5
6
7
8
9
|
apiVersion: v1 kind: Service metadata: name: superapp spec: selector: app: superapp version: "02" ... |
1
|
kubectl scale deployment superapp- 01 --replicas= 0 |
Сделав это, все пользователи работают с новой версией.
Так что Истио пока нет. Все обрабатывается кластером K8s из коробки. Давайте перейдем к следующей стратегии.
канарейка
Мне нравится эта стратегия развертывания, поскольку она позволяет пользователям тестировать новую версию приложения, и они даже не знают об этом. Идея заключается в том, что мы развертываем новую версию приложения и направляем на него 10% трафика. Пользователи понятия не имеют об этом.
Если это работает некоторое время, мы можем сбалансировать трафик 70/30, затем 50/50 и, в конечном итоге, 0/100.
Даже если эту стратегию можно реализовать с помощью ресурсов K8s, только играя с количеством старых и новых модулей, гораздо удобнее реализовать ее с помощью Istio.
Таким образом, старое и новое приложения определяются как следующие развертывания:
01
02
03
04
05
06
07
08
09
10
11
|
apiVersion: apps/v1beta1 kind: Deployment metadata: name: superapp- 01 spec: template: metadata: labels: app: superapp version: "01" ... |
01
02
03
04
05
06
07
08
09
10
11
|
apiVersion: apps/v1beta1 kind: Deployment metadata: name: superapp- 02 spec: template: metadata: labels: app: superapp version: "02" ... |
Служба направляет трафик на них обоих:
1
2
3
4
5
6
7
8
|
apiVersion: v1 kind: Service metadata: name: superapp spec: selector: app: superapp ... |
Кроме того, мы собираемся использовать следующие ресурсы Istio:
VirtualService и DestinationRule.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: superapp spec: host: superapp subsets: - name: green labels: version: "01" - name: blue labels: version: "02" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: superapp spec: hosts: - superapp http: - match: - uri: prefix: /version route: - destination: port: number: 8080 host: superapp subset: green weight: 90 - destination: port: number: 8080 host: superapp subset: blue weight: 10 |
VirtualService направит весь трафик, поступающий в службу superapp (хосты), к зеленым и синим модулям в соответствии с предоставленными весами (90/10).
A / B Тестирование
С помощью этой стратегии мы можем точно контролировать, какие пользователи, с каких устройств, отделов и т. Д. Перенаправляются в новую версию приложения.
Например, здесь мы собираемся проанализировать заголовок запроса, и если его пользовательский тег «конечный пользователь» равен «xammer», он будет перенаправлен в новую версию приложения. Остальные запросы будут перенаправлены на старый:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: superapp spec: gateways: - superapp hosts: - superapp http: - match: - headers: end-user: exact: xammer route: - destination: port: number: 8080 host: superapp subset: blue - route: - destination: port: number: 8080 host: superapp subset: green |
Все примеры и файлы манифеста для этого поста доступны на GitHub, так что вы можете самостоятельно поиграть с различными стратегиями и сложными правилами маршрутизации. Вам просто нужен кластер K8s (например, Minikube на вашем ноутбуке) с предустановленным Istio. Счастливого развертывания!
Это оно!
Опубликовано на Java Code Geeks с разрешения Евгения Федоренко, партнера нашей программы JCG . Смотреть оригинальную статью здесь: Стратегии развертывания с Kubernetes и Istio Мнения, высказанные участниками Java Code Geeks, являются их собственными. |