Стратегии развертывания в Kubernetes
В этой статье, мы узнаем, что такое статегии развертывания, во время установки контейнеров используя систему открестрации контейнеров Kubernetes. В конце этой статьи, мы будем знать различные пути установки в кластере Kubernetes.
Обзорное введение в Kubernetes С популярностью контейнеризации и с револющией в создании, доставке и обслуживании приложений появилась необходимость эффективного обслуживания этих контейнеров. Множество систем оркестраторации контейнеров введены для обслуживания цикла этих контейнеров в больших системах.
Kubernetes один из подобных инструментов оркестрации, который берет на себя заботу о предоставлении и установке, выделении ресурсов, балансировке нагрузки, обнаружении сервисов, предоставлении высокой доступности и другие важные моменты любой системы. С его помощью мы можем разложить наши приложения в на маленькие системы(называемые микросервисами) во время установки. затем мы можем собрать(или оркестрировать) эти системы вместе во время установки.
Применение облачного подхода увеличивает разработку приложений основанных на микросервисной архитектуре. Для таких приложений, наибольший из вызовов это встреча с установкой. Иметь хорошую стратегию - необходимость. В Kubernetes, есть множество путей для выпуска приложений, необходимо выбрать правильную стратегию, чтобы сделать инфраструктуру надежной во время развертывания приложений или обновления. Для примера, в производственной среде, всегда есть требование чтобы пользователи не ощутили время простоя сервиса. В оркестраторе Kubernetes, правильная стратегия - убедиться в верности управления различных версий образов контейнера. В общем, эта статья покрывает различные статегии установки в Kubernetes.
Требования
Чтобы продолжить, нам необходим опыт с кубернетес. Если вы не знакомы с этой платфорой, Пройдите для начала "Step by Step Introduction to Basic Kubernetes Concepts" инструкцию. В ней вы можете найти, всё что нужно для того, чтобы понять, чтоп роисходит в этой иснтрукции. мы также рекомендуем пройти полистать Kubernetes документацию если или когда потребуется.
Кроме того, если нам потребуется kubectl, инструмент командной строки, который позволит нам управлять кластером Kubernetes из терминала. Если у вас нет этого инструмента, проверьт инструкцию по установке kubectl. Так же потребуется базовое понимание Linux и YAML.
Что такое развертывание в Kubernetes?
Развертывание это объект в kubernetes, который определяет желаемое состояние для нашей программы. Развертывание объявляема, это значит, что мы не должны говорить как достигнуть состояния. Вместо этого, мы объявляем желаеме состояние, и позволяем автоматически достигнуть конечного результата наилучшим путём. Развертывание позволяет нам описать жизненный цыкл приложения, к примеру: какой образ использовать для приложения, количество подов, которое необходимо, и способ которым они должны обновляться.
Преимущества использования Kubernetes развертывания.
Процесс ручного обновления контейнеризированных приложенией может занимать много времени и быть скучным. Развертывание Kubernetes делает этот процесс автоматическим и повторяемым. Развертывание полностью управляемое с помощью Kubernetes, и полный процесс производится на стороне сервера без взаимодействия клиента.
Более того, контроллер развертывания Kubernetes всегда мониторит здоровье подов и нод. Он заменяет упавшие поды или пропускает недоступные ноды, убеждаясь в непрерывности критических приложений.
Стратегии развертывания
Последовательное развертывание обновлений
Последовательное развертывание это стандартная развертываемае стратегия для Kubernetes. Он заменяет по одному поды прошлых версий на новые версии, при этом создавая ситуацию в которой не возникает времени простоя. Последовательное развертывание медленно заменяет объекты прошлых верси приложения на новые.
Используя стратегии развертывания, есть две различные возможности, которые позволяют настроить процесс обновления:
Максимальный Всплеск(maxSurge
): количество подов, которое может быть создано над желаемым количеством подов во время обновления. Это может быть абсолютное число в процентах от количества реплик. По умолчанию это 25%.
Максимальная недоступность(maxUnavailable
): количество подов которое может быть недоступно во время процесса обновления. Это может быть обсолютное количество в процентах от количества реплик, по умолчанию 25%.
Первое мы создадим шаблон нашего последовательного развертывания. В шаблон ниже, мы указали maxSurge
= 2 и maxUnavailable
= 1.
apiVersion: apps/v1
kind: Deployment
metadata:
name: rollingupdate-strategy
version: nanoserver-1709
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
selector:
matchLabels:
app: web-app-rollingupdate-strategy
version: nanoserver-1709
replicas: 3
template:
metadata:
labels:
app: web-app-rollingupdate-strategy
version: nanoserver-1709
spec:
containers:
- name: web-app-rollingupdate-strategy
image: hello-world:nanoserver-1709
Мы можем создать развертывание используя kubectl
команду.
kubectl apply -f rollingupdate.yaml
Как только мы получили шаблон развертывания, мы можем предоставить путь для доступа объекта развертывания с помощью создания сервиса. Отметим, что мы развертывая образ hello-world
с помощью
nanoserver-1709. В этом случае мы имеем два заглавия, name= web-app-rollingupdate-strategy
и version=nanoserver-1709
. Мы укажем их как названия для сервисов ниже. и сохраним файл service.yml
apiVersion: v1
kind: Service
metadata:
name: web-app-rollingupdate-strategy
labels:
name: web-app-rollingupdate-strategy
version: nanoserver-1709
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
name: web-app-rollingupdate-strategy
version: nanoserver-1709
type: LoadBalancer
Создание сервиса добавить балансировщик нагрузки который будет доступен снаружи кластера.
$ kubectl apply -f service.yaml
Чтобы проверить наличие деплойментов запускаем команду:
$ kubectl get deployments
Если деплоймент всё еще создается то будет будет следующий ответ:
NAME READY UP-TO-DATE AVAILABLE AGE
rollingupdate-strategy 0/3 0 0 1s
Если еще раз запустить команду kubectl get deployments
чуть позже. Вывод будет выглядить следующийм образом:
NAME READY UP-TO-DATE AVAILABLE AGE
rollingupdate-strategy 3/3 0 0 7s
Чтобы увидеть количество реплик созданых деплойментом, запустите:
$ kubectl get rs
Ответ будет выглядеть следующим образом:
NAME DESIRED CURRENT READY AGE
rollingupdate-strategy-87875f5897 3 3 3 18s
Чтобы увидеть 3 пода запущенных для деплоймента запустите:
$ kubectl get pods
Созданные ReplicaSet(набор реплик)проверять что запущенно 3 рабочих пода. А вывод будет следующим:
NAME READY STATUS RESTARTS AGE
rollingupdate-strategy-87875f5897-55i7o 1/1 Running 0 12s
rollingupdate-strategy-87875f5897-abszs 1/1 Running 0 12s
rollingupdate-strategy-87875f5897-qazrt 1/1 Running 0 12s
Давайте обновим rollingupdate.yaml
шаблон деплоймента чтобы использовать образ hello-world:nanoserver-1809
вместо образа hello-world:nanoserver-1709
. Затем обновим образ существующего запущенного деплоймента используя команду kubectl
.
$ kubectl set image deployment/rollingupdate-strategy web-app-rollingupdate-strategy=hello-world:nanoserver-1809 --record
Вывод будет похожим на:
deployment.apps/rollingupdate-strategy image updated
Теперь мы развертывает образ hello-world
с версией nanoserver-1809
. В данном случае мы обновили lable
в service.yaml
. label
будет обновлет на version=nanoserver-1809
. Еще раз запускаем команду ниже, для обновления сервиса который подберет новый рабочий под, с новой версией образа.
$ kubectl apply -f service.yaml
Чтобы увидеть статус выкатывания запустите команду ниже:
$ kubectl rollout status deployment/rollingupdate-strategy
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
Запустим еще раз чтобы убедиться что обновление прошло успешно:
$ kubectl rollout status deployment/rollingupdate-strategy
deployment "rollingupdate-strategy" successfully rolled out
После успешного обновления, мы можем посмотреть на деплоймент командой kubectl get deployments
:
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
rollingupdate-strategy 3/3 0 0 7s
Выполните kubectl get rs
, чтобы увидеть что Deployment обновился. Новые поды созданы в новом ReplicaSet и запущено 3 копии. Старый ReplicaSet больше не содержит рабочих копий.
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
rollingupdate-strategy-87875f5897 3 3 3 55s
rollingupdate-strategy-89999f7895 0 0 0 12s
Запустите kubectl get pods
теперь должны быть только новые поды из новой ReplicaSet.
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
rollingupdate-strategy-89999f7895-55i7o 1/1 Running 0 12s
rollingupdate-strategy-89999f7895-abszs 1/1 Running 0 12s
rollingupdate-strategy-89999f7895-qazrt 1/1 Running 0 12s
Очень полезна команда rollout
в даннмо случае. Мы можем использовать её чтобы проверить что делает наш deployment. Команда, по-умолчанию, ждет то тех пор пока deplyment не запустит успешно все поды. Когда deployment успешно отработает, команда вернет 0 код в качестве указателя на успех. Если deployment упадет, команда завершиться с ненулевым кодом.
$ kubectl rollout status deployment rollingupdate-strategy
Waiting for deployment "rollingupdate-strategy" rollout to finish: 0 of 3 updated replicas are available…
Waiting for deployment "rollingupdate-strategy" rollout to finish: 1 of 3 updated replicas are available…
Waiting for deployment "rollingupdate-strategy" rollout to finish: 2 of 3 updated replicas are available…
deployment "rollingupdate-strategy" successfully rolled out
Если деплоймент упадет в Kubernetes, процесс deployment остановится, но поды из упавшего deployment остаются. При падении deployment, наше окружение может содержать подыд из двух старых и новых deploymentов. Чтобы вернуться в стабильное, рабочее состояние, мы можем использовать rollout undo
команду, чтобы вернуть назад рабочие поды и очистить упавший деплоймент.
$ kubectl rollout undo deployment rollingupdate-strategy
deployment.extensions/rollingupdate-strategy
Затем проверяем статус deployment еще раз.
$ kubectl rollout status deployment rollingupdate-strategy
deployment "rollingupdate-strategy" successfully rolled out
Чтобы указать Kubernetes что приложение готово, нам необходима помощь от приложения. Kubernetes использует проверку готовности для того чтобы знать, что делает приложение. Как только экземпляр начинает отвечать на проверку готовности позитивно, экземпляр считается готовым для использования. Проверка готовности говорит Kubernetes когда приложение готово, но не когда приложение будет всегда готово. Если приложение продалжает падат, оно сможет никогда не ответить позитивно Kubernetes.
Rolling deployment
обычно ждет когда новые поды будут готовы через проверку готовности прежде чем опустить старые компоненты. Если возникла существенная проблема, rolling deployment
может быть отменен. Если возникает проблема, выкатывание обновлений или развертывания может быть прервано без отключения всего кластера.
Развертывание восстановления
При развертывании восстановления, мы полностью отключаем текущее приложение прежде чем выкатываем новое. На картинке ниже, версия 1 отображает текущую версию приложения, а 2 отражает версию нового приложения. Когда обновление текущей версии приложения, сначала убираем существующие рабочие копии версии 1, затем одновременно развертываем копии с новой версией.
Шаблон ниже показывает развертывание используя стратегию восстановления: Сначала, создаем наш деплоймент и помещаем его в файл recreate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: recreate-strategy
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: web-app-recreate-strategy
version: nanoserver-1809
replicas: 3
template:
metadata:
labels:
app: web-app-recreate-strategy
spec:
containers:
- name: web-app-recreate-strategy
image: hello-world:nanoserver-1809
Затем мы можем создать развертывание используя команду kubectl
$ kubectl apply -f recreate.yaml
Как только у нас будет шаблон развертывания мы можем предоставить способ для доступа в экземпляры развертывания создавая Service. Отметим, что развертывание образа hello-world
с версией nanoserver-1809
. В этом случае мы можем иметь два заголовка: name= web-app-recreate-strategy
и version=nanoserver-1809
. Мы назначим этим загловки для сервиса ниже и сохраним в service.yml.
apiVersion: v1
kind: Service
metadata:
name: web-app-recreate-strategy
labels:
name: web-app-recreate-strategy
version: nanoserver-1809
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
name: web-app-recreate-strategy
version: nanoserver-1809
type: LoadBalancer
Теперь создание этого сервиса создаст балансировщик нагрузки, который доступен вне кластера.
$ kubectl apply -f service.yaml
Метод создания требует некоторое вермя во время процесса обновления. Время простоя не проблема, если приложение может использовать окно обслуживания или сбой. Однако, если работа приложения критична и имеет высокий уровень SLA и требования доступности, использование различных стратегий развертывания будет правильным применением. Развертывание восстановлния в общем используется для целей разработки, так как легко настраивается и прилоежние полностью обновляется на новую версию. Еще, то что нам не нужно обслуживать больше чем одну версию приложения в паралели, и поэтому мы можем избежать проблем обратной совестимости для данных и приложения.
Blue-Green Развертывание
В blue/green стратегия развертывания(иногда называемая red/black), blue
- отражает текущую версию приложения, а green
- новую версию приложения. Тут, только 1 версия живет. Траффик марштутизируется в blue
развертвание пока green
развертывание создается и тестируется. После конца тестирования, направляем траффик на новую версию.
После успешного развертывания, мы можем как сохранить blue
развертывание для возможного отката или вывода из эксплуатации. Другая возножность, это развертывание новой версии приложения на этих экземплярах. В этом случае текущая blue
окружение обслуживается как подгтотовительное для следующего релиза.
Эта техника может устранить время просто которое мы встретили в развертывании восстановления. Так же, blue\green
развертывание сокращает риск: если что-то необычное случиться с нашей green
версией, мы тут же сможем откатиться на прошлую версию просто переключившись на blue
версию. Есть постоянная возможность выкатить\откатиться. Мы так же можем избежать проблем с версией, состояние приложения меняется одним развертыванием.
Blue\Green
развертывание очень дорого, так как требует двойные ресурсы. Полноценное тестирование всей платформы должно быть выполнено до релиза его в производствао. Даже больше, обслуживание незименяемого приложения сложно.
Для начала мы создадим наше blue
развертывание сохранив blue.yaml
file.
apiVersion: apps/v1
kind: Deployment
metadata:
name: blue-deployment
spec:
selector:
matchLabels:
app: blue-deployment
version: nanoserver-1709
replicas: 3
template:
metadata:
labels:
app: blue-deployment
version: nanoserver-1709
spec:
containers:
- name: blue-deployment
image: hello-world:nanoserver-1709
Мы затем создадим развертывание используя kubectl
команду
$ kubectl apply -f blue.yaml
Как только у нас есть шаблон развертывания, мы можем предоставить способ к доступу экземпляра развертывания создав сервис. Отметим, что наше развертывание образа hello-world
с версией nanoserver-1809
. В этом случае у нас есть два
Onceзагловка we have a deployment template, we can provide a way to access the instances of the deployment by creating a Service. Note that we are deploying the image hello-world with version nanoserver-1809. So in this case we have two labels, 'name= blue-
deployment'deploymentandи 'version=nanoserver-
. 1709'1709WeМы willукажем setэтим theseзагловки asв theселекторе labelсервиса selectorи forсохраним theв serviceфайл below. Save this to service.yaml
. file.
apiVersion: v1
kind: Service
metadata:
name: blue-green-service
labels:
name: blue-deployment
version: nanoserver-1709
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
name: blue-deployment
version: nanoserver-1709
type: LoadBalancer
NowТеперь creatingсоздание theсервиса, serviceсоздаст willбалансировщик createнагрузки aкоторый loadдоступен balancerвне that is accessible outside the cluster.кластера.
$ kubectl apply -f service.yaml
We
Наши haveнастроки the below setup in place.готовы.
AltДля text
green
Forразвертывания theмы greenразвернем deploymentновое weразвертывание willрядом deployс ablue
newразвертыванием. deploymentШаблон inниже parallelсодержит withкод theниже, blueсохраним deployment.как The below template is a content of the green.yaml
: file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: green-deployment
spec:
selector:
matchLabels:
app: green-deployment
version: nanoserver-1809
replicas: 3
template:
metadata:
labels:
app: green-deployment
version: nanoserver-1809
spec:
containers:
- name: green-deployment
image: hello-world:nanoserver-1809
NoteЗаметим thatчто imageобраз hello-world:nanoserver-1809 tag-nameизменен. hasЧто changedзначит, toчто 2.мы Soсделали weотдельное haveразвертывание madeс aдвумя separateзагловками, deployment with two labels, name=
green-deploymentandи version=nanoserver-
.1809.1809
$ kubectl apply -f green.yaml
To
Обрезать overgreen
toразвертывание, theмы greenобновим deployment,селектор weдля willсуществующего updateсервиса. theИзменим selector for the existing service. Edit the service.yaml
andи changeзаменим theселектор selectorверсии versionна toвторую 2и andназовем namegreen-deployment
. toЭто green-deployemnt.будет Thatсовпадат willс makeподами itgreen
so that it matches the pods on the green" deployment.развертывания.
apiVersion: v1
kind: Service
metadata:
name: blue-green-service
labels:
name: green-deployment
version: nanoserver-1809
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
name: green-deployment
version: nanoserver-1809
type: LoadBalancer
WeМы createсоздадим theсервис serviceеще againраз usingиспользуя theкоманду kubectl
: command:
$ kubectl apply -f service.yaml
Alt
Завершая, можно оценить что blue\green
развертывание есть всё или ничего. В отличии от развертывания выкатывания обновления, где мы не можем постеменно выктить нашу новую версию. Все пользователи получать обновления в одно и то же время, так же существующим версиям будет позволенно завершить их работу в старом экземпляре. Оно так же требует использования больше серверных ресурсов так как нам нужно запустить две копии каждого пода.
HenceК concluding,счастью weпроцедура canотката seeпроста: theНам blue-greenпросто deploymentнужно isперевести all-or-nothing,выключатель unlikeобратно, aи rollingпредыдущая updateверсия deployment,будет whereвозвращена. weЭто aren'tпотому, ableчто toстарая graduallyверсия rollвсе outеще theкрутиться newна version.старых Allподах. usersПросто willтрафик receiveне theпереводится updateна atних. theКогда sameмы time,убеждаемся althoughчто existingновая sessionsверсия willполноценно beработает, allowedмы toдолжны finishудалить theirстарые work on the old instances. Hence the stakes are a bit higher than everything should work once we initiate the change. It also requires allocating more server resources since we will need to run two copies of every pod.поды.
Fortunately,
Canary the rollback procedure is just as easy: We simply have to flip the switch again, and the previous version is swapped back into place. That's because the old version is still running on the old pods. It is simply that traffic is no longer being routed to them. When we are confident that the new version is here to stay, we should decommission those pods.развертывание
Canary Deployment
The canary update strategy is a partial update process that allows us to test our new program version on a real user base without a commitment to a full rollout. Similar to blue/green deployments, but they are more controlled, and they use a more progressive delivery where deployment is in a phased approach. There are a number of strategies that fall under the umbrella of canary, including dark launches or A/B testing.
In canary deployment, the new version of the application is gradually deployed to the Kubernetes cluster while getting a very small amount of live traffic (i.e., a subset of live users are connecting to the new version while the rest are still using the previous version).In this approach, we have two almost identical servers: one that goes to all the current active users and another with the new features that gets rolled out to a subset of users and then compared. When no errors are reported and the confidence increases, the new version can gradually roll out to the rest of the infrastructure. In the end, all live traffic goes to canaries, making the canary version the new production version.
The below picture shows the most straightforward and simple way to do a canary deployment. A new version is deployed to a subset of servers.
Alt text
While this happens, we watch how the upgraded machines are doing. We check for errors and performance problems, and we listen for user feedback. As we grow confident in the canary, we continue installing it on the rest of the machines until they are all running the latest release.
Alt text
We have to take into account various things when planning a canary deployment:
Stages: how many users will we send to the canary at first, and in how many stages. Duration: how long will we plan to run the canary? Canary releases are different, as we must wait for enough clients to be updated before we can assess the results. This can happen over several days or even weeks. Metrics: what are the metrics to record to analyze progress, including application performance and error reports? Well-chosen parameters are essential for a successful canary deployment. For instance, a very simple way to measure deployment is through HTTP status codes. We can have a simple ping service that returns 200 when the deployment is successful. It will return server end error (5xx) if there is an issue in the deployment. Evaluation: what criteria will we use to determine if the canary is successful A canary is used in scenarios where we have to test a new functionality typically on the backend of our application. Canary deployment should be used when we are not 100% confident in the new version; we predict we might have a low chance of failure. This strategy is usually used when we have a major update, like adding a new functionality or experimental feature.
Summary K8s Deployments Strategies To sum up, there are different ways to deploy an application; when releasing to development/staging environments, a recreate or ramped deployment is usually a good choice. When it comes to production, a ramped or blue/green deployment is usually a good fit, but proper testing of the new platform is necessary. If we are not confident with the stability of the platform and what could be the impact of releasing a new software version, then a canary release should be the way to go. By doing so, we let the consumer test the application and its integration into the platform. In this article, we have only scratched the surface of the capabilities of Kubernetes deployments. By combining deployments with all the other Kubernetes features, users can create more robust containerized applications to suit any need.