Yandex Cloud
Поиск
Связаться с намиПодключиться
  • Документация
  • Блог
  • Все сервисы
  • Статус работы сервисов
    • Популярные
    • Инфраструктура и сеть
    • Платформа данных
    • Контейнеры
    • Инструменты разработчика
    • Бессерверные вычисления
    • Безопасность
    • Мониторинг и управление ресурсами
    • Машинное обучение
    • Бизнес-инструменты
  • Все решения
    • По отраслям
    • По типу задач
    • Экономика платформы
    • Безопасность
    • Техническая поддержка
    • Каталог партнёров
    • Обучение и сертификация
    • Облако для стартапов
    • Облако для крупного бизнеса
    • Центр технологий для общества
    • Облако для интеграторов
    • Поддержка IT-бизнеса
    • Облако для фрилансеров
    • Обучение и сертификация
    • Блог
    • Документация
    • Контент-программа
    • Мероприятия и вебинары
    • Контакты, чаты и сообщества
    • Идеи
    • Истории успеха
    • Тарифы Yandex Cloud
    • Промоакции и free tier
    • Правила тарификации
  • Документация
  • Блог
Проект Яндекса
© 2025 ООО «Яндекс.Облако»
Практические руководства
    • Все руководства
    • Настройка подключения к Managed Service for PostgreSQL из контейнера Serverless Containers
    • Создать ВМ с Container Optimized Image
    • Создать ВМ с Container Optimized Image и дополнительным томом для Docker-контейнера
    • Создать группу ВМ с Container Optimized Image и несколькими Docker-контейнерами
    • Создать группу ВМ с Container Optimized Image
    • Создать ВМ с Container Optimized Image и несколькими Docker-контейнерами
    • Изменить ВМ с Container Optimized Image
    • Настройка вывода информации из Docker-контейнера в серийный порт
      • Создание нового Kubernetes-проекта
      • Создание кластера Kubernetes без доступа в интернет
      • Запуск рабочих нагрузок с GPU
      • Использование групп узлов c GPU без предустановленных драйверов
      • Установка Time-Slicing GPUs
      • Миграция ресурсов в другую зону доступности
      • Шифрование секретов
        • Интеграция с корпоративной зоной DNS
        • Автоматическое масштабирование DNS по размеру кластера
        • Настройка NodeLocal DNS Cache
        • Проверка DNS Challenge для сертификатов Let's Encrypt®

В этой статье:

  • Необходимые платные ресурсы
  • Перед началом работы
  • Создайте инфраструктуру
  • Подготовьте окружение
  • Установите NodeLocal DNS
  • Измените конфигурацию NodeLocal DNS Cache
  • Выполните DNS-запросы
  • Настройте трафик через NodeLocal DNS
  • Проверьте логи
  • Остановите DaemonSet
  • Удалите созданные ресурсы
  1. Контейнерная инфраструктура
  2. Managed Service for Kubernetes
  3. Работа с DNS
  4. Настройка NodeLocal DNS Cache

Настройка NodeLocal DNS Cache в Yandex Managed Service for Kubernetes

Статья создана
Yandex Cloud
Улучшена
mmerihsesh
Обновлена 21 апреля 2025 г.
  • Необходимые платные ресурсы
  • Перед началом работы
    • Создайте инфраструктуру
    • Подготовьте окружение
  • Установите NodeLocal DNS
  • Измените конфигурацию NodeLocal DNS Cache
  • Выполните DNS-запросы
  • Настройте трафик через NodeLocal DNS
  • Проверьте логи
  • Остановите DaemonSet
  • Удалите созданные ресурсы

Чтобы снизить нагрузку по DNS-запросам в кластере Managed Service for Kubernetes, включите NodeLocal DNS Cache.

Совет

Если кластер Managed Service for Kubernetes содержит более 50 узлов, используйте автоматическое масштабирование DNS.

По умолчанию поды отправляют запросы к сервису kube-dns. В поле nameserver в /etc/resolv.conf установлено значение ClusterIp сервиса kube-dns. Для того, чтобы установить соединение с ClusterIP, используется iptables или IP Virtual Server.

При включении NodeLocal DNS Cache в кластере Managed Service for Kubernetes разворачивается DaemonSet. На каждом узле Managed Service for Kubernetes начинает работу кеширующий агент (под node-local-dns). Поды пользователя теперь отправляют запросы к агенту на своем узле Managed Service for Kubernetes.

