Сценарии администрирования#

Администрирование#

Подключение к VM (VM - виртуальная машина), на которых установлен Продукт SynGX, для выполнения действий администрирования, должно осуществляться по протоколу SSH с использованием SSH-ключей.

Администрирование проводится от имени пользователя syngx, созданного ранее при установке SynGX.

Перечень доступных стандартных сценариев администрирования SynGX:

  • Запуск SynGX;

  • Остановка SynGX;

  • Перезапуск SynGX;

  • Изменение конфигурации SynGX;

  • Проверка корректности конфигурации с точки зрения SynGX;

  • Обновление версии SynGX (см. Руководство по установке);

  • Удаление SynGX (см. Руководство по установке);

  • Получение логов (см. раздел События системного журнала);

  • Получение метрик (см. раздел События мониторинга).

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

Описание основных сценариев администрирования#

В данном разделе будут описаны основные сценарии администрирования - запуск, остановка и перезагрузка конфигурации Продукта.

Предполагается, что SynGX уже установлен на сервере и произведена первичная настройка конфигурации Продукта.

Запуск SynGX

Важно: (опционально; обязательно при интеграции с HashiCorp Vault-решением) если требуется интеграция SynGX с HashiCorp Vault, то перед запуском необходимо произвести настройку конфигурационного файла согласно разделу «Настройка интеграции SynGX с HashiCorp Vault» ниже.

В начале переходим под учетную запись ОС с административными правами:

$ sudo su

Затем необходимо прописать переменные окружения для пакета, выполнив команду:

$ source /etc/environment

После чего, нужно убедиться, что syngx не запущен, - проверить c помощью команды ps -ef | grep syngx.

Теперь можно произвести запуск SynGX (варианты на выбор):

  • Запуск с базовой конфигурацией SynGX:

$ syngx
  • Запуск SynGX с отличной от базовой конфигурацией:

$ syngx -c /<путь к требуемому конфигурационному файлу>
  • Запуск SynGX с использованием команды systemctl:

$ systemctl start syngx.service

Тем самым, будет произведен запуск SynGX.

Опцианально, если требуется, чтобы SynGX автоматически запускался после перезагрузки ОС, это можно сделать, выполнив команду:

$ systemctl enable syngx.service

Управление SynGX

Когда SynGX запущен, им можно управлять, вызывая исполняемый файл с параметром -s. Ниже показан базовый синтаксис:

syngx -s сигнал

Флаг -s отправляет сигнал главному процессу SynGX.

Вместо «сигнал» нужно подставить одно из следующих значений для управления процессом SynGX:

  • stop — быстрое завершение работы SynGX: немедленно завершает все процессы SynGX, останавливает обслуживание полученных запросов;

  • quit — плавное завершение работы SynGX: останавливает процессы SynGX после завершения обработки полученных до команды запросов;

  • reload — перезагрузка (применение) конфигурации: позволяет применить новую конфигурацию без остановки работы SynGX. Запросы, которые были получены до перезагрузки SynGX, будут обрабатываться согласно старой конфигурации, а новые запросы - согласно новой конфигурации.

Как происходит перезагрузка конфигурационного файла: получив соответствующий сигнал, главный процесс проверяет правильность синтаксиса нового конфигурационного файла и пытается применить конфигурацию, содержащуюся в нем. Если это ему удается, главный процесс запускает новые рабочие процессы и отправляет сообщения старым рабочим процессам требование завершиться. Если не получается применить новую конфигурацию, главный процесс откатывает изменения и продолжает работать со старой конфигурацией. Старые рабочие процессы, получив команду завершиться, прекращают принимать новые запросы и продолжают обслуживать текущие запросы до тех пор, пока все такие запросы не будут обслужены. После чего старые рабочие процессы завершаются.

Настройка балансировки нагрузки и распределения запросов при проксировании#

SynGX поддерживает следующие способы балансировки нагрузки и распределения запросов при проксировании:

  • (Weighted) Round Robin - запросы распределяются по узлам в группе балансировки циклически в соответствии с весами узлов. Если вес узла не указан явно, он считается равным 1. Это алгоритм используется по умолчанию в upstream и может использоваться для протоколов HTTP, TCP и UDP.

  • (Weighted) Least Connections – запрос посылается на узел в группе балансировки с наименьшим количество активных соединений в соответствии с весами узлов. Если вес узла не указан явно, он считается равным 1. Для использования данного метода балансировки, необходимо указать директиву least_conn в секции upstream. Этот алгоритм может использоваться для протоколов HTTP, TCP и UDP.

  • IP Hash – узел в группе балансировки, на который будет отправлен запрос, определяется на основании IP клиента. Этот метод гарантирует, что запросы с одного IP-адреса будут направляться на один тот же узел, пока он работоспособен. Для использования данного метода балансировки необходимо указать директиву ip_hash в секции upstream. Этот алгоритм может использоваться для протоколов HTTP.

  • Hash - узел в группе балансировки, на который будет направлен запрос, определяется на основании определенного в конфигурации ключа, который может быть строкой, переменной или их комбинацией. Для использования данного метода балансировки необходимо указать директиву hash с параметрами в секции upstream. Этот алгоритм может использоваться для протоколов HTTP, TCP и UDP.

  • Random - запрос передается случайно выбранному узлу в группе балансировки в соответствии с весами узлов. Для использования данного метода балансировки необходимо указать директиву random в секции upstream. Этот алгоритм может использоваться для протоколов HTTP, TCP и UDP.

Для активации требуемого способа балансировки при проксировании запросов, необходимо добавить соответствующую директиву с параметрами в секции upstream.

Пример задания способа балансировки:

    upstream myapp1 {
        <способ балансировки>;
        server srv1.example.com weight=2;
        server srv2.example.com;
        server srv3.example.com;
    }

Примечание: параметр weight опционален.

Внимание:

  • Совместно с методами балансировки hash и ip_hash нельзя использовать параметр backup для server в upstream.

  • При использовании модуля keepalive для upstream соответствующие директивы обязательно должны идти после настроек балансировки.

Настройка прилипания запросов к узлу в группе балансировки#

SynGX поддерживает несколько способов настройки, при которой запросы, обладающие какими-либо общими признаками, будут направляться на один и тот же узел в группе балансировки. Общим признаком может быть, например, наличие в запросе определенной cookie, которая содержит некоторое значение, характеризующее сессию клиента. Перенаправление запросов на один и тот же узел в группе балансировки в этом случае называется прилипанием.

Если признак, на основании которого запросы должны направляться на один и тот же узел в группе балансировки, устанавливается не SynGX и не узлами в группе балансировки (например, если в качестве признака используется cookie или токен, выданная сервисом авторизации, либо IP клиента) следует использовать способы балансировки Hash или IP Hash.

Если такой признак должен устанавливать SynGX в ответ на первый запрос, необходимо использовать директиву sticky cookie или sticky name в секции upstream. В этом случае, SynGX в ответ на первый запрос добавляет в ответ клиенту cookie, которую затем клиент указывает со всех следующих запросах.

Если такой признак должен устанавливать узел в группе балансировки в ответ на первый запрос, необходимо использовать директиву sticky route или sticky learn в секции upstream. В этом случае, узел, на который был перенаправлен первый запрос, в ответ клиенту добавляет cookie, которую затем клиент указывает во всех следующих запросах. Информация, содержащаяся в данной cooke, используется SynGX, чтобы выбрать узел, на который перенаправить запрос.

Во всех случаях прилипания, если запрос не содержит признак, на основании которого можно выбрать узел, либо содержит признак, на основании которого нельзя выбрать узел в соответствии с заданными настройками (в том числе, если выбранный узел выведен из балансировки на основании активной проверки работоспособности), SynGX выбирает узел на основе заданного алгоритма балансировки - например, Round Robin или Least Connections. В конфигурационном файле для группы upstream вместе со sticky можно указать один из следующих способов балансировки - round_robin, least_conn, hash, ip_hash или random.

Описание директив приведено ниже. Все директивы указываются внутри секции http/upstream

Внимание:

  • Совместно с прилипанием нельзя использовать параметр backup для server в upstream.

  • При использовании модуля keepalive для upstream соответствующие директивы обязательно должны идти после директивы sticky.

Возможны два варианта написания - sticky cookie example_cookie и sticky name=cookie_example. Более предпочтительным является вариант написания sticky cookie example_cookie. Вариант написания sticky name=cookie_example оставлен для совместимости с предыдущими версиями SynGX, но в следующих версиях поддерживаться не будет.

    upstream {
      sticky cookie cookie_name;
      server 127.0.0.1:9000;
      server 127.0.0.1:9001;
      server 127.0.0.1:9002;
    }
  sticky cookie example_cookie [domain=.foo.bar] [path=/] [expires=1h]
       [hash=index|md5|sha1] [no_fallback] [secure] [httponly];
    upstream {
      sticky name=cookie_example;
      server 127.0.0.1:9000;
      server 127.0.0.1:9001;
      server 127.0.0.1:9002;
    }
  sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h]
       [hash=index|md5|sha1] [no_fallback] [secure] [httponly];

example_cookie

  • syntax: example_cookie *string*;

  • default: -

  • context: -

Имя cookie. Обязательный параметр при использовании семантики Nginx Plus.

name

  • syntax: name *string*;

  • default: route

  • context: -

Имя cookie.

domain

  • syntax: name *string*;

  • default: ``

  • context: -

Определяет домен, для которого установлен файл cookie.

path

  • syntax: path *string*;

  • default: /

  • context: -

путь, по которому cookie будет действительным.

expires

  • syntax: expires *time*;

  • default: ``

  • context: -

срок действия cookie. Длительность не должна быть меньшще одной секунды.

hash

  • syntax: hash *md5|sha1|index*;

  • default: md5

  • context: -

Hash для кодирования имени вышестоящего сервера. Не может использоваться вместе с hmac параметром. Надо быть осторожным при выборе значения index. Этот метод не делает хеширование. Вместо него используется индекс в памяти - это быстрее и накладные расходы короче.

Внимание: после reload при использовании index не гарантируется совпадение со списком вышестоящих серверов по индексу!

hmac

  • syntax: hmac *md5|sha1*;

  • default: ``

  • context: -

HMAC hash для кодирования имени вышестоящего сервера. Не может использоваться вместе с hash параметром. Работает подобно hash, но использует „hmac_key“ параметр для безопасности.

hmac_key

  • syntax: hmac *string*;

  • default: ``

  • context: -

Ключ безопасности для использования hmac хеширования. Обязательный параметр, если указан параметр hmac.

no_fallback

  • syntax: no_fallback *flag*;

  • default: ``

  • context: -

Если флаг установлен, то SynGX будет возвращать 502 (Bad Gateway или Proxy Error) ошибку, если запрос пришел с cookie, а соответствующий вышестоящий сервер недоступен.

secure

  • syntax: secure *flag*;

  • default: ``

  • context: -

Если флаг установлен, то включается режим безопасной cookie. Работает только через HTTPs соединение.

httponly

  • syntax: httponly *flag*;

  • default: ``

  • context: -

Если флаг установлен, то запрещается утечка cookie через js.

2025/02/05 12:19:52 [error] 63814#63814: *45 [sticky/init_sticky_peer] the cookie "503e61637dd91cd98f986c297ebafdsc" does not match digest for any peer in "test_https" upstream. Just ignoring it ..., client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", host: "127.0.0.1:8001"
2025/02/05 12:19:52 [error] 63814#63814: [sticky/init_sticky_peer] name "vm-lt1-fh-susd-1646.nt-vdc13.solution.sbt:8082", server "127.5.1.1:8082", digest  "f08df3f3df47ceaffa02cf97731b9d2f"
2025/02/05 12:19:52 [error] 63814#63814: [sticky/init_sticky_peer] name "vm-lt1-fh-susd-1646.nt-vdc13.solution.sbt:8082", server "127.5.0.1:8082", digest  "6c9d98341d09d7b262f85c5668e819e0"

Первой строкой логируется информация о пришедшем от клиента запросе с cookie и именем upstream. Последующие несколько строк дают расширенную информацию обо всех вышестоящие серверах в этом upstream

Sticky route#

При использовании метода прилипания route клиенту в ответ на первый запрос назначается «маршрут», ассоциируемый с узлом, на который запрос был перенаправлен. Из всех последующих запросов SynGX извлекает «маршрут» (например, как часть cookie или URI запроса) и сравнивает его значение с параметром route директивы server в upstream. Узел в группе балансировки, для которого значение параметра route совпадает с «маршрутом», выбирается для перенаправления запроса. Однако если выбранный узел выведен из балансировки по результатам активной проверки работоспособности, SynGX выбирает другой узел в соответствии с заданным алгоритмом балансировки.

Если параметр route не указан, имя будет генерироваться как hash MD5 IP-адреса и порта. Если назначенный сервер не может обработать запрос, новый сервер выбирается с помощью настроенного метода балансировки, как если бы в запросе не было информации о маршрутизации.

Параметры метода route определяют переменные, которые могут содержать информацию о маршрутизации. Первая непустая переменная используется для поиска соответствующего сервера.

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

  map $cookie_jsessionid $route_cookie {
      ~.+\.(?P<route>\w+)$ $route;
  }

  map $request_uri $route_uri {
      ~jsessionid=.+\.(?P<route>\w+)$ $route;
  }

upstream backend {
  server 127.0.0.1:8080 route=a;
  server 127.0.0.1:8081 route=b;

  sticky route $route_cookie $route_uri;
}

route

  • syntax: route *string*;

  • default: ``

  • context: - Параметр директивы server, который задает значение для поиска вышестоящего сервера по правилам описанным в параметрах директивы sticky route.

Sticky learn#

При использование метода прилипания learn SynGX проверяет наличие в ответе заданной в конфигурации cookie с помощью переменной в параметре create (в примере ниже эта переменная указывает на заголовок Set-Cookie и в ней cookie «examplecookie»), извлекает ее и запоминает в привязке к узлу в группе балансировки, который ее выставил. Все последующие запросы от клиента с этой cookie будут перенаправляться на этот же узел. Однако если выбранный узел выведен из балансировки по результатам активной проверки работоспособности, SynGX выбирает другой узел в соответствии с заданным алгоритмом балансировки, как если бы привязки не существовало.

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

http {
  upstream backend {
    server backend1.example.com:8080;
    server backend2.example.com:8081;

    sticky learn
            create=$upstream_cookie_examplecookie
            lookup=$cookie_examplecookie
            zone=client_sessions:1m
            timeout=1h
            cookie_max_size=256
            gc_period=5m
            session_rotate=off
            fill_limit_minor_log=70
            fill_limit_major_log=85
            fill_limit_crit_log=90;
  }

  server {
      listen          1984;
      server_name     'localhost';

      location /backend {
          proxy_pass http://our_backend;
      }

      location /learn_json {
          sticky_learn_status_json true;
      }

      location /learn_prometheus {
          sticky_learn_status_prometheus true;
      }
  }
}

create

  • syntax: create *variable*;

  • default: -

  • context: -

    Задает переменные, в которых указывается способ создания новых сессий. В данном примере сервер группы создает сессию путем установки куки “EXAMPLECOOKIE” в ответе. Параметр может быть указан больше одного раза (в этом случае используется первая непустая переменная).

lookup

  • syntax: lookup *variable*;

  • default: -

  • context: -

    Задает переменные, в которых указывается способ поиска существующих сессий. В данном примере сервер группы будет искать сессию содержащую куку “EXAMPLECOOKIE” в запросе. Параметр может быть указан больше одного раза (в этом случае используется первая непустая переменная).

zone

  • syntax: zone *complex*;

  • default: -

  • context: -

    Задает имя и размер зоны в разделяемой памяти для хранения сессий. Для каждой секции upstream создается своя независимая от других секций зона. В одной мегабайтной зоне может храниться около 1850 сессий на 64-битной платформе при дефолтной настройке cookie_max_size параметра.

    Пример сообщения о возможном максимальном количестве сессий, которое печатается в лог файле при старте SynGX:

    2024/02/12 12:20:49 [debug] 96208#96208: [sticky/init_module] sessions max count=1858
    

    Внимание: Расчет максимально доступного количества сессий изменилось в версии 2.1 Оно уменьшилось по сравнению с 2.0.0 версией.

timeout

  • syntax: timeout *time*;

  • default: 10m

  • context: -

    Сессии, к которым не было обращений в течение времени, заданного параметром timeout, удаляются из зоны. По умолчанию timeout равен 10 минутам.

