Я думал, что у меня есть возможность наблюдать — моя краткая история DNS

Я думал, что у меня есть возможность наблюдать — моя краткая история DNS

15 ноября 2022 г.

<цитата>

Я думал, что у меня есть возможность наблюдать, но этого было недостаточно.

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


Привет, гениальный человек! Как оказалось, в критической среде возникла проблема.

Как можно предотвратить подобные проблемы до того, как они повлияют на клиентов? Я расскажу вам чуть позже в этой статье.

Если вы читаете это, скорее всего:

  1. У вас есть или были похожие проблемы с DNS или симптомы DNS
  2. Вы трудолюбивы и хотели бы научиться не наступать на грабли

:::предупреждение Если у вас нет времени читать, и вы хотите сразу увидеть решение, например, как вы просматриваете все ответы на stackoverflow в поисках отмеченного решения, затем прочитайте это подробное руководство по устранению неполадок AWS DNS. .

:::

:::предупреждение Еще один спойлер: официальная документация Kubernetes относится к использованию NodeLocal DNSCache. Это неверный путь, и он не устранит основную причину.

:::

Эта статья поможет вам, если у вас есть один из следующих вопросов или проблем:

  1. Поиск Kubernetes в DNS выполняется медленно
  2. Как изменить значение DNS по умолчанию ndots в Kubernetes
  3. Внешний поиск DNS не работает в пакетах
  4. Рекомендации по DNS для Kubernetes kube (или CoreDNS)
  5. Kubernetes добавляет неправильный суффикс URL cluster.local в конце запроса
  6. CoreDns получил тысячи ответов RCode
  7. На первый взгляд у CoreDns была высокая нагрузка без всякой причины.
  8. Самое главное, приложения не могли разрешать DNS-запросы и не могли извлекать важные данные.

:::подсказка RCodes

Когда CoreDNS обнаруживает ошибку, он возвращает rcode — стандартный код ошибки DNS.

Такие ошибки, как NXDomain и FormErr, могут указывать на проблему с запросами, которые получает CoreDNS, а ошибка ServFail может указывать на проблему с функцией самого сервера CoreDNS.

:::

Итак, ниже я расскажу вам о 3 темах:

* Решение проблем с DNS * Рекомендации по DNS для Kubernetes (но на самом деле больше о DNS с Linux) * Как предотвратить подобные проблемы до того, как они повлияют на клиентов


Подробно о конкретной проблеме с DNS

Сообщается, что некоторые приложения не могут подключиться к службе. Это может быть внешняя служба или внутренняя служба. Пересмотрели эти сервисы, все заработало нормально. Итак, очень странное поведение и не постоянная проблема. Изучив все ошибки в централизованной системе журналов в это конкретное время, мы обнаружили корреляцию со службой DNS (CoreDNS). В то время мы также обнаружили проблемы с этой службой.

Показатели CoreDns во время этого инцидента могут выглядеть следующим образом: количество запросов.

Здесь вы можете увидеть количество ошибок, которые вернули ответ на DNS-запросы

Здесь вы можете увидеть загрузку процессора.

Конфигурация DNS внутри модулей выглядит так, как показано ниже.

/etc/resolv.conf:

nameserver 10.100.0.10
search default.svc.cluster.local svc.cluster.local cluster.local ec2.internal
options ndots:5

:::подсказка NDOTS: нет

Устанавливает пороговое значение количества точек, которое должно появиться в имени, указанном в res_query(), прежде чем будет сделан первоначальный абсолютный запрос. Значение по умолчанию для n равно 1, а это означает, что если в имени есть точки, имя сначала используется как абсолютное имя, прежде чем к нему будут добавлены какие-либо элементы списка поиска.

:::

Журналы ошибок выглядят следующим образом:

[INFO] 192.168.3.71:33238 - 36534 "A IN amazon.com.default.svc.cluster.local. udp 54 false 512" NXDOMAIN qr,aa,rd 147 0.000473434s
[INFO] 192.168.3.71:57098 - 43241 "A IN amazon.com.svc.cluster.local. udp 46 false 512" NXDOMAIN qr,aa,rd 139 0.000066171s
[INFO] 192.168.3.71:51937 - 15588 "A IN amazon.com.cluster.local. udp 42 false 512" NXDOMAIN qr,aa,rd 135 0.000137489s
[INFO] 192.168.3.71:52618 - 14916 "A IN amazon.com.ec2.internal. udp 41 false 512" NXDOMAIN qr,rd,ra 41 0.001248388s
[INFO] 192.168.3.71:51298 - 65181 "A IN amazon.com. udp 28 false 512" NOERROR qr,rd,ra 106 0.001711104s

