1. Обзор
Kubernetes (K8s) — это система оркестрации контейнеров с открытым исходным кодом. Это позволяет нам автоматизировать развертывание, масштабирование и управление контейнерными приложениями.
В этом руководстве мы обсудим два разных способа развертывания нашего приложения (модулей) в Kubernetes с использованием разных ресурсов Kubernetes. Ниже приведены два разных ресурса, которые Kubernetes предоставляет для развертывания модулей:
Давайте начнем с рассмотрения разницы между приложением с сохранением состояния и приложением без сохранения состояния.
2. Приложения с сохранением состояния и без сохранения состояния
Ключевое различие между приложениями с сохранением состояния и приложениями без сохранения состояния заключается в том, что приложения без сохранения состояния не «хранят» данные. С другой стороны, для приложений с отслеживанием состояния требуется резервное хранилище . Например, такие приложения, как базы данных Cassandra, MongoDB и MySQL, требуют определенного типа постоянного хранилища, чтобы выдерживать перезапуски службы.
Сохранение состояния имеет решающее значение для запуска приложения с отслеживанием состояния. Но для службы без сохранения состояния любой поток данных обычно является временным. Кроме того, состояние хранится только в отдельной серверной службе, такой как база данных. Любое связанное хранилище обычно является эфемерным. Например, если контейнер перезапускается, все сохраненное теряется. По мере того как организации внедряют контейнеры, они, как правило, начинают с контейнеров без сохранения состояния, поскольку их легче внедрить.
Kubernetes хорошо известен тем, что управляет сервисами без сохранения состояния. Рабочая нагрузка развертывания больше подходит для работы с приложениями без сохранения состояния. Что касается развертывания, модули взаимозаменяемы. В то время как StatefulSet
сохраняет уникальный идентификатор для каждого модуля, которым он управляет. Он использует один и тот же идентификатор всякий раз, когда ему нужно перепланировать эти модули. В этой статье мы обсудим это подробнее.
3. Развертывание
3.1. Понимание развертывания
: основы
Развертывание Kubernetes предоставляет средства для управления набором модулей. Это может быть один или несколько запущенных контейнеров или группа дублирующих модулей, известная как ReplicaSets
. Развертывание
позволяет нам легко поддерживать группу идентичных модулей с общей конфигурацией.
Сначала мы определяем наше развертывание
Kubernetes, а затем развертываем его. Затем Kubernetes будет работать над тем, чтобы все модули, управляемые развертыванием, соответствовали всем установленным нами требованиям. Развертывание
— это супервизор для подов. Это дает нам детальный контроль над тем, как и когда развертывается новая версия модуля. Он также обеспечивает контроль, когда нам нужно откатиться к предыдущей версии.
В Kubernetes Deployment
с репликой 1 контроллер проверит, равно ли текущее состояние желаемому состоянию ReplicaSet,
т. е. 1. Если текущее состояние равно 0, он создаст ReplicaSet.
ReplicaSet дополнительно создаст модули. Когда мы создаем развертывание
Kubernetes с именем web-app
, оно создаст ReplicaSet
с именем web-app-<replica-set-id>.
Эта реплика далее создаст модуль с именем web-app-<replica-set->-<pod-id>
.
Kubernetes Deployment
обычно используется для приложений без сохранения состояния. Однако мы можем сохранить состояние развертывания
, подключив к нему постоянный том и сделав его состоянием. Развернутые модули будут использовать один и тот же том, и данные будут одинаковыми для всех них.
3.2. Компоненты развертывания
в Kubernetes
Ниже приведены основные компоненты развертывания
Kubernetes :
- `
Шаблон
развертывания` - постоянный объем
- обслуживание
Во-первых, давайте создадим наш шаблон развертывания и сохраним его как « deployment.yaml»
. В приведенном ниже шаблоне мы также подключаем постоянный том:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-deployment
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
selector:
matchLabels:
app: web-app
replicas: 3
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: hello-world:nanoserver-1809
volumeMounts:
- name: counter
mountPath: /app/
volumes:
- name: counter
persistentVolumeClaim:
claimName: counter
В приведенном ниже шаблоне у нас есть PersistentVolumeClaim
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: counter
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Mi
storageClassName: default
3.3. Выполнение развертывания
в Kubernetes
Прежде чем мы выполним наше развертывание
, нам нужна служба для доступа к вышеуказанному развертыванию
. Давайте создадим сервис типа NodePort
и сохраним его как service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
ports:
- name: http
port: 80
nodePort: 30080
selector:
name: web-app
type: NodePort
Сначала мы запускаем шаблон службы с помощью следующей команды kubectl apply
:
kubectl apply -f service.yaml
Затем мы запускаем ту же команду для шаблона развертывания:
kubectl apply -f deployment.yaml
Кроме того, чтобы получить подробное описание развертывания, запустим команду kubectl описать
:
kubectl describe deployment web-app-deployment
Вывод будет примерно таким:
Name: web-app-deployment
Namespace: default
CreationTimestamp: Tue, 30 Aug 2016 18:11:37 -0700
Labels: app=web-app
Annotations: deployment.kubernetes.io/revision=1
Selector: app=web-app
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 2 max surge
Pod Template:
Labels: app=web-app
Containers:
web-app:
Image: spring-boot-docker-project:1
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: web-app-deployment-1771418926 (3/3 replicas created)
No events.
В приведенном выше разделе мы наблюдаем, что Deployment
внутри создает ReplicaSet
. Затем внутри этого ReplicaSet
создаются поды
. В будущем, когда мы обновим текущее развертывание, оно создаст новый ReplicaSet
. Затем он будет постепенно перемещать модули
из старого набора реплик
в новый с контролируемой скоростью.
Если при обновлении произойдет ошибка, новый ReplicaSet
никогда не будет находиться в состоянии Ready. Старый ReplicaSet
больше не прекратит работу, что гарантирует 100% безотказную работу в случае неудачного обновления. В Kubernetes Deployment
мы также можем вручную выполнить откат к предыдущему набору реплик
, если наша новая функция не работает должным образом.
4. Наборы
состояний
4.1. Понимание StatefulSet
s: основы
В Kubernetes Deployment
мы относимся к нашим модулям как к крупному рогатому скоту, а не как к домашним животным. Если один из членов крупного рогатого скота заболеет или умрет, мы можем легко заменить его, купив новую голову. Такое действие незаметно. Точно так же, если один модуль выходит из строя, он запускает другой. В StatefulSet
подам даются имена, и с ними обращаются как с домашними животными. Если кто-то из ваших питомцев заболел, это сразу заметно. То же самое и в случае с StatefulSet
s ,
поскольку он взаимодействует с модулями по их имени.
StatefulSet
предоставляет каждому поду два стабильных уникальных идентификатора. Во-первых, Network Identity позволяет нам назначать поду одно и то же DNS-имя независимо от количества перезапусков . IP-адреса могут по-прежнему отличаться, поэтому потребители должны полагаться на DNS-имя (или следить за изменениями и обновлять внутренний кеш).
Во- вторых, Storage Identity остается прежним . Network Identity всегда получает один и тот же экземпляр Storage, независимо от того, на каком узле он перепланирован.
StatefulSet
также является контроллером, но в отличие от Kubernetes Deployment
, он не создает ReplicaSet
, а создает модуль
с уникальным соглашением об именах. Каждый pod
получает DNS-имя по шаблону: <statefulset name>-<ordinal index>.
Например, для StatefulSet
с именем mysql
это будет mysql-0
.
Каждая реплика набора с отслеживанием состояния будет иметь свое собственное состояние, и каждый из модулей будет создавать свой собственный PVC (Persistent Volume Claim). Таким образом, StatefulSet
с 3 репликами создаст 3 модуля, каждый из которых имеет собственный том, то есть всего 3 PVC. Поскольку StatefulSet
работает с данными, мы должны быть осторожны при остановке экземпляров pod, предоставляя необходимое время для сохранения данных из памяти на диск. По-прежнему могут быть веские причины для принудительного удаления, например, при сбое узла Kubernetes.
4.2. Безголовый сервис
Для приложения с отслеживанием состояния требуются модули с уникальным идентификатором (именем хоста). Один модуль должен иметь доступ к другим модулям с четко определенными именами. Для работы StatefulSet
требуется безголовая служба. Безголовая служба — это служба со служебным IP . Таким образом, он напрямую возвращает IP-адреса наших связанных модулей. Это позволяет нам напрямую взаимодействовать с модулями, а не через прокси. Это так же просто, как указать None
для .spec.clusterIP.
Безголовая служба не имеет IP-адреса. Внутри он создает необходимые конечные точки для предоставления модулей с DNS-именами. Определение StatefulSet
включает ссылку на безголовую службу, но мы должны создать ее отдельно.
4.3. Компоненты StatefulSet
в Kubernetes
Ниже приведены основные компоненты StatefulSet
s :
- StatefulSet
- постоянный объем
- Безголовый сервис
Сначала мы создаем шаблон StatefulSet :
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: myclaim
Во-вторых, мы создаем PersistentVolume, упомянутый в шаблоне StatefulSet :
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
Наконец, теперь мы создаем безголовый сервис для указанного выше StatefulSet
:
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
4.4. Выполнение StatefulSet
в Kubernetes
У нас есть готовые шаблоны для всех трех компонентов. Теперь давайте запустим команду create
kubectl для создания StatefulSet
:
kubectl create -f statefulset.yaml
Он создаст три модуля с именами web-0, web-1, web-2
. Мы можем проверить правильность создания с помощью get pods
:
kubectl get pods
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 1m
web-1 1/1 Running 0 46s
web-2 1/1 Running 0 18s
Мы также можем проверить работающую службу:
kubectl get svc nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx ClusterIP None < none > 80/TCP 2m
StatefulSet
не создает ReplicaSet
, поэтому мы не можем откатить StatefulSet до предыдущей версии. Мы можем только удалить или увеличить/уменьшить Statefulset
. Если мы обновим StatefulSet
, он также выполнит RollingUpdate, т. е. один модуль реплики выйдет из строя, а обновленный модуль появится. Точно так же следующий модуль реплики выйдет из строя таким же образом.
Например, мы меняем изображение указанного выше StatefulSet
. Сеть -2
завершится, и как только она завершится полностью, будет воссоздана сеть-2
, и в то же время будет завершена работа сети-1 .
То же самое происходит для следующей реплики, т . е. web-0
. Если при обновлении произойдет ошибка, то только веб-2
будет недоступен, а веб-1
и веб-0
по- прежнему будут работать на предыдущей стабильной версии. В отличие от развертывания
, мы не можем выполнить откат к какой-либо предыдущей версии StatefulSet
.
Удаление и/или уменьшение StatefulSet
не приведет к удалению томов, связанных с StatefulSet
. Это обеспечивает безопасность данных, что, как правило, более ценно, чем автоматическая очистка всех связанных ресурсов StatefulSet .
После удаления StatefulSets
нет никаких гарантий по завершению подов. Чтобы добиться упорядоченного и корректного закрытия модулей в StatefulSet, перед удалением можно уменьшить StatefulSet
до 0.
4.5. Использование StatefulSet
StatefulSet
позволяет нам развертывать приложения с отслеживанием состояния и кластерные приложения. Они сохраняют данные в постоянном хранилище, таком как постоянные диски Compute Engine. Они подходят для развертывания Kafka, MySQL, Redis, ZooKeeper и других приложений (требующих уникальных, постоянных идентификаторов и стабильных имен хостов).
Например, кластер базы данных Solr управляется несколькими экземплярами Zookeeper. Чтобы такое приложение работало правильно, каждый экземпляр Solr должен знать об экземплярах Zookeeper, которые его контролируют. Точно так же экземпляры Zookeeper сами устанавливают соединения друг с другом для выбора главного узла. Благодаря такому дизайну кластеры Solr являются примером приложений с отслеживанием состояния. Другие примеры приложений с отслеживанием состояния включают кластеры MySQL, Redis, Kafka, MongoDB и другие. В таких сценариях используются StatefulSet
.
5. Развертывание
против StatefulSet
s
Давайте посмотрим на основные различия между Deployment
и StatefulSet
:
| **Развертывание** | **StatefulSet** |
| Развертывание используется для развертывания приложений без сохранения состояния. | `StatefulSet` используется для развертывания приложений с отслеживанием состояния. |
| Капсулы взаимозаменяемы | Поддоны не взаимозаменяемы. Каждый модуль имеет постоянный идентификатор, который сохраняется при любом изменении расписания. |
| Имена подов уникальны | Имена подов идут в последовательном порядке |
| Сервис необходим для взаимодействия с модулями в развертывании. | Безголовая служба отвечает за сетевую идентификацию модулей. |
| Указанный объект PersistentVolumeClaim используется всеми репликами модуля. Другими словами, общий объем | Указаны шаблоны VolumeClaimTemplates, чтобы каждый модуль реплики получал связанный с ним уникальный объект PersistentVolumeClaim. Другими словами, нет общего тома |
Развертывание
Kubernetes — это ресурсный объект в Kubernetes, который предоставляет декларативные обновления для приложений. Развертывание позволяет нам описать жизненный цикл приложения. Например, какие изображения использовать для приложения, сколько модулей должно быть и как их следует обновлять.
StatefulSet
больше подходят для приложений с отслеживанием состояния . Для приложения с отслеживанием состояния требуются модули с уникальным идентификатором (например, именем хоста). Модуль сможет связаться с другими модулями с четко определенными именами. Для подключения к модулям требуется безголовая служба. Безголовая служба не имеет IP-адреса. Внутри он создает необходимые конечные точки для предоставления модулей с DNS-именами.
Определение StatefulSet
включает ссылку на безголовую службу, но мы должны создать ее отдельно. StatefulSet
требуется постоянное хранилище, чтобы размещенное приложение сохраняло свое состояние и данные при перезапусках. После создания StatefulSet
и Headless Service под может получить доступ к другому по имени с префиксом имени службы.
6. Заключение
В этом руководстве мы рассмотрели два способа развертывания в Kubernetes: Statefulset
и Deployment
. Мы увидели их основные характеристики и компоненты и, наконец, сравнили их.