gc_period

  • syntax: gc_period *time*;

  • default: timeout/2 (5 minutes)

  • context: -

    Период запуска garbage collector для удаления просроченных сессий. По умолчанию значение равно половине значения параметра timeout - 5 минут.

cookie_max_size

  • syntax: cookie_max_size *size*;

  • default: 256

  • context: -

    Максимальная длина cookie, которая будет сохраняться в shared memory для поиска клиентских сессий. Значение по умолчанию - 256 символов. Максимальное значение для параметра - 4096 символов. Если длина оригинальной cookie превышает значение, заданное в параметре, то при сохранение в памяти будут обрезаны символы с конца строки. Чем больше значение параметра, тем меньше сессий будет храниться при одном и том же значении значении параметра zone

  • syntax: session_rotate *flag*;

  • default: off

  • context: -

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

    Пример сообщения при достижении максимально возможного количества и при значении параметра off:

    2024/02/06 08:18:23 [error] 16072#16072: *13 [sticky learn] client session cannot be created because the maximum number of sessions has been exceeded while reading response header from upstream
    

    Пример сообщения при достижении максимально возможного количества и при значении параметра on:

    2024/02/06 09:13:31 [warn] 51575#51575: *13 [sticky learn] remove oldest client session while reading response header from upstream
    2024/02/06 09:13:31 [warn] 51575#51575: [sticky] remove client session "cookie_8080"
    2024/02/06 09:13:31 [crit] 51575#51575: *13 [sticky learn] number of sessions exceeds 90% of maximum possible amount of sessions while reading response header from upstream
    



fill_limit_minor_log

  • syntax: fill_limit_minor_log *percents*;

  • default: 70 %

  • context: -

    Пороговое значение количества активных клиентских сессий в процентах от максимально возможного количества, при котором выдается сообщение в лог файл на уровне [warn]. Пример сообщения:

  2023/10/23 14:19:35 [warn] 29885#29885: *7 [sticky learn] number of sessions exceeds 70% of maximum possible amount of sessions



fill_limit_major_log

  • syntax: fill_limit_major_log *percents*;

  • default: 85 %

  • context: -

    Пороговое значение количества активных клиентских сессий в процентах от максимально возможного количества, при котором выдается сообщение в лог файл на уровне [error]. Пример сообщения:

  2023/10/23 14:19:35 [error] 29885#29885: *7 [sticky learn] number of sessions exceeds 85% of maximum possible amount of sessions



fill_limit_crit_log

  • syntax: fill_limit_crit_log *percents*;

  • default: 90 %

  • context: -

    Пороговое значение количества активных клиентских сессий в процентах от максимально возможного количества, при котором выдается сообщение в лог файл на уровне [crit]. Пример сообщения:

  2023/10/23 14:19:35 [crit] 29885#29885: *7 [sticky learn] number of sessions exceeds 90% of maximum possible amount of sessions



Директивы для получения статистики#

Название метрики

Описание метрики

active_sessions

количество сессий

max_possible_sessions

максимально возможное количество сессий на группе балансировки, рассчитывается по размеру выделенному в shared_memory параметром zone директивы sticky

created_sessions

количество созданных сессий за все время (в том числе удаленных)

При выполнении reload статистика по сессиям сохраняется.

Синтаксис: sticky_learn_status_json флаг;
Умолчание: false;
Контекст: http/server/location

Директива для получения статистики в формате json, необязательный параметр. Пример:

curl http://127.0.0.1:1984/learn_json
{"sticky_learn_sessions": {
  "total_servers": 5,
  "upstreams": [
    {
      "name": "our_backend",
      "active_sessions": 4,
      "max_possible_sessions": 5,
      "created_sessions": 4,
      "servers": [
        {"index": 0, "server": "127.0.0.1:8080", "active_sessions": 1, "created_sessions": 1},
        {"index": 1, "server": "127.0.0.1:8081", "active_sessions": 1, "created_sessions": 1},
        {"index": 2, "server": "127.0.0.1:8082", "active_sessions": 1, "created_sessions": 1},
        {"index": 3, "server": "127.0.0.1:8083", "active_sessions": 1, "created_sessions": 1},
        {"index": 4, "server": "127.0.0.1:8084", "active_sessions": 0, "created_sessions": 0}
      ]
    }
  ]
}}



Синтаксис: sticky_learn_status_prometheus флаг;
Умолчание: false;
Контекст: http/server/location

Директива для получения статистики в формате prometheus, необязательный параметр. Пример:

curl http://127.0.0.1:1984/learn_prometheus
# HELP sticky_learn_active_sessions Current number of active sessions
# TYPE sticky_learn_active_sessions gauge
# HELP sticky_learn_max_possible_sessions Max possible number of active sessions
# TYPE sticky_learn_max_possible_sessions gauge
# HELP sticky_learn_created_sessions Total number of created sessions
# TYPE sticky_learn_created_sessions counter
sticky_learn_active_sessions{upstream="our_backend"} 4
sticky_learn_max_possible_sessions{upstream="our_backend"} 5
sticky_learn_created_sessions{upstream="our_backend"} 4
sticky_learn_active_sessions{upstream="our_backend", server="127.0.0.1:8080"} 1
sticky_learn_created_sessions{upstream="our_backend", server="127.0.0.1:8080"} 1
sticky_learn_active_sessions{upstream="our_backend", server="127.0.0.1:8081"} 1
sticky_learn_created_sessions{upstream="our_backend", server="127.0.0.1:8081"} 1
sticky_learn_active_sessions{upstream="our_backend", server="127.0.0.1:8082"} 1
sticky_learn_created_sessions{upstream="our_backend", server="127.0.0.1:8082"} 1
sticky_learn_active_sessions{upstream="our_backend", server="127.0.0.1:8083"} 1
sticky_learn_created_sessions{upstream="our_backend", server="127.0.0.1:8083"} 1
sticky_learn_active_sessions{upstream="our_backend", server="127.0.0.1:8084"} 0
sticky_learn_created_sessions{upstream="our_backend", server="127.0.0.1:8084"} 0



Динамически настраиваемая группа серверов в Upstream с периодическими проверками работоспособности#

SynGX предоставляет возможность в процессе работы отслеживать изменения IP-адресов узла в группе балансировки, соответствующих указанному в директиве server доменному имени и обновлять их в памяти без необходимости перезагрузки конфигурации. Необходимые условия:

  1. В секции upstream должна быть задана директива zone. В одной и той же зоне могут быть сразу несколько групп. В этом случае достаточно указать размер только один раз. Количество разделяемой памяти для каждого сервера в Upstream, у которого есть параметр resolve, составляет порядка 16 килобайт. Такой большой рамер связан с возможностью разрешения DNS имени во множество ip адресов. Более подробная информация - https://nginx.org/ru/docs/http/ngx_http_upstream_module.html#zone и https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#setting-the-zone-size

  2. Должна быть задана директива resolver в соответствующей секции upstream.

  3. Для каждого сервера в группе балансировки, для которого необходимо отслеживать изменения IP-адресов, должен быть задан параметр resolve.

  4. Дополнительно для таких серверов можно указать параметр service, который включает преобразование SRV-записей DNS и задает имя сервиса.

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

Пример конфигурации#

    upstream u {
        zone z 1m;

        server foo.example.com:8081 resolve;
        server bar.example.com service=http resolve;
        server backup.example.com:8081 resolve backup;
        server nonexist.example.com:8081 resolve backup;

        resolver 127.0.0.1:5353 valid=1s ipv6=off;

        server 127.0.0.1:8081;
        server 127.0.0.11:8081;

        check interval=3000 rise=1 fall=1 timeout=1000 type=http;
    }

Параметры#

resolve

  • syntax: resolve flag;

  • default: -

  • context: ``

    Параметр директивы server в секции upsteam. Отслеживает изменения IP-адресов, соответствующих доменному имени сервера, и автоматически изменяет конфигурацию группы. Для работы параметра необходимо указать директиву resolver для соответствующей секции upsteam.

service

  • syntax: service name;

  • default: -

  • context: ``

    Параметр директивы server в секции upsteam. Включает преобразование SRV-записей DNS и задает имя сервиса. Для работы параметра необходимо указать параметр resolve для сервера и не указывать порт сервера. Если имя сервиса не содержит точку (“.”), то имя составляется в соответствии с RFC и в префикс службы добавляется протокол TCP. Например, для получения SRV-записи _http._tcp.backend.example.com необходимо указать директиву:

server backend.example.com service=http resolve;

Если имя сервиса содержит одну и более точек, то имя составляется при помощи соединения префикса службы и имени сервера. Например, для получения SRV-записей _http._tcp.backend.example.com и server1.backend.example.com необходимо указать директивы:

server backend.example.com service=_http._tcp resolve;
server example.com service=server1.backend resolve;

SRV-записи с наивысшим приоритетом (записи с одинаковым наименьшим значением приоритета) преобразуются в основные серверы, остальные SRV-записи преобразуются в запасные серверы. Если в конфигурации сервера указан параметр backup, высокоприоритетные SRV-записи преобразуются в запасные серверы, остальные SRV-записи игнорируются.

resolver

  • syntax: resolver address ... [valid=time] [ipv4=on|off] [ipv6=on|off];

  • default: -

  • context: http/upstream, stream/upstream

Задает серверы DNS, используемые для преобразования имен вышестоящих серверов в адреса, например:

resolver 127.0.0.1 [::1]:5353;

Адрес может быть указан в виде доменного имени или IP-адреса, и необязательного порта. Если порт не указан, используется порт 53. Серверы DNS опрашиваются циклически.

По умолчанию nginx будет искать как IPv4-, так и IPv6-адреса при преобразовании имен в адреса. Если поиск IPv4- или IPv6-адресов нежелателен, можно указать параметр ipv4=off или ipv6=off.

По умолчанию nginx кэширует ответы, используя значение TTL из ответа. Необязательный параметр valid позволяет это переопределить:

resolver 127.0.0.1 [::1]:5353 valid=30s;

Для предотвращения DNS-спуфинга рекомендуется использовать DNS-серверы в защищенной доверенной локальной сети.

resolver_timeout

  • syntax: resolver_timeout time;

  • default: 30s

  • context: http/upstream, stream/upstream

Задает таймаут для преобразования имени в адрес, например:

resolver_timeout 5s;



Примеры вывода статистики при работе с resolver#

Пример конфигурации при запуске SynGX#

    upstream u {
        zone z 1m;

        server foo.example.com:8081 resolve;
        server bar.example.com service=http resolve;
        server backup.example.com:8081 resolve backup;
        server nonexist.example.com:8081 resolve backup;

        resolver 127.0.0.1:5353 valid=1s ipv6=off;

        server 127.0.0.1:8081;
        server 127.0.0.11:8081;

        check interval=3000 rise=1 fall=1 timeout=1000 type=http;
    }

Пример вывода healthcheck статистики при недоступности DNS сервера#

Мы получаем список серверов, которые не требуют разрешение доменных имен с помощью DNS сервера

{"active_healthcheck": {
  "total_servers": 2,
  "generation": 1,
  "servers": [
    {"index": 2, "upstream": "u", "server": "127.0.0.1:8081", "down": false, "active_healthcheck_status": "ON", "rise": 2, "fall": 0, "check_type": "http", "port": 0},
    {"index": 3, "upstream": "u", "server": "127.0.0.11:8081", "down": true, "active_healthcheck_status": "UNDEFINE", "rise": 0, "fall": 3, "check_type": "http", "port": 0}
  ]
}}

Пример вывода healthcheck статистики после разрешения доменных имен в DNS сервере#

Мы получаем дополнительно список серверов, которые были разрешены с помощью DNS сервера. Сервер с доменным именем nonexist.example.com не был в списке DNS сервера.

{"active_healthcheck": {
  "total_servers": 6,
  "generation": 1,
  "servers": [
    {"index": 0, "upstream": "u", "server": "foo.example.com (127.0.0.1:8081)", "down": false, "active_healthcheck_status": "ON", "rise": 1, "fall": 0, "check_type": "http", "port": 0},
    {"index": 1, "upstream": "u", "server": "bar.example.com (127.0.0.2:8082)", "down": false, "active_healthcheck_status": "ON", "rise": 2, "fall": 0, "check_type": "http", "port": 0},
    {"index": 2, "upstream": "u", "server": "127.0.0.1:8081", "down": false, "active_healthcheck_status": "ON", "rise": 1, "fall": 0, "check_type": "http", "port": 0},
    {"index": 3, "upstream": "u", "server": "127.0.0.11:8081", "down": true, "active_healthcheck_status": "UNDEFINE", "rise": 0, "fall": 2, "check_type": "http", "port": 0},
    {"index": 4, "upstream": "u", "server": "backup.example.com (127.0.0.4:8081)", "down": true, "active_healthcheck_status": "UNDEFINE", "rise": 0, "fall": 2, "check_type": "http", "port": 0},
    {"index": 4, "upstream": "u", "server": "backup.example.com (127.0.0.3:8081)", "down": true, "active_healthcheck_status": "UNDEFINE", "rise": 0, "fall": 2, "check_type": "http", "port": 0}
  ]
}}

Примеры логирования в процессе разрешения доменных имен в DNS сервере#

Пример логирования при успешном разрешении доменного имени#

2024/03/27 13:31:58 [debug] 155203#155203: name baz.example.com was resolved to 127.0.0.5:0 s:"" n:"" w:0

Пример логирования при неудачном разрешении доменного имени#

024/03/27 13:31:57 [error] 155203#155203: baz.example.com could not be resolved (110: Operation timed out)

Пример логирования при добавлении нового сервера в группу балансировки#

2025/02/05 09:55:17 [error] 55609#55609: Server "baz.example.com" with IP address "127.5.1.1:8082" added to http upstream "test_https"

Пример логирования при удалении существующего сервера из группы балансировки#

2025/02/05 09:55:17 [error] 55609#55609: Server "baz.example.com" with IP address "127.1.0.1:8082" deleted from http upstream "test_https"

Пример HC логирования при формировании запроса к серверу по ip, полученному из доменного имени#

024/03/27 13:31:58 [debug] 155204#155204: [hc] begin handler for resolved peer (baz.example.com)

Переопределение имен узлов в группе балансировки, используемых при проверке сертификата#

При использовании протокола TLS между SynGX и узлами в группе балансировки возможна ситуация, при которой сертификат каждого узла имеет свой CN или SAN. Чтобы переопределить имя узла, которое будет использоваться при проверке сертификата этого узла, а также для передачи его через SNI при установлении TLS соединения с узлом, необходимо указать дополнительный параметр tag в директиве server в секции upstream. Указанный таким образом параметр определяет проверки, аналогичные проверкам при указании директивы proxy_ssl_name, но на уровне одного узла.

При применении параметра tag в server в upstream и параметра proxy_ssl_name в http/server/location, приоритетным при проверке сертификата этого узла является tag, при этом proxy_ssl_name не используется при проверке сертификата этого узла. Допустимы одновременно сервера в upstream с параметром tag и без него, при этом для server без tag, переопределенное имя узла, которое будет использоваться при проверке сертификата, будет браться из proxy_ssl_name.

Пример конфигурации:

    upstream server_ssl {
        server 127.0.0.1:8001 tag=tag_name;
        server 127.0.0.1:8002;
        server 127.0.0.1:8100;
    }

    server {
        server_name ssl_cert;
        listen 8001 ssl;
	    location / {
            return 200 "SERVER_1_SSL_WORK!\n";
        }
    }

    server {
        server_name ssl_cert;
        listen 8002 ssl;
	    location / {
            return 200 "SERVER_2_SSL_WORK!\n";
        }
    }

    server {
        server_name ssl_test;
        listen 8010 ssl;
        proxy_ssl_certificate         /opt/syngx/ssl/client.crt;
        proxy_ssl_certificate_key     /opt/syngx/ssl/client.key;
        proxy_ssl_trusted_certificate /opt/syngx/ssl/ca.crt;
        proxy_ssl_name  server_ssl_name;
        proxy_ssl_verify on;
        proxy_ssl_protocols TLSv1.2;
        proxy_ssl_ciphers AES256-SHA;
        location / {
            proxy_pass https://server_ssl;
        }
    }

Ограничение на количество HTTP запросов в единицу времени на каждый узел в группе балансировки#

Механизм квотирования на каждый узел в группе балансировки позволяет предотвращать каскадный отказ серверов при уменьшении количества работающих узлов. Механизм позволяет ограничить скорость обработки запросов по заданному ключу или, как частный случай, скорость обработки запросов, поступающих с одного IP-адреса. Ограничение обеспечивается с помощью метода leaky bucket.

