VK Cloud logo
Обновлена19 марта 2024 г. в 14:14

Настройка локального 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

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

    1serviceaccount/node-local-dns created
    2service/kube-dns-upstream created
    3configmap/node-local-dns created
    4daemonset.apps/node-local-dns created
    5service/node-local-dns created

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

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

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

    kubectl get pod dnsutils

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

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

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

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

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

    1Server:         10.254.0.10
    2Address:        10.254.0.10#53
    3
    4Non-authoritative answer:
    5Name:   cloud.vk.com
    6Address: 95.163.254.194
    7Name:   cloud.vk.com
    8Address: 95.163.254.192
    9Name:   cloud.vk.com
    10Address: 95.163.254.193
    11
    12Server:         10.254.0.10
    13Address:        10.254.0.10#53
    14
    15Name:   kubernetes.default.svc.cluster.local
    16Address: 10.254.0.1
  5. Завершите bash-сессию в поде dnsutils:

    exit

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

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

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