Skip to content

Statefulsets

Определение

StatefulSet – это контроллер Kubernetes, применяемый для эксплуатации сохраняющих состояние приложений в виде контейнеров (подов) в кластере Kubernetes.

StatefulSet присваивают каждому поду идентификатор-липучку (sticky identity) – порядковый номер начиная с нуля — а не случайные ID каждой реплике пода. Новый под создается клонированием данных уже существовавшего пода. Если ранее существовавший под находился в ожидающем состоянии, то новый под создан не будет. Удаление подов происходит в обратном порядке, а не в случайном. Например, если у вас было четыре реплики, и в результате масштабирования их количество было сокращено до трех, то под номер 3 будет удален.

Что такое приложения с сохранением состояния?

Это приложения, которые сохраняют данные и помогают их отслеживать. Все базы данных, в частности, MySQL, Oracle и PostgreSQL – это примеры приложений, сохраняющих состояние. С другой стороны, в приложениях без сохранения состояния данные долго не держатся. Примеры приложений без сохранения состояния — Node.js и Nginx. Если состояние в приложении не сохраняется, то на каждый запрос приложение будет получать новые данные и обрабатывать их.

В современных веб-приложениях такие приложения без сохранения состояния соединяются с приложениями, сохраняющими состояние, чтобы обслужить пользовательский запрос. Приложение Node.js не сохраняет состояние, оно получает новые данные при каждом запросе, поступающем от пользователя. Далее это приложение соединяется для обработки данных с другим, сохраняющим состояние, например, с базой данных MySQL. База данных MySQL сохраняет данные и продолжает их обновлять, исходя из пользовательского запроса.

Когда использовать StatefulSets

Есть несколько причин, по которым может быть целесообразно использовать StatefulSets. Рассмотрим два примера:

  1. Допустим, вы развернули базу данных MySQL в кластере Kubernetes и масштабировали ее до трех реплик, а клиентское приложение пытается получить доступ к кластеру MySQL, чтобы считывать и записывать данные. Запрос на считывание будет переадресовываться на три пода. Однако запрос на запись будет переадресовываться только на первый (ведущий) под, а записанные сюда данные будут синхронизироваться с другими подами. Это достижимо при помощи StatefulSets.

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

Как создать StatefulSets в Kubernetes

Для создания нам необходим файл с YAML расширением.

yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-state
spec:
  selector:
    matchLabels:
      app: mysql
  serviceName: "mysql"
  replicas: 3
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0.34
        ports:
        - containerPort: 3306
          name: web
        volumeMounts:
        - name: mysql-store 
          mountPath: /var/lib/mysql
        env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysql-secret
                key: MYSQL_ROOT_PASSWORD
  volumeClaimTemplates:
  - metadata:
      name: mysql-store
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "longhorn"
      resources:
        requests:
          storage: 1Gi

Пройдемся по некоторым значениям:

  • В поле Kind мы прописываем значение файла;

  • Значение name в поле metadata, будущее название Pod'ов;

  • В matchlabels поле app необходимо чтобы связать statefulset с подконтрольными подами;

  • В разделе containers задается образ, который мы планируем равзернуть;

  • volumesMount задает путь монтирования томов хранения;

  • В поле env мы можем указать переменные и их значения, в данном случае мы указавали пароль, который хранится в серкрете mysql-secret, его нам предложат ввести на входе в БД;

  • volumeClaimTemplates представляет собой хранилище, у которого мы запрашиваем 1Гб памяти для одного пода с доступом ReadWriteOnce;

После того, как мы описали файл, его необходимо упомянуть в кубе при создании:

sh
$ kubectl apply -f statefulset.yml
sh
$ kubectl get sts
NAME          READY   AGE
mysql-state   3/3     23h

Увидеть список развернутых подов:

sh
$ kubectl get pods
mysql-state-0     1/1     Running   0     23h
mysql-state-1     1/1     Running   0     23h
mysql-state-2     1/1     Running   0     23h