Когда LLM-шлюз выходит из стадии прототипа в продакшен, главными становятся не фичи, а устойчивость. В этой статье — практический опыт эксплуатации open-source шлюза Keystone (KTMS) на Go: как добавить собственные GPU, как вести себя при отказах каждой зависимости, как ротировать ключи шифрования, как убедиться, что вы скачали официальный релиз, и как обновляться без простоя.

Подключение собственных видеокарт

Шлюз не требует, чтобы все модели были в облаке. Если у вас есть GPU-сервер, его можно подключить как отдельный бэкенд. Вот шаги:

  • Подготовьте ноду: установите драйверы, CUDA (или ROCm), запустите inference-сервер (например, vLLM, TGI или Ollama) с нужной моделью. Убедитесь, что сервер доступен по сети и отвечает на health-check.
  • Зарегистрируйте ноду в шлюзе: добавьте адрес и порт в конфигурацию провайдеров. Укажите тип (openai-совместимый, ollama и т.п.), лимиты и таймауты.
  • Настройте маршрутизацию: определите, какие запросы идут на локальные GPU, а какие — в облако (по модели, по стоимости, по приоритету).
  • Проверьте отказоустойчивость: отключите ноду и убедитесь, что шлюз переключается на резервный бэкенд без ошибок для клиента.

Типичная ошибка — забыть про health-check и таймауты. Если локальная нода зависла, шлюз должен быстро перестать отправлять на неё запросы.

Что происходит, когда отказывает каждая зависимость

В продакшене отказывает всё: сеть, база данных, Redis, внешние API. Шлюз должен деградировать предсказуемо. Вот как это выглядит на практике:

  • Отказ локального GPU-бэкенда: шлюз помечает ноду как недоступную (circuit breaker) и перенаправляет трафик на облачный резерв. Клиент получает ответ, возможно, с большей задержкой.
  • Отказ облачного провайдера: аналогично — переключение на другую модель или локальную ноду. Важно иметь fallback-цепочку.
  • Отказ Redis (кэш, rate limiting): шлюз может продолжать работу в режиме без кэша, но с ограничениями. Нужно предусмотреть graceful degradation: например, пропускать запросы без лимитов или отвечать 503, если лимиты критичны.
  • Отказ базы данных (ключи, конфигурация): если шлюз не может прочитать ключи, он должен использовать закэшированную версию или вернуть ошибку. Лучше — кэшировать конфигурацию в памяти с периодическим обновлением.

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

Ротация ключей шифрования

Шлюз хранит чувствительные данные (API-ключи провайдеров, секреты) в зашифрованном виде. Рано или поздно ключ шифрования нужно сменить. Порядок действий:

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

Ошибка — менять ключ «на горячую» без обратной совместимости. Это приведёт к тому, что старые секреты станут нечитаемыми.

Проверка релиза и обновления без простоя

Скачивая open-source шлюз, важно убедиться, что вы получили именно официальный релиз. Проверяйте подписи и контрольные суммы:

  • Скачивайте бинарники и образы только с официальной страницы релизов.
  • Проверяйте GPG-подпись или SHA-суммы, опубликованные авторами.
  • Собирайте из исходников, если есть сомнения, и сверяйте хеши.

Обновление без простоя требует подготовки:

  • Blue-green или канареечный деплой: запустите новую версию рядом, переключите часть трафика, проверьте метрики и только потом переводите всё.
  • Совместимость конфигурации: перед обновлением прочитайте changelog на предмет breaking changes. Держите конфигурацию в виде кода и версионируйте.
  • Health-check и readiness: шлюз должен корректно сообщать о готовности, чтобы оркестратор не отправлял трафик на нездоровый экземпляр.
  • План отката: всегда имейте возможность вернуться на предыдущую версию. Храните предыдущий образ и конфигурацию.

Пример из практики: обновление через канареечный деплой с 5% трафика позволило заметить ошибку в обработке таймаутов и откатить версию без влияния на большинство пользователей.

В итоге, эксплуатация LLM-шлюза — это не про магию, а про дисциплину: явные health-check, fallback-цепочки, версионность ключей и аккуратные обновления. Эти практики помогут сохранить сервис доступным, даже когда что-то идёт не так.