====== 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"