Реализация шаблона Singleton для регистрации в микросервисах с помощью Kubernetes
Table of Contents
Введение: почему логирование имеет значение в микросервисах
В современных микросервисных архитектурах лесозаготовка является основой наблюдаемости. Без согласованной стратегии лесозаготовок отладка распределенного сбоя становится кошмаром рассеянных временных меток, отсутствующего контекста и несоответствующих форматов. Однотонный шаблон, классический шаблон дизайна, предлагает элегантное решение: единый общий экземпляр для регистрации, в который входят все службы. В сочетании с Kubernetes этот подход обеспечивает последовательную централизованную рубку, которая масштабируется с вашей инфраструктурой.
В этой статье мы рассмотрим, как разработать услугу однотонной лесозаготовки в Кубернетесе, почему она работает, и когда это может быть неправильный выбор. К концу у вас будет четкая дорожная карта для развертывания унифицированных лесозаготовок в вашем парке микросервисов.
Дизайнерский паттерн Singleton: быстрый рефресер
Однопользовательский шаблон ограничивает класс одним экземпляром и обеспечивает глобальную точку доступа к нему. В программном дизайне он контролирует общие ресурсы, такие как конфигурация, пулы потоков или - как мы фокусируемся здесь - журналирование. В контексте микросервисов экземпляр однопользовательского журналирования гарантирует, что каждая запись журнала из каждой службы течет в одно и то же место назначения, сохраняя порядок и устраняя дублирование логики агрегации.
Критики часто предостерегают от чрезмерного использования синглтонов, поскольку они вводят глобальное состояние и скрытые зависимости. Однако при применении к трубопроводу для лесозаготовок без состояния преимущества перевешивают недостатки. Сама услуга лесозаготовок является раковиной без состояния; синглтон применяется только к слою маршрутизации и буферизации, а не к бизнес-логике. Этот нюанс сохраняет практичность шаблона для распределенных систем.
Проблемы ведения лесозаготовок, уникальные для микросервисов
Традиционная монолитная регистрация записывает в один файл на диске. Микросервисы разрушают эту простоту. Вот основные проблемы, которые мы стремимся решить с помощью однотонного подхода:
- Фрагментация журнала (FLT:0) Фрагментация журнала (FLT:1) – Каждая служба записывает свои собственные журналы, часто для локального хранения или стадирования, что затрудняет отслеживание кросс-сервисов.
- Несогласованные форматы — команды могут использовать различные библиотеки журналов, стили вывода (JSON против простого текста) и уровни вербозита.
- Увеличенный объем — С десятками или сотнями экземпляров обслуживания, проглатывание журналов и хранение данных стремительно растут без центрального управления.
- Контекстная корреляция — один пользовательский запрос может перескакивать через несколько сервисов; журналы должны иметь идентификаторы корреляции для восстановления цепочки.
- Операционная сложность — Сбор, агрегирование и запрос журналов из распределенной эфемерной среды, такой как Kubernetes, нетривиальна.
Однотонная схема регистрации напрямую устраняет фрагментацию и несоответствие, перекачивая все журналы по одному стандартизированному трубопроводу.В Кубернете этот трубопровод становится управляемым блоком: единым Подом или Сервисом.
Архитектура службы лесозаготовок Singleton в Кубернете
Kubernetes предлагает несколько способов запуска однотонного регистрационного агента. Наиболее простым является развертывание или StatefulSet с , за Службой для внутреннего обнаружения. Однако настоящий синглтон требует больше, чем просто подсчет реплик - вы должны предотвратить случайные множественные экземпляры от запланированных на разных узлах во время обновления или сетевых разделов. Мы скоро покроем гарантии.
Вариант 1: Централизованный однопользовательский агрегатор (развертывание)
Развернуть выделенный агрегатор журналов — например, Fluentd, Logstash или пользовательский сервис — как развертывание с одной репликой. Микросервисы отправляют журналы по HTTP, gRPC или через боковую коляску, которая пересылается на агрегатор. Агрегатор анализирует, обогащает и пересылает журналы в долгосрочное хранилище (Elasticsearch, Loki, CloudWatch).
Эта модель проста в рассуждении, но вводит единственную точку отказа и узкое место. Чтобы смягчить, используйте постоянный объем для буферизации журналов локально, если одиночник падает, и полагайтесь на зонды жизнеспособности / готовности Kubernetes, чтобы быстро перезапустить его. Для высокой доступности рассмотрите активный-пассивный со вторым резервным чалдом, который активируется только при отказе - хотя это дублирует концепцию одиночного.
Вариант 2: Sidecar-Per-Service с общим экспедитором
Вместо того, чтобы службы отправляли журналы напрямую, каждый сервисный контейнер запускает боковой контейнер (например, легкий Fluent Bit), который отслеживает журналы основного контейнера и отправляет их в агрегатор одиночных узлов. Это отделяет форматирование журналов от бизнес-логики и позволяет буферизацию на подложку. Модель бокового вагона распространена в производстве, потому что она не требует услуг для реализации пользовательского клиента для регистрации.
Вариант 3: DaemonSet на уровне узлов - Анти-Синглтон?
Kubernetes DaemonSets запускают один Pod на узел. Это стандартный подход для регистраторов уровня узлов (например, флуент-демонсет, флуэнтбит-демонсет). Хотя он не является однотонным (поскольку несколько узлов каждый имеют копию), он обеспечивает агрегацию на одноузловом перед пересылкой в центральное хранилище. Это может быть объединено с однотонным агрегатором — DaemonSet становится коллекторным слоем, а синглтон является слоем агрегации. Для истинной однотонной регистрации слой агрегации должен быть одним экземпляром, но слой сбора может быть распределен.
Мы сосредоточимся на централизованном подходе к однотонному агрегатору, потому что он лучше всего обеспечивает единую логическую осечку.
Заставить Синглтона вести себя в Кубернете
Kubernetes изначально не обеспечивает максимальное количество одного запущенного Pod для развертывания по сбоям кластера - если узел умирает, Pod воссоздается на другом узле, но во время этого перехода у вас может быть два Pods кратко. Чтобы гарантировать поведение одиночного компьютера, реализуйте один или несколько из этих методов:
- Pod Anti-Affinity — Используйте с , чтобы предотвратить запуск двух подиумов одного и того же приложения на одном и том же узле. Это не предотвращает два подиума на разных узлах, поэтому объединяйтесь с квотой или выборами лидера.
- Лиз или выборы лидера — Используйте объект аренды Kubernetes (через API ) для выбора лидера среди набора потенциальных однопользовательских стручков. Блок нелидерских стручков до истечения срока аренды лидера. Такие инструменты, как etcd, также могут служить распределенным замком. Это самый надежный способ для настоящего одиночного троса.
- StatefulSet with Persistent Volume Claim — StatefulSet с одной репликой и ПВХ гарантирует, что только один контейнер может записывать в объем данных. Если два контейнера запускаются, второй не сможет связать ПВХ. Это также обеспечивает упорядоченное обновление, уменьшая вероятность двойных экземпляров.
- Пользовательский оператор — Напишите оператора Kubernetes, который управляет ресурсом одной организации, активно сокращая или убивая дополнительные стручки.
На практике для ведения журнала достаточно однореплицированного развертывания с зондами жизнеспособности и зондом готовности, который проходит только тогда, когда одиночник готов. Если ваш кластер имеет PodDisruptionBudgets, установите для предотвращения добровольных выселений одиночника.
Шаг за шагом: развертывание однотонного агрегатора
Давайте рассмотрим конкретную реализацию с использованием Fluentd в качестве агрегатора синглтона. Fluentd - популярный сборщик данных с открытым исходным кодом с надежной поддержкой Kubernetes.
1.Создать плавную конфигурацию
Определите ConfigMap для Fluentd, который слушает на порту (например, 9880) журналы из микросервисов и пересылает их в Elasticsearch или другой бэкэнд.
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-config
data:
fluent.conf: |
<source>
@type http
port 9880
bind 0.0.0.0
body_size_limit 32m
keepalive_timeout 10s
</source>
<match **>
@type elasticsearch
host elasticsearch-logging
port 9200
logstash_format true
flush_interval 5s
</match>
2.Определить развертывание Singleton с анти-аффинити
apiVersion: apps/v1
kind: Deployment
metadata:
name: fluentd-singleton
spec:
replicas: 1
selector:
matchLabels:
app: fluentd-singleton
template:
metadata:
labels:
app: fluentd-singleton
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- fluentd-singleton
topologyKey: kubernetes.io/hostname
containers:
- name: fluentd
image: fluent/fluentd:v1.16-1
ports:
- containerPort: 9880
volumeMounts:
- name: config
mountPath: /fluentd/etc
volumes:
- name: config
configMap:
name: fluentd-config
Это противоаффинность предотвращает работу двух стручков на одном узле, но не предотвращает их на разных узлах. Для более сильной гарантии добавьте аренду лидерства.
3.Разоблачить Синглтон через службу без головы
Служба без головы позволяет использовать DNS-модули в разных контейнерах, но нам нужна только одна конечная точка.
apiVersion: v1
kind: Service
metadata:
name: fluentd-svc
spec:
selector:
app: fluentd-singleton
ports:
- port: 9880
targetPort: 9880
Микросервисы могут отправлять журналы в .
4. Настройка микросервисов для отправки журналов
Каждый микросервис должен писать в stdout/stderr (путь Kubernetes). Контейнер sidecar Fluent Bit подбирает эти журналы и отправляет их в службу singleton Fluentd. Альтернативно, само приложение может отправлять структурированные журналы JSON непосредственно через HTTP-клиент к . Для согласованности мы рекомендуем метод sidecar, чтобы избежать изменения кода приложения.
Пример определения контейнера для коляски в том же контейнере:
containers:
- name: app
image: myapp
...
- name: fluentbit-sidecar
image: fluent/fluent-bit:latest
args: ["-c", "/etc/fluent-bit.conf"]
volumeMounts:
- name: varlog
mountPath: /var/log
env:
- name: FLUENTD_HOST
value: "fluentd-svc"
- name: FLUENTD_PORT
value: "9880"
Конфигурация Fluent Bit отслеживает файл журнала приложения или считывает из драйвера журнала Docker, а затем пересылает в синглтон.
Внешние ссылки для Deeper Dive
Для полного понимания регистрации в Kubernetes обратитесь к официальной Kubernetes Logging Architecture. Для спецификаций Fluentd документация Fluentd охватывает конфигурацию и плагины. Если вы предпочитаете стек EFK (Elasticsearch, Fluentd, Kibana), см. Kubernetes Addons repository. Для шаблонов выборов лидера с использованием аренды, просмотрите примеры client-go.
Преимущества Singleton Logging (расширенный)
- Единый формат журнала — Все журналы проходят через один и тот же парсер и трансформатор. Вы определяете одну схему JSON один раз.
- Упрощенное соблюдение — централизованные политики хранения журналов легче применять во всем флоте.
- Более низкие затраты на инфраструктуру — вместо каждой услуги, работающей на собственном судоводителе (с дублирующими буферизацией и хранением), Singleton обрабатывает агрегацию, уменьшая накладные расходы.
- Легкая отладка — одно место для запроса. Нет необходимости присоединяться к журналам из нескольких источников, если вы не решите.
- Согласованные уровни журналов — синглтон может автоматически устанавливать глобальные пороги уровня журналов (например, только и выше в производстве) или вводить идентификаторы корреляции.
- Изоляция ресурсов — Однопользовательскому стручке могут быть назначены запросы ресурсов и ограничения, гарантирующие, что у него достаточно процессора / памяти для обработки нагрузки, независимо от струн приложений.
Компромиссы и когда следует избегать лесозаготовок
Ни одна архитектура не идеальна. Однопользовательская вырубка вводит несколько оговорок:
- Единая точка отказа — Если одиночный струнок умирает, логи теряются (если вы не буферизуете на стороне клиента). В высокопроизводительных средах даже несколько секунд простоя могут упасть на тысячи строк журнала.
- Боттлнек емкости — Один Fluentd экземпляр должен обрабатывать весь логарифмический трафик.При очень больших объемах (сотни гигабайт в день) нужно масштабироваться вертикально или перейти к распределенному агрегатору вроде Kafka перед синглтоном, который ломает чистый однотонный шаблон.
- Сетевая задержка — Каждая линия журнала проходит по сети. Если синглтон находится на другом узле, затраты на выход и задержка складываются.
- Сложность истинного синглтона — Достижение точно одного запущенного экземпляра при всех условиях отказа (отключение узлов, обновление роллинга, разделение мозга) требует выборов лидера или внешней блокировки, добавляя операционную нагрузку.
- Ограниченная гибкость (FLT:0) — команды, которые хотят отправлять журналы на различные бэкэнды (Dev vs. Prod или экспериментальные службы), могут найти одиночную систему слишком жесткой.
Рассмотрим альтернативные шаблоны, если ваш кластер растет за пределы 20–50 узлов или если объем регистрации превышает то, что может обрабатывать один контейнер. DaemonSet + Centralized Storage шаблон де-факто является отраслевым стандартом для больших кластеров. Используйте одиночную модель только тогда, когда вам нужна сильная согласованность в парке микросервисов малого и среднего уровня или в качестве дополнения к коллектору уровня узла, который все еще воронки в один агрегатор для глобальных запросов.
Лучшие практики для лесозаготовок Singleton в производстве
Используйте структурированную логистику из приложений
Поощряйте все службы выпускать журналы в структурированном формате (JSON) с согласованными полями: , , , , . Синглтон может затем анализировать, индексировать и фильтровать без угадывания. Используйте библиотеки, такие как (Java), (Node.js) или (Python).
Местный буфер, чтобы выжить при сбоях в Синглтоне
В боковом вагоне Fluent Bit включить буферизацию диска. Настроить раздел , который записывает в том или ПВХ. Если однотонный агрегатор недостижим, логирует очередь на узле и переигрывает при возобновлении подключения. Настройка и .
Мониторинг здоровья Синглтона
Настройте метрики Prometheus для одиночного компьютера (т.е. количество обработанных событий, скорость ошибок, размер буфера). Создайте оповещения о том, когда буфер заполняется или когда синглтон перестает получать журналы. Используйте Kubernetes не применимо для одиночного компьютера, но вертикальное автомасштабирование под (VPA) может регулировать ресурсы.
Реализовать Retry и Backpressure
Заготовка трубопровода должна изящно справляться с обратным давлением. Если одиночник перегружен, он должен возвращать 429 Слишком много запросов, а клиенты (или коляски) должны осуществлять экспоненциальный обратный вылет. В противном случае одиночник может сбрасывать пакеты или падать под нагрузкой.
Защищайте вход
Выставляйте услугу одиночного доступа только в кластере (ClusterIP). Если вы должны подвергать ее воздействию извне, ограничивайте сетевые политики и используйте TLS для транспортировки журналов. Fluentd поддерживает ввод TLS через с .
Продвинутые шаблоны: Stateless Singleton с буферным слоем
Для преодоления узкого места, подумайте о вставке буферного слоя, такого как Kafka или Redis перед однотонной. Микросервисы (или коляски) пишут на темы Kafka. Синглтон-агрегатор потребляет из одного раздела темы, обеспечивая упорядоченную обработку. Сам кластер Kafka распределен и отказоустойчив, в то время как потребитель остается однотонным. Этот гибридный шаблон обеспечивает высокую пропускную способность записи и долговечность при сохранении одной логической службы. Накладные расходы на управление Kafka могут быть оправданы только для очень больших систем.
Заключение
Реализация однотонного шаблона для регистрации в микросервисах с Kubernetes обеспечивает чистый, последовательный и управляемый трубопровод для регистрации кластеров умеренного масштаба. Централизуя агрегацию журналов через один экземпляр, вы уменьшаете фрагментацию, обеспечиваете единообразное форматирование и упрощаете устранение неполадок. Однако для многих команд однотонный шаблон служит отличной отправной точкой, пока кластер не вырастет достаточно большим, чтобы оправдать полный распределенный стек регистрации.
Потратьте время на оценку объема лесозаготовок, отказоустойчивости и опыта команды. Рассмотрите возможность запуска с агрегатора Singleton Fluentd, а затем эволюционируйте в сторону коллектора на основе DaemonSet, питающего центральную раковину по мере расширения ваших потребностей. Какой бы путь вы ни выбрали, объединение ваших микросервисов под одной логической точкой входа является шагом к лучшей наблюдаемости и более быстрому разрешению инцидентов.