Istio: ждать готовности sidecar перед стартом приложения

Envoy перехватывает исходящий трафик через iptables-правила, которые
ставит init-контейнер istio-init. Правила появляются раньше, чем envoy
начинает слушать, поэтому приложение, дёрнувшее сеть в первые секунды,
получает не таймаут, а connection refused — пакет уже завёрнут на порт
envoy, а там ещё никого нет.

Так падал workflows-api: контейнер стартовал и умирал в ту же секунду,

  INFO  Starting workflows migrations
  INFO  init database connection...
  FATAL [dial tcp 10.43.195.4:5432: connect: connection refused]

при restartCount=0 у istio-proxy. Со второй попытки envoy успевал, и
дальше всё работало — то есть симптомом был ровно один рестарт на
старте, который легко списать на случайность.

Настройка сделана на уровне mesh, а не аннотацией на поде: уязвимы все,
кто ходит в БД или брокер сразу при запуске, а это почти каждый бэкенд
контура — django катит migrate первым делом, celery подключается к
rabbitmq, workspaces-api и engine-low к postgres. Они не падали не
потому, что устроены иначе, а потому что успевали.

Цена — каждый под стартует на время готовности envoy дольше, обычно
секунду-две: istio добавляет в sidecar postStart-хук, блокирующий запуск
остальных контейнеров. На Job'ы не влияет, у них инжекция отключена.

Действует в момент инжекции, поэтому на уже запущенные поды не
распространяется — хук появится при следующем пересоздании.
This commit is contained in:
emelinda 2026-08-09 11:27:34 +03:00
parent 7d90c23734
commit f9874afb2b
2 changed files with 47 additions and 0 deletions

View File

@ -0,0 +1,44 @@
# Ожидание готовности sidecar'а перед стартом приложения.
#
# ЗАЧЕМ. Envoy перехватывает исходящий трафик пода через iptables-правила,
# которые ставит init-контейнер istio-init. Правила появляются РАНЬШЕ, чем
# сам envoy начинает слушать, и приложение, дёрнувшее сеть в первые секунды,
# получает не таймаут, а connection refused: пакет уже завёрнут на порт
# envoy, а там ещё никого нет.
#
# Так падал workflows-api: контейнер стартовал и умирал в ту же секунду —
# INFO Starting workflows migrations
# INFO init database connection...
# FATAL [dial tcp 10.43.195.4:5432: connect: connection refused]
# при restartCount=0 у istio-proxy. Kubernetes перезапускал его, со второй
# попытки envoy успевал подняться, и дальше всё работало. То есть симптом —
# ровно один рестарт на старте, легко принимаемый за случайность.
#
# ПОЧЕМУ НА УРОВНЕ MESH, А НЕ АННОТАЦИЕЙ НА ПОДЕ. Уязвимы все, кто ходит в
# БД или брокер сразу при запуске, а это почти каждый бэкенд контура:
# django катит migrate первым делом, celery подключается к rabbitmq,
# workspaces-api и engine-low — к postgres. Они не падали не потому, что
# устроены иначе, а потому что успевали. Чинить это по одному поду —
# значит ждать, пока каждый однажды не повезёт.
#
# ЦЕНА. Каждый под стартует на время готовности envoy дольше (обычно 1-2 с):
# istio добавляет в sidecar postStart-хук, который блокирует запуск
# остальных контейнеров. Для контура это несопоставимо дешевле, чем
# ложные падения на старте.
#
# На Job'ы не влияет: у всех, что есть в контуре, инжекция отключена
# аннотацией sidecar.istio.io/inject: "false" — иначе envoy не давал бы им
# завершиться.
#
# Настройка действует В МОМЕНТ ИНЖЕКЦИИ, поэтому на уже запущенные поды не
# распространяется: хук появится у них при следующем пересоздании.
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: istiod
namespace: istio-system
spec:
values:
meshConfig:
defaultConfig:
holdApplicationUntilProxyStarts: true

View File

@ -3,3 +3,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- ../base - ../base
patches:
# holdApplicationUntilProxyStarts — обоснование в шапке файла.
- path: istio-pilot.yaml