Если запрос в кеше агента, он возвращает прямой ответ. В ином случае создается TCP-соединение с kube-dns ClusterIP. По умолчанию кеширующий агент делает cache-miss запросы к kube-dns для DNS-зоны кластера Managed Service for Kubernetes cluster.local.

С помощью такого плана удается избежать правил DNAT, connection tracking и ограничений по количеству соединений. Подробнее о NodeLocal DNS Cache смотрите в документации.

Чтобы настроить кеширование запросов DNS:

  1. Установите NodeLocal DNS.
  2. Измените конфигурацию NodeLocal DNS Cache.
  3. Выполните DNS-запросы.
  4. Настройте трафик через NodeLocal DNS.
  5. Проверьте логи.

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

Необходимые платные ресурсыНеобходимые платные ресурсы

В стоимость поддержки описываемого решения входят:

  • Плата за кластер Managed Service for Kubernetes: использование мастера и исходящий трафик (см. тарифы Managed Service for Kubernetes).
  • Плата за узлы кластера (ВМ): использование вычислительных ресурсов, операционной системы и хранилища (см. тарифы Compute Cloud).
  • Плата за публичный IP-адрес для узлов кластера (см. тарифы Virtual Private Cloud).

Перед началом работыПеред началом работы

Создайте инфраструктуруСоздайте инфраструктуру

Вручную
Terraform
  1. Создайте облачную сеть и подсеть.

  2. Создайте сервисный аккаунт с ролями k8s.clusters.agent и vpc.publicAdmin.

  3. Создайте группы безопасности для кластера Managed Service for Kubernetes и входящих в него групп узлов.

    Важно

    От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.

  4. Создайте кластер Managed Service for Kubernetes и группу узлов с публичным доступом в интернет и с группами безопасности, подготовленными ранее.

  1. Если у вас еще нет Terraform, установите его.

  2. Получите данные для аутентификации. Вы можете добавить их в переменные окружения или указать далее в файле с настройками провайдера.

  3. Настройте и инициализируйте провайдер. Чтобы не создавать конфигурационный файл с настройками провайдера вручную, скачайте его.

  4. Поместите конфигурационный файл в отдельную рабочую директорию и укажите значения параметров. Если данные для аутентификации не были добавлены в переменные окружения, укажите их в конфигурационном файле.

  5. Скачайте в ту же рабочую директорию файл конфигурации кластера Managed Service for Kubernetes k8s-node-local-dns.tf. В файле описаны:

    • Сеть.

    • Подсеть.

    • Кластер Managed Service for Kubernetes.

    • Сервисный аккаунт, необходимый для работы кластера и группы узлов Managed Service for Kubernetes.

    • Группы безопасности, которые содержат необходимые правила для кластера Managed Service for Kubernetes и входящих в него групп узлов.

      Важно

      От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.

  6. Укажите в файле конфигурации:

    • Идентификатор каталога.
    • Версии Kubernetes для кластера и групп узлов Managed Service for Kubernetes.
    • CIDR кластера Managed Service for Kubernetes.
    • Имя сервисного аккаунта кластера Managed Service for Kubernetes.
  7. Проверьте корректность файлов конфигурации Terraform с помощью команды:

    terraform validate
    

    Если в файлах конфигурации есть ошибки, Terraform на них укажет.

  8. Создайте необходимую инфраструктуру:

    1. Выполните команду для просмотра планируемых изменений:

      terraform plan
      

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

    2. Если вас устраивают планируемые изменения, внесите их:

      1. Выполните команду:

        terraform apply
        
      2. Подтвердите изменение ресурсов.

      3. Дождитесь завершения операции.

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

Подготовьте окружениеПодготовьте окружение

  1. Если у вас еще нет интерфейса командной строки Yandex Cloud (CLI), установите и инициализируйте его.

    По умолчанию используется каталог, указанный при создании профиля CLI. Чтобы изменить каталог по умолчанию, используйте команду yc config set folder-id <идентификатор_каталога>. Также для любой команды вы можете указать другой каталог с помощью параметров --folder-name или --folder-id.

  2. Установите kubectl и настройте его на работу с созданным кластером.