Необходимые условия: Должна быть задана по крайней мере одна зона разделяемой памяти - limit_req_zone. Подробное описание директивы - https://nginx.org/ru/docs/http/ngx_http_limit_req_module.html#limit_req_zone

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

Пример конфигурации#

http {
    limit_req_zone $binary_remote_addr zone=one_upstream:10m rate=10r/s;

    upstream u {
        server 127.0.0.1:8081;
        server 127.0.0.2:8082;

        limit_req_by_node zone=one_upstream;
        limit_req_status_by_node 439;
        limit_req_log_level_by_node error;
        limit_req_dry_run_by_node off;
    }

    server {
        listen       127.0.0.1:8080;

        location /upstream {
            proxy_pass http://u;
        }
    }
}

Директивы#

limit_req_by_node

  • syntax: limit_req_by_node zone=название [burst=число] [nodelay | delay=число];

  • default: -

  • context: http/upstream

Задает зону разделяемой памяти zone и максимальный размер всплеска запросов burst. Если скорость поступления запросов, распределенных на выбранный узел, превышает описанную в зоне, то их обработка задерживается так, чтобы запросы обрабатывались с заданной скоростью. Избыточные запросы задерживаются до тех пор, пока их число не превысит максимальный размер всплеска. При превышении запрос завершается с ошибкой. По умолчанию максимальный размер всплеска равен нулю. Например, директивы

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

http {
    upstream u {
        server 127.0.0.2:8082;
        limit_req_by_node zone=one burst=5;
    }
}

позволяют в среднем не более 1 запроса в секунду со всплесками не более 5 запросов.

Если же избыточные запросы в пределах лимита всплесков задерживать не требуется, то следует использовать параметр nodelay:

limit_req zone=one burst=5 nodelay;

Параметр delay задает лимит, по достижении которого избыточные запросы задерживаются. Значение по умолчанию равно нулю и означает, что задерживаются все избыточные запросы.

Директив limit_req_by_node может быть несколько в одной upstream секции.

limit_req_dry_run_by_node

  • syntax: limit_req_dry_run_by_node on | off;

  • default: limit_req_dry_run_by_node off

  • context: http/upstream

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

limit_req_log_level_by_node

  • syntax: limit_req_log_level_by_node info | notice | warn | error;

  • default: limit_req_log_level_by_node error

  • context: http/upstream

Задает желаемый уровень записи в лог случаев отказа в обработке запросов при превышении скорости и случаев задержек при обработке запроса. Задержки записываются в лог с уровнем на единицу меньшим, чем отказы, например, если указано limit_req_log_level_by_node notice, то задержки будут записываться в лог на уровне info.

limit_req_status_by_node

  • syntax: limit_req_status_by_node код;

  • default: limit_req_status_by_node 503

  • context: http/upstream

Позволяет переопределить код ответа, используемый при отклонении запросов.

Примеры логирования задержек проксирования запроса#

При дефолтных настройках limit_req_log_level_by_node и значения параметра delay = 1 в директиве limit_req_by_node в error_log файле на уровне debug будет выводится информация при правильной работе, на уровне warn при задержках, а на уровне error при отклонении запроса.

Пример логирования без задержек проксирования запроса#

2024/04/15 06:17:53 [debug] 6738#6738: *4 limit_req[0]: 0 0.619 by node "127.0.0.1:8081"

Здесь параметр 0.619 - означает время в секундах, прошедшее с предыдущего запроса на этот узел.

Пример логирования с задержкой проксирования запроса#

2024/04/15 06:17:54 [warn] 6738#6738: *7 delaying request by node "127.0.0.1:8081", excess: 1.267, by zone "one" while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8081/", host: "127.0.0.1:8080"

Здесь параметр 1.267 - означает время в секундах, прошедшее с предыдущего запроса на этот узел. Так как это время превышает параметр delay, то SynGX сделает задержку запроса на узел и выдаст предупреждение на уровне warn

Пример логирования c отклонением прокисрования запроса#

2024/04/15 06:19:57 [error] 8377#8377: *10 limiting requests by node "127.0.0.1:8081", excess: 2.162 by zone "one" while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8081/", host: "127.0.0.1:8080"



Сбор информации об IP-адресе клиента#

Статический модуль ngx_http_geoip2_module позволяет создавать переменные со значениями из баз данных MaxMind GeoIP2 на основе IP-адреса клиента (по умолчанию) или из определенной переменной (поддерживает как IPv4, так и IPv6). Модуль работает на уровне http и stream. Базы данных MaxMind GeoIP2 предоставляют контекстные данные для полного профиля IP-адресов, включая данные геолокации (регион, город, почтовый индекс) и дополнительные данные (ISP, домен, тип подключения). Используя эти данные, SynGX сможет выполнять различные сценарии, например, предоставлять разный тип контента в зависимости от страны.

Необходимые условия: Выполните дополнительную настройку в соответствии с требованиями модуля - https://github.com/leev/ngx_http_geoip2_module#user-content-download-maxmind-geolite2-database-optional

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

Пример конфигурации#

http {
    ...
    geoip2 /etc/maxmind-country.mmdb {
        auto_reload 5m;
        $geoip2_metadata_country_build metadata build_epoch;
        $geoip2_data_country_code default=US source=$variable_with_ip country iso_code;
        $geoip2_data_country_name country names en;
    }

    geoip2 /etc/maxmind-city.mmdb {
        $geoip2_data_city_name default=London city names en;
    }
    ....

    fastcgi_param COUNTRY_CODE $geoip2_data_country_code;
    fastcgi_param COUNTRY_NAME $geoip2_data_country_name;
    fastcgi_param CITY_NAME    $geoip2_data_city_name;
    ....
}

stream {
    ...
    geoip2 /etc/maxmind-country.mmdb {
        $geoip2_data_country_code default=US source=$remote_addr country iso_code;
    }
    ...
}

Директивы#

$geoip2

  • syntax: $geoip2 path

  • default: -

  • context: http|stream

Директива geoip2 используется для загрузки и использования базы данных GeoIP2 от MaxMind. Путь к базе данных должен быть записан как параметр к этой директиве. База данных содержит информацию о географическом расположении IP-адресов, такую как страна, регион, город, код ISO и другие данные.

$variable_name metadata

  • syntax: $variable_name metadata <field>

  • default: -

  • context: http/geoip2|stream/geoip2

Используется для извлечения метаданных базы данных GeoIP2 от MaxMind. Доступные значения для <field>:

  • build_epoch: временная метка сборки базы данных maxmind.

  • last_check: последний раз, когда база данных проверялась на наличие изменений (при использовании auto_reload)

  • last_change: последний раз, когда база данных была перезагружена (при использовании auto_reload)

auto_reload

  • syntax: auto_reload <interval>;

  • default: -

  • context: http/geoip2|stream/geoip2

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

$variable_name

  • syntax: $variable_name [default=<value] [source=$remote_addr] path ...;

  • default: -

  • context: http/geoip2|stream/geoip2

Заполняется переменная с заданным вместо variable_name именем - например $geoip2_data_country_code_our. Если значение параметра default не указано, то значение переменной будет пустой, если соответствие ip не будет найдено в базе данных. Если параметр source не указан, то для выполнения поиска будет использоваться встроенная переменная nginx $remote_addr. Обязательным параметром является путь до поля в базе данных, значение которого подставлено в переменную в зависимости от значения параметра source. База данных имеет древовидную структуру и путь до поля представляет список названия листьев дерева. В качестве разделителя используется пробел. Например $geoip2_data_location_latitude location latitude; будет обозначать, что в переменную $geoip2_data_location_latitude по $remote_addr необходимо записать географическую широту места, где зарегистрирован ip соответствующий $remore_addr. Чтобы определить путь к нужным данным (например: названия стран en), используйте инструмент mmdblookup - https://maxmind.github.io/libmaxminddb/mmdblookup.html

geoip2_proxy

  • syntax: geoip2_proxy <CIDR>;

  • default: -

  • context: http|stream

Определяет доверенные адреса. Когда запрос поступает с доверенного адреса, вместо него будет использоваться адрес из поля заголовка запроса X-Forwarded-For. Однако, если вы укажете параметр source=$variable_with_ip для переменной, то эта настройка будет игнорироваться для этой конкретной переменной.

geoip2_proxy_recursive

  • syntax: geoip2_proxy_recursive <on | off>;

  • default: off

  • context: http|stream

Если рекурсивный поиск отключен, то вместо исходного адреса клиента, который соответствует одному из доверенных адресов, будет использоваться последний адрес, отправленный в X-Forwarded-For. Если включен рекурсивный поиск, то вместо исходного адреса клиента, который соответствует одному из доверенных адресов, будет использоваться последний недоверенный адрес, отправленный в X-Forwarded-For. Однако если вы укажете параметр source=$variable_with_ip для переменной, то эта настройка будет игнорироваться для этой конкретной переменной.

Пример конфигурации для ограничения доступа по географическому местоположению#

В этом примере IP-адрес будет проверен в базе данных GeoLite2-Country.mmdb и результат будет записан в переменную $geoip2_data_continent_code. SynGX будет сопоставлять значение переменной со значениями в директиве map и записывать результат в пользовательской переменной $nearest_server. Исходя из значения $nearest_server, директива proxy_pass выберет соответствующий upstream.

# Может быть в "http {}" или "stream {}" секции
#...
geoip2 GeoIP2/GeoLite2-Country.mmdb {
    $geoip2_data_continent_code continent code;
}

map $geoip2_data_continent_code $nearest_server {
    default all;
    EU      eu;
    NA      na;
    AS      as;
    AF      af;
}

server {
    listen 12346;
    proxy_pass http://$nearest_server;
    }

upstream all {
    server all1.example.com:12345;
    server all2.example.com:12345;
}

upstream eu {
    server eu1.example.com:12345;
    server eu2.example.com:12345;
}

upstream na {
    server na1.example.com:12345;
    server na2.example.com:12345;
}

Получение обратной трассировки программных вызовов в случае аварийного завершения рабочего процесса#

Эта функциональность может быть использована для восстановления обратной трассировки syngx в случае аварийного завершения рабочего процесса, например, при получении сигналов - SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV. Сигналы, на которые выдаётся обратная трассировка

SIGABRT - Сигнал, посылаемый функцией abort() SIGBUS - Неправильное обращение в физическую память SIGFPE - Ошибочная арифметическая операция SIGILL - Недопустимая инструкция процессора SIGSEGV - Нарушение при обращении в память (segmentation fault)

Эта функциональность используется для целей отладки.

Директивы#

$backtrace

  • syntax: $backtrace flag

  • default: off

  • context: main

Директива backtrace разрешает рабочему процессу перехватывать сигнал и записывать обратную трассировку в файл.

$backtrace_log

  • syntax: $backtrace_log path

  • default: -

  • context: main

Директива backtrace_log указывает файл, в который будет записана обратная трассировка. Если директива не указана, то запись будет осуществленна в error.log файл на уровне error.

$backtrace_max_stack_size

  • syntax: $backtrace_max_stack_size number

  • default: 30

  • context: main

Директива backtrace_max_stack_size указывает размер стека для записи обратной трассировки.

Пример конфигурации#

worker_processes auto;

error_log /opt/syngx/logs/error.log error;
backtrace_log /opt/syngx/logs/backtrace.log;
backtrace_max_stack_size 40;
backtrace on;

events {
    worker_connections  4096;
}

http {
}

Пример записи в backtrace.log в случае аварийного завершения рабочего процесса#

2025/03/10 14:26:34 [error] 89149#89149: [backtrace] coredump by signal 4 (SIGILL)
syngx: worker process[0x54c760]
/lib64/libpthread.so.0(+0x12cf0)[0x7f206d612cf0]
/lib64/libc.so.6(epoll_wait+0x1b)[0x7f206a92f20b]
syngx: worker process[0x44af1a]
syngx: worker process(ngx_process_events_and_timers+0xab)[0x43eee2]
syngx: worker process[0x448d89]
syngx: worker process(ngx_spawn_process+0x572)[0x447181]
syngx: worker process[0x447def]
syngx: worker process(ngx_master_process_cycle+0x1c8)[0x449818]
syngx: worker process(main+0xe09)[0x41c1e3]

Подключение динамических модулей SynGX#

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

Ниже представлен список модулей с динамическим подключением:

Наименование модуля (названия динамических модулей SynGX)

Функционал модуля

Настройка модуля

ngx_devel_kit (ndk_http_module)

Модуль предназначен для расширения основных функциональных возможностей NGINX

См. информацию тут https://github.com/vision5/ngx_devel_kit

lua-nginx-module (ngx_http_lua_module)

Модуль позволяет добавить логику обработки запросов с использованием языка программирования Lua

См. информацию тут https://github.com/openresty/lua-nginx-module

stream-lua-nginx-module (ngx_stream_lua_module)

Модуль позволяет добавить логику обработки запросов с использованием языка программирования Lua для протоколов TCP и UDP

См. информацию тут https://github.com/openresty/stream-lua-nginx-module

lua-upstream-nginx-module (ngx_http_lua_upstream_module)

Модуль позволяет реализовать на языке Lua логику взаимодействия со статусом узла в группе балансировки в http контексте

См. информацию тут https://github.com/openresty/lua-upstream-nginx-module

njs/nginx (ngx_http_js_module, ngx_stream_js_module)

Модуль позволяет добавлять логику обработки запросов с использованием подмножества языка JavaScript

См. информацию тут https://nginx.org/ru/docs/http/ngx_http_js_module.html , https://nginx.org/ru/docs/stream/ngx_stream_js_module.html

nginx-sslkeylog (ngx_http_sslkeylog_module)

Модуль добавляет переменные для логгирования данных SSL сессий

См. информацию тут https://github.com/tiandrey/nginx-sslkeylog

ngx_brotli (ngx_http_brotli_filter_module, ngx_http_brotli_static_module)

Модуль позволяет добавить алгоритм сжатия данных без потерь. Используется для сжатия ответов на лету либо для отдачи предварительно сжатых файлов

См. информацию тут https://github.com/google/ngx_brotli

nginx-module-stream-sts

Модуль производит сбор статистики на уровне L4 OSI (UDP и TCP соединения)

См. информацию тут https://github.com/vozlt/nginx-module-stream-sts

nginx-module-sts

Модуль добавляет возможность отображения статистики по запросам на уровне L4

См. информацию тут https://github.com/vozlt/nginx-module-sts

nginx-upload-module

Модуль разбирает тело запроса и сохраняет все загружаемые файлы в каталог, заданный директивой upload_store. Загружаемые файлы исключаются из тела запроса, и измененный запрос после этого отправляется на location, задаваемый директивой upload_pass, позволяя обрабатывать загрузку файлов произвольным образом

См. информацию тут https://github.com/vkholodkov/nginx-upload-module/tree/develop

set-misc-nginx-module (ngx_http_set_misc_module)

Модуль расширяет стандартный набор директив HttpRewriteModule - добавляет экранирование/отмену экранирования URI, обработку кавычек в JSON, шестнадцатеричное/MD5/SHA1/Base32/Base64 дайджест-кодирование и декодирование, генератор случайных чисел и пр.

См. информацию тут https://github.com/openresty/set-misc-nginx-module

ngx_hashicorp_vault_module

Модуль позволяет получать из Hashicorp Vault PKI сертификаты и ключи сертификатов, которые могут быть использованы вместо директив ssl_certificate, ssl_certificate_key, proxy_certificate, proxy_ssl_certificate, grpc_ssl_certificate, grpc_ssl_certificate_key, snx_ahc_ssl_certificate и snx_ahc_ssl_certificate_key для секций http и stream

См. раздел «Настройка интеграции SynGX с HashiCorp Vault» ниже

ngx_stream_rst_send_module

Модуль позволяет настроить отправку пакета TCP с флагом RST для отклонения входящих соединений по результатам активной проверки работоспособности, когда все узлы в группе балансировки stream секции выведены из балансировки

См. раздел «Отправка пакета TCP с флагом RST на входящие TCP соединения» ниже

ngx_http_rst_send_module

Модуль позволяет настроить отправку пакета TCP с флагом RST для отклонения входящих соединений по результатам активной проверки работоспособности, когда все узлы в группе балансировки http секции выведены из балансировки

См. раздел «Отправка пакета TCP с флагом RST на входящие TCP соединения» ниже

