Поскольку компания со страшной силы использует 1С, то сложились некие неизменные традиции, одна из которых – это веб-публикации 1С. Плодятся они примерно так: 1 ИБ (информационная база) + например несколько ИБ с тем же смыслом = 1 отдельный web(iis)-сервер, а таких конструкций полно. Получается, что помимо лицензий, мы тратим кучу ресурсов просто на веб-доступ. Поступила идея, что пора экономить (а заодно отказоустойчивость). Пока на этапе экспериментов/тестов.

Стек планируется следующий:

  • ОС — Ubuntu 22.04

  • Docker для создания образа, состоящий из:a) Платформа Ubuntu 22.04b) Apache + gssapi модуль для SSO) Kerberos плюшки

  • Два «стендбай контрол‑узла» k8s в разных ЦОДах для георезерва (bgp‑anycast, haproxy) + ingress.

Долго страдал с подключением SSO, доходило до того, что начинал сомневаться в работоспособности данной конструкции ввиду поломок заголовков при обработке в контейнере, не говоря о дальнейшей миграции в Kubernetes и ingress-прослойке. Но рабочий вариант всё-таки появился. Начну с Dockerfile, состав docker-compose выкладывать не вижу смысла, там всё индивидуально:

FROM docker-hub-proxy-lsus.*/ubuntu:22.04

COPY sources.list /etc/apt/sources.list

ENV DEBIAN_FRONTEND=noninteractive \
    PLATFORM_VERSION=83 \
    SERVER_VERSION=8.3.25-1546

# Установка зависимостей и модулей Apache
RUN echo "krb5-config krb5-config/default_realm string *.RU" | debconf-set-selections && \
    apt update -o Acquire::https::Verify-Peer=false -o Acquire::https::Verify-Host=false && \
    apt install -y \
        apache2 \
        krb5-user \
        libapache2-mod-auth-gssapi \
        vim \
        systemctl \
        apt-utils \
        openssl && \
    a2enmod auth_gssapi

