Разбираем запуск Loginom в Kubernetes: лицензии, образы, манифесты и подводные камни. Готовые решения для стабильной и масштабируемой работы.
Итак, вам предстоит запустить Loginom в Kubernetes. Это может быть осознанным выбором для обеспечения масштабируемости и отказоустойчивости или же просто необходимостью, продиктованной требованиями инфраструктуры вашей компании. В любом случае, задача потребует внимания и определенных знаний.
Так как мы запускаем Loginom в контейнере, использование софтовой лицензии бессмысленно и требуется развертывание сетевого сервера лицензий.
Вариант с пробрасыванием USB-ключа на каждый используемый узел кластера или ноду с сервером лицензий рассматривать не будем — в облаках трудно с физическим доступом, да и эта архитектура не лучшая.
Если вам не повезло и выделить виртуальную машину под сервер лицензий не удалось, то придется запускать его в контейнере, что чревато потерей лицензий при миграции на другой хост — ключи привязываются к оборудованию.
Важно: особенностью программного SP-ключа является криптографическая привязка к оборудованию, т.е. после активации, SP-ключ нельзя повторно активировать или перенести на другой компьютер.
Смотрите документацию.
Формируем Dockerfile:
FROM docker.io/debian:bookworm-slim
LABEL Description="Guardant License Server" \
Version="7.0"
ENV GLDSD_BIN=/usr/sbin/gldsd
ENV GLDSD_PID=/var/run/glds/gldsd.pid
RUN --mount=type=bind,target=/tmp/pkg,source=pkg \
apt upgrade && \
apt update -y && \
apt install -y procps && \
dpkg -i /tmp/pkg/glds-7.*_amd64.deb && \
tar -xz -f /tmp/pkg/sp-7*.tar.gz -C /tmp/ && /tmp/sp-7.0-8/install.sh && \
mkdir -p /opt/guardant/grdspinfo && tar -xz -f /tmp/pkg/grdspinfo.tar.gz -C /opt/guardant/grdspinfo && \
rm -rf /tmp/sp-7* /var/lib/apt/lists/*
SHELL ["/bin/bash", "-c"]
ENTRYPOINT rm -f /var/run/grddaemon.pid /var/run/glds/gldsd.pid && \
/usr/sbin/grddaemond && /usr/sbin/gldsd && \
/opt/guardant/grdspinfo/grdspinfo && \
tail -F /var/log/glds_log.txt
Рядом с Dockerfile создаем каталог pkg
, куда выкладываем glds-7.0-8_amd64.deb
, sp-7.0-8.tar.gz
и grdspinfo.tar.gz
из инсталлятора Loginom.
Собираем базовый образ:
docker build -t glds:7.0 .
Непосредственно на хосте ноды, где будет запущен сервер лицензий, собираем образ с активированной лицензией.
Запускаем консоль в контейнере на базе glds:7.0
, подмонтировав к нему файл с лицензией:
GRD_FILE=./GrdVD_SP.grdvd
docker run -it --name glds --mount type=bind,source=$GRD_FILE,target=/tmp/key.grdvd glds:7.0
Внутри контейнера активируем лицензию:
grdspactivation /tmp/key.grdvd /serial='$serial'
Останавливаем контейнер и сохраняем его как образ — контейнеры сервера лицензий будем создавать уже из него:
docker stop glds
docker commit glds glds-activated:1.0.0
docker rm
Для проверки запускаем на том же хосте, где собирали образ:
docker run -d --name glds-act -p 3185:3185 -p 3186:3186 -p 3187:3187 glds-activated:1.0.0
Собираем образы Loginom в соответствии с инструкцией. Нет, просто docker pull нельзя — это Спарта.
В остальном оставляем настройки по умолчанию. Для удобства пушим образы в приватный container registry, условно cr.example.local:
После подготовки образов Loginom и сервера лицензий необходимо описать их развертывание в Kubernetes. Для этого используются манифесты — YAML-файлы, определяющие конфигурацию подов, сервисов, хранилища и сетевых настроек. В этом разделе рассмотрим примеры манифестов для dev-среды и основные отличия для production-развертывания.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: guardant-server
spec:
replicas: 1
selector:
matchLabels:
app: guardant-server
template:
metadata:
labels:
app: guardant-server
spec:
restartPolicy: Always
containers:
- name: guardant-server
env:
- name: TZ
value: Europe/Moscow
image: glds-activated:1.0.0
imagePullPolicy: IfNotPresent
ports:
# Веб интерфейс сервера guardant
- containerPort: 3185
name: guardant-web
protocol: TCP
# Порт выдачи лицензий
- containerPort: 3186
name: guardant-lic
protocol: TCP
# Порт обмена сообщениями
- containerPort: 3187
name: guardant-msg
protocol: TCP
# Порты должны быть также доступны по UDP
# Порт выдачи лицензий
- containerPort: 3186
name: guardant-lic-udp
protocol: UDP
# Порт обмена сообщениями
- containerPort: 3187
name: guardant-msg-udp
protocol: UDP
affinity:
# Определяем ноду, где будет развернут сервер лицензий
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-2
---
apiVersion: v1
kind: Service
metadata:
name: guardant-server
spec:
type: ClusterIP
ports:
- port: 3185
targetPort: 3185
protocol: TCP
name: guardant-web
- port: 3186
targetPort: 3186
protocol: TCP
name: guardant-lic
- port: 3187
targetPort: 3187
protocol: TCP
name: guardant-msg
- port: 3186
targetPort: 3186
protocol: UDP
name: guardant-lic-udp
- port: 3187
targetPort: 3187
protocol: UDP
name: guardant-msg-udp
selector:
app: guardant-server
В примере сформируем самый простой манифест для dev среды, где в одном поде будут работать сервер Loginom, Integrator и веб-сервер с Loginom Studio.
Рабочий каталог Server будет храниться в постоянном хранилище в файловой системе хоста.
Создаем класс и том хранилища на узле, к примеру, node-2:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-sc
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: loginom-dev-pv
spec:
# Выделенный объем хранилища
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-sc
# Каталог хранилища в файловой системе хоста ноды
local:
path: /mnt/loginom-dev
# Определяем ноду, где будет находиться хранилище
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-2
В node2:/mnt/loginom-dev
выкладываем GnClient.ini
с guardant-server
в качестве адреса сервера лицензий.
Создаем манифест для Loginom:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: loginom-dev-statefulset
spec:
replicas: 1
selector:
matchLabels:
app: loginom
env: dev
Шаблон запроса хранилища:
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
name: loginom-dev-workdir-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: local-sc
volumeMode: Filesystem
Шаблон пода:
template:
metadata:
labels:
app: loginom
env: dev
spec:
restartPolicy: Always
Объявляем необходимые тома:
volumes:
# Здесь будет размещаться сокет для подключения Integrator к Server
- emptyDir:
sizeLimit: 1Mi
name: loginomd-socket-volume
# Если логирование выполняется в journald
- hostPath:
path: /run/systemd/journal/
type: ""
name: journald-socket
# При необходимости в Server использовать кастомные сертификаты с хоста ноды
- hostPath:
path: /usr/share/ca-certificates
type: ""
name: certs
- hostPath:
path: /etc/ca-certificates.conf
type: File
name: etc-certs
- hostPath:
path: /etc/ssl/certs
type: Directory
name: etc-ssl-certs
- hostPath:
path: /etc/ssl/private
type: Directory
name: etc-ssl-private
Определяем контейнеры:
containers:
Server:
При выделении ресурсов контейнеру Server установите одинаковые значения для memory в requests и limits. Также в файле конфигурации сервера Loginom
Settings.cfg
установите атрибут/Settings/@RAMLimitRatio
(«Доля используемой памяти», подробнее в Параметрах сервера) в значении 0.9 — это позволит снизить для него риск быть завершенным OOM Killer'ом.
- name: loginom-server
env:
- name: TZ
value: Europe/Moscow
image: cr.example.local/loginom-ent/server:7.2.3
imagePullPolicy: IfNotPresent
ports:
# Порт для подключения из Studio
- containerPort: 8080
name: loginom-ws
protocol: TCP
# Порт для сетевого подключения Integrator или BatchLauncher
- containerPort: 4580
name: loginom-tcp
protocol: TCP
# Определяем политику использования ресурсов
resources:
requests:
cpu: 4
memory: 8Gi
limits:
memory: 8Gi
volumeMounts:
# Сокет для подключения Integrator
- mountPath: /run/loginom
name: loginomd-socket-volume
# Рабочий каталог Server в постоянном хранилище
- mountPath: /workdir
name: loginom-dev-workdir-pvc
# Сокет для логирования в journald
- mountPath: /run/systemd/journal
name: journald-socket
# Сертификаты
- mountPath: /usr/share/ca-certificates
name: certs
- mountPath: /etc/ca-certificates.conf
name: etc-certs
- mountPath: /etc/ssl/certs
name: etc-ssl-certs
- mountPath: /etc/ssl/private
name: etc-ssl-private
# healthcheck
startupProbe:
tcpSocket:
port: 4580
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 10 # periodSeconds * failureThreshold на запуск loginomd
readinessProbe:
tcpSocket:
port: 4580
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
livenessProbe:
tcpSocket:
port: 4580
initialDelaySeconds: 15
periodSeconds: 20
failureThreshold: 1
Integrator:
- name: loginom-integrator
env:
- name: TZ
value: Europe/Moscow
image: cr.example.local/loginom-ent/integrator:7.2.3
imagePullPolicy: IfNotPresent
ports:
# Порт http для вызова опубликованных сервисов
- containerPort: 5000
name: http-integrator
protocol: TCP
volumeMounts:
# Сокет для подключения к Server
- mountPath: /run/loginom
name: loginomd-socket-volume
# Сокет для логирования в journald
- mountPath: /run/systemd/journal
name: journald-socket
Studio:
- name: loginom-studio
env:
- name: TZ
value: Europe/Moscow
# Включаем wsproxy
- name: USE_WS_PROXY
value: 1
image: cr.example.local/loginom-ent/studio:7.2.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: http-studio
protocol: TCP
Доступ к веб-интерфейсу Studio и Integrator для простоты откроем через NodePort:
apiVersion: v1
kind: Service
metadata:
name: loginom-dev-studio
spec:
type: NodePort
ports:
- port: 80
nodePort: 300001
protocol: TCP
name: http-studio
selector:
app: loginom
env: dev
---
apiVersion: v1
kind: Service
metadata:
name: loginom-dev-integrator
spec:
type: NodePort
ports:
- port: 5000
nodePort: 300002
protocol: TCP
name: http-integrator
selector:
app: loginom
env: dev
---
Studio будет доступна по адресу: http://ip_любой_ноды:30001/app
.
Integrator — http://ip_любой_ноды:30002/rest/help
или http://ip_любой_ноды:30001/lgi/rest/help
.
Прод разворачивается в целом также, в зависимости от кейса использования стоит:
Запуск Loginom в Kubernetes — открывает перед вами возможности по масштабируемости, отказоустойчивости и гибкости управления средой. В процессе развертывания придется решить ряд технических вопросов: от лицензирования и проброса ключей до грамотного конфигурирования манифестов.
Мы разобрали основные этапы:
Теперь у вас есть базовые ориентиры, которые помогут развернуть Loginom в Kubernetes с минимальными подводными камнями. Однако, как и в любом сложном проекте, не забывайте тестировать и адаптировать конфигурацию под свои требования.
Дополнительные материалы:
Использование OpenID для входа в Loginom
Как избежать проклятий: правильная организация сценариев в Loginom