Необходимые действия для подключения динамического модуля:

  1. (опционально; пройти этот шаг 1, если требуется установка динамических модулей ngx_http_lua_module, ngx_stream_lua_module, ngx_http_lua_upstream_module либо ngx_http_set_misc_module) Установить и добавить в конфигурационный файл SynGX (файл с расширением .conf) модуль ndk_http_module (контекст main). Без него подключить модуль ngx_http_lua_module, ngx_stream_lua_module либо ngx_http_set_misc_module будет нельзя!

    • Для установки модуля ndk_http_module в командной строке необходимо выполнить команду (пример команды): $sudo yum install ndk_http_module.rpm .

    • После чего в конфигурационном файле SynGX (файл с расширением .conf) требуется добавить директиву с указанием пути к файлу ndk_http_module.so (контекст main). Пример задания директивы: load_module /opt/syngx/modules/ndk_http_module.so .

  2. Установить модуль(-и) из RPM-пакета(-в) и добавить в конфигурационный файл (файл с расширением .conf) директиву(-ы) подключения модуля(-ей) (контекст main):

    • установить требуемый(-ые) динамический(-ие) модуль(-и). Для этого нужно для каждого модуля выполнить команду $sudo yum install {module_name}.rpm. Где {module_name} - название модуля (см. в таблице выше, названия динамических модулей SynGX даны в скобках);

    • после чего в конфигурационном файле SynGX (файл с расширением .conf) требуется добавить директиву(-ы) с указанием пути(-ей) к файлу(-ам) динамических модулей (контекст main). Пример задания директивы: load_module /opt/syngx/modules/{module_name}.so .

  3. После выполнения действий в шаге 2 необходимо выполнить перезагрузку конфигурационного файла SynGX сигналом reload.

Пример указания динамических модулей в конфигурационном файле SynGX (часть конфигурации SynGX):

syngx_dynamic_modules

Важно!:

  • при применении директив из модуля ngx_http_set_misc_module следует использовать актуальные криптостойкие алгоритмы, исходя из требований эксплуатирующей организации (не следует использовать слабые криптографиеские алгоритмы, например, SHA-1 либо SSHA).

Настройка интеграции SynGX с HashiCorp Vault#

Описание

Примечание: возможно использование как HashiCorp Vault, так и Secret Management System/SecMan. Далее по тексту интеграцию с HashiCorp Vault (упоминание HashiCorp Vault) считать аналогичным интеграции с Secret Management System/SecMan.

Краткая информация для администратора:

SynGX может получать сертификаты и закрытые ключи сертификатов из движка секретов PKI Hashicorp Vault и использовать их вместо следующих директив в секциях http и stream:

  • http/ssl_certificate, http/ssl_certificate_key

  • http/proxy_ssl_certificate, http/proxy_ssl_certificate_key

  • grpc_ssl_certificate и grpc_ssl_certificate_key

  • http/snx_ahc_ssl_certificate, http/snx_ahc_ssl_certificate_key

  • stream/ssl_certificate, stream/ssl_certificate_key

  • stream/proxy_ssl_certificate, stream/proxy_ssl_certificate_key

  • stream/snx_ahc_ssl_certificate, stream/snx_ahc_ssl_certificate_key

Функциональность получения сертификатов и закрытых ключей сертификатов из движка секретов PKI Hashicorp Vault обеспечивает динамический модуль ngx_hashicorp_vault, который должен быть подключен в конфигурации SynGX.

Модуль работает следующим образом:

  • после старта SynGX:

  1. с помощью указанных в конфигурации секретов проходит аутентификацию и авторизацию в HashiCorp Vault и получает необходимые для дальнейшей работы токены;

  2. с помощью полученных на предыдущем шаге токенов запрашивает в HashiCorp Vault все определенные в конфигурации SynGX сертификаты;

  3. для каждого сертификата разделяет ответ на две части - публичную часть сертификата и закрытый ключ сертификата. Публичная часть сертификата сохраняется на файловой системе на VM SynGX. Закрытый ключ хранится в hashicorp_shm_zone (shared memory), доступ к которому есть только у привилегированного агент-процесса (privileged agent process) и мастер процесса (master). Обе части сертификата используются для инициализации в памяти значений переменных для сертификатов, которые указываются в конфигурации.

  • во время работы SynGX:

  1. проверяет срок действия сертификатов, и при приближении к дате окончания действия сертификата - запрашивает новый сертификат, обновляет публичную часть сертификата на файловой системе, обновляет в памяти соответствующие переменные и перезагружает SynGX;

  2. при перезагрузке SynGX, в том числе, при изменении конфигурации - проверяет наличие в конфигурации директив для работы с Hashicorp Vault и наличие в памяти соответствующих публичных частей сертификатов и закрытых ключей сертификатов;

  3. предоставляет метрики по взаимодействию с Hashicorp Vault;

  4. запись в error log событий, связанных с взаимодействием с Hashicorp Vault.

Настройка модуля ngx_hashicorp_vault_module

Ниже будет дана информация о настройках динамического модуля ngx_hashicorp_vault_module, который обеспечивает интеграцию SynGX с HashiCorp Vault.

Модуль ngx_hashicorp_vault_module поддерживает работу как с PKI, так и с KV движком Hashicorp Vault

Поддержка TLS: модуль поддерживает обращение к Hashicorp Vault с использованием протокола TLS версии не ниже 1.2

Пререквизиты для интеграции SynGX с HashiCorp Vault (что необходимо сделать перед настройкой интеграции SynGX с HashiCorp Vault):

  1. наличие и штатная работа HashiCorp Vault в сети;

  2. до запуска SynGX на сервер SynGX администратором загружены актуальные role_id и wrapped_token.

  3. установлен модуль ngx_hashicorp_vault_module из RPM пакета, и добавлены директивы для работы модуля в конфигурацию SynGX. Описание шагов установки и подключения приведено в разделе «Подключение динамических модулей SynGX».

Для включения возможности интеграции SynGX с HashiCorp Vault необходимо в конфигурации syngx.conf (конфигурационный файл SynGX с расширением .conf; далее будем обозначать как syngx.conf):

  • задать директиву delayed_load_cert (контекст: main); после чего указать директивы и параметры к ним для получения сертификатов (конфигурация для интеграции с с HashiCorp Vault);

  • потом задать директивы для использования сертификатов.

Ниже будет дан пример части конфигурации с параметрами для интеграции с PKI движком HashiCorp Vault.

Пример части конфигурации для интеграции с PKI движком HashiCorp Vault

...

delayed_load_cert;

hv_pki secman_1 {
    host <адрес SecMan>; # HashiCorp Vault hostname, обязательный параметр
    port 8443;  # HashiCorp Vault port, обязательный параметр
    api_version v1; # версия api Hashicorp Vault, необязательный параметр, если не указан - используется значение по умолчанию - v1
    namespace DEV_TEST; # используется для получения токена и генерации сертификата (заголовок X-Vault-Namespace), обязательный параметр

    # параметры для аутентификации и получения токена, который будет использоваться установкой заголовка "X-Vault-Token:"
    auth_approle {
       role_id_file /opt/secman/syngx/roleid.txt; #обязательный параметр
       wrapped_token_file /opt/secman/syngx/wrapped_token2.txt; # обязательный параметр

    # Рекомендуется обязательно настраивать TLS версии не ниже 1.2 для взаимодействия с Hashicorp Vault. Пример такой настройки приведен ниже
        hv_ssl_trusted_certificate /home/syngx/syngx/tests/cert/ca.crt;
        hv_ssl_verify on; # default off
        hv_ssl_protocols TLSv1.2;
        hv_ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
    }

    # параметры для поиска или генерации сертификата.
    get_cert cert1 {
        path PKI; # path - путь до хранилища (он же PKI), обязательный параметр
        role role-secman-snx; # роль, обязательный параметр

        email test@example.ru;  # Почтовый адрес владельца сертификата для отправки уведомлений от УЦ, обязательный параметр
        common_name test.app.yyy; # Указывает CN для сертификата, обязательный параметр
        # alt_names example.ru; # Указывает SAN в списке, необязательный параметр, если не указан - не используется

        save_certificate_path /opt/syngx/ssl/server3.crt; # путь для сохранения публичной части сертификата, обязательный параметр
    }

    get_cert cert2 {
        path PKI; # path - путь до хранилища (он же PKI), обязательный параметр
        role role-secman-snx2; # роль, обязательный параметр

        email test@example.ru;  # Почтовый адрес владельца сертификата для отправки уведомлений от УЦ, обязательный параметр
        common_name test.app.yyy; # Указывает CN для сертификата, обязательный параметр

        save_certificate_path /opt/syngx/ssl/server4.crt; # путь для сохранения публичной части сертификата, обязательный параметр
    }
}
...

Ниже будет дан пример части конфигурации с параметрами для интеграции с KV движком HashiCorp Vault.

Пример части конфигурации для интеграции с KV движком HashiCorp Vault

...

delayed_load_cert;

hashicorp_vault secman_1 {
    host <адрес SecMan>; # HashiCorp Vault hostname, обязательный параметр
    port 8443;  # HashiCorp Vault port, обязательный параметр
    namespace DEV_TEST; # используется для получения токена и генерации сертификата (заголовок X-Vault-Namespace), обязательный параметр
    # параметры для аутентификации и получения токена, который будет использоваться установкой заголовка "X-Vault-Token:"
    auth_approle {
       role_id_file /opt/secman/syngx/roleid.txt; #обязательный параметр
       wrapped_token_file /opt/secman/syngx/wrapped_token2.txt; # обязательный параметр

    # Рекомендуется обязательно настраивать TLS версии не ниже 1.2 для взаимодействия с Hashicorp Vault. Пример такой настройки приведен ниже
        hv_ssl_trusted_certificate /home/syngx/syngx/tests/cert/ca.crt;
        hv_ssl_verify on; # default off
        hv_ssl_protocols TLSv1.2;
        hv_ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
    }

    # параметры для поиска или генерации сертификата.
    get_cert_kv cert1 {
        path_engine                  A/DEV/APP/GATEWAYS/SNGX/KV2;
        path_secret                  /storage1;
        hv_kv_ssl_certificate_key prv_key;
        hv_kv_ssl_certificate pub_key;

        save_certificate_path /opt/syngx/ssl/server1.crt;

        reserved_path_engine         A/DEV/APP/GATEWAYS/SNGX/KV2; # путь до резервного KV движка
        reserved_path_secret         /reserv1; # путь до резервного KV хранилища
        update_expiring_cert_interval 60; # время в минутах, через которое SynGX делает попытку получить новый валидный сертификат, если срок действия ранее полученного сертификата истекает
        update_cert_before_expiration 10;
    }

    get_cert_pki cert2 {
        path PKI; # path - путь до хранилища (он же PKI), обязательный параметр
        role role-secman-snx2; # роль, обязательный параметр

        email test@example.ru;  # Почтовый адрес владельца сертификата для отправки уведомлений от УЦ, обязательный параметр
        common_name test.app.yyy; # Указывает CN для сертификата, обязательный параметр

        save_certificate_path /opt/syngx/ssl/server4.crt; # путь для сохранения публичной части сертификата, обязательный параметр
    }
}
...

Описание параметров

Контекст

Название параметра и синтаксис

Описание

Обязательность

Значение по умолчанию

main

hv_pki <имя approle> {}

Директива. Блок с настройками одной approle. Применяется для PKI движка

Обязательный

-

main

hashicorp_vault <имя approle> {}

Директива. Блок с настройками одной approle. Применяется для KV и для PKI движка

Обязательный

-

hv_pki
hashicorp_vault

type <http/https>

Тип соединения - HTTP/HTTPs

Необязательный

type https

hv_pki
hashicorp_vault

host <ссылка>

IP-адрес или доменное имя HashiCorp Vault

Обязательный

-

hv_pki
hashicorp_vault

port <номер>

HashiCorp Vault порт

Обязательный

-

hv_pki
hashicorp_vault

api_version <номер>

Версия API Hashicorp Vault

Необязательный

api_version v1

hv_pki
hashicorp_vault

namespace <имя>

Namespace, который будет использоваться для получения токена и генерации сертификата (заголовок X-Vault-Namespace)

Обязательный

-

hv_pki
hashicorp_vault

response_timeout <число в секундах>

Время ожидания ответа в секундах. Если ответ не пришел, производится повторная попытка. Общее количество попыток определяется параметром num_retries

Необязательный

response_timeout 3

hv_pki
hashicorp_vault

get_certs_on_reload <on/off>

Флаг для принудительного запроса и применения новых сертификатов после перезагрузки (reload) SynGX

Необязательный

get_certs_on_reload off

hv_pki
hashicorp_vault

auth_approle {}

Блок параметров для аутентификации и получения токена, который будет использоваться установкой заголовка «X-Vault-Token:»

Обязательный

-

auth_approle

role_id_file <путь>

Путь расположения файла role_id

Обязательный

-

auth_approle

wrapped_token_file <путь>

Путь расположения файла wrapped_token

Обязательный

-

auth_approle

wrapped_token_ttl <число в минутах>

Время жизни wrapped_token в минутах

Необязательный

wrapped_token_ttl 10080

auth_approle

wrapped_token_interval <число в минутах>

Период перевыпуска wrapped_token в минутах

Необязательный

wrapped_token_interval 720

auth_approle

num_retries <число>

Количество попыток при неуспешном запросе. Количество „0“ означает бесконечное количество попыток

Необязательный

num_retries 1440

auth_approle

retry_interval <число в секундах>

Время между повторными попытками при неуспешных запросах на аутентификацию, wrap/unwrap/rewrap токенов и получение сертификатов. Запрещено использовать одновременно с retry_interval_gap

Необязательный

retry_interval 5

auth_approle

retry_interval_gap <нижняя граница в секундах> <верхняя граница в секундах>

Интервал, из которого случайным образом будет вычисляться время между повторными попытками при неуспешных запросах на аутентификацию, wrap/unwrap/rewrap токенов и получение сертификатов. Запрещено использовать одновременно с retry_interval. Минимальное значение нижней границы - 1 секунда, максимальное значение верхней границы не ограничено

Необязательный

retry_interval_gap 5 10

auth_approle

access_interval <число в секундах>

Время между последовательными успешными запросами на аутентификацию, wrap/unwrap/rewrap токенов и получение сертификатов. В случае неуспешного запроса, следующая попытка делается через время, определенное директивой retry_interval

Необязательный

access_interval 2

auth_approle

retry_codes <http коды>

Список кодов ответа на запрос в HashiCorp Vault, при которых SynGX будет делать повторный запрос по правилам описанным выше для неуспешных запросов. При получении ответа с кодом 200 запрос считается успешным. В случае, если полученный код не содержится в директиве retry_codes, то попытки буду возобновлены через время указанное в директивах wrapped_token_interval/get_cert_interval

Необязательный

retry_codes 307 429 500 502 503

auth_approle

retcode_invalid_token <код http ответа>

Ожидаемый код ответа от HashiCorp Vault при невалидином wrapped token

Необязательный

retcode_invalid_token 400

auth_approle

error_invalid_token <текст ошибки>

Ожидаемый текст ошибки от HashiCorp Vault при невалидином wrapped token

Необязательный

<строка для проверки не задана, проверка текста ошибки не производится>

hv_pki

get_cert <имя роли> {}

Параметры для поиска или генерации сертификатов и ключей с помощью PKI движка

Обязательный

-

hashicorp_vault

get_cert_kv <имя роли> {}

Параметры для поиска или генерации сертификатов и ключей с помощью KV движка

Обязательный

-

hashicorp_vault

get_cert_pki <имя роли> {}

Параметры для поиска или генерации сертификатов и ключей с помощью PKI движка

Обязательный

-

get_cert
get_cert_pki

path <путь>

Путь до хранилища (например: PKI)

Обязательный

-

get_cert_kv

path_engine <путь>

Путь до используемого движка KV2

Обязательный

-

get_cert_kv

path_secret <путь>

Путь до используемого хранилища KV2

Обязательный

-

get_cert
get_cert_pki

role <роль>

Роль в HashiCorp Vault. В Secret Management System соответствует полю name

Обязательный

-

get_cert
get_cert_kv
get_cert_pki

get_cert_retries <число>

Количество попыток при неуспешном запросе

Необязательный

get_cert_retries 5

get_cert
get_cert_pki

method <название метода получения>

Название метода для получения сертификата. Возможные значения - fetch/issue

Необязательный

method fetch

get_cert
get_cert_kv
get_cert_pki

update_cert_before_expiration <число в днях>

Количество дней до окончания срока действия сертификата, когда надо запросить новый сертификат

Необязательный

update_cert_before_expiration 10

get_cert
get_cert_kv
get_cert_pki

min_delay_update <число в минутах>