Установите NodeLocal DNSУстановите NodeLocal DNS

Yandex Cloud Marketplace
Вручную

Установите NodeLocal DNS с помощью Cloud Marketplace, как описано в инструкции.

  1. Узнайте IP-адрес сервиса kube-dns:

    kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}
    
  2. Создайте файл node-local-dns.yaml. В настройках DaemonSet node-local-dns укажите IP-адрес сервиса kube-dns:

    node-local-dns.yaml
    # Copyright 2018 The Kubernetes Authors.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    # Modified for Yandex Cloud Usage
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: node-local-dns
      namespace: kube-system
      labels:
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: kube-dns-upstream
      namespace: kube-system
      labels:
        k8s-app: kube-dns
        kubernetes.io/name: "KubeDNSUpstream"
    spec:
      ports:
      - name: dns
        port: 53
        protocol: UDP
        targetPort: 53
      - name: dns-tcp
        port: 53
        protocol: TCP
        targetPort: 53
      selector:
        k8s-app: kube-dns
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: node-local-dns
      namespace: kube-system
      labels:
    data:
      Corefile: |
        cluster.local:53 {
          errors
          cache {
            success 9984 30
            denial 9984 5
          }
          reload
          loop
          bind 169.254.20.10 <IP-адрес_сервиса_kube-dns>
          forward . __PILLAR__CLUSTER__DNS__ {
            prefer_udp
          }
          prometheus :9253
          health 169.254.20.10:8080
        }
        in-addr.arpa:53 {
          errors
          cache 30
          reload
          loop
          bind 169.254.20.10 <IP-адрес_сервиса_kube-dns>
          forward . __PILLAR__CLUSTER__DNS__ {
            prefer_udp
          }
          prometheus :9253
          }
        ip6.arpa:53 {
          errors
          cache 30
          reload
          loop
          bind 169.254.20.10 <IP-адрес_сервиса_kube-dns>
          forward . __PILLAR__CLUSTER__DNS__ {
            prefer_udp
          }
          prometheus :9253
          }
        .:53 {
          errors
          cache 30
          reload
          loop
          bind 169.254.20.10 <IP-адрес_сервиса_kube-dns>
          forward . __PILLAR__UPSTREAM__SERVERS__ {
            prefer_udp
          }
          prometheus :9253
          }
    ---
    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: node-local-dns
      namespace: kube-system
      labels:
        k8s-app: node-local-dns
    spec:
      updateStrategy:
        rollingUpdate:
          maxUnavailable: 10%
      selector:
        matchLabels:
          k8s-app: node-local-dns
      template:
        metadata:
          labels:
            k8s-app: node-local-dns
          annotations:
            prometheus.io/port: "9253"
            prometheus.io/scrape: "true"
        spec:
          priorityClassName: system-node-critical
          serviceAccountName: node-local-dns
          hostNetwork: true
          dnsPolicy: Default # Don't use cluster DNS.
          tolerations:
          - key: "CriticalAddonsOnly"
            operator: "Exists"
          - effect: "NoExecute"
            operator: "Exists"
          - effect: "NoSchedule"
            operator: "Exists"
          containers:
          - name: node-cache
            image: registry.k8s.io/dns/k8s-dns-node-cache:1.17.0
            resources:
              requests:
                cpu: 25m
                memory: 5Mi
            args: [ "-localip", "169.254.20.10,<IP-адрес_сервиса_kube-dns>", "-conf", "/etc/Corefile", "-upstreamsvc", "kube-dns-upstream" ]
            securityContext:
              privileged: true
            ports:
            - containerPort: 53
              name: dns
              protocol: UDP
            - containerPort: 53
              name: dns-tcp
              protocol: TCP
            - containerPort: 9253
              name: metrics
              protocol: TCP
            livenessProbe:
              httpGet:
                host: 169.254.20.10
                path: /health
                port: 8080
              initialDelaySeconds: 60
              timeoutSeconds: 5
            volumeMounts:
            - mountPath: /run/xtables.lock
              name: xtables-lock
              readOnly: false
            - name: config-volume
              mountPath: /etc/coredns
            - name: kube-dns-config
              mountPath: /etc/kube-dns
          volumes:
          - name: xtables-lock
            hostPath:
              path: /run/xtables.lock
              type: FileOrCreate
          - name: kube-dns-config
            configMap:
              name: kube-dns
              optional: true
          - name: config-volume
            configMap:
              name: node-local-dns
              items:
                - key: Corefile
                  path: Corefile.base
    ---
    # A headless service is a service with a service IP but instead of load-balancing it will return the IPs of our associated Pods.
    # We use this to expose metrics to Prometheus.
    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        prometheus.io/port: "9253"
        prometheus.io/scrape: "true"
      labels:
        k8s-app: node-local-dns
      name: node-local-dns
      namespace: kube-system
    spec:
      clusterIP: None
      ports:
        - name: metrics
          port: 9253
          targetPort: 9253
      selector:
        k8s-app: node-local-dns
    

    Важно

    Приложение работает корректно только с пространством имен kube-system.

  3. Создайте ресурсы для NodeLocal DNS:

    kubectl apply -f node-local-dns.yaml
    

    Результат:

    serviceaccount/node-local-dns created
    service/kube-dns-upstream created
    configmap/node-local-dns created
    daemonset.apps/node-local-dns created
    service/node-local-dns created
    
  4. Убедитесь, что DaemonSet успешно развернут и запущен:

    kubectl get ds -l k8s-app=node-local-dns -n kube-system
    

    Результат:

    NAME            DESIRED  CURRENT  READY  UP-TO-DATE  AVAILABLE  NODE SELECTOR  AGE
    node-local-dns  3        3        3      3           3          <none>         24m
    

