Пожелания программистам и DevOps от админов эксплуатации

Программистам

В первую очередь, почитайте вот этот документ.

Общие вопросы.

  • Масштабируйте приложения не вертикально, а горизонтально. Ресурсы серверов не безграничны.

Конфигурация приложений

  • По возможности, используйте переменные среды окружения.
  • Логины, пароли и прочие параметры, которые не стоит показывать всему миру, выносите в переменные среды окружения или в отдельный конфигурационный файл.
  • В качестве формата для конфигурационного файла попробуйте использовать yaml.

Состояния

  • Запускайте приложение как один или несколько процессов не сохраняющих внутреннее состояние.
  • Если приложению необходимо сохранить состояние, это следует делать во внешней БД или кэш (Redis и т.п.).

Логи приложений

  • Логи должны быть в формате json в виде одной строки. Если в сообщении приложения есть переводы строки, они заменяются на ‘\n’.
  • Логи должны выводиться в stdout и stderr.
  • Система логирования приложений, кроме стандартного вывода и вывода ошибки, должна иметь возможность параллельно выводить логи в определенный в конфигурации приложения файл или по сети на роутер логов.
    • Необходимо предусмотреть ротацию логов самим приложением. Значение по умолчанию (можно изменять под свою ситуацию):
      • Один файл не более 50Мб;
      • Срок хранения файлов не более 7 дней;
      • Общий размер лог-файлов не более 200M.
  • Настройку логирования выносите в конфигурационные параметры.
  • Присваивайте ошибкам уникальные номера.

Метрики

  • Используйте метрики формата Prometheus.
  • Предусмотрите возможность отключения аутентификации для сбора метрик.
  • Вынесите в конфигурацию путь, по которому можно собирать метрики и выключение аутентификации.

Резервирование ресурсов для приложения

  • Разработчик должен определить необходимые для работы приложения ресурсы (CPU и RAM): запросы (requests) и лимиты (limits).

Проверка работоспособности приложений.

  • В приложении должны быть реализованы проверки, доступные через отдельный контекст, например /health (путь к контексту должен быть вынесен в конфигурационные параметры):
    • Готовность к запуску (readiness).
    • Работоспособность приложения (liveness).
  • Предусмотрите возможность отключения аутентификации при проверках.
  • Информация о запросах к проверкам не должны отражаться в логах приложения. Или отображаться на уровне важности debug. Или должна быть возможность включения/выключения вывода сообщений в логи.

Контекст (location)

  • В конфигурации приложения должна быть возможность определения контекста, например:
    • http://app.any.com/ — контекст = /
    • http://app.any.com/context — контекст = /context.

Безопасность

  • Приложения должны иметь возможность работать, не используя учетную запись root.

DevOps-ам

В первую очередь, почитайте вот этот документ.

Сборка контейнера

  • В теге контейнера в хранилище обязательно указывайте версию приложения:
    • Обычный номер версии должен иметь формат X.Y.Z, где X, Y и Z — неотрицательные целые числа и не должны начинаться с нуля. X — мажорная версия, Y — минорная версия и Z — патч-версия. Каждый элемент должен увеличиваться численно. Например: 1.9.0 ->1.10.0 -> 1.10.1.
    • Предрелизная версия может быть обозначена добавлением дефиса и серией разделённых точкой идентификаторов, следующих сразу за патч-версией. Идентификаторы должны содержать только ASCII буквенно-цифровые символы и дефис [0-9A-Za-z-]. Идентификаторы не должны быть пустыми. Числовые идентификаторы не должны начинаться с нуля. Предрелизные версии имеют более низкий приоритет, чем соответствующая релизная версия. Предрелизная версия указывает на то, что эта версия не стабильна и может не удовлетворять требованиям совместимости, обозначенными соответствующей нормальной версией. Примеры: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92.
  • Никогда не используйте тэг latest.

Сервера не резиновые

  • В случае использования встроенных баз данных (типа SQL Light), больших по объему конфигурационных файлов, файлов изображений и т.д., их нельзя размещать внутри контейнера. Необходимо использовать подключаемые тома. При передаче приложения в эксплуатацию, данные файлы должны быть предоставлены в виде отдельного архива.
  • Тома типа emptyDir занимают место на локальном диске ноды кластера. Используйте их аккуратно.

Логи приложений

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

  • Настройте приложение на параллельный вывод логов в файл, доступный внутри пода (например том типа emptyDir) или передачу логов по сети.
    • В случае файла, добавьте в под дополнительный контейнер сборщика логов со своими конфигурационными файлами.
    • Во втором случае, само приложение должно уметь отправлять логи по сети.

В качестве сборщика логов рекомендую присмотреться к fluentbit.

Пример дополнительного контейнера для сбора логов.

Безопасность

  • Приложения должны иметь возможность работать, не используя учетную запись root.
  • В Dockerfile обязательно указывайте пользователя и его UID, с правами которого выполняется приложение.
  • Контейнер в поде должен иметь возможность запускаться от обычных пользователей (не root). Определяйте securityContext — пользователя и группу, с правами которого будет выполняться контейнер.
  • Переменные среды окружения, используемые приложениями, выносите в ConfigMap или Secret.
  • Пароли, токены и прочие конфигурационные параметры, содержащие закрытую информацию, выносите в Secret. Не помещайте их содержимое в git. Создавайте их самостоятельно или при помощи службы поддержки непосредственно в кластере.
  • А еще есть Hashicorp Vault.

Метрики

  • Уточните у админов, эксплуатирующих приложение:
    • Как они собирают метрики?
    • Где графана?
    • Что используется для обработки алёртов?
  • Настройте доступ к метрикам в контейнере.

kubernetes общее

  • По возможности используйте kind Deployment.
  • Если используется StatefulSet, по возможности применяйте podManagementPolicy: Parallel.
  • Используйте imagePullPolicy: IfNotPresent.
  • Обязательно определяйте:
    • readinessProbe и livenessProbe.
    • resources requests и limits.