Минимальное количество минут для запроса нового сертификата, время действия которого при выпуске меньше суток. В основном этот параметр используется для отладочных целей

Необязательный

min_delay_update 60

get_cert
get_cert_kv
get_cert_pki

get_cert_interval <число в минутах>

Время, через которое возобновятся попытки получения сертификата, в случае если количество неудачных попыток достигло значение get_cert_retries

Необязательный

get_cert_interval 60

get_cert
get_cert_pki

email <адрес email>

Почтовый адрес владельца сертификата для отправки уведомлений от УЦ

Обязательный

-

get_cert
get_cert_pki

common_name <адрес>

Указывает CN для сертификата

Обязательный

-

get_cert
get_cert_pki

alt_names <имя1,имя2>

Указывает SAN в виде списка

Необязательный

Если не указан, то параметр не используется

get_cert
get_cert_pki

ip_sans <ip1,ip2>

Указывает IP для SAN в виде списка

Необязательный

Если не указан, то параметр не используется

get_cert
get_cert_pki

uri_sans <uri1,uri2>

Указывает URI для SAN в виде списка

Необязательный

Если не указан, то параметр не используется

get_cert
get_cert_pki

other_sans

Задает настраиваемые SAN со строкой OID/UTF8

Необязательный

Если не указан, то параметр не используется

get_cert
get_cert_pki

exclude_cn_from_sans

Параметр, включающий/выключающий возможность исключить common_name из DNS или электронной почты SAN

Необязательный

Если не указан, то параметр не используется

get_cert
get_cert_kv
get_cert_pki

save_certificate_path <путь>

Путь для сохранения сертификата (указать путь до файла), полученного от HashiCorp Vault

Обязательный

-

get_cert_kv

hv_kv_ssl_certificate <имя ключа>

Наименование ключа в KV хранилище для публичной части сертификата

Обязательный

-

get_cert_kv

hv_kv_ssl_certificate_key <имя ключа>

Наименование ключа в KV хранилище для приватной части сертификата

Обязательный

-

get_cert_kv

reserved_path_engine <путь>

Путь до резервного KV2 движка, который будет использоваться в случае невалидности сертификата из основного хранилища

Необязательный

-

get_cert_kv

reserved_path_secret <путь>

Путь до резервного KV2 хранилища с сертификатом, который будет использоваться в случае невалидности сертификата из основного хранилища

Необязательный

-

get_cert_kv

update_expiring_cert_interval <число в минутах>

Время в минутах, через которое SynGX делает попытку получить новый валидный сертификат, если срок действия ранее полученного сертификата истекает

Необязательный

update_expiring_cert_interval 60

auth_approle

hv_ssl_verify <on/off>

Проверка ssl_verify для TLS-соединения с HashiCorp Vault

Необязательный

hv_ssl_verify off

auth_approle

hv_ssl_verify_depth <число>

Устанавливает глубину проверки в цепочке сертификатов

Необязательный

hv_ssl_verify_depth 1

auth_approle

hv_ssl_protocols <TLSvномер версии>

Версия TLS для TLS-соединения с HashiCorp Vault

Необязательный

hv_ssl_protocols TLSv1.2

auth_approle

hv_ssl_ciphers <шифры>

Используемые шифры для TLS-соединения с HashiCorp Vault (не рекомендуется использовать шифры с алгоритмами шифрования MD5, DES, CBC, RC4 и длинами ключей шифрования меньше 256 бит)

Необязательный

hv_ssl_ciphers DEFAULT

Параметры format и private_key_format в конфигурации не указываются, но при обращении в HashiCorp Vault они указываются со значением pem.

Полный список параметров для интеграции с Secret Management System можно изучить в документации на данную систему (Руководство администраторов АС по выпуску сертификатов через плагин SbrCA).

Примечание: SynGX не поддерживает метод passphrase. Остальные - поддерживает.

Описание и настройка директив для использования сертификатов

После настройки секции конфигурации интеграции с HashiCorp Vault, нужно внести директивы с параметрами для использования сертификатов и ключей, которые будут получены из HashiCorp Vault. Возможно использовать для следующих функциональностей:

  1. Для настройки TLS между клиентом и SynGX (работа в режиме веб-сервера) - вместо директив ssl_certificate, ssl_certificate_key:

    • указать директиву и параметры (approle:роль) вида: hv_pki_ssl_certificate secman_2:cert1 или hv_ssl_certificate secman_2:cert1. Примечание: для настройки TLS между клиентом и SynGX по протоколам http2 и grpc используются те же самые директивыили

  2. Для настройки TLS между SynGX и узлами в группе балансировки (работа в режиме прокси-сервера) - вместо директив proxy_ssl_certificate, proxy_ssl_certificate_key:

    • указать директиву и параметры (approle:роль) вида: hv_pki_proxy_ssl_certificate      secman_1:cert2 или hv_proxy_ssl_certificate      secman_1:cert2 .

  3. Для настройки TLS между SynGX и grpc узлами в группе балансировки (работа в режиме grpc-прокси-сервера) - вместо директив grpc_ssl_certificate, grpc_ssl_certificate_key:

    • указать директиву и параметры (approle:роль) вида: hv_pki_grpc_ssl_certificate secman_1:cert2 или hv_grpc_ssl_certificate      secman_1:cert2.

  4. Для настройки TLS при активной проверке работоспособности узлов в группе балансировки - вместо директив snx_ahc_ssl_certificate и snx_ahc_ssl_certificate_key:

    • указать директиву и параметры (approle:роль) вида: hv_pki_ahc_ssl_certificate      secman_1:cert1 или hv_ahc_ssl_certificate      secman_1:cert1.

Примечание: approle:роль могут называться произвольным образом - в зависимости от заданных <имя approle> и <имя роли> в настройках с HashiCorp Vault.

Ниже дан пример частей конфигурации с указанием директив для использования сертификатов и ключей при активной проверке узлов в группе балансировки, обработке запросов в качестве веб-сервера и при проксировании запросов с использованием TLS-соединения (будут использоваться approle, роль, полученные из HashiCorp Vault).

Примечание: approle и роль (например: secman_1:cert1) для получения сертификатов и ключей можно задавать как в контексте http, так и в контексте stream.

...
    upstream cluster_https {
        server 127.0.0.1:8997;

        check interval=3000 rise=2 fall=5 timeout=2000 type=https;
        hv_pki_ahc_ssl_certificate      secman_1:cert1;
    }
    upstream cluster_grpcs {
        server 127.0.0.1:50051;
    }
...
    server {
	    listen 8998 ssl;
        hv_pki_ssl_certificate      secman_2:cert1;
        location /xxx_https {
            return 200 "Upstream 8998! Hello world TLS\n";
        }
    }
...
    server
    {
...
        location /xxx_https {
            proxy_pass https://cluster_https;
            hv_pki_proxy_ssl_certificate      secman_1:cert2;
        }
    }
    server
    {
        listen 10000 ssl http2;
        hv_pki_ssl_certificate secman_1:cert1;
        location /xxx_grpcs {
            grpc_pass grpcs://cluster_grpcs;
            hv_pki_grpc_ssl_certificate      secman_1:cert2;
        }
    }

Действия при невалидном wrapped token

В случае если во время выполнения unwrap была получена ошибка от HashiCorp Vault, сообщающая что wrapped token является не корректным или срок его действия истек, то существует 2 варианта:

  1. Если хотя бы один раз до этого выполнение unwrap прошло успешно и был получен secret_id, то SynGX перейдет к шагу «Запрос на авторизацию», используя сохраненное в оперативной памяти значение secret_id. При этом в error_log будет выведено следующее сообщение:

2024/07/19 03:13:37 [info] 65903#65903:  [hashicorp vault] skip unwrap request with invalid wrapped token
  1. В противном случае SynGX создает файл по пути, указанном в параметре wrapped_token_file с нулевым размером и прекращает дальнейшее взаимодейтсвие с HashiCorp Vault.

При этом в error_log одонократно будет выведено следующее сообщение. Никаких многократно повторяющихся сообщений выводиться не будет.

2024/07/19 03:13:37 [info] 65903#65903:  [hashicorp vault] wrapped_token is not valid or does not exist, waiting for the token to change

При возникновении данной ситуации, SynGX будет неограниченное количество раз проверять, появился ли новый wrapped token в файле по пути, указанном в параметре wrapped_token_file с переодичностью указанной в параметре retry_interval/retry_interval_gap. Администратору необходимо получить новый wrapped token и записать его в файл по пути, указанном в параметре wrapped_token_file. После его изменения SynGX возобновит взаимодействие с HashiCorp Vault со стадии unwrap через время заданное в параметре retry_interval/retry_interval_gap. При этом принудительной перезагрузки не требуется.

Проверки сертификатов, полученных из KV хранилища

При использовании KV движка Hashicorp Vault, каждый полученный из KV сертификат применяется в случае если выполняются следующие критерии:

  • Данные полученные по ключу, который указан в директиве hv_kv_ssl_certificate, являются публичной частью TLS сертификата

  • Данные полученные по ключу, который указан в директиве hv_kv_ssl_certificate не являются TLS сертификатом удостоверяющего центра

  • Данные полученные по ключу, который указан в директиве hv_kv_ssl_certificate, не содержат в себе цепочек доверия TLS сертификата

  • Данные полученные по ключу, который указан в директиве hv_kv_ssl_certificate_key, являются приватной частью TLS сертификата

  • Срок действия полученного TLS сертификата не истек и не меньше чем значение указанное в параметре update_cert_before_expiration

Логика работы с резервным хранилищем KV Hashicorp Vault

При взаимодействии SynGX с KV движком Hashicorp Vault имеется возможность резервирования используемых сертификатов. Резервирование осуществляется на этапе получения сертификата в случае недоступности сертификата из основного хранилища по следующим критериям:

  • При запросе сертификата на все попытки был получен код отличный от 200

  • Полученное значение не является сертификатом

  • Полученный сертификат является сертификатом удостоверяющего центра

  • Полученный сертификат содержит цепочку доверия

  • Срок действия сертификата истек или меньше чем заданный период.

Указать резервное хранилище можно с помощью директивы reserved_path

Пример настройки резервного хранилища:

    get_cert_kv cert1 {
        path A/DEV/APP/GATEWAYS/SNGX/KV/storage1;
        hv_kv_ssl_certificate_key prv_key;
        hv_kv_ssl_certificate pub_key;

        save_certificate_path /opt/syngx/ssl/server1.crt;

        reserved_path A/DEV/APP?GATEWAYS/SNGX/KV/reserv1; # путь до резервного KV хранилища
        update_expiring_cert_interval 60; # время в минутах, через которое SynGX делает попытку получить новый валидный сертификат, если срок действия ранее полученного сертификата истекает
        update_cert_before_expiration 10;
    }

Логика повторных запросов в Hashicorp Vault

Повторный запрос в Hashicorp Vault будет произведен в случае, если полученный HTTP код в ответе отличен от 200 и задан в директиве retry_codes. Интервал, через который будет совершен запрос рассчитывается из следующей логики:

  • Если в ответе от Hashicorp Vault был получен HTTP заголовок Retry-After и значение этого заголовка больше нуля и меньше 5 минут, то повторный запрос будет совершен через указанное в нем время

  • В случае отсутствия данного заголовка, повторный запрос будет совершен исходя из заданных директив retry_interval/retry_interval_gap. Если ни одна директива не задана, то в расчет будут взяты значения по умолчанию директивы retry_interval_gap

Если полученный HTTP код ответа от Hashicorp Vault не задан в директиве retry_codes, то повторные попытки будут возобновлены через время указанное в директиве wrapped_token_intrval в случае ошибок при получении wrapped token или get_cert_interval в случае ошибок при получении сертификата.

Поэтапное логгирование работы модуля ngx_hashicorp_vault

Ниже приведено описание сообщений, которые SynGX пишет в error.log при работе с Hashicorp Vault Схема работы при получении секретов из Hashicorp Vault описана в документе «Детальная архитектура»

  1. Запрос на unwrap (use: wrapped_token, role_id):

  • Удаление файла с wrapped_token с диска перед запросом

2024/07/19 03:13:37 [info] 65903#65903: [hashicorp vault] file "/opt/secman/syngx/wrapped_token.txt" removed before unwrap request
  • Отправка HTTP запроса на unwrap в Hashicorp Vault

2024/07/19 03:13:37 [info] 65903#65903: [hashicorp vault] unwrap request: "POST /v1/sys/wrapping/unwrap HTTP/1.1
Host: secman-dzo.solution.sbt:8200
X-Vault-Namespace: DEV_DZO
X-Vault-Token: XXX
Content-Length: 0
Connection: close
"
  • Получение secret_id после успешного выполнения unwrap

024/07/19 03:13:37 [debug] 65903#65903: [hashicorp vault] wrapped-token set state=1 for approle "secman_pki" at stage=5
  • Запрос на unwrap оказался неуспешным

Получен код ответа отличный от 200:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] bad http response status code (http code not 200): 400

Ответ, полученный от Hashicorp Vault, не соответствует стандарту протокола HTTP:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] http response parse error (http not valid):
  1. Запрос на авторизацию (use: role_id, secret_id)

  • Перед запросом

2024/07/19 03:13:38 [info] 65903#65903: [hashicorp vault] add timeout event for login with approle "secman_pki"
  • Отправка HTTP запроса на авторизацю

2024/07/19 03:13:39 [info] 65903#65903: [hashicorp vault] authentification request: "POST /v1/auth/approle/login HTTP/1.1
Host: secman-dzo.solution.sbt:8200
Content-Type: application/json
X-Vault-Namespace: DEV_DZO
Content-Length: 106
Connection: close

{
"role_id": "XXX",
"secret_id": "YYY"
}"
  • Получение client token после успешной авторизации

2024/07/19 03:13:39 [debug] 65903#65903: [hashicorp vault] set state=1 for approle "secman_pki"
  • Ошибка при авторизации

Получен код ответа отличный от 200:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] bad http response status code (http code not 200): 400

Ответ, полученный от Hashicorp Vault, не соответствует стандарту протокола HTTP:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] http response parse error (http not valid):
  1. Запрос на получение сертификатов и секретов - Fetch (use: client token)

  • Перед запросом

2024/07/19 03:13:42 [info] 65903#65903: [hashicorp vault] get_cert request: "POST /v1/PKI/fetch/role-ga-secman-syngx HTTP/1.1
Host: secman-dzo.solution.sbt:8200
Content-Type: application/json
X-Vault-Namespace: DEV_DZO
X-Vault-Token: XXX
Connection: close
"
  • Успешное получение сертификатов и секретов из Hashicorp Vault (Fetch Success):

    • Получение секретов

    2024/07/19 03:13:42 [info] 65903#65903: [hashicorp vault] received certificate for "secman_pki:hc_cert_1"
    2024/07/19 03:13:42 [debug] 65903#65903: [hashicorp vault] set state=3 for "secman_pki:hc_cert_1" certificate
    
    • Запись публичной части сертификата в файл

    2024/07/19 03:13:42 [info] 65903#65903: [hashicorp vault] write to file "/opt/syngx/ssl/hc_cert_1.crt" data with size 1288
    
    • Выставляется переменная для вызова перезагрузки (reload) для применения полученных из Hashicorp Vault сертификатов в новых рабочих (worker) процессах

    2024/07/19 03:13:42 [info] 65903#65903: [hashicorp vault] set reload_required=1 after success fetch for "secman_pki:hc_cert_1" certificate
    
    • Вызов reload

    2024/07/19 03:13:50 [info] 65903#65903: [hashicorp vault] calling reload to apply newly certificates
    
    • Применяет сертификаты ко всем контекстам OpenSSL и выставляет таймер на переиздание сертификатов

    2024/07/19 03:13:50 [debug] 65901#65901: [hashicorp vault] ssl ctx allocated elements: 5
    2024/07/19 03:13:50 [debug] 65901#65901: [hashicorp vault] ssl part elements: 3
    2024/07/19 03:13:50 [debug] 65901#65901: [hashicorp vault] ssl ctx 0 name: "secman_pki:hc_cert_1" section: "http/ssl" ctx: 0000000002073748 ca: "" ca_depth 1
    2024/07/19 03:13:50 [debug] 65901#65901: [hashicorp vault] find shm ssl ctx serial_number: "2d:cc:0b:53:98:f2:39:69:b3:af:49:a8:94:a3:46:51:be:9d:32:bd" cert: "/opt/syngx/ssl/hc_cert_1.crt" ca: ""
    ...
    2024/07/19 03:13:50 [info] 66087#66087: [hashicorp vault] certificate "secman_pki:hc_cert_1" ready for use
    ...
    2024/07/19 03:13:50 [info] 66087#66087: [hashicorp vault] 10 days before fetch new certificate "secman_pki:hc_cert_1"
    
  • Ошибка при отправке сертификатов и секретов (Fetch Fail)

