• Русский
  • Процесс обновления ZTunnel

    ZTunnel работает на уровне 4 (L4) модели OSI: он проксирует TCP byte streams и не имеет представления о прикладном протоколе поверх них. Поэтому установленное TCP-соединение нельзя передать от одного процесса ZTunnel его замене. Поскольку ZTunnel работает как DaemonSet на каждый node, его замена затрагивает как минимум весь mesh traffic на одном node за раз. Понимание такого поведения rolling update помогает планировать обновления для workload-ов, зависящих от долгоживущих соединений.

    Фазы rolling update

    По умолчанию DaemonSet ZTunnel использует стратегию RollingUpdate и обрабатывает по одному node за раз. На каждом node замена проходит через следующие фазы:

    • Startup — новый pod ZTunnel запускается, пока старый продолжает обслуживать traffic.
    • Readiness — новый ZTunnel устанавливает свои listeners в каждом pod на node и сообщает о готовности. Оба экземпляра некоторое время работают параллельно, и поскольку ZTunnel использует SO_REUSEPORT, любой из них может принять новое соединение в этот промежуток.
    • Draining — Kubernetes отправляет SIGTERM старому ZTunnel, который немедленно закрывает свои listeners и начинает draining. С этого момента только новый ZTunnel принимает соединения; ни в один момент node не остается без listening ZTunnel.
    • Connection processing — старый ZTunnel продолжает обслуживать уже установленные соединения.
    • Termination — когда истекает период draining, определенный terminationGracePeriodSeconds, старый ZTunnel принудительно закрывает все оставшиеся открытыми соединения.

    Любое соединение, пережившее период draining, будет сброшено. Два раздела ниже описывают, как либо увеличить этот период, либо полностью избежать принудительного сброса.

    Настройка корректного завершения соединений

    Самый простой способ смягчить проблему — увеличить terminationGracePeriodSeconds настолько, чтобы соединения ваших приложений успевали завершаться естественным образом во время фазы draining. Чтобы выбрать подходящее значение, нужно знать время жизни соединений workload-ов в mesh. Имейте в виду, что DaemonSet обрабатывает по одному node за раз, поэтому слишком большое значение увеличивает общую длительность обновления всего cluster — стремитесь к сбалансированному значению.

    Установите значение в custom resource (CR) ZTunnel:

    apiVersion: sailoperator.io/v1
    kind: ZTunnel
    metadata:
      name: default
    spec:
      version: v1.28.6
      namespace: ztunnel
      values:
        ztunnel:
          terminationGracePeriodSeconds: 300
    1. В этом примере — пять минут. Настройте значение на максимальное время жизни соединения, которое нужно защитить.
    NOTE

    Приложения, которые реализуют retry logic или используют короткие timeouts keepalive, восстанавливаются после перезапуска ZTunnel значительно более корректно, чем приложения, удерживающие очень долгие idle TCP-соединения.

    Безопасное обновление ZTunnel через draining node-ов

    Поскольку TCP-соединение нельзя передать между процессами ZTunnel, единственный надежный способ переместить application на новый ZTunnel — корректно перезапустить само application. Draining node решает эту задачу контролируемым образом: applications завершают работу в соответствии со своими собственными termination grace period-ами, пустой node получает замену ZTunnel без риска для traffic, а applications повторно подключаются через новый ZTunnel после возврата.

    Процедура

    1. Переключите DaemonSet ZTunnel на стратегию обновления OnDelete, чтобы новые pod-ы создавались только после удаления старых:

      apiVersion: sailoperator.io/v1
      kind: ZTunnel
      metadata:
        name: default
      spec:
        version: v1.28.6
        namespace: ztunnel
        values:
          ztunnel:
            updateStrategy:
              type: OnDelete
      1. При OnDelete обновление ресурса ZTunnel само по себе не заменяет ни один работающий pod; каждый node обновляется только после удаления его pod-а ZTunnel.
    2. Установите поле spec.version в CR ZTunnel в целевую версию.

    3. Выполните draining node. Все applications перемещаются на другие node и корректно закрывают свои долгоживущие соединения, руководствуясь собственным terminationGracePeriodSeconds.

    4. Удалите старый pod ZTunnel на drained node и дождитесь запуска нового. Поскольку на node не остается workload-ов, замена не несет риска для traffic.

    5. Снова пометьте node как schedulable. Workload-ы, которые вернутся на node, автоматически используют новый ZTunnel.

    6. Повторите шаги 3–5 для каждого оставшегося node в cluster.

    Дополнительные ресурсы