Автор статьи: Рустем Галиев

IBM Senior DevOps Engineer & Integration Architect. Официальный DevOps ментор и коуч в IBM

Привет, Хабр! Сегодня мы узнаем, как запустить надежный одноэлементный инстанс базы данных MySQL в качестве пода в Kubernetes и как предоставить этот под другим приложениям в кластере. Для этого мы создадим три основных объекта:

  • Persistent Volume для управления сроком службы дискового хранилища независимо от срока службы работающего приложения MySQL.

  • Под MySQL, который будет запускать приложение MySQL.

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

Создаем persistent volume

Мы определяем IP-адрес кластера службы, которая предоставляет под, чтобы позже ссылаться на него при монтировании службы NFS в PersistentVolume:

kubectl get service nfs-service -n storage -o jsonpath='{.spec.clusterIP}'

Для начала создадим PV для нашей базы данных MySQL.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: database
  labels:
    volume: my-volume
spec:
  accessModes:
  - ReadWriteMany
  capacity:
    storage: 1Gi
  nfs:
    server: <добавьте-свой-nfs-service-cluster-ip-здесь>
    path: "/nfs-direct"

Это определяет объект NFS PersistentVolume с 1 ГБ дискового пространства.

Создаем

kubectl apply -f nfs-volume.yaml

Создадим PersistentVolumeClaim

Теперь, когда у нас есть PV, нам нужно залкэймить PV для нашего пода. Мы делаем это с помощью объекта PersistentVolumeClaim:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: database
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  selector:
    matchLabels:
      volume: my-volume


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

Создаем объект с помощью следующей команды:

kubectl apply -f nfs-volume-claim.yaml

Создание набора реплик MySQL

Теперь, когда заклэймили PV, мы можем использовать ReplicaSet для создания нашего пода. Может показаться странным, что мы используем ReplicaSet для управления одним подом, но это необходимо для надежности. Если нода перестает работать, то любые поды, которые находятся на этой ноде и не управляются контроллером более высокого уровня, таким как ReplicaSet, исчезают вместе с нодой и не переназначаются другой ноде. Следовательно, чтобы убедиться, что наш под  базы данных перепланируется при наличии сбоев ноды, мы используем контроллер ReplicaSet более высокого уровня с количеством реплик, равным единице, для управления нашей базой данных.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: database
        image: mysql
        resources:
          requests:
            cpu: 1
            memory: 2Gi
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: root
        livenessProbe:
          tcpSocket:
            port: 3306
        ports:
        - containerPort: 3306
        volumeMounts:
          - name: database
            mountPath: "/var/lib/mysql"
      volumes:
      - name: database
        persistentVolumeClaim:
          claimName: database


Создаем kubectl apply -f mysql-replicaset.yaml

ReplicaSet создает один под с парой «ключ-значение» метки app=label. Вы можете запросить его с помощью следующей команды:

kubectl get pods -l app=mysql

После запуска пода, управляемого набором реплик, и перехода в статус «Running», вы сможете проверить содержимое пути монтирования тома. Следующая команда предполагает, что имя Pod — mysql-XXXX(тут должны быть ваши цифры).

kubectl exec -it mysql-xxxx -- ls /var/lib/mysql

Предоставление MySQL как службы

Как только мы создадим ReplicaSet, он, в свою очередь, создаст под с MySQL, используя изначально созданный персистент диск. Последний шаг — представить это как сервис Kubernetes.

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - port: 3306
    protocol: TCP
  selector:
    app: mysql


Создаем

kubectl apply -f mysql-service.yaml

Теперь у нас есть надежный одноэлементный экземпляр MySQL, работающий в нашем кластере и представленный как служба с именем mysql, к которой мы можем получить доступ по полному доменному имени mysql.svc.default.cluster.local.

Мы создали persistent volume для использования базой данных MySQL. В этом примере для максимальной переносимости использовалась NFS, но Kubernetes поддерживает множество различных типов persistent volume. Например, существуют persistent volume drivers томов для всех основных клауд провайдеров. Чтобы использовать эти решения, просто замените nfs на соответствующий тип тома облачного провайдера (например, azure, awsElasticBlockStore или gcePersistentDisk). Во всех случаях это изменение — все, что вам нужно. Kubernetes знает, как создать соответствующий диск для хранения в соответствующем клауд провайдере.

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

Комментарии (3)


  1. stitrace
    00.00.0000 00:00
    +8

    Я бы убрал на вашем месте слово «надежный» из описания, т.к. в процессе эксплуатации этого решения, вы неизбежно получите повреждение базы данных. Первая и самая серьезная опасность, это поднятие двух независимых инстансов mysql на одной и той же папке с данными БД, которая произойдет при первом же обновлении конфигурации деплоя, в том виде, в котором он описан у вас. Ну и, конечно, если у вас контрол плэйн потеряет ноду с подом, он заскедулит реплику рода на любую из доступных, но это вовсе не гарантирует, что нода умерла и на ней не продолжает работать инстанс mysql и даже, то что в данный момент, в него не пишет ПО. Короче говоря, не делайте так.


    1. ggo
      00.00.0000 00:00

      да ну что вы, право боже.

      Базы данных внутри кубера - это же надежно, все так делают ;)


      1. vasyakrg
        00.00.0000 00:00

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

        А вот nfs - действительно не очень хорошая идея