====== Kubernetes: DNS ====== ====== Общие вопросы ====== Все примеры и допущения будут приводиться с учётом того, что кластер Kubernetes поставлен с использованием kubespray.\\ Для проверки работы DNS будем использовать образ infoblox/dnstools: kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools ===== Домен для кластера ===== Домен кластера определяется при установке кластера. Посмотрите в kubespray inventory вашего кластера. Нас интересует файл group_vars/k8s-cluster/k8s-cluster.yml # DNS configuration. # Kubernetes cluster name, also will be used as DNS domain cluster_name: cluster.local При установке кластера мы не меняли значения этого поля. ===== Записи A и AAAA ===== ==== Для services ==== В системе можно выделить два типа сервисов: обычные и headless. Обычным сервисам присваивается ip адрес, headless нет. При обращении к обычному сервису, к его IP адресу, происходит NAT преобразование «подставляющее» IP адрес пода (подов). headless service по своей сути – это запись типа А в DNS, указывающая непосредственно на IP пода. Типичное FQDN имя сервиса: service-name.namespace-name.svc.cluster.local ==== Для pods ==== FQDN имя для простого пода: pod-ip-address.namespace-name.pod.cluster.local Например: 10-233-79-186.default.pod.cluster.local ====== DNS сервер кластера ====== ===== Схема kubespray ===== {{https://fatalex.cifro.net/lib/plugins/ckgedit/fckeditor/userfiles/image/devops/k8s/kubernetes-dns.png?nolink&809x556}} **Kubespray ставит следующие компоненты системы:** - coredns – основной DNS сервер, отвечающий за разрешение имен внутри кластера Kubernetes. - nodelocaldns – кеширующий DNS сервер. По одному на каждую ноду кластера. - dns-autoscaler – приложение, автоматически увеличивающее или уменьшающее количество подов coredns в кластере ([[https://github.com/kubernetes-sigs/cluster-proportional-vertical-autoscaler|https://github.com/kubernetes-sigs/cluster-proportional-vertical-autoscaler]]). Основным DNS сервером является coredns ([[https://coredns.io/|https://coredns.io]]). На него ложится все преобразования внутри кластера DNS. Для доступа и распределения запросов между подами coredns, создан соответствующий сервис. На самом деле сервис один, хотя на схеме показаны три штуки. Но мы знаем, что сервис – это набор правил NAT преобразований на каждой ноде кластера. Nodelocaldns выполнен в виде daemonSet. Это значит, что по одному экземпляру пода будет запущено на каждом кластере сети. Задача nodelocaldns – кеширование запросов от приложений, расположенных на ноде. Файлы манифестов всех системных компонент кластера, установленного при помощи kubespray, можно найти в директории /etc/kubernetes. В том числе configMaps системы DNS: coredns-config.yml, nodelocaldns-config.yml. Рассмотрим конфигурацию coredns. .:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa } prometheus :9153 forward . /etc/resolv.conf { prefer_udp } cache 30 loop reload loadbalance } Как видно из файла, сервер отвечает на все запросы на 53 порту. Модуль Kubernetes отвечает за домен cluster.local и обратные преобразования. Все остальные запросы будут пересылаться на DNS сервера, описанные в файле /etc/resolv.conf того компьютера, на котором запущен этот под. Модуль кubernetes реализует концепцию Kubernetes DNS-Based Service Discovery ([[https://github.com/kubernetes/dns/blob/master/docs/specification.md|https://github.com/kubernetes/dns/blob/master/docs/specification.md]]). Кеширующий DNS сервер тоже реализован с использованием coredns, но с другой конфигурацией. cluster.local:53 { errors cache { success 9984 30 denial 9984 5 } reload loop bind 169.254.25.10 forward . 10.233.0.3 { force_tcp } prometheus :9253 health 169.254.25.10:9254 } in-addr.arpa:53 { errors cache 30 reload loop bind 169.254.25.10 forward . 10.233.0.3 { force_tcp } prometheus :9253 } ip6.arpa:53 { errors cache 30 reload loop bind 169.254.25.10 forward . 10.233.0.3 { force_tcp } prometheus :9253 } .:53 { errors cache 30 reload loop bind 169.254.25.10 forward . /etc/resolv.conf prometheus :9253 } Обратите внимание на схеме приложения обращаются напрямую на 53-й порт DNS сервера. Service для доступа к подам не определен. Основная задача кеширущего сервера – получать запросы от приложений, расположенных непосредственно на ноде. Если определить сервис, то мы не сможем ограничить запросы только на данный сервер. Поэтому разработчики пошли на хитрость: bind 169.254.25.10 Сеть 169.254.0.0/16 – это так называемая Link-Local (см. RFC 3927). Подсети link-local не маршрутизируются: маршрутизаторы не должны отправлять пакеты с адресами link-local в другие сети. Система поднимает IP 169.254.25.10 на каждой ноде. С другой стороны, DaemonSet запускает на каждой ноде под nodelocaldns, в котором DNS сервер будет открывать 53-й порт на этом IP. В результате, на каждой ноде мы получаем кеширующий DNS сервер, находящийся на одном и том же IP. Теперь достаточно сконфигурировать resolver в каждом поде на использование DNS на IP 169.254.25.10. IP адрес задаётся в конфигурационном файле kubespray inventory: group_vars/k8s-cluster/k8s-cluster.yml # Enable nodelocal dns cache enable_nodelocaldns: true nodelocaldns_ip: 169.254.25.10 nodelocaldns_health_port: 9254 Запросы к внутренним зонам кластера (cluster.local, in-addr.arpa и ip6.arpa), будут пересылаться на service coredns. Но поскольку мы настраиваем пересылку в DNS сервере, мы должны использовать IP адрес сервиса. В kubespray по умолчанию это 10.233.0.3. Еще один интересный момент: force_tcp Кеширующие DNS сервера ходят к coredns по протоколу TCP. Разработчики говорят, что в связи с большим количеством NAT преобразований внутри сети Kubernetes, использование TCP ускоряет доставку запросов. Запросы на все остальные домены пересылаются на DNS сервера, определённые в стандартных файлах /etc/resolv.conf, находящихся на нодах, где запущены поды nodelocaldns. Важно отметить, что данные из этих файлов читаются только при старте пода. Поэтому внесение изменений в resolv.conf не повлияет на работу кеширующего DNS сервера. Поэтому, после изменения этого файла, перезапустите nodelocaldns на этой ноде. ====== Настройки pod ====== ===== Hostname и subdomain ===== По умолчанию под имеет только краткое имя. Если по каким-то причинам ему надо задать FQDN имя, его можно определить непосредственно в yaml файле. apiVersion: v1 kind: Pod metadata: name: dnstools namespace: default spec: hostname: dns subdomain: tools containers: - name: dnstools image: infoblox/dnstools:latest command: - sleep - "36000" imagePullPolicy: IfNotPresent restartPolicy: Always В итоге у контейнера будет установлено имя: dns.tools.default.svc.cluster.local Преобразование имени в ip адрес будет добавлено в файл /etc/hosts контейнера. dnstools# cat /etc/hosts # Kubernetes-managed hosts file. 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet fe00::0 ip6-mcastprefix fe00::1 ip6-allnodes fe00::2 ip6-allrouters 10.233.79.189 dns.tools.default.svc.cluster.local dns В зону DNS это преобразование добавляться не будет! ===== Файл hosts ===== Для добавления записей в файл /etc/hosts контейнеров пода можно использовать следующую конструкцию: apiVersion: apps/v1 kind: Deployment metadata: name: dnstools spec: replicas: 1 selector: matchLabels: app: dnstools template: metadata: labels: app: dnstools spec: hostname: dns subdomain: tools hostAliases: - ip: 8.8.8.8 hostnames: - dns.google.local - dns8.google.local - ip: 8.8.4.4 hostnames: - dns4.google.local containers: - name: dnstools image: infoblox/dnstools:latest command: - sleep - "36000" imagePullPolicy: IfNotPresent restartPolicy: Always Смотрите секцию hostAliases. ===== Pod – конфигурация resolver ===== При описании пода можно вместо стандартного файла /etc/resolvr.conf настроить свой собственный вариант. В этом случае необходимо изменить dnsPolicy на none: dnsPolicy: "None" Эта политика заставляет под игнорировать настройки DNS Kubernetes. При этом требуется настроить DNS с использованием параметра dnsConfig: nameservers: - 8.8.8.8 - 8.8.4.4 searches: - auchan.ru options: - name: ndots value: "2"