Получен код ответа отличный от 200:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] bad http response status code (http code not 200): 400

Ответ, полученный от Hashicorp Vault, не соответствует стандарту протокола HTTP:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] http response parse error (http not valid):
  1. Запрос wrap (use: secret_id, client token)

  • Перед запросом

2024/07/19 03:13:47 [info] 65903#65903: [hashicorp vault] wrap request: "POST /v1/sys/wrapping/wrap HTTP/1.1
Host: secman-dzo.solution.sbt:8200
Content-Type: application/json
X-Vault-Namespace: DEV_DZO
X-Vault-Token: XXX
X-Vault-Wrap-TTL: 604800000
Content-Length: 55
Connection: close


{
"secret_id": "YYY"
}"
  • Запрос на unwrap выполнился успешно - запись wrapped_token в файловую систему SynGX

2024/07/19 03:13:47 [info] 65903#65903: [hashicorp vault] write to file "/opt/secman/syngx/wrapped_token.txt" data with size 34
...

2024/07/19 03:13:47 [debug] 65903#65903: [hashicorp vault] wrapped-token set state=1 for approle "secman_pki" at stage=3
  • Запрос на unwrap оказался неуспешным

Получен код ответа отличный от 200:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] bad http response status code (http code not 200): 400

Ответ, полученный от Hashicorp Vault, не соответствует стандарту протокола HTTP:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] http response parse error (http not valid):
  1. Запрос rewrap (use: client token, wrapped token)

  • Перед запросом

2025/01/27 15:23:04 [info] 45615#45615: [hashicorp vault] rewrap request: "POST /v1/sys/wrapping/rewrap HTTP/1.1
Host: 127.0.0.1:8200
Content-Type: application/json
X-Vault-Namespace: DEV_DZO
X-Vault-Token: XXX
Content-Length: 49
Connection: close

{
"token": "YYY"
}"
2024/08/07 15:23:04 [info] 45615#45615: [hashicorp vault] file "/opt/secman/syngx/wrapped_token.txt" removed before stage - rewrap requested
  • Запрос на rewrap выполнился успешно - запись wrapped_token в файловую систему SynGX

2024/07/19 03:13:47 [info] 65903#65903: [hashicorp vault] write to file "/opt/secman/syngx/wrapped_token.txt" data with size 34
...

2024/07/19 03:13:47 [debug] 65903#65903: [hashicorp vault] wrapped-token set state=1 for approle "secman_pki" at stage=3
  • Запрос на rewrap оказался неуспешным

Получен код ответа отличный от 200:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] bad http response status code (http code not 200): 400

Ответ, полученный от Hashicorp Vault, не соответствует стандарту протокола HTTP:
2024/08/07 08:45:16 [error] 5434#5434: [hashicorp vault] http response parse error (http not valid):
  1. Ошибки при получении сертификата из KV хранилища SecMan

  • Полученный сертификат не является сертификатом (не удалось создать контекст для чтения)

2024/07/19 03:13:47 [error] 65903#65903: [hashicorp vault] certificate is not valid "/opt/syngx/ssl/cerver.pem" - error create BIO
  • Полученный сертификат не является сертификатом (не удалось протирать сертификат

2024/07/19 03:13:47 [error] 65903#65903: [hashicorp vault] certificate is not valid "/opt/syngx/ssl/cerver.pem" - error read BIO
  • Полученная приватная часть сертификата не является сертификатом (не удалось создать контекст для чтения)

2024/07/19 03:13:47 [error] 65903#65903: [hashicorp vault] private key is not valid "/opt/syngx/ssl/cerver.pem" - error create BIO
  • Полученная приватная часть сертификата не является сертификатом (не удалось протирать ключ)

2024/07/19 03:13:47 [error] 65903#65903: [hashicorp vault] private key is not valid "/opt/syngx/ssl/cerver.pem" - error read BIO
  • Полученный сертификат является сертификатом центра сертификации

2024/07/19 03:13:47 [error] 65903#65903: [hashicorp vault] certificate is a CA certificate "/opt/syngx/ssl/cerver.pem"
  • Полученный сертификат содержит цепочку доверия

2024/07/19 03:13:47 [error] 65903#65903: [hashicorp vault] the certificate contains a chain of trust "/opt/syngx/ssl/cerver.pem"
  • Полученный сертификат является истекающим

2024/07/19 03:13:47 [error] 65903#65903: [hashicorp vault] the certificate expires after 5 for "secman_kv:hc_cert_1"
  • Полученный сертификат является истекшим

2024/07/19 03:13:47 [error] 65903#65903: [hashicorp vault] the certificate expired for "secman_kv:hc_cert_1"
  • Применение истекающего сертификата

2024/07/19 03:13:47 [warn] 65903#65903: [hashicorp vault] use an expiring certificate - "secman_kv:hc_cert_1"

Отправка пакета TCP с флагом RST на входящие TCP соединения#

Отправку пакета TCP с флагом RST на входящие TCP соединения по результатом активной проверки работоспособности узлов в группе балансировки обеспечивают модули ngx_stream_rst_send_module и ngx_http_rst_send_module с помощью утилиты iptables. Работа данных модулей осуществляется с помощью привилегированного агента процесса.

Важно!:

  • Для работы данных модуля требуется, чтобы master процесс и привилегированный агент процесс SynGX были запущены от имени пользователя, у которого есть права на запуск утилиты iptables.

  • Должна быть установлена утилита iptables

Название модуля

Назначение модуля

ngx_http_rst_send_module

Отправка пакета TCP с флагом RST на входящие TCP соединения на уровне секции http (L7 уровень модели OSI)

ngx_stream_rst_send_module

Отправка пакета TCP с флагом RST на входящие TCP соединения на уровне секции stream (L4 уровень модели OSI)

Логика данного функционала заключается в отправке TCP пакета с флагом RST на входящий TCP пакет с флагом SYN, при попытке установить новое TCP (уровень L4) соединение с сервером, сетевой адрес IPv4:port которого, указан в директиве depending_server, в случае если все проксируемые сервера, указанные в контексте stream/upstream или http/upstream выпали из балансировки по результатам активной проверки работоспособности узлов в группе балансировки.

Название директивы

Контекст

Параметры

depending_server

stream/http

<ip>:<port> - сервер/серверы, которые проксируют на выбранный upstream

stream{
  upstream backend_tcp_servers {
      server <адрес сервера1>:<port>;
      server <адрес сервера2>:<port>;
      server <адрес сервера3>:<port>;
      check interval=5000 rise=1 fall=3 timeout=4000 default_down=true type=tcp;
      depending_server 127.0.0.1:522 127.0.0.1:523;
  }

  server{
      listen 127.0.0.1:522;
      proxy_pass backend_tcp_servers;
  }

}

При выпадении всех серверов в группе балансировки в error_log будет выведено сообщение с уровнем INFO. Для stream секции оно будет выглядеть следующим образом:

[rst_stream] all servers off in upstream - <upstream name>, iptables close server - <ip>:<port> (указанные в директиве depending_server)

Для http контекста:

[rst_http] all servers off in upstream - <upstream name>, iptables close server - <ip>:<port> (указанные в директиве depending_server)

Так же будет выведено сообщение о завершении работы утилиты iptables c уровнем NOTICE

signal 17 (SIGCHLD) received from <pid> (пид процесса iptables)

И так как процесс iptables не является worker процессом, то выведется сообщение об этом на уровне INFO

waitpid() failed (10: No child processes)
  • При возвращении в балансировку хотя бы одного узла, указанного в upstream модули ngx_stream_rst_send_module или ngx_http_rst_send_module возобновят прием входящих соединений для обмена с сервером указанным в директиве depending_server для stream или http контекста

При этом в error_log будет выведено следующее сообщение с уровнем INFO для stream секции

[rst_stream] live servers found in upstream - <upstream name>, iptables open server <ip>:<port> (указанные в директиве depending_server)

Для http секции аналогичное сообщение будет выглядеть следующим образом:

[rst_http] live servers found in upstream - <upstream name>, iptables open server <ip>:<port> (указанные в директиве depending_server)

Так же будет выведено сообщение о завершении работы утилиты iptables c уровнем NOTICE

signal 17 (SIGCHLD) received from <pid> (пид процесса iptables)

И так как процесс iptables не является worker процессом, то выведется сообщение об этом на уровне INFO

waitpid() failed (10: No child processes)
  • При завершении работы SynGX или его перезагрузке все примененные правила удаляются, при этом в error_log будет выведено следующее сообщение с уровнем INFO для stream контекста

[rst_stream] SynGX is shut down, iptables delete rules for server <ip>:<port> (указанные в директиве depending_server)

Для http секции аналогичное сообщение будет выглядеть следующим образом:

[rst_http] SynGX is shut down, iptables delete rules for server <ip>:<port> (указанные в директиве depending_server)

Так же будет выведено сообщение о завершении работы утилиты iptables c уровнем NOTICE

signal 17 (SIGCHLD) received from <pid> (пид процесса iptables)

И так как процесс iptables не является worker процессом, то выведется сообщение об этом на уровне INFO

waitpid() failed (10: No child processes)

Настройка активной проверки работоспособности узлов (active healthcheck)#

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

Функционал активного healthcheck предоставляют модули ngx_stream_upstream_check_module и nginx_upstream_check_module:

Название модуля

Назначение модуля

nginx_upstream_check_module

active healthcheck на уровне секции http (L7 уровень модели OSI)

ngx_stream_upstream_check_module

active healthcheck на уровне секции stream (L4 уровень модели OSI)

Для настройки активной проверки работоспособности на уровне секции http (L7 уровень модели OSI) с помощью модуля nginx_upstream_check_module и/или на уровне секции stream (L4 уровень модели OSI) с помощью модуля ngx_stream_upstream_check_module необходимо добавить директиву check в контекст директивы upstream.

Результаты активной проверки работоспособности узлов могут использоваться для следующих алгоритмов балансировки:

  • Round Robin;

  • Least Connections;

  • Hash;

  • IP Hash.

Для информации: узел (server) в секции upstream - это peer в терминологии модуля.

Параметры директивы check:#

interval

  • syntax: interval=*time (msec)*

  • default: 10000

  • context: upstream/check Параметр interval указывает интервал опроса узлов в группе балансировки. Для стабильной работы модуля значение параметра interval должно быть больше, чем значение параметра timeout

timeout

  • syntax: timeout=*time (msec)*

  • default: 3000

  • context: upstream/check Параметр timeout указывает время ожидания ответа на запрос от узла в группе балансировки, по истечению которого запрос считается неуспешным. Для стабильной работы модуля значение параметра interval должно быть больше, чем значение параметра timeout

fall

  • syntax: fall=*count*

  • default: 5

  • context: upstream/check Параметр fall указывает количество неуспешных запросов, чтобы считать, что узел не доступен

rise

  • syntax: rise=*count*

  • default: 2

  • context: upstream/check Параметр rise указывает количество успешных запросов, чтобы включить узел в балансировку

default_down

  • syntax: default_down=*flag true/false*

  • default: true

  • context: upstream/check Параметр default_down указывает статус узла по умолчанию. true - узел не доступен для балансировки, false - узел доступен для балансировки

port

  • syntax: port=*number*

  • default: 0

  • context: upstream/check Параметр port указывает порт узла, который отличается от заданного в конфигурации в директиве server. Значением по умолчанию является 0, что означает, что порт такой же, как в директиве server

type

  • syntax: type=*string*

  • default: tcp

  • context: upstream/check Параметр type указывает необходимый тип проверки работоспособности. Возможные значения: для http - tcp, ssl_hello, http, https; для stream - udp, tcp, http, ssl_hello, tcp_tls

mandatory

  • syntax: mandatory

  • default: ``

  • context: upstream/check Параметр mandatory устанавливает исходное состояние «off» для узлов в группе балансировки до завершения первой проверки работоспособности. При наличии данного параметра первоначальный статус будет определен по результатам первой проверки не зависимо от значения параметров fall, rise и default_down. Если параметр не указан, то исходное состояние сервера будет равно значению, указанному в параметре default_down

  • syntax: persistent

  • default: ``

  • context: upstream/check Параметр persistent не изменяет состояние сервера после перезагрузки в случае, если указан параметр mandatory. Данный параметр запрещено использовать без опции mandatory

Описание типов проверки:

Секция

Тип проверки

Описание

http

tcp

SynGX устанавливает TCP-соединение с узлом. Попытка считается успешной, если TCP-соединение установлено и закрыто

http

ssl_hello

SynGX отправляет на узел «ssl hello»-пакет и получает «ssl hello»-пакет. Проверка считается успешной, если от узла получен «ssl hello»-пакет

http

http

SynGX отправляет HTTP-запрос (по умолчанию GET / HTTP/1.1\r\nHost: <имя хоста>\r\nConnection: close\r\n\r\n), который можно изменить с помощью параметра check_http_send, и проверяет код ответа на соответствие кодам ответов, указанных в директиве check_http_expect alive (http_2xx, http_3xx и прочее)

http

https

SynGX отправляет HTTP-запрос по протоколу TLS (по умолчанию GET / HTTP/1.1\r\nHost: <имя хоста>\r\nConnection: close\r\n\r\n), который можно изменить с помощью параметра check_http_send, и проверяет код ответа на соответствие кодам ответов, указанных в директиве check_http_expect alive (http_2xx, http_3xx и прочее)

stream

udp

SynGX производит проверку в 2 этапа: 1 этап заключется в отправке в сторону узла ICMP «эхо-запроса». Если в ответ получен ICMP-«эхо-ответ», то будет переход ко второму этапу, иначе попытка считается неуспешной. 2 этап состоит в отправке на сервер тестового UDP-пакета по порту балансировки. Попытка считается успешной, если в ответ не пришло сообщение «UDP Port Unreachable». В противном случае попытка считается неуспешной

stream

tcp

SynGX устанавливает TCP-соединение с узлом. Попытка считается успешной, если TCP-соединение установлено и проходит попытка чтения одного байта из соединения.

Дополнительно:
1) если задана директива check_send, то отправляется TCP-запрос, который указан в этой директиве.
2) если задана директива check_expect_alive, то сравнивается ответ от узла cо значением этой директивы.

stream

ssl_hello

SynGX отправляет на узел «ssl hello»-пакет и получает «ssl hello»-пакет. Проверка считается успешной, если от узла получен «ssl hello»-пакет

stream

http

SynGX отправляет HTTP-запрос (по умолчанию GET / HTTP/1.1\r\nHost: <имя хоста>\r\nConnection: close\r\nsyngx-stream-active-healthcheck: true\r\n\r\n), который можно изменить с помощью параметра check_send.

Дополнительно:
если задана директива check_expect_alive, то сравнивается ответ от узла cо значением этой директивы.

stream

tcp_tls

SynGX устанавливает TCP-соединение с узлом по протоколу TLS (предварительно делается ssl hahdshake). Попытка считается успешной, если TCP-соединение по протоколу TLS установлено и проходит попытка чтения одного байта из соединения.

Дополнительно:
1) если задана директива check_send, то отправляется TCP-запрос по протоколу TLS, который указан в этой директиве.
2) если задана директива check_expect_alive, то сравнивается ответ от узла cо значением этой директивы.

Примечание: описание директив см. ниже.

Пример базовой конфигурации для активной проверки работоспособности узлов на уровне секции http:

http {
    upstream <название кластера> {
        # simple round-robin
        server <ip-адрес узла>:<port>;
        server <ip-адрес узла>:<port>;
        check interval=3000 rise=2 fall=5 timeout=5000 default_down=true type=tcp;
    }
    server {
        listen 522;
        proxy_pass <название кластера>;
    }
    ...
}

Ниже приведен пример базовой конфигурации для активной проверки работоспособности узлов на уровне секции stream:

stream {
    upstream <название кластера> {
        # simple round-robin
        server <ip-адрес узла>:<port>;
        server <ip-адрес узла>:<port>;
        check interval=3000 rise=2 fall=5 timeout=5000 default_down=true type=udp;
    }
    server {
        listen 522;
        proxy_pass <название кластера>;
    }
    ...
}

Дополнительные директивы, необходимые для разных типов проверки:

(секция - http или stream) Тип проверки type

Требуемые директивы

(stream) udp

(stream, http) tcp

