55. State и Ingress в Kubernetes

Обновлено: 2024-03-12
9 мин

State и Ingress в Kubernetes

В этом заключительном разделе, посвященном Kubernetes, мы рассмотрим State и ingress.

Все, о чем мы говорили до сих пор, касается stateless, stateless - это когда нашим приложениям не важно, какую сеть они используют, и им не нужно постоянное хранение данных. В то время как приложения с состоянием, например, базы данных, чтобы такое приложение функционировало правильно, вам нужно убедиться, что стручки могут обращаться друг к другу через уникальную идентификацию, которая не меняется (имена хостов, IP… и т.д.). Примерами stateful-приложений являются кластеры MySQL, Redis, Kafka, MongoDB и другие. В принципе, любое приложение, которое хранит данные.

Stateful Application

StatefulSets представляют собой набор Pods с уникальными, постоянными идентификаторами и стабильными именами хостов, которые Kubernetes поддерживает независимо от того, где они запланированы. Информация о состоянии и другие устойчивые данные для любого данного StatefulSet Pod хранятся в постоянном дисковом хранилище, связанном с StatefulSet.

Развертывание против StatefulSet

  • Репликация stateful-приложений является более сложной задачей.
  • Репликация наших стручков в развертывании (Stateless Application) идентична и взаимозаменяема.
  • Создаем капсулы в случайном порядке со случайными хэшами
  • Один сервис, который балансирует нагрузку на любой стручок.

Когда дело доходит до StatefulSets или Stateful Applications, вышеописанное становится сложнее.

  • Невозможно одновременно создавать и удалять.
  • Не может быть случайного обращения.
  • реплики Pods не являются идентичными.

То, что вы увидите в нашей демонстрации в ближайшее время, заключается в том, что каждая копия имеет свою собственную идентичность. В приложении без статического состояния вы увидите случайные имена. Например, app-7469bbb6d7-9mhxd, в то время как Stateful Application будет иметь имя mongo-0, а затем при масштабировании создаст новую капсулу под названием mongo-1.

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

Каждый стручок в StatefulSet будет иметь доступ к своему собственному постоянному тому и копии базы данных для чтения, которая постоянно обновляется с главного сервера. Также интересно отметить, что каждый pod будет хранить свое состояние pod в этом постоянном томе, если mongo-0 умрет, то при инициализации нового pod он возьмет состояние pod, хранящееся в хранилище.

TLDR; StatefulSets vs Deployments

  • Predicatable pod name = mongo-0
  • Fixed individual DNS name
  • Pod Identity - Retain State, Retain Role
  • Replicating stateful apps is complex
    • There are lots of things you must do:
      • Configure cloning and data synchronisation.
      • Make remote shared storage available.
      • Management & backup

Как сохранять данные в Kubernetes?

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

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

Постоянный том

  • Ресурс кластера (например, процессор и оперативная память) для хранения данных.
  • Создается с помощью файла YAML.
  • Требуется реальное физическое хранилище (NAS)
  • Внешняя интеграция в ваш кластер Kubernetes.
  • В вашем хранилище могут быть доступны различные типы хранилищ.
  • PV не имеют пространства имен
  • Локальное хранилище доступно, но оно будет специфично для одного узла в кластере
  • Персистентность базы данных должна использовать удаленное хранилище (NAS)

Утверждение о постоянном томе

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

  • Создается с помощью файла YAML
  • Утверждение постоянного тома используется в конфигурации стручка (атрибут volumes)
  • PVC находятся в том же пространстве имен, что и pod
  • Том монтируется в капсулу
  • Стручки могут иметь несколько различных типов томов (ConfigMap, Secret, PVC).

Другой способ представить PVs и PVCs заключается в следующем

PVs создаются администратором Kubernetes Admin PVC создаются пользователем или разработчиком приложения.

У нас также есть два других типа томов, которые мы не будем подробно описывать, но о которых стоит упомянуть:

ConfigMaps | Secrets

  • Конфигурационный файл для вашего стручка.
  • Файл сертификата для вашей капсулы.

StorageClass

  • Создается с помощью файла YAML
  • Предоставляет постоянные тома динамически, когда PVC заявляет об этом.
  • Каждый бэкенд хранилища имеет свой собственный провизор
  • Бэкенд хранилища определяется в YAML (через атрибут provisioner)
  • Абстракции базового провайдера хранения
  • Определяет параметры для этого хранилища

Время просмотра

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

Напомним команду minikube, которую мы используем, чтобы иметь возможность и аддоны для использования персистентности: minikube start --addons volumesnapshots,csi-hostpath-driver --apiserver-port=6443 --container-runtime=containerd -p mc-demo --kubernetes-version=1.21.2.

Эта команда использует драйвер csi-hostpath-driver, который дает нам наш класс хранилища, что я покажу позже.

Сборка приложения выглядит следующим образом:

Вы можете найти файл конфигурации YAML для этого приложения здесь pacman-stateful-demo.yaml

Конфигурация класса хранилища

Есть еще один шаг, который мы должны выполнить перед началом развертывания нашего приложения, а именно убедиться, что наш класс хранилища (csi-hostpath-sc) является классом по умолчанию. Сначала мы можем проверить это, выполнив команду kubectl get storageclass, но из коробки кластер minikube будет показывать стандартный класс хранения по умолчанию, поэтому мы должны изменить его с помощью следующих команд.

