Kubernetes створює DNS-записи для Services та Podʼів. Ви можете звертатися до Services за стабільними DNS-іменами замість IP-адрес.
Kubernetes публікує інформацію про Podʼи та Services, яка використовується для програмування DNS. kubelet налаштовує DNS Podʼів так, щоб запущені контейнери могли знаходити Services за іменем, а не за IP.
Services, визначеним у кластері, призначаються DNS-імена. Стандартно список пошуку DNS клієнтського Podʼа містить власний простір імен Podʼа та стандартний домен кластера.
DNS-запит може повертати різні результати залежно від простору імен Podʼа, який його робить. DNS-запити, які не вказують простір імен, обмежуються простором імен Podʼа. Щоб отримати доступ до Services в інших просторах імен, вказуйте простір імен у DNS-запиті.
Наприклад, розгляньмо Pod у просторі імен test. Service data міститься в просторі імен prod.
Запит data не повертає результатів, оскільки використовує простір імен Podʼа test.
Запит data.prod повертає очікуваний результат, оскільки вказує простір імен.
DNS-запити можуть бути розширені за допомогою /etc/resolv.conf Podʼа. kubelet налаштовує цей файл для кожного Podʼа. Наприклад, запит лише data може бути розширено до data.test.svc.cluster.local. Для розширення запитів використовуються значення параметра search. Щоб дізнатися більше про DNS-запити, див. сторінку довідки resolv.conf.
nameserver 10.32.0.10
search <namespace>.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
Отже, Pod у просторі імен test може успішно розвʼязувати як data.prod, так і data.prod.svc.cluster.local.
Для яких обʼєктів створюються DNS-записи?
У розділах нижче докладно описано підтримувані типи DNS-записів та їхню структуру. Будь-яка інша структура, імена чи запити, які випадково працюють, вважаються деталями реалізації й можуть змінитися без попередження. Актуальнішу специфікацію див. у Kubernetes DNS-Based Service Discovery.
«Звичайні» (не headless) Services отримують DNS-записи A та/або AAAA залежно від сімейства або сімейств IP цього Service, з іменем у вигляді my-svc.my-namespace.svc.cluster-domain.example. Це імʼя розвʼязується в кластерний IP Service.
Headless Services
(без кластерного IP) теж отримують DNS-записи A та/або AAAA, з іменем у вигляді my-svc.my-namespace.svc.cluster-domain.example. На відміну від звичайних Services, це імʼя розвʼязується в набір IP-адрес усіх Podʼів, вибраних Service. Очікується, що клієнти використовуватимуть увесь набір або стандартний вибір round-robin із нього.
Записи SRV створюються для іменованих портів, які є частиною звичайних або headless Services.
_port-name._port-protocol.my-svc.my-namespace.svc.cluster-domain.example.my-svc.my-namespace.svc.cluster-domain.example.hostname.my-svc.my-namespace.svc.cluster-domain.example.Версії Kube-DNS до впровадження специфікації DNS мали таке розвʼязання DNS:
<pod-IPv4-address>.<namespace>.pod.<cluster-domain>
Наприклад, якщо Pod в просторі імен default має IP-адресу 172.17.0.3, а доменне імʼя вашого кластера — cluster.local, то у Podʼа буде DNS-імʼя:
172-17-0-3.default.pod.cluster.local
Деякі кластерні механізми DNS, такі як CoreDNS, також надають записи A для:
<pod-ipv4-address>.<service-name>.<my-namespace>.svc.<cluster-domain.example>
Наприклад, якщо Pod у просторі імен cafe має IP-адресу 172.17.0.3, є точкою доступу Service з назвою barista, а доменне імʼя вашого кластера — cluster.local, то Pod матиме такий запис DNS A в межах Service.
172-17-0-3.barista.cafe.svc.cluster.local
Наразі під час створення Podʼа його імʼя хоста (як його видно зсередини Podʼа) — це значення metadata.name Podʼа.
У специфікації Podʼа є необовʼязкове поле hostname, яке можна використовувати, щоб вказати інше імʼя хоста. Якщо його вказано, воно має пріоритет над назвою Podʼа й стає іменем хоста Podʼа (знову ж таки, як його видно зсередини Podʼа). Наприклад, Pod зі spec.hostname, встановленим у "my-host", матиме імʼя хоста "my-host".
У специфікації Podʼа також є необовʼязкове поле subdomain, яким можна вказати, що Pod є частиною підгрупи простору імен. Наприклад, Pod зі spec.hostname, встановленим у "foo", і spec.subdomain, встановленим у "bar", у просторі імен "my-namespace" матиме імʼя хоста "foo" та повне доменне імʼя (FQDN) "foo.bar.my-namespace.svc.cluster.local" (знову ж таки, як його видно зсередини Podʼа).
Якщо в тому самому просторі імен, що й Pod, існує headless Service із такою самою назвою, як піддомен, DNS-сервер кластера також повертає записи A та/або AAAA для повного імені хоста Podʼа.
Приклад:
apiVersion: v1
kind: Service
metadata:
name: busybox-subdomain
spec:
selector:
name: busybox
clusterIP: None
ports:
- name: foo # name не є обовʼязковим для Services з одним портом
port: 1234
---
apiVersion: v1
kind: Pod
metadata:
name: busybox1
labels:
name: busybox
spec:
hostname: busybox-1
subdomain: busybox-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
---
apiVersion: v1
kind: Pod
metadata:
name: busybox2
labels:
name: busybox
spec:
hostname: busybox-2
subdomain: busybox-subdomain
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
name: busybox
Для наведеного вище Service "busybox-subdomain" і Podʼів, які встановлюють spec.subdomain у "busybox-subdomain", перший Pod бачитиме своє FQDN як "busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example". DNS обслуговує за цим іменем записи A та/або AAAA, що вказують на IP-адресу Podʼа. Обидва Podʼи, "busybox1" та "busybox2", матимуть власні адресні записи.
EndpointSlice може вказувати DNS-імʼя хоста для будь-яких адрес точок доступу разом з їхнім IP.
hostname. Pod без hostname, але з subdomain створить запис A або AAAA лише для headless Service (busybox-subdomain.my-namespace.svc.cluster-domain.example), що вказує на IP-адреси Podʼів. Крім того, Pod має бути готовим, щоб мати запис, якщо для Service не встановлено publishNotReadyAddresses=True.Коли Pod налаштовано так, що він має повне доменне імʼя (FQDN), його імʼя хоста — це коротке імʼя хоста. Наприклад, якщо у вас є Pod із повним доменним імʼям busybox-1.busybox-subdomain.my-namespace.svc.cluster-domain.example, то стандартно команда hostname в цьому Podʼі повертає busybox-1, а команда hostname --fqdn повертає FQDN.
Коли ви встановлюєте setHostnameAsFQDN: true у специфікації Podʼа, kubelet записує FQDN Podʼа в імʼя хоста для простору імен цього Podʼа. У цьому випадку як hostname, так і hostname --fqdn повертають FQDN Podʼа.
У Linux поле hostname ядра (поле nodename структури struct utsname) обмежено 64 символами.
Якщо Pod вмикає цю можливість, а його FQDN довше за 64 символи, він не запуститься. Pod залишиться у статусі Pending (ContainerCreating, як показує kubectl), генеруючи події помилок, такі як Failed to construct FQDN from Pod hostname and cluster domain, FQDN long-FQDN is too long (64 characters is the max, 70 characters requested). Один зі способів покращити досвід користувача в цьому сценарії — створити контролер вебхука допуску, щоб контролювати розмір FQDN під час створення користувачами обʼєктів верхнього рівня, наприклад Deployment.
Політику DNS можна встановлювати для кожного Podʼа окремо. Наразі Kubernetes підтримує такі політики DNS для Podʼів. Ці політики вказуються в полі dnsPolicy специфікації Podʼа.
Default": Pod успадковує конфігурацію розвʼязання імен від вузла, на якому він працює. Докладніше дивіться в повʼязаному обговоренні.ClusterFirst": Будь-який DNS-запит, який не відповідає налаштованому суфіксу домену кластера, наприклад "www.kubernetes.io", DNS-сервер пересилає до вищестоящого сервера імен. Адміністратори кластера можуть налаштувати додаткові stub-домени та вищестоящі DNS-сервери. Як у цих випадках обробляються DNS-запити, дивіться в повʼязаному обговоренні.ClusterFirstWithHostNet": Для Podʼів, що працюють із hostNetwork, слід явно встановити політику DNS "ClusterFirstWithHostNet". Інакше Podʼи, що працюють із hostNetwork і "ClusterFirst", повернуться до поведінки політики "Default".None": Дозволяє Podʼу ігнорувати налаштування DNS із середовища Kubernetes. Усі налаштування DNS мають надаватися за допомогою поля dnsConfig у специфікації Podʼа. Див. підрозділ Конфігурація DNS Podʼа нижче.dnsPolicy не вказано явно, використовується "ClusterFirst".У прикладі нижче показано Pod із політикою DNS "ClusterFirstWithHostNet", оскільки hostNetwork встановлено в true.
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: default
spec:
containers:
- image: busybox:1.28
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
Конфігурація DNS Podʼа дає користувачам більше контролю над налаштуваннями DNS Podʼа.
Поле dnsConfig є необовʼязковим і може працювати з будь-якими налаштуваннями dnsPolicy. Однак коли dnsPolicy Podʼа встановлено в "None", поле dnsConfig потрібно вказати обовʼязково.
Нижче наведено властивості, які користувач може вказати в полі dnsConfig:
nameservers: список IP-адрес, які використовуватимуться як DNS-сервери для Podʼа. Можна вказати не більше 3 IP-адрес. Коли dnsPolicy Podʼа встановлено в "None", список повинен містити принаймні одну IP-адресу, інакше ця властивість є необовʼязковою. Указані сервери буде обʼєднано з базовими серверами імен, згенерованими із зазначеної політики DNS, а дубльовані адреси вилучено.searches: список доменів пошуку DNS для пошуку імен хостів у Podʼі. Ця властивість є необовʼязковою. Якщо її вказано, цей список буде обʼєднано з базовими доменами пошуку, згенерованими з вибраної політики DNS. Дубльовані доменні імена вилучаються. Kubernetes дозволяє до 32 доменів пошуку.options: необовʼязковий список обʼєктів, де кожний обʼєкт може мати властивість name (обовʼязкова) і властивість value (необовʼязкова). Вміст цієї властивості буде обʼєднано з параметрами, згенерованими із зазначеної політики DNS. Дубльовані записи вилучаються.Ось приклад Podʼа з власними налаштуваннями DNS:
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: dns-example
spec:
containers:
- name: test
image: nginx
dnsPolicy: "None"
dnsConfig:
nameservers:
- 192.0.2.1 # this is an example
searches:
- ns1.svc.cluster-domain.example
- my.dns.search.suffix
options:
- name: ndots
value: "2"
- name: edns0
Коли наведений вище Pod створено, контейнер test отримує такий вміст у своєму файлі /etc/resolv.conf:
nameserver 192.0.2.1
search ns1.svc.cluster-domain.example my.dns.search.suffix
options ndots:2 edns0
Для налаштування IPv6 шлях пошуку та сервер імен слід налаштувати так:
kubectl exec -it dns-example -- cat /etc/resolv.conf
Вивід буде подібний до такого:
nameserver 2001:db8:30::a
search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
options ndots:5
Kubernetes сам не обмежує конфігурацію DNS, доки довжина списку доменів пошуку не перевищить 32 або загальна довжина всіх доменів пошуку не перевищить 2048. Це обмеження стосується файлу конфігурації резолвера вузла, конфігурації DNS Podʼа та обʼєднаної конфігурації DNS відповідно.
Деякі середовища виконання контейнерів раніших версій можуть мати власні обмеження щодо кількості доменів пошуку DNS. Залежно від середовища виконання контейнерів, Podʼи з великою кількістю доменів пошуку DNS можуть залишатися в стані очікування.
Відомо, що цю проблему мають containerd v1.5.5 або раніші та CRI-O v1.21 або раніші.
ClusterFirstWithHostNet не підтримується для Podʼів, що працюють на вузлах Windows. Windows вважає всі імена з крапкою . повними доменними іменами (FQDN) і пропускає розвʼязання FQDN.Resolve-DNSName.mydns.svc.cluster.local). Windows може розвʼязувати FQDN, Services або мережеві імена, які можна розвʼязати за допомогою цього єдиного суфікса. Наприклад, Pod, запущений у просторі імен default, матиме суфікс DNS default.svc.cluster.local. Усередині Podʼа Windows можна розвʼязувати і kubernetes.default.svc.cluster.local, і kubernetes, але не частково кваліфіковані імена (kubernetes.default або kubernetes.default.svc).Настанови щодо адміністрування конфігурацій DNS дивіться на сторінці Налаштування DNS Service.