(stream, http) ssl_hello

check

(http) http

check, check_http_send, check_http_expect_alive

(stream) http

check, check_send, check_expect_alive

(http) https

check, check_http_send, check_http_expect_alive + параметры TLS, которые будут использоваться при отправке запросов healthcheck (см. ниже «Дополнительные директивы для поддержки запросов active healthcheck по TLS»)

(stream) tcp_tls

check, check_send, check_expect_alive + параметры TLS, которые будут использоваться при отправке запросов healthcheck (см. ниже «Дополнительные директивы для поддержки запросов active healthcheck по TLS»)

Описание дополнительных директив: (каждая прописывается в отдельной строке)

  • check_http_send (string; Default для типов проверки http, https: GET / HTTP/1.1\r\nHost: <имя хоста>\r\nConnection: close\r\n\r\n, Default для остальных типов: «»). Эта инструкция может настроить контент запроса, отправленный модулем. Если строка для tcp типа не задана - будет произведена попытка установить соединение с узлом в группе балансировки, но запрос отправляться не будет; установление соединения будет означать успешное прохождение проверки. Директива доступна только в секции http/upstream.

  • check_http_expect_alive (syntax: [ http_2xx | http_3xx | http_4xx | ⁣http_5xx ]; Default: http_2xx | http_3xx). Задает коды ответа, которые будут означать успешность прохождения проверки. Директива доступна только в секции http/upstream.

  • check_send (string; Default для типа проверки http: «GET / HTTP/1.1\r\nHost: <имя хоста>\r\nConnection: close\r\nsyngx-stream-active-healthcheck: true\r\n\r\n», Default для остальных типов: «»). Эта инструкция может настроить контент запроса, отправленный модулем. Если строка для tcp типа не задана - будет произведена попытка создать соединение с узлом в группе балансировки, но запрос отправляться не будет; установление соединения будет означать успешное прохождение проверки. Директива доступна только в секции stream/upstream.

  • check_expect_alive (string; Default: none). Строка для сравнения успешного состояния ответа. Сравнение ответа с параметром происходит по минимальной длине. Если параметр не указан, то строка ответа не сравнивается и запрос считается успешным. Директива доступна только в секции stream/upstream.

  • check_shm_size (size; Default: 3Mb). Все проверки работоспособности узлов балансировки хранятся в общей памяти. Данная директива позволяет задать размер общей памяти. На один сервер в апстриме отводится приблизительно 1 килобайт. То есть, для значения по умолчанию, память расчитана на 3000 серверов. В тоже время, если в upstream используется DNS resolver, то количество памяти для одного сервера увеличивается в 16 раз из за возможности разрешения имени сервера во множество ip адресов. В таком случае количество доступных серверов будет в 16 раз меньше. Директива доступна только в секции http или stream.

Дополнительные директивы для поддержки запросов active healthcheck по TLS

Если требуется поддержка TLS, нужно выпустить SSL сертификаты и добавить параметры в конфигурацию. Каждая директива прописывается в отдельной строке.

  • snx_ahc_ssl_certificate (файл; Default: none). Задает файл с сертификатом в формате PEM для аутентификации на upstream HTTPS-сервере. Можно использовать переменные.

  • snx_ahc_ssl_certificate_key (файл; Default: none). Задает файл с секретным ключом в формате PEM для аутентификации на узле в группе балансировки. Вместо файла можно указать значение engine:имя:id (1.7.9), которое загружает ключ с указанным id из OpenSSL engine с заданным именем. Можно использовать переменные.

  • snx_ahc_ssl_ciphers (шифры; Default: snx_ahc_ssl_ciphers DEFAULT). Описывает разрешенные шифры, которые будут использоваться при отправке запроса health check к узлу в группе балансировки. Шифры задаются в формате, поддерживаемом библиотекой OpenSSL. Полный список можно посмотреть с помощью команды «openssl ciphers».

  • snx_ahc_ssl_name (имя; Default: snx_ahc_ssl_name $peer_name). Позволяет переопределить имя сервера, используемое при проверке сертификата узла в группе балансировки, а также для передачи его через SNI при установлении соединения с узлов в группе балансировки. По умолчанию используется имя хоста из URLа upstream сервера.

  • snx_ahc_ssl_protocols (TLSv1.2/TLSv1.3; Default: TLSv1.2). Разрешает указанные протоколы для запросов к узлу в группе балансировки.

  • snx_ahc_ssl_server_name (on/off; Default: off). Разрешает или запрещает передачу имени сервера через расширение Server Name Indication протокола TLS (SNI, RFC 6066) при установлении соединения с проксируемым HTTPS-сервером. Работает аналогично директиве proxy_ssl_server_name. Если необходимо использование SNI, то надо выставить эту директиву в значение on и задать правильное имя сервера в директиве snx_ahc_ssl_name!

  • snx_ahc_ssl_trusted_certificate (файл; Default: -). Задает файл с доверенными сертификатами CA в формате PEM, используемыми при проверке сертификата узла в группе балансировки.

  • snx_ahc_ssl_verify (on/off; Default: off). Включает или выключает проверку сертификата узла в группе балансировки.

  • snx_ahc_ssl_verify_depth (число; Default: 1). Устанавливает глубину проверки в цепочке сертификатов узла в группе балансировки…

  • snx_ahc_ssl_conf_command (имя значение; Default: -). Задает произвольные конфигурационные команды OpenSSL при установлении соединения с узлов. На одном уровне может быть указано несколько директив snx_ahc_ssl_conf_command.

  • snx_ahc_ssl_crl (файл; Default: -). Указывает файл с отозванными сертификатами (CRL) в формате PEM, используемыми при проверке сертификата узла в группе балансировки.

Важно: Если используется активная проверка работоспособности узлов по протоколу TLS с использованием сертификатов из Hashicorp Vault, то SynGX начинает отправлять проверочные запросы только после того, как по всем сертификатам получен ответ на запрос. Это позволяет избежать ситуации, при которой узел в группе выводится из балансировки из-за задержки в получении сертификата.

Дополнительные директивы для поддержки запросов active healthcheck по TCP: (каждая прописывается в отдельной строке)

  • proxy_session_drop (on/off; Default: off). SynGX прекращает при проксировании запроса использовать ранее установленные соединения с узлом (сервером), когда он переходит в состояние „down“ при проверке active health check. Для проксирования выбирается новый узел, который находится в состоянии „up“ по результатам active health check. Директива доступна только в секции stream или stream/server. Внимание: Не используйте proxy_session_drop директиву при использовании TLS для проксирования запросов, так как при выборе нового узла для соединения проксируемый сервер ожидает процедуру handshake между клиентом и сервером, а клиент не знает об этом. В результате как клиент, так и сервер получат ошибку при попытке установить новое соединение. Используйте директиву client_connection_close при использовании TLS при проксировании запросов!

  • client_connection_close (off/RST/FIN; Default: off). При установленном значении RST или FIN, SynGX закрывает установленные соединения с клиентами, которые имели открытые сессии с узлом (сервером), когда он переходит в состояние „down“ при проверке active health check. Запрещено одновременное использование директив client_connection_close и proxy_session_drop. Директива доступна только в секции stream.

Настройка location для получения данных по healthcheck

Пример базовой конфигурации для получения данных по healthcheck:

