Проблемы с DNS в Kubernetes. Публичный постмортем

Original author: Amet Umerov
  • Translation
Прим. перев.: это перевод публичного постмортема из инженерного блога компании Preply. В нем описывается проблема с conntrack в Kubernetes-кластере, которая привела к частичному простою некоторых сервисов продакшна.

Данная статья может быть полезной тем, кто хочет узнать немного больше о постмортемах или предотвратить некоторые потенциальные проблемы с DNS в будущем.

image

Это не DNS
Не может быть что это DNS
Это был DNS


Немного о постмортемах и процессах в Preply


В постмортеме описывается сбой в работе или какое-либо событие в продашкне. Постмортем включает в себя хронологию событий, описание воздействия на пользователя, первопричину, действия и извлеченные уроки.

Seeking SRE

На еженедельных совещаниях с пиццей, в кругу технической команды, мы делимся различной информаций. Одной из важнейшних частей таких совещаний являются постмортемы, которые чаще всего сопровождаются презентацией со слайдами и более глубоким анализом произошедшего инцидента. Несмотря на то, что мы не «хлопаем» после постмортемов, мы стараемся развивать культуру «без упреков» (blameless cluture). Мы верим в то, что написание и представление постмортемов может помочь нам (и не только) в предотвращении подобных инцидентов в будущем, именно поэтому мы и делимся ими.

Лица, вовлеченные в инцидент, должны чувствовать, что они могут подробно рассказать о нем, не опасаясь наказания или возмездия. Никакого порицания! Написание постмортема — это не наказание, а возможность обучения для всей компании.

Keep CALMS & DevOps: S is for Sharing

Проблемы с DNS в Kubernetes. Постмортем


Дата: 28.02.2020

Авторы: Амет У., Андрей С., Игорь К., Алексей П.

Статус: Законченный

Кратко: Частичная недоступность DNS (26 мин) для некоторых сервисов в Kubernetes-кластере

Влияние: 15000 событий потеряно для сервисов A, B и C

Первопричина: Kube-proxy не смог корректно удалить старую запись из таблицы conntrack, поэтому некоторые сервисы все еще пытались соединиться к несуществующим подам
E0228 20:13:53.795782       1 proxier.go:610] Failed to delete kube-system/kube-dns:dns endpoint connections, error: error deleting conntrack entries for UDP peer {100.64.0.10, 100.110.33.231}, error: conntrack command returned: ...

Триггер: Из-за низкой нагрузки внутри Kubernetes-кластера, CoreDNS-autoscaler уменьшил количество подов в деплойменте с трех до двух

Решение: Очередной деплой приложения инициировал создание новых нод, CoreDNS-autoscaler добавил больше подов для обслуживания кластера, что спровоцировало перезапись таблицы conntrack

Обнаружение: Prometheus мониторинг обнаружил большое количество 5xx ошибок для сервисов A, B и C и инициировал звонок дежурным инженерам


5xx ошибки в Kibana

Действия


Действие Тип Ответственный Задача
Отключить автоскейлер для CoreDNS предотвр. Амет У. DEVOPS-695
Установить кеширующий DNS-сервер уменьш. Макс В. DEVOPS-665
Настроить мониторинг conntrack предотвр. Амет У. DEVOPS-674

Извлеченные уроки


Что пошло хорошо:

  • Мониторинг сработал четко. Реакция была быстрой и организованной
  • Мы не уперлись ни в какие лимиты на нодах


Что было не так:

  • Все еще неизвестная реальная первопричина, похоже на специфический баг в conntrack
  • Все действия исправляют только последствия, не первопричину (баг)
  • Мы знали, что рано или поздно у нас могут быть проблемы с DNS, но не приоритизировали задачи

Где нам повезло:

  • Очередной деплой затриггерил CoreDNS-autoscaler, который перезаписал таблицу conntrack
  • Данный баг затронул только часть сервисов

Хронология (EET)


