В одном из прошлых постов я рассказывал про Pod и упоминал, что в нём может быть несколько контейнеров. Один из них основной, а второй - просто помощник. Сегодня разберу этот паттерн подробно: зачем он нужен, как работает и какие новые возможности появились в Kubernetes 1.28+💻
Sidecar (сайдкар, «боковой автомобиль») - дополнительный контейнер в поде, который работает рядом с основным и расширяет или дополняет его функциональность, не вмешиваясь в бизнес-логику
Технически это второй (или третий) контейнер в том же поде, который разделяет с основным:
• Network namespace - оба контейнера доступны по localhost на одном IP
• Volumes - могут обмениваться данными через общую файловую систему
• Жизненный цикл - создаются и удаляются вместе с подом
Sidecar решает задачи, которые критично привязаны к конкретному экземпляру приложения:
• Низкая задержка (общий localhost быстрее, чем поход по сети)
• Совместное использование файлов (через Volume)
• Гарантия, что sidecar живёт ровно столько же, сколько основное приложение
А если вы решите вынести sidecar в отдельный Deployment, вы потеряете все эти свойства и получите дополнительные сетевые издержки
Типичные сценарии использования🤔
• Проксирование и Service Mesh
Контейнер-прокси (например, Envoy в Istio) перехватывает весь входящий и исходящий трафик основного контейнера. Делает mTLS, retry, rate limiting, tracing. Основной контейнер даже не знает, что трафик идёт через прокси
• Сбор логов и метрик
Основной контейнер пишет логи в файл на общий Volume. Sidecar (Fluent Bit, Filebeat, Prometheus exporter) читает этот файл и отправляет данные в централизованную систему (Elasticsearch, Loki, Prometheus)
• Синхронизация данных
Sidecar периодически подтягивает конфигурацию или данные из внешнего источника (S3, Git, API) и кладёт их на общий Volume. Основной контейнер перечитывает их без перезапуска
• Инициализация и warm-up
Sidecar прогревает кэш или делает pre-flight проверки перед тем, как основной контейнер начнёт принимать трафик
Если говорить о жизненном цикле sidecara, то по умолчанию все контейнеры в поде стартуют параллельно, из-за чего создаётся проблема, что sidecar (например, прокси) может быть ещё не готов, когда основное приложение уже пытается отправить запрос💀
Решение - есть, и их даже несколько:
• Readiness probe у sidecar'а: под не станет Ready, пока sidecar не поднимется
• Init containers: запускаются до основных контейнеров, но не живут вместе с ними (выполняются и завершаются)
• Retry-логика в приложении: основное приложение само ретраит подключения
Начиная с версии 1.28 (beta) и 1.29 (GA), в Kubernetes появился штатный механизм sidecar-контейнеров через init-контейнеры с `restartPolicy: Always`🥳
initContainers:
- name: envoy-proxy
image: envoyproxy/envoy:v1.28
restartPolicy: Always # ← ключевое поле
Такой «init-контейнер» стартует строго до основных контейнеров и продолжает жить вместе с ними на протяжении всего жизненного цикла пода. Это гарантирует, что сайдкар (например, прокси или агент синхронизации) будет полностью готов к работе к моменту запуска основного приложения. Кроме того, при завершении пода такой контейнер корректно останавливается в правильном порядке, что автоматически решает давнюю проблему с Job и CronJob: раньше джобы бесконечно зависали в статусе выполнения, пока живой сайдкар не завершался, а теперь оркестратор понимает его специфическую роль и управляет его жизненным циклом корректно
