Как стать автором
Обновить

Разворачиваем PostgreSQL, Redis и RabbitMQ в Kubernetes-кластере

Время на прочтение9 мин
Количество просмотров34K

В этой статье я не буду объяснять, зачем вот это всё нужно, или обсуждать достоинства и недостатки этого решения. Воспринимайте эту статью как инструкцию (заметку) для быстрого развёртывания базы и брокера сообщений в dev-кластере Kubernetes.

Содержание

  1. Введение

  2. Установка PostgreSQL

  3. Установка Redis

  4. Установка RabbitMQ


Введение

Установки PostgresSQL, Redis и RabbitMQ очень похожи друг на друга. Можно выделить три основных этапа:

  • Создание Persistent Volume (PV) и Persistent Volume Claim (PVC).

  • Установка Helm-чарта целевого приложения.

  • Проверка работы.

Я не буду объяснять, что такое PV и PVC. Есть отличная лекция на эту тему, после которой можете смело возвращаться к моей инструкции. Перед началом работ нужно минимально настроить кластер Kubernetes. Вот небольшие требования:

  1. Версия Kubernetes 1.20+.

  2. Одна master-нода и одна worker-нода.

  3. Настроенный Ingress-controller.

  4. Если кластер развернут на bare-metal, то необходимо заменить внешний балансировщик. Например, поставить MetalLB или PorterLB.

  5. На виртуальной машине установлен Helm.

Как создать свой ламповый dev-кластер на голом железе подробно рассказано в предыдущей статье.

Установка PostgreSQL

Создадим ресурс StorageClass, для этого в файл storage.yaml вставьте следующую конфигурацию:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

Применим манифест:

Создадим ресурс Persistent Volume. Для этого в файл pv.yaml вставьте следующий манифест:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-for-pg
  labels:
    type: local
spec:
  capacity:
    storage: 4Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /devkube/postgresql
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - 457344.cloud4box.ru

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

kubectl get nodes

Для удобства будем монтировать диск сразу на мастер-ноде, хотя это можно сделать на любой из доступных в списке. Монтировать будем директорию /devkube/postgresql. Заходим на удалённую машину и создаём директорию такой командой:

mkdir -p /devkube/postgresql

Создадим ресурс Persistent Volume:

kubectl apply -f pv.yaml

Проверим состояние:

kubectl get pv

Применим манифест с Persistent Volume Claim:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pg-pvc
spec:
  storageClassName: "local-storage"
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

Посмотрим состояние ресурса:

Ресурс PVC в ожидании привязки. Настало время развернуть Postgres в кластере. Подтягиваем к себе репозиторий Bitnami:

helm repo add bitnami https://charts.bitnami.com/bitnami

Устанавливаем чарт Helm с Postgres:

helm install dev-pg bitnami/postgresql --set primary.persistence.existingClaim=pg-pvc,auth.postgresPassword=pgpass

Посмотрим на состояние PVC:

kubectl get pvc

Ресурс в статусе bound, теперь pod с Postgres будет писать данные в директорию /devkube/postgresql. Посмотрим на состояние pod, statefulset:

kubectl get pod,statefulset

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

1. Пробросить порт на локальную машину

Для этого требуется установить на машину утилиту psql. Проверим, что она установлена:

psql -V

Экспортируем пароль от админ-пользователя в переменную окружения:

export POSTGRES_PASSWORD=$(kubectl get secret --namespace default dev-pg-postgresql -o jsonpath="{.data.postgres-password}" | base64 --decode)

Выполним проброс порта:

kubectl port-forward --namespace default svc/dev-pg-postgresql 5432:5432

Консоль после выполнения команды будет заблокирована. В другом окне подключитесь к этой же машине и выполните подключение к БД:

PGPASSWORD="$POSTGRES_PASSWORD" psql --host 127.0.0.1 -U postgres -d postgres -p 5432

Или так, но тогда придётся ввести пароль вручную:

psql --host 127.0.0.1 -U postgres -d postgres -p 5432

2. Создать поду с psql клиентом

Экспортируем пароль от админ-пользователя в переменную окружения:

export POSTGRES_PASSWORD=$(kubectl get secret --namespace default dev-pg-postgresql -o jsonpath="{.data.postgres-password}" | base64 --decode)

Создадим под с утилитой psql и выполним в ней команду подключения к БД:

kubectl run dev-pg-postgresql-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:14.2.0-debian-10-r22 --env="PGPASSWORD=$POSTGRES_PASSWORD" \
      --command -- psql --host dev-pg-postgresql -U postgres -d postgres -p 5432

