С ростом использования контейнерных приложений и микросервисов сейчас самое подходящее время, чтобы стать экспертом по Kubernetes.

Kubernetes — это система оркестрации контейнеров с открытым исходным кодом, предназначенная для автоматизации масштабирования приложений и управления ими. Несмотря на то, что Kubernetes невероятно мощен, его сложно освоить.

Сегодня мы сделаем вас на один шаг ближе к опыту работы с Kubernetes, познакомив вас с объектом развертывания, инструментом Kubernetes для управления набором реплик и оперативными обновлениями системы.

Вот что мы сегодня рассмотрим:

  • Что такое развертывание в Kubernetes?
  • Стратегии обновления развертывания
  • Стратегия непрерывного обновления
  • Воссоздать стратегию обновления
  • Канарская стратегия обновления
  • Что изучать дальше

Что такое развертывание в Kubernetes?

Развертывание — это объект ресурса в Kubernetes, который определяет желаемое состояние для вашей программы.

Развертывания являются декларативными, что означает, что вы не диктуете, как достичь состояния. Вместо этого вы объявляете свою конечную точку (называемую «желаемым состоянием») и позволяете контроллеру развертывания автоматически достигать этой конечной цели наиболее эффективным способом.

После запуска развертывание сравнивает текущее состояние программы с желаемым состоянием. Если они не совпадают, контроллер развертывания автоматически изменяет состояние для соответствия.

Это автоматическое поддержание состояния — то, что дает Kubernetes его любимые свойства самовосстановления.

Желаемые состояния могут включать в себя количество запущенных модулей, тип этих модулей, образы контейнеров, доступные для программы, и желаемую рабочую нагрузку для каждого модуля.

Если какой-либо аспект желаемого состояния отсутствует, Контроллер развертывания будет изменять программу до тех пор, пока они не будут выполнены.

наборы реплик

Основной способ, с помощью которого развертывания поддерживают желаемое состояние программы, заключается в использовании ReplicaSets.

ReplicaSet — это набор идентичных модулей резервного копирования, которые поддерживаются на стороне серверной части, чтобы обеспечить постоянную доступность модуля. Если работающий с пользователем модуль Pod дает сбой или становится перегруженным, развертывание выделяет работу Pod из ReplicaSet для поддержания скорости реагирования.

Если под из ReplicaSet выходит из строя, он автоматически создает дополнительный под из шаблона.

Поды в наборе реплик разрабатываются с использованием одного шаблона пода, предоставленного развертыванием, которое определяет спецификации, общие для кластера пода. Спецификации шаблона — это такие свойства, как:

  • Какие приложения должны работать в модулях?
  • Какие этикетки должны быть у стручков?
  • При каких условиях Pod перезапустится?

Лучше всего не управлять наборами реплик напрямую. Вы должны выполнить все действия с объектом Deployment и оставить Deployment для управления наборами реплик.

Каждое развертывание может управлять только одним шаблоном модуля, но может управлять несколькими модулями реплик из одного и того же шаблона.

Вам потребуется создать несколько развертываний, чтобы поддерживать несколько разных наборов реплик.

Обновление с помощью развертываний

Основное преимущество развертываний заключается в автоматическом обновлении вашей программы Kubernetes.

Без развертываний вам пришлось бы вручную завершать все старые поды, запускать новые версии подов и запускать проверку на наличие проблем во время создания подов.

Развертывания автоматизируют весь процесс обновления, поскольку вы можете просто обновить шаблон пода или желаемое состояние. Развертывание изменит состояние программы в фоновом режиме с помощью таких действий, как создание новых модулей, выделение дополнительных ресурсов и т. д., пока не будет достигнуто обновленное желаемое состояние.

Вы даже можете откатить обновления до предыдущей версии. Старые наборы реплик все еще существуют с полными конфигурациями подов, но после создания нового набора реплик они просто не управляют никакими подами.

Если вы хотите вернуться к предыдущей версии, вам просто нужно изменить желаемое состояние в пользу старого набора реплик, и развертывание автоматически вернется.

Обновление стратегий развертывания

Kubernetes предлагает стратегии развертывания, которые позволяют выполнять обновления различными способами в зависимости от потребностей системы. Наиболее распространены три:

  • Стратегия непрерывного обновления: сводит к минимуму время простоя за счет скорости обновления.
  • Стратегия отдыха: вызывает простои, но быстро обновляется.
  • Стратегия Канарейки: быстрое обновление для нескольких избранных пользователей с последующим полным развертыванием.

Давайте подробнее рассмотрим каждую из этих трех стратегий!

Стратегия непрерывного обновления

Стратегия непрерывного обновления — это постепенный процесс, который позволяет вам обновлять систему Kubernetes с незначительным влиянием на производительность и без простоев.

В этой стратегии развертывание выбирает модуль со старым программным обеспечением, деактивирует его и создает обновленный модуль для его замены. Развертывание повторяет этот процесс до тех пор, пока не останется устаревших модулей.

