Разворачиваем через консоль управляемый кластер (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