Создадим роль (пользователя) и пароль для неё:

CREATE ROLE qa_user WITH LOGIN ENCRYPTED PASSWORD 'qa-pg-pass';

Посмотреть список ролей:

\du

Создадим базу, владельцем которой будет пользователь qa_user:

CREATE DATABASE qa_db OWNER qa_user;

Теперь отключимся:

\q

И подключимся к базе с данными нового пользователя (вторым способом):

kubectl run dev-pg-postgresql-client --rm --tty -i --restart='Never' --namespace default --image docker.io/bitnami/postgresql:14.2.0-debian-10-r22 --env="PGPASSWORD=qa-pg-pass"  --command -- psql --host dev-pg-postgresql -U qa_user -d qa_db -p 5432

Создадим небольшую табличку:

CREATE TABLE qa_table (id int, name varchar(255));

Добавим запись:

INSERT INTO qa_table VALUES (1, 'first');

Теперь сделаем select, чтобы убедиться в работоспособности:

SELECT * FROM qa_table;

Посмотреть список таблиц в базе:

\dt+

Готово, база успешно развёрнута! В приложении нужно указывать такой адрес БД:

DATABASE_URI=postgresql://qa_user:qa-pg-pass@dev-pg-postgresql:5432/qa_db

Установка Redis

Redis можно установить в нескольких конфигурациях. Мы развернём вариант с двумя репликами на чтение и одной репликой на запись в базу. Прежде всего применим манифест со StorageClass:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
kubectl apply -f storage.yaml

У меня уже был установлен этот ресурс, поэтому манифест не применился.

Дальше настроим Persistent Volumes. Зарезервируем 2 Гб для каждой slave-реплики и 4 Гб для мастер-реплики. Создадим файлы pv-slave1.yaml, pv-slave2.yaml и pv-master.yaml и вставим в них эти конфигурации:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-redis-slave1
  labels:
    type: local
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /devkube/redis/slave1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - 457344.cloud4box.ru
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-redis-slave2
  labels:
    type: local
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /devkube/redis/slave2
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - 457344.cloud4box.ru
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-redis-master
  labels:
    type: local
spec:
  capacity:
    storage: 4Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /devkube/redis/master
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - 457344.cloud4box.ru

Все реплики будут складывать свои данные на ноде 457344.cloud4box.ru, хотя, конечно, можно монтировать диски на разных виртуальных машинах. Создадим три директории:

mkdir -p /devkube/redis/slave1
mkdir -p /devkube/redis/slave2
mkdir -p /devkube/redis/master

Применим конфигурации:

kubectl apply -f .

Проверим созданные ресурсы:

kubectl get pv

Созданные PV ещё свободны и ждут заявки на использование пространства. А Persistent Volumes Postgres уже связан со своим Persistent Volumes Сlaim (так осталось после поднятия Postgres-базы в Kubernetes).

Создадим PVC для мастер-реплики. Их нужно обязательно создавать в том namespace, в котором вы развернёте базу. Redis будет развёрнут в пространстве dev-redis. Создадим пространство:

kubectl create ns dev-redis
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: pvc-for-master-redis
  namespace: dev-redis
spec:
  storageClassName: "local-storage"
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi
kubectl apply -f pvc-master.yaml

Для slave-реплик создавать PVC не будем, они будут автоматически созданы при установке чарта Helm.

Пришло время установить Redis. Подтягиваем к себе репозиторий Bitnami, если ещё этого не сделали (у меня уже добавлен):

helm repo add bitnami https://charts.bitnami.com/bitnami

Устанавливаем чарт Helm с Redis:

helm install dev-redis-chart bitnami/redis --namespace dev-redis --set global.redis.password=redispass,master.persistence.existingClaim=pvc-for-master-redis,replica.replicaCount=2,replica.persistence.storageClass=local-storage,replica.persistence.size=2Gi

В этой команде указываю:

  • password=redispass — пароль для авторизации;

  • existingClaim=pvc-for-master-redis — название созданного выше PVC для мастер-реплики;

  • replicaCount, storageClass, size — количество slave-реплик, название ресурса StorageClass и размер PV. Это всё нужно для автоматического создания PVC.

После выполнения команды в консоль будет выведено несколько способов подключения к Redis. Но сначала проверим состояние Persistent Volumes:

kubectl get pv

Все ресурсы стали связаны с конкретным PVC. И посмотрим на созданные ресурсы:

kubectl get pod,svc,statefulset -n dev-redis

