Стратегии развертывания в 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 DeploymentРазвертывание
In aВ blue/green deploymentстратегия strategyразвертывания(иногда (sometimes also referred to asназываемая red/black), theblue
- отражает текущую версию приложения, а green
- новую версию приложения. Тут, только 1 версия живет. Траффик марштутизируется в blue
representsразвертвание theпока currentgreen
applicationразвертывание version,создается andи greenтестируется. representsПосле theконца newтестирования, applicationнаправляем version.траффик Inна this,новую only one version is live at a time. Traffic is routed to the blue deployment while the green deployment is created and tested. After we are finished testing, we then route traffic to the new version.версию.
AfterПосле theуспешного deploymentразвертывания, succeeds,мы weможем canкак eitherсохранить keepblue
theразвертывание для возможного отката или вывода из эксплуатации. Другая возножность, это развертывание новой версии приложения на этих экземплярах. В этом случае текущая blue
deploymentокружение forобслуживается aкак possibleподгтотовительное rollbackдля orследующего decommission it. Alternatively, it is possible to deploy a newer version of the application on these instances. In that case, the current (blue) environment serves as the staging area for the next release.релиза.
ThisЭта techniqueтехника canможет eliminateустранить downtimeвремя asпросто weкоторое facedмы inвстретили theв recreateразвертывании deploymentвосстановления. strategy.Так Inже, addition,blue\green
blue-развертывание сокращает риск: если что-то необычное случиться с нашей green
deploymentверсией, reducesмы risk:тут ifже somethingсможем unexpectedоткатиться happensна withпрошлую ourверсию newпросто versionпереключившись onна Green,blue
weверсию. canЕсть immediatelyпостоянная rollвозможность backвыкатить\откатиться. toМы theтак lastже versionможем byизбежать switchingпроблем backс toверсией, Blue.состояние Thereприложения isменяется instantодним rollout/rollback. We can also avoid versioning issues; the entire application state is changed in one deployment.развертыванием.
AltBlue\Green
textразвертывание очень дорого, так как требует двойные ресурсы. Полноценное тестирование всей платформы должно быть выполнено до релиза его в производствао. Даже больше, обслуживание незименяемого приложения сложно.
TheДля Blue-Greenначала deploymentмы isсоздадим expensiveнаше asblue
itразвертывание requiresсохранив doubleblue.yaml
the resources. A proper test of the entire platform should be done before releasing it to production. Moreover, handling stateful applications is hard.
First, we create our blue deployment by saving the following yaml to a 'blue.yaml' file: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
We can then create the deployment using the kubectl command.
$ kubectl apply -f blue.yaml 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' and 'version=nanoserver-1709'. We 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 now have the below setup in place.
Alt text
For the green deployment we will deploy a 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-deployment and version=nanoserver-1809.
$ kubectl apply -f green.yaml To cut over 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 name to green-deployemnt. That will make it 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 text
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, 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.