Измените конфигурацию NodeLocal DNS CacheИзмените конфигурацию NodeLocal DNS Cache

Чтобы изменить конфигурацию, отредактируйте соответствующий configmap. Например, чтобы включить логи DNS-запросов для зоны cluster.local:

  1. Выполните команду:

    kubectl -n kube-system edit configmap node-local-dns
    
  2. Добавьте строку log в конфигурацию зоны cluster.local:

    ...
    apiVersion: v1
      data:
        Corefile: |
          cluster.local:53 {
              log
              errors
              cache {
                      success 9984 30
                      denial 9984 5
              }
    ...
    
  3. Сохраните изменения.

    Результат:

    configmap/node-local-dns edited
    

Обновление конфигурации может занять несколько минут.

Выполните DNS-запросыВыполните DNS-запросы

Чтобы выполнить тестовые запросы, используйте под с утилитами диагностики DNS.

  1. Запустите под:

    kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
    

    Результат:

    pod/dnsutils created
    
  2. Убедитесь, что под перешел в состояние Running:

    kubectl get pods dnsutils
    

    Результат:

    NAME      READY  STATUS   RESTARTS  AGE
    dnsutils  1/1    Running  0         26m
    
  3. Подключитесь к поду:

    kubectl exec -i -t dnsutils -- sh
    
  4. Получите IP-адрес локального DNS-кеша:

    nslookup kubernetes.default
    

    Результат:

    Server:         <IP-адрес_kube-dns>
    Address:        <IP-адрес_kube-dns>#53
    
    Name:   kubernetes.default.svc.cluster.local
    Address: 10.96.128.1
    
  5. Выполните запросы:

    dig +short @169.254.20.10 www.com
    dig +short @<IP-адрес_сервиса_kube-dns> example.com
    

    Результат:

    # dig +short @169.254.20.10 www.com
    52.128.23.153
    # dig +short @<IP-адрес_kube-dns> example.com
    93.184.216.34
    

    После запуска node-local-dns правила iptables настраиваются так, что по обоим адресам (<IP-адрес_сервиса_kube-dns>:53 и 169.254.20.10:53) отвечает local DNS.

    К kube-dns можно обращаться по адресу ClusterIp сервиса kube-dns-upstream. Этот адрес может понадобиться, чтобы настроить перенаправление запросов.

Настройте трафик через NodeLocal DNSНастройте трафик через NodeLocal DNS

Все поды
Выбранные поды
  1. Создайте под для настройки сетевого трафика:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: dnschange
      namespace: default
    spec:
      priorityClassName: system-node-critical
      hostNetwork: true
      dnsPolicy: Default
      hostPID: true
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
        - effect: "NoExecute"
          operator: "Exists"
        - effect: "NoSchedule"
          operator: "Exists"
      containers:
      - name: dnschange
        image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3
        tty: true
        stdin: true
        securityContext:
          privileged: true
        command:
          - nsenter
          - --target
          - "1"
          - --mount
          - --uts
          - --ipc
          - --net
          - --pid
          - --
          - sleep
          - "infinity"
        imagePullPolicy: IfNotPresent
      restartPolicy: Always
    EOF
    
  2. Подключитесь к созданному поду dnschange:

    kubectl exec -it dnschange -- sh
    
  3. Откройте файл /etc/default/kubelet в контейнере для редактирования:

    vi /etc/default/kubelet
    
  4. В файле добавьте к значению переменной KUBELET_OPTS параметр --cluster-dns=169.254.20.10 (адрес кеша NodeLocal DNS):

    KUBELET_OPTS="--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig.conf --cert-dir=/var/lib/kubelet/pki/   --cloud-provider=external --config=/home/kubernetes/kubelet-config.yaml --kubeconfig=/etc/kubernetes/  kubelet-kubeconfig.conf --resolv-conf=/run/systemd/resolve/resolv.conf --v=2 --cluster-dns=169.254.20.10"
    
  5. Сохраните файл и выполните команду перезапуска компонента kubelet:

    systemctl daemon-reload && systemctl restart kubelet
    

    Затем выйдите из режима контейнера командой exit.

  6. Удалите под dnschange:

    kubectl delete pod dnschange
    
  7. Чтобы все поды начали работать через NodeLocal DNS, перезапустите их, например, командой:

    kubectl get deployments --all-namespaces | \
      tail +2 | \
      awk '{
        cmd=sprintf("kubectl rollout restart deployment -n %s %s", $1, $2) ;
        system(cmd)
      }'
    
  1. Выполните команду:

    kubectl edit deployment <имя_развертывания_пода>
    
  2. Замените в спецификации пода, в ключе spec.template.spec, настройку dnsPolicy: ClusterFirst на блок:

      dnsPolicy: "None"
      dnsConfig:
        nameservers:
          - 169.254.20.10
        searches:
          - default.svc.cluster.local
          - svc.cluster.local
          - cluster.local
          - ru-central1.internal
          - internal
          - my.dns.search.suffix
        options:
          - name: ndots
            value: "5"
    

