VK Cloud logo
Обновлена 15 апреля 2024 г. в 08:50

Настройка локального DNS-кеша

На каждом узле кластера можно настроить локальный кеширующий DNS-сервер на базе CoreDNS. Такая схема также известна как NodeLocal DNS. Это позволит повысить стабильность и производительность сервиса DNS в кластере, не меняя уже существующих приложений.

Обзор архитектуры DNS в кластере

Пусть некоторый под инициирует DNS-запрос.

  • Без использования кеширующих DNS-серверов произойдет следующее:

    1. DNS-запрос будет отправлен на IP-адрес сервиса kube-dns кластера.
    2. Этот IP-адрес будет транслирован kube-proxy в IP-адрес эндпоинта kube-dns с помощью правил iptables. При этом iptables использует conntrack для отслеживания соединений.
    3. При получении ответа от kubedns будет выполнен обратный процесс.

    Если DNS-запросы преимущественно отправляются по протоколу UDP, то высокая нагрузка на kube-dns (например, если какое-либо приложение активно отправляет DNS-запросы) может привести к проблемам:

    • Состояние гонки (racing condition) для conntrack. В результате существенно (до нескольких раз) замедляется получение ответов на DNS-запросы.
    • Переполнение служебных таблиц для conntrack. Записи для UDP удаляются из них только по таймауту (по умолчанию — 30 секунд). При переполнении таблиц новые DNS-запросы, отправленные по UDP, будут отбрасываться.
  • При использовании кеширующих DNS-серверов произойдет следующее:

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

      Это позволит избежать трансляции адресов (Dynamic NAT, DNAT), использования iptables и conntrack. Описанные выше проблемы будут сняты.

    2. Сам кеширующий DNS-сервер будет обращаться к сервису kube-dns, используя iptables и conntrack, но уже по протоколу TCP.

      В этом случае нагрузка на kube-dns снижается, поскольку к нему обращается напрямую ограниченное количество DNS-серверов, а не все сервисы кластера, требующие DNS для своей работы. Кроме того, при использовании TCP снижается задержка (latency), связанная с потерей UDP-пакетов и таймаутами.

Подробнее в официальной документации Kubernetes.

1. Подготовительные шаги

  1. Создайте кластер Kubernetes самой актуальной версии.

    Параметры кластера выберите на свое усмотрение.

  2. Убедитесь, что вы можете подключиться к кластеру с помощью kubectl.

2. Разверните кеширующий DNS-сервер на каждом узле

DNS-сервер будет развернут в следующей конфигурации:

  • Тип развертывания: DaemonSet, чтобы сервер был доступен на всех узлах кластера.

  • IP-адреса, которые слушает сервер:

    • Локальный IP-адрес 169.254.0.10 на каждом узле. Такой link-local-адрес выбран специально, чтобы не было пересечений с адресами из других подсетей, используемых кластером.
    • IP-адрес сервиса kube-dns. В кластерах Cloud Containers это всегда 10.254.0.10.

    Такая конфигурация используется, потому что kube-proxy в кластерах Cloud Containers работает в режиме iptables.

  • Порт, к которому будет обращаться Prometheus для сбора метрик: 9153.

  • Метка для выбора сервиса: kube-dns: coredns.

  • Домен кластера: cluster.local.

Подробнее о конфигурациях и настройке в официальной документации Kubernetes.

Чтобы развернуть DNS-сервер:

  1. Создайте файл манифеста для NodeLocal DNS:

    Этот файл создан на основе манифеста из официального репозитория Kubernetes с учетом конфигурации, приведенной выше.

  2. Создайте нужные для работы NodeLocal DNS ресурсы Kubernetes на основе манифеста:

    kubectl apply -f nodelocaldns.yaml

    Должна быть выведена следующая информация о созданных ресурсах:

    serviceaccount/node-local-dns createdservice/kube-dns-upstream createdconfigmap/node-local-dns createddaemonset.apps/node-local-dns createdservice/node-local-dns created

3. Проверьте работу кеширующего DNS-сервера

  1. Создайте под, включающий в себя утилиты для работы с DNS:

    kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
  2. Убедитесь, что под успешно создан, выполнив команду:

    kubectl get pod dnsutils

    Должна быть выведена следующая информация:

    NAME       READY   STATUS    RESTARTS    AGEdnsutils   1/1     Running   ...         ...
  3. Подключитесь к bash-сессии внутри этого пода:

    kubectl exec -it dnsutils -- bash
  4. Проверьте, что DNS-запросы успешно выполняются:

    nslookup cloud.vk.com && \nslookup kubernetes.default

    Должна быть выведена похожая информация:

    Server:         10.254.0.10Address:        10.254.0.10#53Non-authoritative answer:Name:   cloud.vk.comAddress: 95.163.254.194Name:   cloud.vk.comAddress: 95.163.254.192Name:   cloud.vk.comAddress: 95.163.254.193Server:         10.254.0.10Address:        10.254.0.10#53Name:   kubernetes.default.svc.cluster.localAddress: 10.254.0.1
  5. Завершите bash-сессию в поде dnsutils:

    exit

Удалите неиспользуемые ресурсы

  1. Если созданные ресурсы Kubernetes вам больше не нужны, удалите их.

    kubectl delete -f https://k8s.io/examples/admin/dns/dnsutils.yamlkubectl  -f nodelocaldns.yaml
  2. Работающий кластер потребляет вычислительные ресурсы. Если он вам больше не нужен: