В этой статье автор не будет объяснять, зачем нужны все эти манипуляции, или обсуждать преимущества и недостатки данного решения. Он надеется, что читатели достаточно умны. 😎
Рассматривайте эту статью как продолжение истории о постоянных томах и как руководство по развертыванию базы данных в локальном кластере Kubernetes dev.
0. Введение
Можно выделить три основных этапа:
- Создание
PersistentVolume
(PV) иPersistentVolumeClaim
(PVC) — какая неожиданность, нам нужно stateful приложение. - Устанавливаем график Helm целевого приложения.
- Проверяем, что все работает.
Перед началом работы нам необходимо минимально настроить кластер Kubernetes. Вот небольшие требования:
- Актуальная версия Kubernetes (v1.22+).
- Один главный узел и один рабочий узел.
- Сконфигурированный Ingress-контроллер.
Как вы, возможно, уже знаете, автор предпочитает использовать k3s/k3d в качестве локальной стадии разработки Kubernetes.
1. Подготовка хранилища
При работе с k3s необходимо сначала включить так называемый local-path
provisoner.
Установите провизор:
$ kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
Установите провизор local-path
по умолчанию:
$ kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
Проверьте, что провайдер запущен:
$ kubectl --namespace kube-system get pod
NAME READY STATUS RESTARTS AGE
...
local-path-provisioner-84bb864455-tmpht 1/1 Running ...
С этого момента мы можем создать ресурсы PersistentVolume
и PersistentVolumeClaim
для нашего выделенного пространства хранения. Для этого вставьте следующий манифест в файл 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-path"
hostPath:
path: /opt/local-path-provisioner
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- k3d-my-cluster-agent-0
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pg-pvc
spec:
storageClassName: "local-path"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi
В поле matchExpressions
указываем имя узла, на котором будет смонтирован диск (здесь это должен быть наш рабочий узел k3d-my-cluster-agent-0
).
Для удобства мы смонтируем диск сразу на главном узле, хотя это можно сделать на любом из доступных в списке. K3s смонтирует том в каталог /opt/local-path-provisioner
в файловой системе ведущего узла.
$ docker exec -it k3d-my-cluster-agent-0 sh
/ # ls
bin dev etc k3d lib opt proc run sbin sys tmp usr var
/ # cd opt
/opt # ls
local-path-provisioner
/opt # cd local-path-provisioner/
/opt/local-path-provisioner # ls
data
/opt/local-path-provisioner # cd data
/opt/local-path-provisioner/data # ls
PG_VERSION global pg_dynshmem pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_xact postmaster.opts
base pg_commit_ts pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc pg_wal postgresql.auto.conf postmaster.pid
/opt/local-path-provisioner/data #
Посмотрите результат:
$ kubectl apply -f pvc.yaml
persistentvolume/pv-for-pg created
persistentvolumeclaim/pg-pvc created
Хорошо. Проверим состояние продвинутого PersistentVolumeClaim
:
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pg-pvc Bound pv-for-pg 4Gi RWO local-path 1m43s
Как мы видим, ресурс PersistentVolumeClaim
связан.
2. Установка PostgreSQL
Пришло время развернуть Postgres на кластере. Как раз на этом этапе нам уже нужен helm
. Тянем репозиторий Bitnami к себе (они добрые и замечательные, у них там в репозитории ⭐5k+ много полезных готовых схем):
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories
Продолжаем установку helm install
:
$ helm install dev-pg bitnami/postgresql --set primary.persistence.existingClaim=pg-pvc,auth.postgresPassword=pgpass,volumePermissions.enabled=true
NAME: dev-pg
LAST DEPLOYED: Tue May 3 19:25:34 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
⚠️ Из-за продолжающейся проблемы с разрешениями kubernetes и использованием containerSecurityContext.runAsUser
, вы должны включить volumePermissions
, чтобы убедиться, что все работает как ожидалось.
🥁 Барабаны тикают! С этого момента Postgres Pod будет способен записывать данные в каталог /opt/local-path-provisioner
.
Давайте посмотрим на состояние Pod и StatefulSet:
$ kubectl get pod,statefulset
NAME READY STATUS RESTARTS AGE
pod/dev-pg-postgresql-0 1/1 Running 0 26m
NAME READY AGE
statefulset.apps/dev-pg-postgresql 1/1 1h
Проверьте версию:
$ kubectl logs --tail 20 dev-pg-postgresql-0 | grep starting
...[1] LOG: starting PostgreSQL 14.2 on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
Отличная работа.
3. Общение с базой данных
База данных успешно развернута, теперь давайте попробуем подключиться к ней: создадим пользователя, таблицу и настроим учетные данные доступа.
Существует два основных способа взаимодействия с базой данных:
- Перенаправление портов
- Привлечение Pod с клиентским инструментом onboard
Переадресация порта
Нам понадобится утилита psql
(обратите внимание, в некоторых случаях необходимо добавить PgSQL PPA repo, автор использует Ubuntu Focal):
$ sudo apt install postgresql-client-14
Экспортируем пароль от пользователя admin в переменную окружения:
$ 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
Или вы можете открыть отдельную консоль:
$ export KUBECONFIG=$(k3d kubeconfig write my-cluster)
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 5432psql (14.2 (Ubuntu 14.2-1.pgdg20.04+1+b1))
Type "help" for help.
postgres=#
Привлечение Pod с клиентским инструментом onboard
Экспортируйте пароль от пользователя admin в переменную окружения:
$ export POSTGRES_PASSWORD=$(kubectl get secret --namespace default dev-pg-postgresql -o jsonpath="{.data.postgres-password}" | base64 --decode)
Затем создадим Pod с утилитой 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
If you don't see a command prompt, try pressing enter.
postgres=#
Давайте перечислим роли, чтобы убедиться, что мы на связи:
postgres=# du;
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
postgres=#
🎯 Вот и все, ребята! Мы развернули рабочую базу данных в кластере, она также сохраняет свое состояние, это stateful database.
Я рекомендую всем своим читателям регулярно просматривать блоги разработчиков в сети. Это того стоит. Спасибо Roger Lipscombe 🇬🇧 и Fadhil Yaacob 🇲🇾!
В следующей части автор рассмотрит удивительный инструмент, позволяющий наблюдать за функционированием контейнерной базы данных практически в реальном времени.