Первая команда сделает наш класс хранилища csi-hostpath-sc классом по умолчанию.

kubectl patch storageclass csi-hostpath-sc -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class": "true"}}}'}''

Эта команда удалит аннотацию по умолчанию из стандартного StorageClass.

kubectl patch storageclass standard -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class": "false"}}}'}''

Начнем с того, что в нашем кластере нет пространства имен pacman. kubectl get namespace

Затем мы развернем наш YAML-файл. kubectl create -f pacman-stateful-demo.yaml Из этой команды видно, что мы создаем ряд объектов в нашем кластере Kubernetes.

Теперь у нас есть наше только что созданное пространство имен.

Из следующего изображения и команды kubectl get all -n pacman видно, что в нашем пространстве имен происходит несколько вещей. У нас есть pods, запускающий наш NodeJS web front end, у нас есть mongo, запускающий нашу backend базу данных. Есть сервисы для pacman и mongo для доступа к этим стручкам. У нас есть развертывание для pacman и statefulset для mongo.

У нас также есть наши постоянные тома и утверждения постоянных томов. Выполнив команду kubectl get pv, мы получим наши постоянные тома, не связанные с именами, а выполнив команду kubectl get pvc -n pacman, мы получим наши утверждения постоянных томов, связанные с именами.

Играем в игру | Я имею в виду доступ к нашему критически важному приложению

Поскольку мы используем Minikube, как уже упоминалось в приложении без статических данных, нам предстоит преодолеть несколько препятствий, когда дело доходит до доступа к нашему приложению. Однако если бы у нас был доступ к ingress или балансировщику нагрузки в нашем кластере, служба настроена на автоматическое получение IP-адреса от него для получения доступа извне. (Вы можете видеть это выше на изображении всех компонентов в пространстве имен pacman).

В данном демонстрационном примере мы будем использовать метод проброса портов для доступа к нашему приложению. Открыв новый терминал и выполнив следующую команду kubectl port-forward svc/pacman 9090:80 -n pacman, открыв браузер, мы получим доступ к нашему приложению. Если вы запускаете это в AWS или в определенных местах, то это также сообщит об облаке и зоне, а также о хосте, который равен вашему стручку в Kubernetes, опять же, вы можете оглянуться назад и увидеть это имя стручка на наших скриншотах выше.

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

Хорошо, у нас есть высокий балл, но что произойдет, если мы удалим наш mongo-0 pod? Выполнив команду kubectl delete pod mongo-0 -n pacman, я могу удалить его, и если вы все еще находитесь в приложении, вы увидите, что высокий балл недоступен, по крайней мере, в течение нескольких секунд.

Теперь, если я вернусь в свою игру, я смогу создать новую игру и увидеть свои высокие баллы. Единственный способ поверить мне в это - попробовать и поделиться в социальных сетях своими высокими результатами!

С развертыванием мы можем увеличить масштаб с помощью команд, которые мы рассматривали в предыдущей сессии, но в частности здесь, особенно если вы хотите устроить огромную вечеринку pacman, вы можете увеличить масштаб с помощью kubectl scale deployment pacman --replicas=10 -n pacman.

Ingress объяснено

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

Что такое ingress?

До сих пор в наших примерах мы использовали port-forward или определенные команды в minikube, чтобы получить доступ к нашим приложениям, но в производстве это не сработает. Нам нужен лучший способ доступа к нашим приложениям в масштабе с множеством пользователей.

Мы также говорили о возможности использования NodePort, но это опять же должно быть только в тестовых целях.

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

Для ingress мы создадим запрос на внутреннюю службу нашего приложения.

Когда вам нужен ingress?

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

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

Настройка Ingress на Minikube

На моем конкретном запущенном кластере под названием mc-demo я могу выполнить следующую команду, чтобы включить ingress на моем кластере.

minikube --profile='mc-demo' addons enable ingress.

Если теперь мы проверим наши пространства имен, то увидим, что у нас есть новое пространство имен ingress-nginx. kubectl get ns

Теперь мы должны создать YAML-конфигурацию ingress для запуска нашего сервиса Pacman. Я добавил этот файл в репозиторий pacman-ingress.yaml.

Затем мы можем создать его в нашем пространстве имен ingress с помощью kubectl create -f pacman-ingress.yaml.

Затем, если мы запустим kubectl get ingress -n pacman

Затем мне говорят, что поскольку мы используем minikube, работающий на WSL2 в Windows, мы должны создать туннель minikube, используя minikube tunnel --profile=mc-demo.

Но я все еще не могу получить доступ к 192.168.49.2 и играть в свою игру pacman.

Если у кого-нибудь есть или есть возможность заставить это работать под Windows и WSL, я буду благодарен за отзывы. Я подниму вопрос об этом в репозитории и вернусь к нему, как только у меня появится время и исправление.

UPDATE: Мне кажется, что этот блог помогает определить причину того, что игра не работает на WSL Configuring Ingress to run Minikube on WSL2 using Docker runtime

Ресурсы

На этом мы завершаем раздел Kubernetes. Существует так много дополнительных материалов, которые мы могли бы осветить на тему Kubernetes, и 7 дней дают нам базовые знания, но есть люди, которые проходят 100DaysOfKubernetes, где вы можете погрузиться в самую гущу событий.

Далее мы рассмотрим инфраструктуру как код и ту важную роль, которую она играет с точки зрения DevOps.