Как видите, уровень сообщения информационный, поэтому раньше мы этих сообщений не видели. Вы видите, что DNS-имена абсолютно неверны.

:::информация NXDOMAIN означает, что запись домена не найдена, а NOERROR означает, что запись домена найдена.

:::

:::информация CoreDNS интегрируется с Kubernetes с помощью плагина Kubernetes. , или etcd с плагином etcd.

:::

Это логика этих запросов.

Почему CoreDNS ищет внешние домены в локальных доменах и почему есть 4 новых доменных суффикса, например .default.svc.cluster.local. код> ?

  1. Приложение выполняет DNS-запрос, например secretsmanager.ca-central-1.amazonaws.com
  2. CoreDNS проверяет, где следует выполнять поиск в этом домене

k8s основан на Linux, поэтому он ищет этот домен в локальной внутренней системе или внешней системе.

Таким образом, если доменное имя имеет формат FQDN, то CoreDNS должен сделать абсолютный запрос (внешняя система), иначе поиск в локальной системе .

НО у нас есть опция ndots.

  1. Если доменное имя не является полным доменным именем, выполните поиск во внутренней системе

    my-internal-service, CoreDNS возвращает IP-адрес внутренней службы в том же пространстве имен. 2. Проверьте, имеет ли доменное имя формат FQDN, и проверьте параметр ndots и точку в конце имени домена. 3. Если в имени домена меньше точек, чем в параметре ndots, сначала выполните поиск этого домена в локальных доменах, определенных в директиве search.

    В нашем примере secretsmanager.ca-central-1.amazonaws.com имеет только 3 точки, тогда как параметр ndots имеет значение 5.

    Итак, первый поиск:

    баш secretsmanager.ca-central-1.amazonaws.com.default.svc.cluster.local secretsmanager.ca-central-1.amazonaws.com.svc.cluster.local secretsmanager.ca-central-1.amazonaws.com.cluster.local secretsmanager.ca-central-1.amazonaws.com.ec2.internal

    И только после этих запросов сделайте абсолютно запрос: secretsmanager.ca-central-1.amazonaws.com 4. Если имя домена содержит более 4 точек или имеет точку в конце, задайте абсолютное значение. 3. Если у доменного имени есть полное доменное имя, сделайте запрос абсолютно. Если доменное имя имеет абсолютное доменное имя (точка в конце) FQDN, сделайте абсолютный запрос

:::информация FQDN: полное доменное имя

Полное доменное имя состоит из двух частей: имени хоста и имени домена. Например, полное доменное имя гипотетического почтового сервера может быть mymail.somecollege.edu. Имя хоста — mymail, и хост расположен в домене somecollege.edu.

:::

:::подсказка Точка в имени домена означает, что этот домен является абсолютным полным доменным именем.

Например: "amazon.com". означает, сделать только абсолютно запрос.

:::

Хорошо, мы нашли первопричину. Есть 2 вопроса:

  1. Почему в приложении возникали ошибки подключения?
  2. Как это исправить?

Почему в приложении возникали ошибки подключения?

Как мы обнаружили, CoreDNS выполнял 4 дополнительных запроса на каждый запрос из приложения. В пики высокой нагрузки CoreDNS ему не хватает ресурсов. Мы увеличили количество подов, на какое-то время забыли об этой проблеме.

После того, как мы снова увидели эту проблему, мы добавили NodeLocal, как указано в официальной документации, но это не помогло. устранить первопричину. Через какое-то время количество запросов вырастет, и мы снова увидим эту проблему. Вот почему мы должны устранить основную причину.

Как это исправить?

Мы должны уменьшить значение параметра ndots в resolv.conf.

Что ж, слава богу, k8s позволяет изменить эту опцию в манифесте модуля (потому что, если вы используете управление Kubernetes, у вас не всегда есть разрешение на изменение таких параметров).

Итак, /etc/resolv.conf в нашем модуле будет выглядеть так:

После устранения основной причины мы можем улучшить настройки DNS с помощью приведенных ниже рекомендаций.

DNS для k8s, советы и рекомендации PRO

Если вы используете управляемую службу k8s, для масштабирования DNS используйте HPA (или что-то вроде KEDA, Kubernetes Event-driven Autoscaling) вместо того, чтобы вручную изменять настройки, потому что ваш провайдер в любой момент может перезаписать ваши изменения.

Пример HPA:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: coredns
  namespace: kube-system
spec:
  maxReplicas: 20
  minReplicas: 2
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: coredns
  metrics:
  - type: Resource
    resource:
    name: cpu
    target:
      type: Utilization
      averageUtilization: 80
  - type: Resource
    resource:
    name: memory
    target:
      type: AverageValue
      averageUtilization: 80