Преимущество стратегии последовательного обновления заключается в том, что обновление применяется по модулям, поэтому большая система может оставаться активной.

Во время этого процесса обновления происходит незначительное снижение производительности, поскольку в системе постоянно на один активный модуль не хватает желаемого количества модулей. Это часто предпочтительнее полной деактивации системы.

Стратегия непрерывного обновления используется в качестве стратегии обновления по умолчанию, но подходит не для всех ситуаций. При принятии решения об использовании стратегии последовательного обновления необходимо учитывать следующие факторы:

  • Как моя система отреагирует на моментальное дублирование модулей?
  • Является ли обновление достаточно существенным для того, чтобы работать со старыми спецификациями некоторых модулей?
  • Повлияет ли незначительное снижение производительности на удобство использования моей системы? Насколько чувствительна ко времени моя система?

Например, представьте, что мы хотим изменить спецификации для наших модулей. Сначала мы изменим шаблон пода на новые спецификации, которые передаются из развертывания в набор реплик.

Затем развертывание распознает, что текущее состояние программы (модули со старыми спецификациями) отличается от желаемого состояния (модули с новыми спецификациями).

Развертывание создаст модули Pod и ReplicaSet с обновленными спецификациями и перенесет рабочую нагрузку один за другим из старых модулей в новые.

К концу у нас будет совершенно новый набор Pod и ReplicaSet без простоя службы.

Реализация непрерывного обновления

Мы будем использовать объявление файла YAML с именем deploy.yaml для создания нашего развертывания.

apiVersion: apps/v1  #Older versions of k8s use apps/v1beta1
kind: Deployment
metadata:
  name: hello-deploy
spec:
  replicas: 10
  selector:
    matchLabels:
      app: hello-world
  minReadySeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: hello-Pod
        image: educative/k8sbook:latest
        ports:
        - containerPort: 8080

В самом верху вы указываете используемую версию API Kubernetes. Предполагая, что вы используете актуальную версию Kubernetes, объекты развертывания находятся в группе apps/v1 API.

Затем поле .kind сообщает Kubernetes, что вы определяете объект Deployment.

В разделе .metadata мы даем развертыванию имя и метки.

В разделе .spec происходит большая часть действий. Все, что находится непосредственно под .spec, относится к поду. Все, что вложено ниже .spec.template, относится к шаблону пода, которым будет управлять развертывание. В этом примере шаблон Pod определяет один контейнер.

  • .spec.replicas сообщает Kubernetes, сколько реплик Pod нужно развернуть.
  • spec.selector — это список меток, которые должны быть у модулей, чтобы развертывание могло ими управлять.
  • .spec.strategy сообщает Kubernetes, как выполнять обновления модулей, управляемых развертыванием, в данном случае RollingUpdate.

Наконец, мы применим это развертывание к нашему кластеру Kubernetes с помощью команды:

$ kubectl apply -f deploy.yml

Воссоздать стратегию обновления

Стратегия повторного обновления — это процесс «все или ничего», который позволяет обновлять все аспекты системы одновременно с коротким периодом простоя.

В этой стратегии развертывание выбирает все устаревшие модули и сразу деактивирует их.

Как только все старые модули будут деактивированы, развертывание создаст обновленные модули для всей системы. Система неработоспособна, начиная с деактивации старого модуля и заканчивая созданием окончательного обновленного модуля.

Стратегия воссоздания используется для систем, которые не могут работать в частично обновленном состоянии, или если вы предпочитаете простои, чем предоставлять пользователям меньший опыт. Чем больше обновление, тем больше вероятность того, что последовательное обновление вызовет ошибку.

Поэтому повторная стратегия лучше подходит для крупных обновлений и капитальных изменений.

Когда вы обдумываете стратегию воссоздания, спросите себя:

  • Будут ли мои пользователи лучше работать с простоем или временным снижением производительности?
  • Может ли моя система работать во время непрерывного обновления?
  • Есть ли время, когда я могу обновить систему, не затрагивая значительное количество пользователей?

Воссоздать реализацию обновления

Эта реализация очень похожа на стратегию непрерывного обновления.

apiVersion: apps/v1  #Older versions of k8s use apps/v1beta1
kind: Deployment
metadata:
  name: hello-deploy
spec:
  replicas: 10
  selector:
    matchLabels:
      app: hello-world
  minReadySeconds: 10
  strategy:
    type: Recreate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: hello-Pod
        image: educative/k8sbook:latest
        ports:
        - containerPort: 8080

Как видите, единственная разница между реализацией последовательного обновления и воссоздания заключается в строке 12, где мы заменили strategy.type: RollingUpdate на strategy.type: Recreate.

Как и в прошлый раз, мы развернем Deployment через командную строку, используя:

$ kubectl apply -f deploy.yml

Канарская стратегия обновления

Стратегия канареечного обновления — это процесс частичного обновления, который позволяет протестировать новую версию программы на реальной пользовательской базе, не прибегая к полному развертыванию.

