суббота, 6 января 2024 г.

Разворачивание в кластере кубернетес базы данных postgres и wiki.js

 Разворачиваем через консоль управляемый кластер (master) в яндекс облаке (YC) и сразу добавляем рабочие узлы (worker node(s)). Также, в той же локации (зоне обслуживания ...-a (b,c,d)), добавляем отдельный диск под Persistent Volume (PV), и  запоминаем его "disk-id" Настраиваем локальную работу kubectl по инструкции от яндекс облако.

Затем развернем 2 деплоймента: postgres and wiki.js 

1. Postgres, 

сначала создадим PV и PV Claim (PVC): (pv-pvc.yaml) 

apiVersion: v1
kind: PersistentVolume
metadata:
  name: persistent-volume-pv
  labels:
    type: local
    app: my-database
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  storageClassName: yc-network-hdd # match to disk type in ya cloud
  csi:
    driver: disk-csi-driver.mks.ycloud.io
    fsType: ext4
    volumeHandle: epd6onn7r80053mlt1ad # "Disk-id" from ya cloud
  storageClassName: manual
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-db # will apply to this name of PVC in deployment
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: manual
  volumeName: persistent-volume-pv

запускаем:  kubectl apply -f .\pv-pvc.yaml

в консоли яндекс клауд должно появиться "Bound" для обоих сущностей (пункт Хранилище)

красным  цветом указано как ссылаются сущности, на зеленый будет ссылка ниже, из деплоймента PG. 

далее разворачиваем еще 2 сущности ConfigMap and Secret (conf-map-sec.yaml)

kind: ConfigMap
apiVersion: v1
metadata:
  name: database-cm
data:
  create-database-table.sql: |
    CREATE TABLE gifts (
      id SERIAL PRIMARY KEY,
      name VARCHAR,
      sold INT
    );

    INSERT INTO gifts (name,sold) VALUES ('Pumpkin', 3000);
    INSERT INTO gifts (name,sold) VALUES ('Christmas Tree', 1000);
    INSERT INTO gifts (name,sold) VALUES ('Socks', 10000);
---
apiVersion: v1
kind: Secret

metadata:
  name: db-secret-credentials
  labels:
    app: my-database
data:
  POSTGRES_DB: Z2lmdHMtdGFibGU= # gifts-table all coded by base64, below too
  POSTGRES_USER: YWRtaW4= # admin
  POSTGRES_PASSWORD: UEBzc3cwcmQ= # P@ssw0rd
 

запускаем:  kubectl apply -f .\conf-map-sec.yaml

ConfigMap здесь только для примера, чтобы понять как могут  передаваться в контейнер файл с нужным содержимым, там можно создать базу, таблицу, внести строки, создать пользователя и т.д. Использовал для проверки работоспособности базы и чтобы потом, подключившись к Pod руками пролить нужные настройки, т.к. пока не изучал как может повлиять многоразовая инициализация рабочей (нужной) базы, которая хранится в отдельном, от кластера кубернетис, диске. Если всё правильно, то должны появиться в секции "Конфигурация" обе сущности с нужными переменными. На белый и светло-коричневый пункты будет ссылка из деплоймента PG