Время Действие
22:13 CoreDNS-autoscaler уменьшил число подов с трех до двух
22:18 Дежурные инженеры стали получать звонки от системы мониторинга
22:21 Дежурные инженеры начали выяснять причину ошибок
22:39 Дежурные инженеры начали откатывать один из последних сервисов на предыдущую версию
22:40 5xx ошибки перестали появляться, ситуация стабилизировалась

  • Время до обнаружения: 4 мин
  • Время до совершения действий: 21 мин
  • Время до исправления: 1 мин

Дополнительная информация



Для минимизации использования процессора, ядро Linux использует такую штуку как conntrack. Если кратко, то это утилита, которая содержит список NAT-записей, которые хранятся в специальной таблице. Когда следующий пакет приходит из того же пода в тот же под что и раньше, конечный IP-адрес не будет рассчитан заново, а будет взят из таблицы conntrack.

Как работает conntrack

Итоги


Это был пример одного из наших постмортемов с некоторыми полезными ссылками. Конкретно в этой статье мы делимся информацией, которая может быть полезна другим компаниям. Вот почему мы не боимся совершать ошибок и вот почему мы сделать один из наших постмортемов публичным. Вот еще несколько интересных публичных постмортемов:

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 10

    +2

    Судя по описанию проблему, вы спокойно можете воспроизвести ее:


    • Запустить в кластере под с dnsperf: https://github.com/guessi/docker-dnsperf (или любым другим подобным ПО)
    • Скейлить coredns/kube-dns в кластере вверх и вниз
    • Смотреть логи kube-proxy
    • Смотреть состояние conntrack: conntrack -L на машинах фильтруя по адресам подов dns и dnsperf

    Данный способ будет корректным, так как в conntrack будет минимальное количество записей связанных с данным подов dnsperf'а, так как src и sport будет один и тот же, при этом в качестве dst будут поды dns.


    Ну и на тестовом сетапе вы сможете разобраться более глубоко в проблеме и решить первопричину.


    Тут в диагностике не сильно поможет какой-нибудь while true; do host test.com <DNS_POD_IP>, так как в этом случае с большой вероятностью наплодится большое количество записей в conntrack и отдебажить будет куда сложнее.

      0
      Интересует, что дальше было сделано с этим протоколом пост-мортема
        0
        Все посмтортемы у нас хранятся в Confluence, ну и как написано в статье, обсуждаются на еженедельных митингах.
          0
          Ну т.е. пользы почти никакой нет. Выглядит, что где-то увидели, что надо писать протоколы, и написали.
            0
            Конкретно для нас польза такая.
            1. Инцидент зафиксирован и донесен до всех членов команды, в будущем такого повториться не должно
            2. Если даже вдруг он в будущем повторится, у нас зафиксированно все в документации
            3. Плюс это расширение экспертизы (опыт) для других членов команды, которые работают со смежной технологией например
              +1
              Польза огромная обычно. Просто в данном конкретном случае:
              1) проблема или в ядре или в k8s
              2) проблема появилась впервые
              3) Preply скорее всего не обладает необходимой экспертизой и достаточными ресурсами чтобы решать проблему на столь низком уровне так сразу
              Поэтому задокументировали и оставили как есть.
              Если этот баг будет появляться вновь — тогда у них будет уже «след» и из инцидентов они создадут «проблему» (по ITIL) и будут или просить кого-то починить или сами попытаются разобраться
              Обычно же проблемы более тривиальны и постмортемы позволяют или предотвратить появление проблемы или как минимум создать runbook
              Обычно инциденты связаны с
          0
          А какую версию ядра используете?
            0
            $ uname -v
            #1 SMP Debian 4.9.189-3+deb9u2 (2019-11-11)
            $ conntrack --version
            conntrack v1.4.4 (conntrack-tools)
            0
            А k8s какой версии? Мы на похожую проблему напарывались в 1.15, когда ipvs не удалял записи о старых маршрутах:

            github.com/kubernetes/kubernetes/issues/78421
            github.com/kubernetes/kubernetes/issues/89947
              0
              1.13, не IPVS

            Only users with full accounts can post comments. Log in, please.