Loginom в Kubernetes

7 апреля 2025
0 комментариев

Разбираем запуск Loginom в Kubernetes: лицензии, образы, манифесты и подводные камни. Готовые решения для стабильной и масштабируемой работы.

Итак, вам предстоит запустить Loginom в Kubernetes. Это может быть осознанным выбором для обеспечения масштабируемости и отказоустойчивости или же просто необходимостью, продиктованной требованиями инфраструктуры вашей компании. В любом случае, задача потребует внимания и определенных знаний.

Лицензии

Так как мы запускаем Loginom в контейнере, использование софтовой лицензии бессмысленно и требуется развертывание сетевого сервера лицензий.

Вариант с пробрасыванием USB-ключа на каждый используемый узел кластера или ноду с сервером лицензий рассматривать не будем — в облаках трудно с физическим доступом, да и эта архитектура не лучшая.

Если вам не повезло и выделить виртуальную машину под сервер лицензий не удалось, то придется запускать его в контейнере, что чревато потерей лицензий при миграции на другой хост — ключи привязываются к оборудованию.

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

Смотрите документацию.

Loginom в Kubernetes

Собираем образ сервера лицензий

Формируем 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

Loginom в Kubernetes

Собираем образы Loginom в соответствии с инструкцией. Нет, просто docker pull нельзя — это Спарта.

  • При сборке образа loginom-httpd (== studio) можно включить в него каталог conf (вместо монтирования в контейнер).
  • При этом из env.conf можно удалить директивы USE_SSL и USE_WS_PROXY и задать их как переменные окружения образа/контейнера для большей гибкости.
  • Желательно включить wsproxy (USE_WS_PROXY=1), иначе надо будет еще server:8080 публиковать (подробнее об использовании wsproxy).

В остальном оставляем настройки по умолчанию. Для удобства пушим образы в приватный container registry, условно cr.example.local:

  • cr.example.local/loginom-ent/server:7.2.3
  • cr.example.local/loginom-ent/studio:7.2.3
  • cr.example.local/loginom-ent/integrator:7.2.3

Манифесты

После подготовки образов 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

Loginom

В примере сформируем самый простой манифест для 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.

Продакшен

Прод разворачивается в целом также, в зависимости от кейса использования стоит:

  1. StatefulSet заменить на Deployment.
  2. Для Server сформировать образы, сразу включающие в себя необходимые сценарии и конфигурации — упростит развертывание версий.
  3. Или монтировать UserStorage с какого-либо единого ресурса, к примеру NFS.
  4. Добавить init-контейнеры для формирования конфигураций.
  5. Добавить side-контейнеры для вывода файловых логов (если journald не используется).
  6. Подключать конфигурации из ConfigMap.

Заключение

Запуск Loginom в Kubernetes — открывает перед вами возможности по масштабируемости, отказоустойчивости и гибкости управления средой. В процессе развертывания придется решить ряд технических вопросов: от лицензирования и проброса ключей до грамотного конфигурирования манифестов.

Мы разобрали основные этапы:

  • Развертывание сервера лицензий и его особенности в контейнерной среде.
  • Сборку и настройку образов Loginom.
  • Создание манифестов для Kubernetes с учетом специфики среды.
  • Отличия между Dev и Production-развертыванием.

Теперь у вас есть базовые ориентиры, которые помогут развернуть Loginom в Kubernetes с минимальными подводными камнями. Однако, как и в любом сложном проекте, не забывайте тестировать и адаптировать конфигурацию под свои требования.

Дополнительные материалы:

Использование OpenID для входа в Loginom

Использование PMML в Loginom

Как избежать проклятий: правильная организация сценариев в Loginom

#loginom

Смотрите также

Подписывайтесь на телеграмм-канал Loginom
Новости, материалы по аналитике, кейсы применения, активное сообщество
Подписаться