Всё успешно развернуто, пора подключиться и попинговать базу. Экспортируем пароль авторизации в переменную окружения:

export REDIS_PASSWORD=$(kubectl get secret --namespace dev-redis dev-redis-chart -o jsonpath="{.data.redis-password}" | base64 --decode)

Создадим под с redis-cli на борту:

kubectl run --namespace dev-redis redis-client --restart='Never'  --env REDIS_PASSWORD=$REDIS_PASSWORD  --image docker.io/bitnami/redis:6.2.6-debian-10-r146 --command -- sleep infinity

Проходим внутрь созданного пода:

kubectl exec --tty -i redis-client \
   --namespace dev-redis -- bash

И теперь можно подключиться к master- или slave-реплике на выбор:

   REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h dev-redis-chart-master
   или
   REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h dev-redis-chart-replicas

Подключимся к master-реплике:

Пинганём базу:

Записать данные можно в любую из 15 автоматически созданных баз (по умолчанию база под номером ноль). Выберем, например, вторую:

Запишем некоторые данные:

И запросим их же:

Готово! Redis успешно развёрнут и готов к использованию. В приложении нужно указывать такой адрес:

REDIS=redis://redispass@dev-redis-chart-master:6379/0

Установка RabbitMQ

Запишем манифест с ресурсом StorageClass в файл storage.yaml:

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

И применим его:

kubectl apply -f storage.yaml

У меня уже был установлен этот ресурс, поэтому манифест не применился.

Создадим Persistent Volume:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-for-rmq
  labels:
    type: local
spec:
  capacity:
    storage: 4Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /devkube/rabbitmq
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - 457344.cloud4box.ru

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

kubectl get nodes

Для удобства будем монтировать диск сразу на master-ноде, хотя это можно сделать на любой из доступных в списке. Создадим директорию, в которую RabbitMQ будет складывать свои данные:

mkdir -p /devkube/rabbitmq

Создадим ресурс Persistent Volume:

kubectl apply -f pv.yaml

И проверим состояние:

Осталось только создать Persistent Volume Claim. Его нужно обязательно создавать в том namespace, в котором будете разворачивать будущую очередь. RabbitMQ развернётся в пространстве dev-rmq. Создадим его:

kubectl create ns dev-rmq

Запишем манифест в файл pvc.yaml:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: rmq-pvc
  namespace: dev-rmq
spec:
  storageClassName: "local-storage"
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

Применим:

kubectl apply -f pvc.yaml

И, наконец, развернём RabbitMQ. Добавляем к себе репозиторий Bitnami, если ещё этого не сделали (у меня уже добавлен):

helm repo add bitnami https://charts.bitnami.com/bitnami

Установим чарт Helm RabbitMQ:

helm install dev-rmq-chart bitnami/rabbitmq --namespace dev-rmq --set persistence.existingClaim=rmq-pvc,ingress.enabled=true,ingress.hostname=dashboard.dev.rmq.cryptopantry.tech,auth.username=rmq_admin,auth.password=devrmquser,ingress.ingressClassName=nginx

В этой команде я указываю следующие настройки:

  •  existingClaim=rmq-pvc — имя существующего ресурса PVC, который мы выше создали;

  • ingress.enabled=true — активируем Ingress, это нужно для разворачивания удобной борды;

  • ingress.hostname=dashboard.dev.rmq.somedomain.com — адрес борды;

  • auth.username=rmq_admin и auth.password=devrmquser — тут всё и так понятно;

  • ingress.ingressClassName=nginx — обязательная настройка для Ingress-ресурса.

Чарт Helm установлен. Проверим, что ресурсы успешно развёрнуты:

Теперь перейдите в браузере по доменному имени, которое указали в ingress.hostname:

Заходим с учётными данными login=rmq_admin и password=devrmquser, и переходим во вкладку Admin:

Создадим нового пользователя qa_user с паролем qa_pass:

Создадим virtual host:

И привяжем пользователя к virtual host:

Готово! RabbitMQ развёрнут и готов к использованию:

В приложении укажите такой адрес:

RabbitMQ=amqp://qa_user:qa_pass@dev-rmq-chart-rabbitmq.dev-rmq:5672/qa_host

На этом у меня всё, мы успешно развернули PostgreSQL, Redis и RabbitMQ в небольшом dev-кластере.

Теги:
Хабы:
Всего голосов 44: ↑43 и ↓1+47
Комментарии15

Публикации

Информация

Сайт
domclick.ru
Дата регистрации
Дата основания
Численность
501–1 000 человек
Местоположение
Россия
Представитель
Dangorche