Проверьте логиПроверьте логи

Выполните команду:

kubectl logs --namespace=kube-system -l k8s-app=node-local-dns -f

Чтобы остановить вывод лога на экран, нажмите Ctrl + C.

Результат:

...
[INFO] 10.112.128.7:50527 - 41658 "A IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR qr,aa,rd 106 0.000097538s
[INFO] 10.112.128.7:44256 - 26847 "AAAA IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR qr,aa,rd 147 0.057075876s
...

Остановите DaemonSetОстановите DaemonSet

Чтобы выключить DaemonSet NodeLocal DNS Cache, выполните команду:

kubectl delete -f node-local-dns.yaml

Результат:

serviceaccount "node-local-dns" deleted
service "kube-dns-upstream" deleted
configmap "node-local-dns" deleted
daemonset.apps "node-local-dns" deleted
service "node-local-dns" deleted

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

Удалите ресурсы, которые вы больше не будете использовать, чтобы за них не списывалась плата:

  1. Удалите ресурсы в зависимости от способа их создания:

    Вручную
    Terraform

    Удалите кластер Managed Service for Kubernetes.

    1. В терминале перейдите в директорию с планом инфраструктуры.

      Важно

      Убедитесь, что в директории нет Terraform-манифестов с ресурсами, которые вы хотите сохранить. Terraform удаляет все ресурсы, которые были созданы с помощью манифестов в текущей директории.

    2. Удалите ресурсы:

      1. Выполните команду:

        terraform destroy
        
      2. Подтвердите удаление ресурсов и дождитесь завершения операции.

      Все ресурсы, которые были описаны в Terraform-манифестах, будут удалены.

  2. Если для доступа к кластеру Managed Service for Kubernetes или узлам использовались статические публичные IP-адреса, освободите и удалите их.

Была ли статья полезна?

Предыдущая
Автоматическое масштабирование DNS по размеру кластера
Следующая
Проверка DNS Challenge для сертификатов Let's Encrypt®
Проект Яндекса
© 2025 ООО «Яндекс.Облако»