Service Discovery и DNS
Service Discovery и DNS
1) Навіщо це потрібно
У розподілених системах вузли з'являються і зникають, а клієнти повинні знаходити робочі екземпляри сервісу швидко і надійно. DNS - універсальний шар імен; service discovery - стратегія зіставлення імені сервісу реальним ендпойнтам з урахуванням здоров'я, ваги і політики маршрутизації.
Ключові цілі:- стабільні імена замість ефемерних адрес,
- точний, але не галасливий апдейт (баланс між свіжістю і TTL),
- деградація без повного падіння (failover/health-check),
- мінімум «здогадок» на клієнті: таймаути, ретраї, кеш-політики.
2) Моделі service discovery
2. 1 Клієнтська (client-side)
Клієнт сам дозволяє ім'я в набір ендпойнтів і балансує (round-robin, EWMA, хеш по ключу). Джерело - DNS (A/AAAA/SRV), сервіс-реєстр (Consul/Eureka), статичний список.
Плюси: менше центральних SPOF, гнучкі алгоритми.
Мінуси: неоднорідність клієнтів, складніше оновлювати логіку.
2. 2 Серверна (server-side)
Клієнт йде на front/LB (L4/L7, gateway/ingress). Балансування і health-checking - на стороні проксі/балансувальника.
Плюси: єдине місце політики, спостережуваність.
Мінуси: потрібен високодоступний периметр (N + 1, multi-AZ).
2. 3 Гібрид
DNS дає набір точок входу (регіональні LB), далі - балансування на L7/mesh.
3) DNS: основи, записи та TTL
3. 1 Базові типи
A/AAAA - IPv4/IPv6 адреси.
CNAME - аліас на інше ім'я (не на apex).
SRV — `_service._proto. name'→ хост/порт/вага/пріоритет (для gRPC/LDAP/SIP тощо).
TXT/HTTP/HTTPS - метадані/покажчики (в т.ч. для HTTP-discovery).
NS/SOA - делегування та атрибути зони.
3. 2 TTL і кеш-каскад
Кеш є у: резолвера ОС, локального stub-резолвера, вузлів (NodeLocal DNS/CoreDNS), провайдера, проміжних рекурсорів і у клієнта бібліотеки. Фактична свіжість = min (TTL, політика клієнта). Негативний кеш (NXDOMAIN) теж кешується по'SOA. MINIMUM`/`TTL`.
Рекомендації:- Прод - TTL 30-120s для динамічних записів, 300-600s для стабільних.
- Для перемикань (фейловер) готуйте знижений TTL заздалегідь, а не «під час пожежі».
- Враховуйте sticky-кеш бібліотек (Java/Go/Node) - при необхідності налаштовуйте TTL резолвера всередині рантайму.
4) Політики DNS-балансування та відмовостійкості
Weighted RR - ваги на A/AAAA/SRV.
Failover - первинний/вторинний набори (health-check зовні).
Geo/Latency - відповідь на «найближчу» РОР/регіон.
Anycast - один IP в різних POP (BGP); стійко до регіональних збоїв.
Split-horizon - різні відповіді всередині VPC/он-прем і в інтернеті.
GSLB - глобальний балансувальник з health-перевірками і політиками (latency, гео, capacity).
5) Health-checks і свіжість
DNS сам по собі «тупий»: він не знає здоров'я бекендів. Тому:- Або зовнішній health-checker управляє записами/вагами (GSLB, Route53/Traffic-policy, external-dns + проби).
- Або клієнт/mesh робить активний outlier-ejection і retry з безлічі ендпойнтів.
6) Kubernetes: discovery з коробки
Сервісні імена: `svc. namespace. svc. cluster. local`.
ClusterIP: стабільний віртуальний IP + kube-proxy/ebpf.
Headless Service (`clusterIP: None`): віддає A-записи на pod'и (або їх піддомен), SRV для портів.
EndpointSlice: масштабований список ендпойнтів (заміна Endpoints).
CoreDNS: DNS-резолвер кластера; плагіни rewrite/template/forward/cache;'kube-dns'зону.
NodeLocal DNSCache: локальний кеш на вузлі → менше latency і перехоплення проблем апстрім-резолвера.
Приклад: Headless + SRV
yaml apiVersion: v1 kind: Service metadata: { name: payments, namespace: prod }
spec:
clusterIP: None selector: { app: payments }
ports:
- name: grpc port: 50051 targetPort: 50051
Клієнт може резолвить'_ grpc. _ tcp. payments. prod. svc. cluster. local'( SRV) і отримати хост/порт/ваги.
CoreDNS (фрагмент ConfigMap)
yaml apiVersion: v1 kind: ConfigMap metadata: { name: coredns, namespace: kube-system }
data:
Corefile:
.:53 {
errors health ready cache 30 loop forward. /etc/resolv. conf prometheus:9153 reload
}
NodeLocal DNS (ідеї):
- DaemonSet з локальним резолвером на'169. 254. 20. 10`; kubelet вказує цю точку.
- Знижує p99 name-resolution і захищає від «флапа» апстрім-DNS.
7) Service discovery вне K8s
Consul: агент, health-checks, сервіс-каталог, DNS-інтерфейс ('.consul'), KV для конфігов.
Eureka/ZooKeeper/etcd: реєстри для JVM/legacy; часто в зв'язці з sidecar/шлюзом.
Envoy/Istio: EDS/xDS (Endpoint Discovery) і SDS (секрети); сервіси оголошуються через control-plane.
8) Безпека DNS
DNSSEC: захист цілісності записів (підпис зон). Критично для публічних доменів.
DoT/DoH: шифрування каналу до рекурсора (внутрішні політики, сумісність).
ACL и split-horizon: приватна зона - тільки з VPC/VPN.
Захист від кеш-отруєння: рандомізація портів/ID, короткі TTL для динаміки.
Політики на egress: дозволяйте DNS тільки на довірені резолвери, журналюйте.
9) Поведінка клієнтів і ретраї
Поважайте TTL: не кешуйте нескінченно, не «свавільте» частими резолвами (шторм до рекурсора).
Happy Eyeballs (IPv4/IPv6), паралельні коннекти до декількох A/AAAA зменшують tail.
Ретраї тільки при ідемпотентних запитах; джиттер, обмеження budget ретраїв.
- Java: `networkaddress. cache. ttl`, `networkaddress. cache. negative. ttl`.
- Go: `GODEBUG=netdns=go`/`cgo`, `Resolver. PreferGo`, `DialTimeout`.
- Node: `dns. setDefaultResultOrder('ipv4first')`, `lookup` с `all:true`.
10) GSLB/DNS-перемикання: Практика
Знизьте TTL з 300→60 за 24-48 годин до планового перемикання.
Тримайте канарний набір ендпойнтів з малою вагою для валідації.
Застосовуйте weighted + health-check замість ручного масового апдейта A-записів.
Для статики/edge - Anycast; для API - Geo/Latency + швидкий L7-фейловер.
11) Спостережуваність і SLO для імені
Метрики:- Rate/latency DNS-запитів, cache hit-ratio, помилки за типами (SERVFAIL/NXDOMAIN).
- Частка запитів з stale-відповідями (якщо використовуєте stale-cache).
- Успіх користувацьких операцій при змінах записів (бізнес-SLI).
- p95/p99 resolve-time в додатках.
- Розшаруйте шлях: клієнт → локальний кеш → нодовий кеш → кластерний резолвер → рекурсор провайдера.
- Відстежуйте сплески NXDOMAIN (помилки імен/помилки) і SERVFAIL (проблеми рекурсора/ресурс-ліміти).
12) Приклади конфігурацій
CoreDNS: rewrite і stub-зона
yaml
.:53 {
log errors cache 60 rewrite name suffix. svc. cluster. local. svc. cluster. local forward. 10. 0. 0. 2 10. 0. 0. 3
}
example. internal:53 {
file /zones/example. internal. signed dnssec
}
systemd-resolved (форс локального резолверу)
ini
[Resolve]
DNS=169. 254. 20. 10
FallbackDNS=1. 1. 1. 1 8. 8. 8. 8
Domains=~cluster. local ~internal
DNSSEC=yes
Envoy: динамічний DNS-refresh
yaml dns_refresh_rate: 5s dns_failure_refresh_rate:
base_interval: 2s max_interval: 30s respect_dns_ttl: true
external-dns (підтримка публічної зони)
yaml args:
- --source=service
- --source=ingress
- --domain-filter=example. com
- --policy=upsert-only
- --txt-owner-id=cluster-prod
13) Чек-лист впровадження (0-30 днів)
0-7 днів
Каталог імен сервісів, вибір моделі (client-/server-side/гібрид).
Базові TTL, включити NodeLocal DNSCache, дашборди DNS-метрик.
Заборона «жорстких IP» в конфігу/коді.
8-20 днів
Headless-сервіси + SRV для gRPC; EndpointSlice включений.
GSLB/weighted для зовнішніх; health-checks і канарка.
Налаштовані таймаути/ретраї клієнтів і бюджет ретраїв.
21-30 днів
Split-horizon і приватні зони; DoT/DoH з політики.
Тест перемикань (по TTL) і фейловера; пост-аналіз.
Політики mesh/EDS, outlier-ejection включені.
14) Анти-патерни
TTL = 0 в проді → шторм до рекурсорів, непередбачувані затримки.
Хардкод IP/портів, відсутність CNAME/аліасів для рівнів.
Зміна записів «вручну» без health-checks і канарок.
Один глобальний резолвер без кешу на вузлах (вузьке місце).
Ігнорування негативного кешу (сплески NXDOMAIN).
Спроби «лікувати» відмову БД через DNS замість рівня даних/фейловера.
15) Метрики зрілості
100% сервісів використовують імена; нульові випадки hard-IP.
CoreDNS/NodeLocal в проді, cache hit-ratio> 90% на вузлах.
GSLB з health-checks, документовані TTL і runbook перемикань.
SRV/EndpointSlice для stateful/gRPC, p99 resolve-time в додатках ≤ 20-30 мс.
Алерти по SERVFAIL/NXDOMAIN і деградації cache hit-ratio.
Перевірки в CI: заборона':latest'і hard-IP в чартах/конфігах.
16) Висновок
Service discovery - це договір про стабільне ім'я і дисципліна кеша. Будуйте гібридну модель: DNS дає швидкий і простий вхід, L7/mesh - здоров'я і розумні політики. Підтримуйте розумні TTL, кеш на вузлах, headless-сервіси і SRV там, де потрібно, використовуйте GSLB/Anycast для кордонів регіонів, стежте за NXDOMAIN/SERVFAIL і p99 resolve-time. Тоді ваше ім'я буде таким же надійним активом, як і сам сервіс.