Указанного выше параметра должно быть достаточно, чтобы не использовать NodeLocal.

Но если вам нужно изменить параметры в службе DNS, и вы не можете сделать эти изменения (в случае с управлением k8s), вы можете установить NodeLocal в ваш кластер k8s.

Эта опция позволит добавить еще одну точку кэширования DNS (это снимет нагрузку с основного DNS-сервиса) и настроить параметры по своему усмотрению.

Вы не должны изменять параметр сервера имен в своих модулях, если у вас есть dnsPolicy ClusterFirst.

Если один из модулей CoreDNS в вашей системе k8s вернет ошибку, все будет неработоспособно, просто повторите запрос DNS. Этот параметр мы можем настроить на системном уровне.

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: web-server
spec:
  containers:
    - name: test
      image: nginx
  dnsConfig:
    options:
      - name: ndots
        value: "2"
      - name: attempts
        value: "3"

Если у вас недостаточно времени, чтобы сделать патч для вашей среды, добавьте «точку» в конце вашего DNS-запроса. Тогда ваше доменное имя будет полностью полным доменным именем, например, secretsmanager.ca-central-1.amazonaws.com.

Чтобы распространить эти изменения на все узлы, вы должны изменить настройки kubelet, используя resolvConf option для настроек kubelet

~~В чем твоя проблема?~~ Почему я сначала не знал о проблеме?

Короткий ответ: я не выполнял следующие шаги:

  1. Недостаточно внимания уделялось настройке уведомлений о критических ошибках.
  2. Аудит всех критически важных компонентов не проводился, чтобы потом проверить настройки мониторинга
  3. Не существовало «контрольного списка перед отправкой», такого как этот контрольный список

Подробнее об этой методике.

Как вы знаете, DevOps — это не человек, это набор лучших практик и подходов, предполагающих реализацию непрерывной интеграции и развертывания...

У нас есть журналы, метрики и трассировки, которые часто называют тремя столпами наблюдаемости (как описано в Наблюдаемость распределенных систем).

Все журналы, извлеченные из текущей среды, отправляются в централизованную систему журналов, такую ​​​​как ELK, New Relic, DataDog. Таким образом, в одном месте вы можете найти и проанализировать практически любую проблему, связанную с вашим приложением или системной службой.

Трассировки приложений отправляются в том же месте, что и журналы, и помогают найти последовательность событий, пошагово отфильтровать все приложения, связанные с конкретным событием/запросом.

Все метрики из текущего окружения отправляются в централизованную систему мониторинга и соотносятся с логами и трассировками.

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


Мое лицо, когда я впервые увидел критическую проблему в критической среде, тогда как я думал, что все в порядке.

Фото из фильма "Они живут" (1988).

Как предотвратить подобные проблемы до того, как они повлияют на клиентов?

Но журналов, метрик было недостаточно, почему?

У нас были логи, метрики, трейсы, у нас были ошибки в наших логах, но кто непрерывно смотрит все логи (10к записей в логах каждый день — это нормально)? Мы копаемся в журналах, метриках и т. д., когда сталкиваемся с проблемой. Но это очень дорого, когда проблема находит ваших клиентов. Вот почему мы должны предсказывать проблемы по некоторым симптомам и предотвращать проблемы до того, как они повлияют на что-то критическое.

Другими словами. Потому что недостаточно внимания уделялось настройке уведомлений о критических ошибках. DNS в инфраструктуре kubernetes — одна из критически важных систем.

Итак, как я упоминал выше, мы должны составить контрольный список env для критических компонентов и пройти его шаг за шагом. Некоторые пункты этого контрольного списка должны быть такими: мы должны иметь журналы, метрики и уведомления о критических проблемах и, конечно же, проверять их в реальной инфраструктуре.

В результате должны быть выполнены следующие шаги:

  • Исправить проблему
  • Выполнить вскрытие (пример: вскрытие базы данных сбой 31 января)
  • Составьте контрольный список для критически важных компонентов, особенно для важных миграций, обновлений и развертываний.
  • Используйте этот список по крайней мере один раз в существующей инфраструктуре или используйте его перед такими событиями, как миграция, обновление

Список полезных ссылок


Итак, почему я написал эту историю сегодня?

Все совершают ошибки (например: инцидент с базой данных GitLab.com< /a>), тот, кто ничего не делает и не учится на своих ошибках, не достигает успеха!

Удачи! Надеюсь, это поможет.

Пожалуйста, не стесняйтесь оставлять комментарии и связываться со мной https://kazakov.xyz.


Оригинал