# Установка 1С
ADD *.deb /tmp/
RUN dpkg -i /tmp/1c-enterprise-8.${PLATFORM_VERSION}.${SERVER_VERSION}-*.deb 2>/dev/null || true && \
    rm -f /tmp/*.deb

COPY container/webinst /usr/local/sbin/webinst
COPY container/default.vrd /var/www/test_database/default.vrd
COPY container/svc_1c3.keytab /etc/apache2/apache.keytab
COPY container/000-default.conf /etc/apache2/sites-enabled/000-default.conf
#COPY container/krb5.conf /etc/krb5.conf необязательно, если в дальнейшим идем в кубер

RUN echo "127.0.0.1 ru-rzn-tkube01.*.ru" >> /etc/hosts && \
    webinst -publish -apache24 -wsdir web -dir /var/www/test_database \
            -connstr "Srvr=ru-rzn-t1capp:1541;Ref=web;" \
            -descriptor /var/www/test_database/default.vrd
CMD ["apachectl", "-D", "FOREGROUND"]

Собственно, основные моменты: используем команду "webinst -publish -apache24…" для включения публикации и автоматического заполнения apache2.conf, далее идёт строка подключения к серверу приложений, путь к дескрипшену (.vrd) и копия конфига активированного сайта. Повторюсь, что с SSO были серьезные проблемы, и для стабильной работы получился вот такой конфиг сайта (/etc/apache2/sites-enabled/000-default.conf ):

<VirtualHost *:80>
    ServerName ru-rzn-tkube01.*.ru
    DocumentRoot /var/www/test_database
    <Location /web>
        SetHandler 1c-application
        ManagedApplicationDescriptor "/var/www/test_database/default.vrd"
        
        AuthType GSSAPI
        AuthName "Kerberos Auth"
        GssapiCredStore keytab:/etc/apache2/apache.keytab
        GssapiDelegCcacheDir /var/www/test_database/tmp
        GssapiUseS4U2Proxy On
        GssapiImpersonate On 
        Require valid-user
    </Location>
    LogLevel auth_gssapi:debug
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined     
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Authorization}i\"" authlog
    CustomLog ${APACHE_LOG_DIR}/auth.log authlog
</VirtualHost>

Кроме того, Apache нужно сказать, чтобы он стартовал от пользователя usr1cv8 и группы grp1cv8 (можно задать через переменные или апдейтом apache2.conf), права на kerberos-тикеты аналогичны, и вишенка на торте – это обязательное инициирование Kerberos-билета после деплоя от имени usr1cv8, но инициировать уже после переезда.

Переезд в Kubernetes.  Ломается инициирование Kerberos-билета, но это вполне нормально и ожидаемо. Перед выполнением манифестов сделаю так: создаю директорию /var/www/test_database/tmp и даю ей права chown -R 999:1000 /var/www/test_database/tmp, создаю PVC. Пользователи 999 и 1000 соответствуют usr1cv8 и grp1cv8, похоже, что эта история с правами по умолчанию при установке платформы на Linux.

Манифест без PVC выглядит так:

# ConfigMap: default.vrd
apiVersion: v1
kind: ConfigMap
metadata:
  name: default-vrd
data:
  default.vrd: |
    <?xml version="1.0" encoding="UTF-8"?>
    <point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           base="/web"
           ib="Srvr=ru-rzn-t1capp.*.ru:1541;Ref=web">
        <ws pointEnableCommon="true"/>
        <standardOdata enable="false"
                       reuseSessions="autouse"
                       sessionMaxAge="20"
                       poolSize="10"
                       poolTimeout="5"/>
        <analytics enable="true"/>
    </point>
  
---
# ConfigMap: krb5.conf

apiVersion: v1
kind: ConfigMap
metadata:
  name: krb5-conf
data:
  krb5.conf: |
    [libdefaults]
      default_realm = *.RU
      dns_lookup_realm = false
      dns_lookup_kdc = false
      ticket_lifetime = 24h
      renew_lifetime = 7d
      forwardable = true
  
    [realms]
      *.RU = {
        kdc = ru-dtc-.*.ru
        admin_server = ru-dtc-.*.ru
      }
  
    [domain_realm]
      .*.ru = *
      *.ru = *
  
# Deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache-1c
spec:
  replicas: 1
  selector:
    matchLabels:
      app: apache-1c
  template:
    metadata:
      labels:
        app: apache-1c
    spec:
      hostAliases:
        - ip: "10.101.192.190"
          hostnames:
            - ru-rzn-t1capp     
      containers:
        - name: apache-1c
          image: docker-images-local-lsus.*.ru/apache-1c:http
          ports:
            - containerPort: 80
          volumeMounts:
            - name: default-vrd
              mountPath: /var/www/test_database/default.vrd
              subPath: default.vrd
            - name: www-data
              mountPath: /var/www
            - name: krb5-conf
              mountPath: /etc/krb5.conf
              subPath: krb5.conf
      volumes:
        - name: default-vrd
          configMap:
            name: default-vrd
        - name: www-data
          persistentVolumeClaim:
            claimName: www-data-pvc
        - name: krb5-conf
          configMap:
            name: krb5-conf
---
 
# Service
apiVersion: v1
kind: Service
metadata:
  name: apache-1c-service
spec:
  selector:
    app: apache-1c
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: apache-1c-ingress
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    traefik.ingress.kubernetes.io/router.tls: "true"
    traefik.ingress.kubernetes.io/service.serverstransport: insecure-skip-verify@file
    traefik.ingress.kubernetes.io/service.serversscheme: https
    traefik.ingress.kubernetes.io/auth-pass-through: "true"
    traefik.ingress.kubernetes.io/auth-response-headers: Authorization
spec:
  rules:
    - host: ru-rzn-tkube01.*.ru
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: apache-1c-service
                port:
                  number: 80
  tls:
    - hosts:
        - ru-rzn-tkube01.*.ru
      secretName: apache-1c-tls 

Замечу, что .vrd и krb.conf отправляются в ConfigMaps и не забываем про  kinit -V -k -t /etc/apache2/apache.keytab HTTP/ru-rzn-tkube01.*  от имени usr1cv8, любым, удобным для вас способом (exec, init, post…)

Всё работает исправно две недели подряд. Под нагрузкой пока не тестировался, но чувствую, что будут проблемы на первых парах.

Спасибо за внимание и жду комментариев уже «прохававших» подобный кейс с 1С :-)

Комментарии (8)


  1. shachneff
    16.06.2025 09:03

    Денис, я старый универсальный 1Сник. Не по теме статьи вопрос. Хочу научиться делать георезервирование. Про bgp, anycast, haproxy теорию знаю. Правильно ли я понимаю, что нужно еще иметь свою автономную систему AS и блок PI-адресов?

    Если да, то много ли возни стало с отчетами в РКН, а то ведь и требовать подключение к СОРМ грозились всем владельцам AS?

    И второе. Как реплицируете базы данных между ЦОДами? Быстрой сетки там не будет.

    Спасибо.


    1. Den4irou4 Автор
      16.06.2025 09:03

      Да, Asa участвует в процессе, пиринги, фильтра и т.д. Насчет ркн не могу сказать, у меня другое рабочее поле и честно говоря даже не интересовался) реплика между цодами проходит в обычном режиме, etcd общаются между сегментами, any cast строился для возможности использовать vip между цодами, т.к vrrp не позволяет это выполнить в разных сетях.


  1. siran0
    16.06.2025 09:03

    Привет! спасибо за статью) Сам поел немного с кубером, апачом и пробросом доменки)

    Чтобы не делать ручную инициализацию билета можно воспользоваться параметром GssapiCredStore client_keytab:/etc/httpd.keytab

    Вижу используется ограниченное делегирование GssapiUseS4U2Proxy в апаче. Т.е. на домене для УЗ под которой служба 1С севера работает включено ограниченное делегирование?
    Не было странного поведения при использовании GssapiBasicAuth ? Клиент, вводит свой пароль и попадает в 1С под УЗ другого пользователя, который последний раз авторизовался. При нажатии f5 может оказаться под собой, а может под другим "последним"


    1. Den4irou4 Автор
      16.06.2025 09:03

      УЗ под которой создавался кейтаб имеет делегирование с SPN, который прописан в свойствах 1с админ-консоли, позже попробую убрать делегирование и посмотрю реакцию. GssapiBasicAuth это в работу пока не смотрел. У меня всегда моя учетка) на основании залогиненой УЗ прилетает krb билет под эту УЗ и без стороннего вмешательства, думаю, что схема будет отрабатывать нормально ) GssapiCredStore client_keytab:/etc/httpd.keytab - спасибо, попробуем)


  1. 4iker
    16.06.2025 09:03

    Вопрос к ТС:
    У вас в инфраструктуре ИБ запрещали использование протоколов на уровне домена rc4-hmac?
    Наша доменная авторизация после этого перестала работать на клиентах 1С, различные махинации пока не дали никаких плодов в связке 1С и Ubuntu 20.04\22.04

    Интересует именно вопрос проброса керберос тикета через веб, с какими типами шифрования Вы это выполняете, и использовались ли какие-то особые ключи на формирование keytab со стороны контроллера домена?
    Заранее спасибо!


    1. Den4irou4 Автор
      16.06.2025 09:03

      Про подобный запрет я не слышал. У нас AES-256. я понял о чем вы) нет, я конкретно шифр не выбираю при создании, мне по умолчанию приходит AES-256. Из такого разве что попробовать -crypto ALL


  1. VenbergV
    16.06.2025 09:03

    Возможно спрошу глупость, но все же.
    Разве нельзя все связанное с проксированием и резервированием делать исключительно средствами nginx/haproxy? А apache оставить один, там же где 1С, лицензии, базы данных?
    Как поведет себя конструкция, когда придет OOM Killer за 1С? Или вы рассматриваете свой случай для лицензии 1С Корп?
    Хотя по конструкции у вас похоже ключи находятся на клиенте и файловая база.
    Но возможно я не понял полноты замысла.


    1. Den4irou4 Автор
      16.06.2025 09:03

      В нашем случае будет проще iis ставить на апликейшены) Вот с учетом разделенных компонентов 1с-инфраструктуры и придумывается такой вариант, а так я думаю это далеко не глупость и вариант вполне рабочий. Дело в том, что в случае контейнеров, можно сделать реплики и разгрузить нагрузку на единичный экземпляр и в целом масштабирование. Hasp ключ натравлен на app1c для серверной лицензии, клиентские обращаются за своими.