http {
    server {
        listen 8080;

        # status interface
        location /hc_status {
            <вид метрик>;
        }
     ...
}
  • <вид метрик> - заменить на: check_status - для метрик по healthcheck из секции http (L7 уровень модели OSI), либо l4check_status - для метрик по healthcheck из секции stream (L4 уровень модели OSI).

Формат вывода метрик задается добавлением вида (по умолчанию html):

* <вид метрик> `html`
* <вид метрик> `json`
* <вид метрик> `prometheus`

Пример настройки активной проверки работоспособности узлов с разными типами соединений (tcp, udp, http, ssl_hello, tcp_tls) в секции stream

...

stream {
    upstream tcp_cluster {
        # simple round-robin
        server 127.0.0.1:8010;
        server 127.0.0.1:8011;
        check interval=2000 rise=2 fall=2 timeout=3000 default_down=true type=tcp;
        check_send "HEAD / HTTP/1.0\r\nConnection: close\r\n\r\n";
        # check_send "Hello from hc stream tcp!"; для чистого tcp
        check_expect_alive "HTTP/1.1 200";
        # check_expect_alive "Ok"; для чистого tcp
    }
    upstream udp_cluster {
        server 127.0.0.1:8020;
        server 127.0.0.1:8021;
        check interval=3000 rise=2 fall=5 timeout=5000 default_down=true type=udp;
    }

    upstream http_cluster {
        server 127.0.0.1:8030;
        server 127.0.0.1:8031;
        check interval=2000 rise=2 fall=5 timeout=3000 type=http;
        check_send "HEAD / HTTP/1.1";
        check_expect_alive "HTTP/1.1 200";
    }
    upstream ssl_hello_cluster {
        server 127.0.0.1:8040;
        server 127.0.0.1:8041;
        check interval=2000 rise=2 fall=5 timeout=3000 type=ssl_hello;
    }
    upstream tcp_tls_cluster {
        server 127.0.0.1:8050;
        server 127.0.0.1:8051;
        check interval=2000 rise=2 fall=5 timeout=3000 type=tcp_tls;
        check_send "HEAD / HTTP/1.0\r\n\r\n";
        # check_send "Hello from hc stream tcp!"; для чистого tcp
        check_expect_alive "HTTP/1.1 200";
        # check_expect_alive "Ok"; для чистого tcp

        snx_ahc_ssl_certificate           /home/syngx/syngx/ssl_src/client.crt;
        snx_ahc_ssl_certificate_key       /home/syngx/syngx/ssl_src/client.key;
        snx_ahc_ssl_trusted_certificate   /home/syngx/syngx/ssl_src/ca.crt;
        snx_ahc_ssl_verify on;
        snx_ahc_ssl_server_name on;
        snx_ahc_ssl_name <имя сервера>;
        snx_ahc_ssl_protocols TLSv1.2;
        snx_ahc_ssl_ciphers AES256-SHA;
    }

    server {
        listen 8101;
        proxy_pass tcp_cluster;
    }
    server {
        listen 8102 udp;
        proxy_pass udp_cluster;
    }
    server {
        listen 8103;
        proxy_pass http_cluster;
    }
    server {
        listen 8104;
        proxy_ssl_certificate           /home/syngx/syngx/ssl_src/client.crt;
        proxy_ssl_certificate_key       /home/syngx/syngx/ssl_src/client.key;
        proxy_ssl_trusted_certificate   /home/syngx/syngx/ssl_src/ca.crt;
        proxy_ssl_session_reuse on;
        proxy_ssl_verify on;
        proxy_ssl_server_name on;
        proxy_ssl_name <имя сервера>;
        proxy_ssl_protocols TLSv1.2;
        proxy_ssl_ciphers AES256-SHA;
        proxy_pass ssl_hello_cluster;
    }
    server {
        listen 8105;
        proxy_ssl_certificate           /home/syngx/syngx/ssl_src/client.crt;
        proxy_ssl_certificate_key       /home/syngx/syngx/ssl_src/client.key;
        proxy_ssl_trusted_certificate   /home/syngx/syngx/ssl_src/ca.crt;
        proxy_ssl_session_reuse on;
        proxy_ssl_verify on;
        proxy_ssl_server_name on;
        proxy_ssl_name <имя сервера>;
        proxy_ssl_protocols TLSv1.2;
        proxy_ssl_ciphers AES256-SHA;
        proxy_pass tcp_tls_cluster;
    }
}

http {
    server {
        listen 8999;
        location /status_html {
            l4check_status html;
        }
        location /status_json {
            l4check_status json;
        }
        location /status_prometheus {
            l4check_status prometheus;
        }
    }
}

Примеры логирования с указанием типа проверки#

Записи в error.log выглядят следующим образом: [hc] type <сheck type>…, где сheck type - это тип проверки.

2024/03/21 15:51:04 [error] 63662#63662: [hc] type http: node fail, server (127.0.0.1:830) OFF in upstream (cluster1)

конфигурация:

upstream cluster1 {
    server 127.0.0.1:830;
    check interval=5000 rise=1 fall=3 timeout=4000 default_down=false type=http;
    check_http_send "HEAD / HTTP/1.0\r\n\r\n1";
}

Задание условий, при которых узел считается работоспособным по результатам активной проверки, с помощью секции match в http секции#

Секция match позволяет задать условия, по которым будет проверяться ответ от узла на запрос активной проверки работоспособности. При этом узел будет считаться работоспособным только при выполнении всех перечисленных в секции условий. Имя секции match также нужно указать в значении параметра match в директиве check. Проверка работоспособности с использованием параметра match в директиве check работает для http и https типов. При установки других типов проверки работоспособности будет выдаваться ошибка при старте:

syngx: [emerg] [hc] match argument is valid only with type of check http and https!

match

  • syntax: match name { ... }

  • default: -

  • context: http

Для задания условий используются следующие директивы:

  • status - позволяет задать условие для кода ответа, может быть объявлена 1 раз в секции. Пример:

status 200;
код ответа равен 200
status ! 500;
код ответа не равен 500
status 200 204;
код ответа равен 200 или 204
status ! 301 302;
код ответа не равен ни 301, ни 302
status 200-399;
код ответа находится в диапазоне от 200 до 399
status ! 400-599;
код ответа находится вне диапазона от 400 до 599
status 301-303 307;
код ответа равен 301, 302, 303 или 307
  • header - позволяет задать условие для заголовка, может быть объявлена несколько раз в секции. Пример:

header Content-Type = text/html;
ответ от узла содержит заголовок “Content-Type” со значением text/html
header Content-Type != text/html;
ответ от узла содержит заголовок “Content-Type” со значением, отличным от text/html
header Connection ~ close;
ответ от узла содержит заголовок “Connection” со значением, совпадающим с регулярным выражением close
header Connection !~ close;
ответ от узла содержит заголовок “Connection” со значением, не совпадающим с регулярным выражением close
header Host;
ответ от узла содержит заголовок “Host”
header ! X-Accel-Redirect;
ответ от узла не содержит заголовок “X-Accel-Redirect”
  • body - позволяет задать условие для тела ответа, может быть объявлена несколько раз в секции. Пример:

body ~ "Welcome to syngx!";
тело ответа совпадает с регулярным выражением “Welcome to syngx!”
body !~ "Welcome to syngx!";
тело ответа не совпадает с регулярным выражением “Welcome to syngx!”

Пример конфигурации:

http {
    match m1 {
        status 100-300;
        header Content-Type = text/plain;
        header Content-Language ~ ru;
        body = "gop gop, hop hop";
        body ^~ "pam pam";
    }

    upstream cluster1 {
        server 127.0.0.1:10001;
        check interval=1000 rise=1 fall=1 timeout=1000 type=http match=m1;
    }
}

Итоговое состояние работоспособности узла в группе балансировки: result = (условие для status) И (условие для header1) И … И (условие для headerN) И (условие для body1 ИЛИ … ИЛИ условие для bodyN) Модификаторы для директив header и body:

модификатор

описание

=

значение должно точно соответствовать указанному шаблону

^~

значение должно начинаться с указанного шаблона

~

значение должно соответствовать указанному регулярному выражению с учетом регистра

~*

значение должно соответствовать указанному регулярному выражению без учета регистра

Реализация секции match в syngx по большей части аналогична реализации в коммерческой версии nginx (более подробная информация https://nginx.org/ru/docs/http/ngx_http_upstream_hc_module.html#match).

Задание условий, при которых узел считается работоспособным по результатам активной проверки, с помощью секции match в stream секции#

Секция match позволяет задать условия, по которым будет проверяться ответ от узла на запрос активной проверки работоспособности. При этом узел будет считаться работоспособным только при выполнении всех перечисленных в секции условий. Имя секции match также нужно указать в значении параметра match в директиве check.

Проверка работоспособности с использованием параметра match в директиве check работает для tcp, tcp_tls и http типов. При установки других типов проверки работоспособности будет выдаваться ошибка при старте:

syngx: [emerg] [hc_stream] match argument is valid only with type of check tcp, tcp_tls and http!

match

  • syntax: match name { ... }

  • default: -

  • context: stream

Для задания условий используется директива:

  • expect - позволяет задать условие для ответа, полученного от сервера. Может быть объявлена несколько раз в секции. Параметр expect может содержать строки в шестнадцатеричном виде с префиксом “\x” и последующими двумя шестнадцатеричными цифрами, например “\x8a”. Строки в шестнадцатеричном виде не работают совместно с регулярными выражениями.

Пример:

expect ~ "Welcome to syngx!";
ответ совпадает с регулярным выражением “Welcome to syngx!”
expect !~ "Welcome to syngx!";
ответ не совпадает с регулярным выражением “Welcome to syngx!”

Пример конфигурации:

stream {
    match m1 {
        expect = "gop gop, hop hop";
        expect ^~ "pam pam";
    }

    upstream cluster1 {
        server 127.0.0.1:10001;
        check interval=1000 rise=1 fall=1 timeout=1000 type=http match=m1;
    }
}

Итоговое состояние работоспособности узла в группе балансировки: result = условие для expect1 ИЛИ … ИЛИ условие для expectN Модификаторы для директивы expect:

модификатор

описание

=

значение должно точно соответствовать указанному шаблону

^~

значение должно начинаться с указанного шаблона

~

значение должно соответствовать указанному регулярному выражению с учетом регистра

~*

значение должно соответствовать указанному регулярному выражению без учета регистра

Реализация секции match в syngx по большей части аналогична реализации в коммерческой версии nginx (более подробная информация https://nginx.org/ru/docs/stream/ngx_stream_upstream_hc_module.html#match).

Состояние DRAIN для узла в группе балансировки по результатам активной проверки работоспособности в секции stream#

Состояние DRAIN позволяет «мягко» вывести узел из балансировки, не прерывая уже установленных соединений. Состояние DRAIN для узла в группе балансировки означает, что SynGX не будет устанавливать новые соединения с данным узлом, при этом ранее установленные TCP соединения от SynGX до данного узла могут продолжать использоваться. Состояние выставляется с помощью обработки результатов ответа сервера с использованием секции match - аналогично работе параметра match в директиве check. Имя секции match нужно указать в значении параметра match_drain в директиве check. Проверка параметра match_drain осуществляется до проверки параметра match. Если проверка проходит удачно, то для сервера выставляется состояние DRAIN, а в противном случае продолжается проверка по параметру match. Состояние DRAIN работает для тех же типов проверки работоспособности, как и для match. При установки неподдерживаемых типов проверки работоспособности будет выдаваться ошибка при старте:

syngx: [emerg] [hc_stream] match argument is valid only with type of check tcp, tcp_tls and http!

Пример конфигурации:

stream {
    match m_main {
        # Response should start with 'ON' or 'TURN ON'
        expect ^~ "ON";
        expect ^~ "TURN ON";
    }
    match m_drain {
        # Response should start with 'DRAIN'
        expect ^~ "DRAIN";
    }

    upstream cluster1 {
        server 127.0.0.1:10001;
        server 127.0.0.1:10002;
        server 127.0.0.1:10003;
        check interval=1000 rise=1 fall=1 timeout=1000 type=http match=m_main match_drain=m_drain;
    }
}

В этом примере если сервер будет отвечать строкой, которая начинается с «DRAIN», то сервер будет находится в состоянии DRAIN. Если сервер будет отвечать строкой, которая начинается с «ON» или «TURN ON», то сервер будет находится в состоянии ON. В противном случае состояние сервера будет OFF. Вот пример статистики, полученной для серверов в трех состояниях:

sh-4.4$ curl 127.0.0.1:10000/monitor_json
{"active_healthcheck": {
  "total_servers": 3,
  "generation": 4,
  "servers": [
    {"index": 0, "upstream": "cluster", "server": "127.0.0.1:10001", "down": false, "active_healthcheck_status": "ON", "rise": 4185, "fall": 0, "check_type": "http", "port": 0},
    {"index": 1, "upstream": "cluster", "server": "127.0.0.1:10002", "down": false, "active_healthcheck_status": "DRAIN", "rise": 4310, "fall": 0, "check_type": "http", "port": 0},
    {"index": 2, "upstream": "cluster", "server": "127.0.0.1:10003", "down": true, "active_healthcheck_status": "OFF", "rise": 0, "fall": 2, "check_type": "http", "port": 0}
  ]
}}

Составные проверки работоспособности#

В SynGX реализована возможность задать статус пассивной проверки работоспособности одного узла на основании произвольной комбинации активных и пассивных проверок работоспособности других узлов. При проксировании запроса сначала проверяется состояние узла выставленное активной проверкой работоспособности (при наличие соответствующей директивы), а затем состояние выставленное пассивной проверкой работоспособности. Задача выставления статуса узла по результату проверки работоспособности нескольких узлов решается средствами доработанных динамических lua модулей. Работу функционала данных модулей рекомендуется выполнять в процессе привилегированного агента (чтобы решить проблему распределения работы между процессами).

Название модуля

Назначение модуля

lua-upstream-nginx-module

Получение статистики, выставление состояния пассивной проверки работоспособности узла в группе балансировки для секции http (L7 уровень модели OSI)

lua-stream-upstream-nginx-module

Получение статистики, выставление состояния пассивной проверки работоспособности узла в группе балансировки для секции stream (L4 уровень модели OSI)

Доработки модулей помимо исходного функционала (Исходный функционал смотри: https://github.com/openresty/lua-upstream-nginx-module):

get_primary_peers_ahc#

syntax: peers = upstream.get_primary_peers_ahc(upstream_name)

Получить таблицу состояний для всех основных (не резервных) узлов в указанной группе балансировки в виде массива.

Возвращаемое значение — это таблица Lua в виде массива для всех основных узлов (в качестве индекса выступает целочисленное значение начиная с 1). Каждая запись таблицы — это (вложенная) хэш-подобная таблица Lua, которая принимает следующие ключи:

  • id

    Идентификатор (ID) узла. Этот идентификатор можно использовать в качестве индекса узла в upstream (индексирование начинается с 1)

  • name

    Адрес сокета для текущего узла

  • down

    Хранит значение true, если узел в состоянии «down» по результатам активной проверки работоспособности, в противном случае false

  • fall_count

    Количество неуспешных проверок узла с момента выставления состояния down = false

  • rise_count

    Количество успешных проверок узла с момента выставления состояния down = true

  • tag

    Аргумент директивы server, значение заголовка Host в запросе активной проверки работоспособности (доступно только для секции http)

get_backup_peers_ahc#

syntax: peers = upstream.get_backup_peers_ahc(upstream_name)

Получить таблицу состояний для всех резервных узлов в указанной группе балансировки.

Возвращаемое значение имеет ту же структуру, что и функция get_primary_peers_ahc.

get_primary_peers_ahc_in_kv#

syntax: peers = upstream.get_primary_peers_ahc_in_kv(upstream_name)

Получить таблицу состояний для всех основных (не резервных) узлов в указанной группе балансировки в виде словаря, где в качестве ключа выступает адрес сокета.

Возвращаемое значение — это таблица Lua в виде словаря для всех основных узлов (в качестве индекса выступает строка с адресом сокета). Каждая запись таблицы — это (вложенная) хэш-подобная таблица Lua, которая принимает следующие ключи:

  • name

    Адрес сокета для текущего узла. Этот идентификатор можно использовать в качестве ключа узла в upstream

  • id

    Идентификатор (ID) узла.

  • down

    Хранит значение true, если узел в состоянии «down» по результатам активной проверки работоспособности, в противном случае false

  • fall_count

    Количество неуспешных проверок узла с момента выставления состояния down = false

  • rise_count

    Количество успешных проверок узла с момента выставления состояния down = true

  • tag

    Аргумент директивы server, значение заголовка Host в запросе активной проверки работоспособности (доступно только для секции http)

get_backup_peers_ahc_in_kv#

syntax: peers = upstream.get_backup_peers_ahc(upstream_name)

Получить таблицу состояний для всех резервных узлов в указанной группе балансировки в виде словаря.

Возвращаемое значение имеет ту же структуру, что и функция get_primary_peers_ahc_in_kv.

set_peer_down_by_ip_and_port#

syntax: ok, err = upstream.set_peer_down_by_ip_and_port(upstream_name, is_backup, name, down_value)

Установит атрибут «down» (логический) указанного узла в группе балансировки.

Выполняемый функционал аналогичен методу upstream.set_peer_down.

Чтобы однозначно указать узел, вам нужно указать имя группы балансировки, является ли он резервным узлом или нет, и идентификатор узла (адрес сокета).

Обратите внимание, что этот метод изменяет только настройки узла в текущем рабочем процессе SynGX. Для изменения состояния во всех рабочих процессах необходимо, чтобы в группе балансировки был указан размер и имя разделяемой памяти.

Примеры настройки составной проверки работоспособности узлов в секции http

...
load_module /opt/syngx/modules/ndk_http_module.so;
load_module /opt/syngx/modules/ngx_http_lua_module.so;
load_module /opt/syngx/modules/ngx_http_lua_upstream_module.so;

events {}

http {
    lua_package_path "/opt/syngx/modules/lua_libs/?.lua;;";
    init_by_lua_block {
        require "resty.core"
        local process = require "ngx.process"
        local ok, err = process.enable_privileged_agent()
        if not ok then
            ngx.log(ngx.ERR, "failed to enable_privileged_agent: ", err)
        end
    }

    init_worker_by_lua_block {
        local delay = 1  -- in seconds
        local new_timer = ngx.timer.at
        local log = ngx.log
        local ERR = ngx.ERR
        local check

        local concat = table.concat
        local upstream = require "ngx.upstream"
        local get_primary_peers_ahc = upstream.get_primary_peers_ahc
        local process = require "ngx.process"

        check = function(premature)
            if not premature then
                -- do the health check or other routine work
                local ok, err = new_timer(delay, check)
                if not ok then
                    log(ERR, "failed to create timer: ", err)
                    return
                end
            end

            -- do something in timer
            local u2 = upstream.get_primary_peers_ahc("u2")
            local u3 = upstream.get_primary_peers_ahc("u3")
            for i = 1, 3 do
                if (u2[i].down and u3[i].down) then
                    upstream.set_peer_down("master_upstream", false, i  - 1, true)
                else
                    upstream.set_peer_down("master_upstream", false, i  - 1, false)
                end
            end
        end

        if process.type() == "privileged agent" then
            local hdl, err = new_timer(delay, check)
            if not hdl then
                log(ERR, "failed to create timer: ", err)
                return
            end
        end

        -- other job in init_worker_by_lua
    }

    upstream master_upstream {
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
        server 127.0.0.1:9002;
        zone z 1m;
    }

    upstream u2 {
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
        server 127.0.0.1:9002;
        check interval=1000 rise=1 fall=1 timeout=1000 default_down=false type=http;
    }

    upstream u3 {
        server 127.0.0.1:11000;
        server 127.0.0.1:11001;
        server 127.0.0.1:11002;
        check interval=1000 rise=1 fall=1 timeout=1000 default_down=false type=http;
    }

...

load_module /opt/syngx/modules/ndk_http_module.so;
load_module /opt/syngx/modules/ngx_http_lua_module.so;
load_module /opt/syngx/modules/ngx_http_lua_upstream_module.so;

events {}

http {
    lua_package_path "/opt/syngx/modules/lua_libs/?.lua;;";
    init_by_lua_block {
        require "resty.core"
        local process = require "ngx.process"
        local ok, err = process.enable_privileged_agent()
        if not ok then
            ngx.log(ngx.ERR, "failed to enable_privileged_agent: ", err)
        end
    }

    init_worker_by_lua_block {
        local delay = 1  -- in seconds
        local new_timer = ngx.timer.at
        local log = ngx.log
        local ERR = ngx.ERR
        local check

        local concat = table.concat
        local upstream = require "ngx.upstream"
        local process = require "ngx.process"

        check = function(premature)
            if not premature then
                -- do the health check or other routine work
                local ok, err = new_timer(delay, check)
                if not ok then
                    log(ERR, "failed to create timer: ", err)
                    return
                end
            end

            -- do something in timer
            local u1 = upstream.get_primary_peers_ahc_in_kv("u1")
            local u2 = upstream.get_primary_peers_ahc_in_kv("u2")
            local u3 = upstream.get_primary_peers_ahc_in_kv("u3")
            if (u1["127.0.0.1:9000"].down and u3["127.0.0.1:12001"].down) then
                upstream.set_peer_down_by_ip_and_port("master_upstream", false, "127.0.0.1:9000", true)
            else
                upstream.set_peer_down_by_ip_and_port("master_upstream", false, "127.0.0.1:9000", false)
            end
            if ((u1["127.0.0.1:9001"].down or u2["127.0.0.1:11000"].down) and u3["127.0.0.1:12000"].down) then
                upstream.set_peer_down_by_ip_and_port("master_upstream", false, "127.0.0.1:9001", true)
            else
                upstream.set_peer_down_by_ip_and_port("master_upstream", false, "127.0.0.1:9001", false)
            end
        end

        if process.type() == "privileged agent" then
            local hdl, err = new_timer(delay, check)
            if not hdl then
                log(ERR, "failed to create timer: ", err)
                return
            end
        end

        -- other job in init_worker_by_lua
    }

    upstream master_upstream {
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
        zone z 1m;
    }

    upstream u1 {
        server 127.0.0.1:9000;
        server 127.0.0.1:9001;
        check interval=1000 rise=1 fall=1 timeout=1000 default_down=false type=http;
    }

    upstream u2 {
        server 127.0.0.1:11000;
        check interval=1000 rise=1 fall=1 timeout=1000 default_down=false type=tcp;
    }

    upstream u3 {
        server 127.0.0.1:12000;
        server 127.0.0.1:12001;
        check interval=1000 rise=1 fall=1 timeout=1000 default_down=false type=tcp;
    }

Медленный старт (slow start) узла при введении в балансировку#

Функция медленного старта (slow start) заключается в плавном увеличении веса узла, который ранее с помощью активной проверки работоспособности был выведен из балансировки, а затем введен снова, с 0 до номинального значения в течение заданного времени.

Как включить медленный старт на SynGX

Пример конфигурации:

upstream backend_servers {
    server <адрес сервера1>:<port>;
    server <адрес сервера2>:<port> slow_start=30s;
    server <адрес сервера3>:<port> slow_start=120s;
}

Примечание: slow start работает только в секции http.

Параметр slow_start - задает время, в течение которого вес сервера восстановится от нуля до своего номинального значения в ситуации, когда неработоспособный/недоступный сервер вновь становится работоспособным/доступным. Значение по умолчанию равно нулю и означает, что медленный старт выключен.

Важно: параметр нельзя использовать совместно с методами балансировки нагрузки hash, ip_hash и random.

Разрыв соединения при выпадении всех серверов из балансировки на уровне HTTP#

Данный функционал заключается в разрыве соединения путем отправки TCP пакета с флагом RST на запрос отправленный клиентом при отсутствии «живых» узлов в группе балансировки по результатам активной проверки работоспособности.

Включение данного функционала осуществляется с помощью директивы send_rst указанной в контесте upstream

upstream backend_http_servers {
    server <адрес сервера1>:<port>;
    server <адрес сервера2>:<port>;
    server <адрес сервера3>:<port>;
    send_rst;
}

При этом в error_log будет выведено сообщение с уровнем INFO

no live servers in upstream - <upstream name>, closing connection with client by sending TCP RST while connecting to upstream, client: <client ip>, server: <server name>, request: <request head>, host: <host ip>:<host port>

Возможность скрыть имя SynGX в ответах#

Директива hide_syngx_name позволяет скрыть имя сервера в заголовках и в теле стандартного html ответа с кодами 3xx, 4xx, 5xx

название директивы

Контекст

Параметры

Значение по умолчанию

hide_syngx_name

http

on - скрывает имя сервера в заголовках и теле ответа
off - разрешает использовать имя сервера в заголовках и теле ответа

off

Мониторинг работы SynGX#

Администратору SynGX необходимо периодически производить проверку и осуществлять просмотр:

  • системных метрик сервера и SynGX (подробнее - см. ниже в разделе События мониторинга);

  • метрик работоспособности и статистики обработки запросов (подробнее - см. ниже в разделе События мониторинга);

  • журналов событий - error.log и access.log (подробнее - см. ниже в разделе События системного журнала).

Администратору сервера нужно периодически проверять значения системных метрик SynGX и утилизации ресурсов сервера компонентом SNGX, чтобы они не превышали допустимых пороговых значений согласно нормам эксплуатирующей организации.

При превышении пороговых значений, администратору нужно оперативно выявить причину повышенной нагрузки путем анализа значений различных системных метрик, метрик мониторинга SynGX, логов компонента SNGX, и предпринять необходимые действия для решения проблемы в соответствии с порядком разбора инцидентов АС (руководствоваться внутренним регламентом, порядком и нормами эксплуатирующей организации).

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