Настройка NodeLocal DNS
Совет
Если кластер Managed Service for Kubernetes содержит более 50 узлов, используйте автоматическое масштабирование DNS.
Важно
Если в кластере Managed Service for Kubernetes используется контроллер сетевых политик Cilium, то настройка имеет свои особенности. Воспользуйтесь следующей инструкцией.
NodeLocal DNS является системным компонентом кластера Managed Service for Kubernetes, выполняющим роль локального DNS-кеша на каждом узле.
NodeLocal DNS разворачивается в кластере как DaemonSetnode-local-dns в пространстве имен kube-system. NodeLocal DNS настраивает iptableskube-dns перенаправлялись в под node-local-dns на этом же узле (локальный кеш):
- Если в кеше есть подходящая запись и ее срок действия не истек, ответ возвращается без обращения к основному DNS-сервису кластера.
- Если в кеше нет записи или ее срок действия истек, запрос пересылается на основной DNS-сервис
kube-dns.
Примечание
DNS-запросы перенаправляются в локальный кеш прозрачно для подов: для этого не нужно изменять файл /etc/resolv.conf на поде и перезапускать его. Отключение NodeLocal DNS тоже не требует этих действий.
Использование NodeLocal DNS в кластере Managed Service for Kubernetes имеет ряд преимуществ
- Уменьшение времени обработки DNS-запросов.
- Снижение объема внутреннего сетевого трафика, что позволяет избежать ограничений по количеству соединений.
- Снижение риска сбоев механизма connection tracking (conntrack) за счет уменьшения числа UDP-запросов к DNS-сервису.
- Повышение устойчивости и масштабируемости кластерной DNS-подсистемы.
В этом руководстве вы установите компонент NodeLocal DNS в кластере Managed Service for Kubernetes и проверите его работу с помощью пакета сетевых утилит dnsutils. Для этого выполните следующие шаги:
Если созданные ресурсы вам больше не нужны, удалите их.
Необходимые платные ресурсы
- Мастер Managed Service for Kubernetes (см. тарифы Managed Service for Kubernetes).
- Узлы кластера Managed Service for Kubernetes: использование вычислительных ресурсов и хранилища (см. тарифы Compute Cloud).
- Публичные IP-адреса для узлов кластера Managed Service for Kubernetes (см. тарифы Virtual Private Cloud).
Перед началом работы
Создайте инфраструктуру
-
Создайте облачную сеть и подсеть.
-
Создайте сервисный аккаунт с ролями
k8s.clusters.agentиvpc.publicAdmin. -
Создайте группы безопасности для кластера Managed Service for Kubernetes и входящих в него групп узлов.
Важно
От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.
-
Создайте кластер Managed Service for Kubernetes и группу узлов с публичным доступом в интернет и с группами безопасности, подготовленными ранее.
-
Если у вас еще нет Terraform, установите его.
-
Получите данные для аутентификации. Вы можете добавить их в переменные окружения или указать далее в файле с настройками провайдера.
-
Настройте и инициализируйте провайдер. Чтобы не создавать конфигурационный файл с настройками провайдера вручную, скачайте его
. -
Поместите конфигурационный файл в отдельную рабочую директорию и укажите значения параметров. Если данные для аутентификации не были добавлены в переменные окружения, укажите их в конфигурационном файле.
-
Скачайте в ту же рабочую директорию файл конфигурации кластера Managed Service for Kubernetes k8s-node-local-dns.tf
. В файле описаны:-
Сеть.
-
Кластер Managed Service for Kubernetes.
-
Сервисный аккаунт, необходимый для работы кластера и группы узлов Managed Service for Kubernetes.
-
Группы безопасности, которые содержат необходимые правила для кластера Managed Service for Kubernetes и входящих в него групп узлов.
Важно
От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.
-
-
Укажите в файле конфигурации:
- Идентификатор каталога.
- Версии Kubernetes для кластера и групп узлов Managed Service for Kubernetes.
- CIDR кластера Managed Service for Kubernetes.
- Имя сервисного аккаунта кластера Managed Service for Kubernetes.
-
Проверьте корректность файлов конфигурации Terraform с помощью команды:
terraform validateЕсли в файлах конфигурации есть ошибки, Terraform на них укажет.
-
Создайте необходимую инфраструктуру:
-
Выполните команду для просмотра планируемых изменений:
terraform planЕсли конфигурации ресурсов описаны верно, в терминале отобразится список изменяемых ресурсов и их параметров. Это проверочный этап: ресурсы не будут изменены.
-
Если вас устраивают планируемые изменения, внесите их:
-
Выполните команду:
terraform apply -
Подтвердите изменение ресурсов.
-
Дождитесь завершения операции.
-
В указанном каталоге будут созданы все требуемые ресурсы. Проверить появление ресурсов и их настройки можно в консоли управления
. -
Подготовьте окружение
-
Если у вас еще нет интерфейса командной строки Yandex Cloud (CLI), установите и инициализируйте его.
По умолчанию используется каталог, указанный при создании профиля CLI. Чтобы изменить каталог по умолчанию, используйте команду
yc config set folder-id <идентификатор_каталога>. Также для любой команды вы можете указать другой каталог с помощью параметров--folder-nameили--folder-id. -
Установите kubectl
и настройте его на работу с созданным кластером.
Установите NodeLocal DNS
Установите NodeLocal DNS с помощью Cloud Marketplace, как описано в инструкции.
-
Узнайте IP-адрес сервиса
kube-dns:kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP} -
Создайте файл
node-local-dns.yaml. В настройках DaemonSetnode-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 --- 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 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 --- # Headless Service has no ClusterIP and returns Pod IPs via DNS. # Used for Prometheus service discovery of node-local-dns metrics. 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. -
Создайте ресурсы для 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 -
Убедитесь, что 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
Создайте тестовое окружение
Для проверки работы локального DNS в кластере Managed Service for Kubernetes будет запущен под nettool, содержащий в себе пакет сетевых утилит dnsutils.
-
Запустите под
nettool:kubectl run nettool --image cr.yandexcloud.kz/yc/demo/network-multitool -- sleep infinity -
Убедитесь, что под перешел в состояние
Running:kubectl get pods -
Выясните, на каком узле кластера Managed Service for Kubernetes развернут под
nettool:kubectl get pod nettool -o wideИмя узла указано в столбце
NODE, например:NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nettool 1/1 Running 0 23h 10.1.0.68 <имя_узла> <none> <none> -
Узнайте IP-адрес пода, на котором развернут NodeLocal DNS:
kubectl get pod -o wide -n kube-system | grep 'node-local.*<имя_узла>'Результат:
node-local-dns-gv68c 1/1 Running 0 26m <IP-адрес_пода> <имя_узла> <none> <none>
Проверьте работу NodeLocal DNS
Для проверки работы локального DNS с пода nettool будут выполнены несколько DNS-запросов. При этом будут изменяться метрики количества DNS-запросов на поде, обслуживающем NodeLocal DNS.
-
Узнайте значение метрик для DNS-запросов до начала проверки:
kubectl exec -ti nettool -- curl http://<IP-адрес_пода>:9253/metrics | grep coredns_dns_requests_totalРезультат:
# HELP coredns_dns_requests_total Counter of DNS requests made per zone, protocol and family. # TYPE coredns_dns_requests_total counter coredns_dns_requests_total{family="1",proto="udp",server="dns://10.96.128.2:53",type="A",zone="."} 18 coredns_dns_requests_total{family="1",proto="udp",server="dns://10.96.128.2:53",type="A",zone="cluster.local."} 18 coredns_dns_requests_total{family="1",proto="udp",server="dns://10.96.128.2:53",type="AAAA",zone="."} 18 coredns_dns_requests_total{family="1",proto="udp",server="dns://10.96.128.2:53",type="AAAA",zone="cluster.local."} 18 coredns_dns_requests_total{family="1",proto="udp",server="dns://169.254.20.10:53",type="other",zone="."} 1 coredns_dns_requests_total{family="1",proto="udp",server="dns://169.254.20.10:53",type="other",zone="cluster.local."} 1 coredns_dns_requests_total{family="1",proto="udp",server="dns://169.254.20.10:53",type="other",zone="in-addr.arpa."} 1 coredns_dns_requests_total{family="1",proto="udp",server="dns://169.254.20.10:53",type="other",zone="ip6.arpa."} 1Из результата следует, что NodeLocal DNS принимает DNS-запросы на двух IP-адресах:
-
Адрес, совпадающий с Cluster IP сервиса
kube-dns(в данном случае10.96.128.2:53, значение может отличаться).Этот адрес является основным. NodeLocal DNS настраивает iptables так, что запросы к сервису
kube-dnsперенаправляются на подnode-local-dnsна этом же узле. -
Локальный адрес NodeLocal DNS (
169.254.20.10:53).Этот адрес является резервным. Его можно использовать для прямого обращения к поду
node-local-dns.
-
-
Выполните DNS-запросы:
kubectl exec -ti nettool -- nslookup kubernetes && \ kubectl exec -ti nettool -- nslookup kubernetes.default && \ kubectl exec -ti nettool -- nslookup ya.ruРезультат (IP-адреса могут отличаться):
Server: 10.96.128.2 Address: 10.96.128.2#53 Name: kubernetes.default.svc.cluster.local Address: 10.96.128.1 Server: 10.96.128.2 Address: 10.96.128.2#53 Name: kubernetes.default.svc.cluster.local Address: 10.96.128.1 Server: 10.96.128.2 Address: 10.96.128.2#53 Non-authoritative answer: Name: ya.ru Address: 5.255.255.242 Name: ya.ru Address: 77.88.44.242 Name: ya.ru Address: 77.88.55.242 Name: ya.ru Address: 2a02:6b8::2:242 -
Повторно получите значения метрик для DNS-запросов:
kubectl exec -ti nettool -- curl http://<IP-адрес_пода>:9253/metrics | grep coredns_dns_requests_totalРезультат:
# HELP coredns_dns_requests_total Counter of DNS requests made per zone, protocol and family. # TYPE coredns_dns_requests_total counter coredns_dns_requests_total{family="1",proto="udp",server="dns://10.96.128.2:53",type="A",zone="."} 27 coredns_dns_requests_total{family="1",proto="udp",server="dns://10.96.128.2:53",type="A",zone="cluster.local."} 30 coredns_dns_requests_total{family="1",proto="udp",server="dns://10.96.128.2:53",type="AAAA",zone="."} 25 coredns_dns_requests_total{family="1",proto="udp",server="dns://10.96.128.2:53",type="AAAA",zone="cluster.local."} 26 coredns_dns_requests_total{family="1",proto="udp",server="dns://169.254.20.10:53",type="other",zone="."} 1 coredns_dns_requests_total{family="1",proto="udp",server="dns://169.254.20.10:53",type="other",zone="cluster.local."} 1 coredns_dns_requests_total{family="1",proto="udp",server="dns://169.254.20.10:53",type="other",zone="in-addr.arpa."} 1 coredns_dns_requests_total{family="1",proto="udp",server="dns://169.254.20.10:53",type="other",zone="ip6.arpa."} 1Из результата следует, что значения метрик увеличились для адреса сервиса
kube-dnsи не изменились для локального адреса NodeLocal DNS. Это означает, что поды продолжают отправлять DNS-запросы по адресу сервисаkube-dns, но теперь эти запросы обрабатываются сервисом NodeLocal DNS.
Удалите NodeLocal DNS
Удалите приложение NodeLocal DNS, как описано в инструкции.
Выполните команду:
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
Удалите созданные ресурсы
Удалите ресурсы, которые вы больше не будете использовать, чтобы за них не списывалась плата:
-
Удалите ресурсы в зависимости от способа их создания:
ВручнуюTerraform-
В терминале перейдите в директорию с планом инфраструктуры.
Важно
Убедитесь, что в директории нет Terraform-манифестов с ресурсами, которые вы хотите сохранить. Terraform удаляет все ресурсы, которые были созданы с помощью манифестов в текущей директории.
-
Удалите ресурсы:
-
Выполните команду:
terraform destroy -
Подтвердите удаление ресурсов и дождитесь завершения операции.
Все ресурсы, которые были описаны в Terraform-манифестах, будут удалены.
-
-
-
Если для доступа к кластеру Managed Service for Kubernetes или узлам использовались статические публичные IP-адреса, освободите и удалите их.