В этой стратегии развертывание создает несколько новых модулей, сохраняя при этом большинство модулей в предыдущей версии, обычно в соотношении 1:4.

Большинство пользователей по-прежнему используют предыдущую версию, но небольшая часть неосознанно использует новую версию в качестве тестировщиков.

Если мы не обнаружим никаких ошибок в этом подмножестве, мы можем масштабировать обновленный ReplicaSet, чтобы произвести полное развертывание.

Если мы обнаружим ошибку, мы можем легко откатить несколько обновленных модулей, пока не исправим ошибку.

Преимущество канареечной стратегии обновления в том, что она позволяет протестировать новую версию без риска полного сбоя системы.

В худшем случае все пользователи из тестового подмножества сталкиваются с критическими ошибками, в то время как 75% или более пользователей продолжают работать без перерыва.

Процесс отката также намного быстрее, чем стратегия последовательного обновления, потому что вам нужно откатить только часть модулей, а не всю систему.

Недостатком является то, что обновленные модули потребуют отдельного развертывания, которым может быть сложно управлять в масштабе. Кроме того, канареечная стратегия приводит к более медленному развертыванию из-за периода ожидания после развертывания нашего начального подмножества и завершения полного развертывания.

При рассмотрении канареечной стратегии спросите себя:

  • Каков наихудший сценарий, если это обновление не удастся?
  • Как скоро мне нужно завершить полное развертывание?
  • Сколько внутренних тестов я провел?

Реализация канареечного обновления

Для этой реализации нам нужно создать два развертывания в двух файлах YAML.

Развертывание версии 1

Наш первый файл, k8s-deployment.yaml, будет нашей устаревшей версией, которую будет запускать большинство наших модулей.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld
spec:
  replicas: 3
  strategy:
    rollingUpdate:
    maxSurge: 1
    maxUnavailable: 1
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: helloworld
        track: stable
    spec:
      containers:
      - name: helloworld
        image: educative/helloworld:1.0
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 50m
          limits:
            cpu: 100m

Это создаст 3 модуля v1 с меткой app:helloworld, которые ищет наш сервис Kubernetes. Наш образ для этих подов — educative/helloworld:1.0, что означает, что эти поды будут созданы на основе старых спецификаций подов.

Это развертывание равномерно распределит любую рабочую нагрузку между доступными модулями.

Вы развернете это, введя эту строку в командную строку:

kubectl apply -f k8s-deployment.yaml

Примечание. В отличие от предыдущих реализаций, canary не указан в списке strategy, так как его реализация сложнее.

Вместо этого обе версии отмечены как rollingUpdates, потому что обновления в каждой версии будут развертываться, пока общая стратегия системы канареечна.

Развертывание версии 2

Теперь мы создадим наш второй файл yaml, k8s-deployment-canary.yaml, который является нашей новой версией canary v2.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-canary
spec:
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: helloworld
        track: canary
    spec:
      containers:
      - name: helloworld
        image: educative/helloworld:2.0
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 50m
          limits:
            cpu: 100m

Для этого развертывания мы создаем только один модуль (строка 6), чтобы большая часть нашей пользовательской базы по-прежнему взаимодействовала с v1.

Оба развертывания будут балансировать рабочую нагрузку между всеми модулями, что гарантирует, что только 25% нашей рабочей нагрузки будет приходиться на обновленный модуль.

Вы можете развернуть это развертывание через командную строку, используя:

kubectl apply -f k8s-deployment-canary.yaml

Как только вы убедитесь, что v2 работает, просто замените образ в нашем первом YAML-файле развертывания, k8s-deployment.yaml, на educative/helloworld:2.0, а не educative/helloworld:1.0.

Затем удалите канареечное развертывание с помощью:

kubectl delete -f k8s-deployment-canary.yaml

Наше желаемое состояние будет состоять в том, чтобы иметь все модули с v2, а рабочая нагрузка будет сбалансирована между оставшимися 3 модулями v2.

Канарское обновление достигнуто!

Что изучать дальше

На этом мы закончили подробное описание развертывания, но есть множество других основных тем Kubernetes, о которых вам следует узнать.

Продолжайте свое путешествие в Kubernetes, изучая дополнительные темы, такие как:

  • Моделирование угроз
  • StatefulSets
  • Кубернетес Безопасность
  • Динамическое обеспечение

Чтобы помочь вам с этими и другими темами Kubernetes, Educative создал курс Изучение Kubernetes: глубокое погружение. Этот курс начинается с объяснений и примеров всех основных компонентов Kubernete и постепенно переходит к расширенным концепциям с AWS, Azure и GKE. К концу у вас будут готовые к собеседованию знания обо всем, что может предложить Kubernetes.

Удачного обучения!

Продолжить чтение о Kubernetes на Educative

Начать обсуждение

Какую стратегию вы предпочитаете использовать и почему? Была ли эта статья полезна? Дайте нам знать в комментариях ниже!