Если вы видите что-то необычное, просто сообщите мне. Skip to main content

Стратегии развертывания в 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.