Разворачиваем деплоймент postgres (kubectl apply -f .\depl-pd.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-database
  template:
    metadata:
      labels:
        app: my-database
    spec:
      containers:
        - name: my-database
          image: postgres:latest
          ports:
            - containerPort: 5432
          env:
            - name: POSTGRES_DB
              valueFrom:
                secretKeyRef:
                  name: db-secret-credentials
                  key: POSTGRES_DB

            - name: POSTGRES_USER
              valueFrom:
                secretKeyRef:
                  name: db-secret-credentials
                  key: POSTGRES_USER

            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret-credentials
                  key: POSTGRES_PASSWORD

          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: db-data
              subPath: data

            - mountPath: /docker-entrypoint-initdb.d
              name: postgresdb-loadsql
      volumes:
        - name: postgresdb-loadsql
          configMap:
            name: database-cm

        - name: db-data
          persistentVolumeClaim:
            claimName: pvc-db

Здесь видно, что запрошено (зеленым) PVC который описан ранее, и ему дано имя db-data (голубым) и уже это имя тома/раздела будет подмонтировано к каталогу "/var/lib/postgresql/data" -где лежат сами файлы БД, важно добавить параметр subPath: data

т.к. он указывает и на подкаталоги(?), иначе postgres (PG) находит прежние файлы БД, но считает их чужими, т.к. его конфиг возможно ничего не знает о старой, с параметром же, он находит и конфиг в этом же каталоге и запускается без ошибок. Можно это увидеть в секции "Логи" в YC для данного деплоймента.

Для опубликования внутри кластера порта (5432) для подключения к PG запустим service (svc-db.yaml)

apiVersion: v1
kind: Service
metadata:
  name: svc-db # hostname to connect from app (wiki.js)
  labels:
    app: my-database
spec:
  selector:
    app: my-database
#  type: NodePort
  ports:
  - protocol: TCP
    port: 5432
    targetPort: 5432

запускаем   kubectl apply -f .\svc-db.yaml

Здесь объявлен hostname (светло-бежевым) , который мы укажем в деплойменте wiki.js для подключения к БД.

проверяем:

  C:\work\projects>kubectl get deployments

NAME            READY   UP-TO-DATE   AVAILABLE   AGE

deployment-db   1/1     1            1           106m

C:\work\projects>kubectl get pods

NAME                             READY   STATUS    RESTARTS   AGE

deployment-db-7f9649d79f-65swk   1/1     Running   0          97m

подключаемся к БД и убеждаемся, что БД работает:

C:\work\projects>kubectl exec -it deployment-db-7f9649d79f-65swk -- psql -h localhost -U admin --password -p 5432 gifts-table

Password:

psql (16.1 (Debian 16.1-1.pgdg120+1))

Type "help" for help.

gifts-table=#

Создаем пользователя, базу данных и права для wiki.js (вставляем в промт)

CREATE DATABASE wikijs;

CREATE USER wikijs WITH PASSWORD 'wikijsrocks';

GRANT CONNECT ON DATABASE wikijs TO wikijs;

GRANT USAGE ON SCHEMA public TO wikijs;

GRANT SELECT,UPDATE,INSERT,DELETE ON ALL TABLES IN SCHEMA public TO wikijs;

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO wikijs;

ALTER DATABASE wikijs OWNER TO wikijs;

Выходим из БД и заходим повторно но уже с пользователем wikijs:

kubectl exec -it deployment-db-7f9649d79f-65swk -- psql -h localhost -U wikijs --password -p 5432 wikijs

Должно пустить.


2. Wiki.js

Создаем ConfigMap  (conf-map-sec-wiki-js.yaml)

apiVersion: v1
kind: ConfigMap
metadata:
  name: wikijs
data:
  DB_TYPE: postgres
  DB_HOST: svc-db # hostname from svc-db.yaml
  DB_PORT: "5432"
  DB_NAME: "wikijs"
  DB_USER: "wikijs"
  DB_PASS: "wikijsrocks"

запускам:  kubectl apply -f .\conf-map-sec-wiki-js.yaml

Передаем таким образом параметры в переменные для контейнера с wiki.js 

Создаем деплоймент (и сразу service) для приложения Wiki.js (depl-wiki-js.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wikijs
  name: wikijs
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wikijs
  template:
    metadata:
      labels:
        app: wikijs
    spec:
      containers:
        - name: wikijs
          image: 'requarks/wiki:2'
          ports:
            - name: http-3000
              protocol: TCP
              containerPort: 3000
          envFrom:
          - configMapRef:
              name: wikijs
---
apiVersion: v1
kind: Service
metadata:
  name: wikijs
spec:
  selector:
    app: wikijs
  ports:
    - protocol: TCP
      port: 3000
      targetPort: http-3000

Запускаем:  kubectl apply -f .\depl-wiki-js.yaml

Желтым цветом показана привязка к ConfigMap wikijs. В секции "полезная нагрузка" , в соответствующем  деплойменте, провалившись в строку, можно посмотреть "Логи" там должно быть успешное соединение с БД. (используется Deployment c replica=1, но правильно д.б. StatefulSet).

для публикации Wiki.js в интернет понадобится еще один сервис типа loadBalancer 

запускаю его вручную (т.к. это для теста и учебы):

kubectl expose deployment wikijs --type=LoadBalancer --name=my-serv-wiki


Важно, создается новый сервис my-serv-wiki, 

узнаем внешний IP:

 kubectl get services my-serv-wiki

и можно соединяться по 3000 порту  на внешний IP, который виден в выводе комнады.


Замечания:

можно собрать в один файл, но кубернетес нет  команды "depends on:, считается, что все компоненты/сущности, что работают в кубернетес, должно быть толерантны к времени своего запуска/перезапуска.

Деплоймент читает ConfigMap и Secret только один раз, при запуске/перезапуcке, т.е. даже изменив их, надо заставить обновиться Pod-ы (рестарт/scaling и т.д.)


команды для тестирования (kubectl port-forward <pod-name> <localhost-port>:<pod-port>):

kubectl port-forward wikijs-678fdfd978-7tgdj 3000:3000  (прибиндить порт Pod к 127.0.0.1:3000)


ниже полный (по опциям) эквивалент сервиса ...expose ...  LoadBalancer

kubectl expose deployment example --port=8765 --target-port=9376 \
     --name=example-service --type=LoadBalancer



apiVersion: v1
kind: Service
metadata: 
  name: example-service
spec:
  selector:
    app: example
  ports:
    - port: 8765
      targetPort: 9376
  type: LoadBalancer





Комментариев нет:

Отправить комментарий