Використання NodeLocal DNSCache в кластерах Kubernetes
Kubernetes v1.18 [stable]
Ця сторінка надає огляд функції NodeLocal DNSCache в Kubernetes.
Перш ніж ви розпочнете
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Для перевірки версії введітьkubectl version
.Вступ
NodeLocal DNSCache поліпшує продуктивність кластерного DNS, запускаючи агента кешування DNS на вузлах кластера як DaemonSet. За поточної архітектури, Podʼи в режимі DNS ClusterFirst
звертаються до serviceIP
kube-dns для DNS-запитів. Вони переводяться в точку доступу kube-dns/CoreDNS за допомогою прав iptables, доданих kube-proxy. За цією новою архітектурою Podʼи звертаються до агента кешування DNS, що працює на тому ж вузлі, тим самим уникнувши прав iptables DNAT та відстеження зʼєднань. Локальний агент кешування буде запитувати службу kube-dns про пропуски кешування для імен кластера (типовий суфікс "cluster.local
").
Мотивація
За поточної архітектури DNS, є можливість того, що Podʼи з найвищим QPS DNS повинні звертатися до іншого вузла, якщо на цьому вузлі немає локального екземпляра kube-dns/CoreDNS. Наявність локального кешу допоможе покращити час відгуку в таких сценаріях.
Пропускаючи iptables DNAT та відстеження зʼєднань допоможе зменшити перегони з відстеженням зʼєднань та уникнути заповнення таблиці conntrack UDP DNS-записами.
Зʼєднання від локального агента кешування до служби kube-dns можуть бути підвищені до TCP. Записи conntrack для TCP будуть видалені при закритті зʼєднання, на відміну від записів UDP, які мусять перейти у режим очікування (типово
nf_conntrack_udp_timeout
становить 30 секунд)Перехід DNS-запитів з UDP до TCP зменшить хвостовий час відповіді, спричинений втратою пакетів UDP та зазвичай таймаутами DNS до 30 секунд (3 повтори + 10 секунд таймауту). Оскільки кеш NodeLocal прослуховує UDP DNS-запити, застосунки не потребують змін.
Метрики та видимість DNS-запитів на рівні вузла.
Відʼємне кешування можна повторно включити, тим самим зменшивши кількість запитів до служби kube-dns.
Діаграма архітектури
Це шлях, яким йдуть DNS-запити після ввімкнення NodeLocal DNSCache:
Конфігурація
Примітка:
Локальна IP-адреса прослуховування для NodeLocal DNSCache може бути будь-якою адресою, яка гарантовано не перетинається з будь-яким наявним IP у вашому кластері. Рекомендується використовувати адресу з місцевою областю, наприклад, з діапазону 'link-local' '169.254.0.0/16' для IPv4 або з діапазону 'Unique Local Address' у IPv6 'fd00::/8'.Цю функцію можна ввімкнути за допомогою таких кроків:
Підготуйте маніфест, схожий на зразок
nodelocaldns.yaml
та збережіть його якnodelocaldns.yaml
.Якщо використовуєте IPv6, файл конфігурації CoreDNS потрібно закрити всі IPv6-адреси у квадратні дужки, якщо вони використовуються у форматі 'IP:Port'. Якщо ви використовуєте зразок маніфесту з попереднього пункту, це потребує зміни рядка конфігурації L70 таким чином: "
health [__PILLAR__LOCAL__DNS__]:8080
"Підставте змінні в маніфест з правильними значеннями:
kubedns=`kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}` domain=<cluster-domain> localdns=<node-local-address>
<cluster-domain>
типово "cluster.local
".<node-local-address>
— це локальна IP-адреса прослуховування, обрана для NodeLocal DNSCache.Якщо kube-proxy працює в режимі IPTABLES:
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml
__PILLAR__CLUSTER__DNS__
та__PILLAR__UPSTREAM__SERVERS__
будуть заповнені під час роботи підсистемиnode-local-dns
. У цьому режимі підсистемиnode-local-dns
прослуховують як IP-адресу служби kube-dns, так і<node-local-address>
, тому Podʼи можуть шукати записи DNS, використовуючи будь-яку з цих IP-адрес.Якщо kube-proxy працює в режимі IPVS:
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/,__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml
У цьому режимі підсистеми
node-local-dns
прослуховують лише<node-local-address>
. Інтерфейсnode-local-dns
не може привʼязати кластерну IP kube-dns, оскільки інтерфейс, що використовується для IPVS-балансування навантаження, вже використовує цю адресу.__PILLAR__UPSTREAM__SERVERS__
буде заповнено підсистемамиnode-local-dns
.
Запустіть
kubectl create -f nodelocaldns.yaml
.Якщо використовуєте kube-proxy в режимі IPVS, прапорець
--cluster-dns
для kubelet потрібно змінити на<node-local-address>
, який прослуховує NodeLocal DNSCache. В іншому випадку не потрібно змінювати значення прапорця--cluster-dns
, оскільки NodeLocal DNSCache прослуховує як IP-адресу служби kube-dns, так і<node-local-address>
.
Після ввімкнення, Podʼи node-local-dns
будуть працювати у просторі імен kube-system
на кожному з вузлів кластера. Цей Pod працює з CoreDNS у режимі кешування, тому всі метрики CoreDNS, що надаються різними втулками, будуть доступні на рівні кожного вузла.
Цю функцію можна вимкнути, видаливши DaemonSet, використовуючи kubectl delete -f <manifest>
. Також слід скасувати будь-які зміни, внесені до конфігурації kubelet.
Конфігурація StubDomains та Upstream серверів
StubDomains та upstream сервери, вказані в ConfigMap kube-dns в просторі імен kube-system
автоматично використовуються підсистемами node-local-dns
. Вміст ConfigMap повинен відповідати формату, показаному у прикладі. ConfigMap node-local-dns
також можна змінити безпосередньо з конфігурацією stubDomain у форматі Corefile. Деякі хмарні постачальники можуть не дозволяти змінювати ConfigMap node-local-dns
безпосередньо. У цьому випадку ConfigMap kube-dns можна оновити.
Налаштування обмежень памʼяті
Podʼи node-local-dns
використовують памʼять для зберігання записів кешу та обробки запитів. Оскільки вони не стежать за обʼєктами Kubernetes, розмір кластера або кількість Service / EndpointSlice не впливає на використання памʼяті безпосередньо. Використання памʼяті впливає на шаблон DNS-запитів. З документації CoreDNS:
Типовий розмір кешу — 10000 записів, що використовує приблизно 30 МБ, коли повністю заповнений.
Це буде використання памʼяті для кожного блоку сервера (якщо кеш буде повністю заповнений). Використання памʼяті можна зменшити, вказавши менші розміри кешу.
Кількість одночасних запитів повʼязана з попитом памʼяті, оскільки кожен додатковий goroutine, використаний для обробки запиту, потребує певної кількості памʼяті. Ви можете встановити верхню межу за допомогою опції max_concurrent
у втулку forward.
Якщо Pod node-local-dns
намагається використовувати більше памʼяті, ніж доступно (через загальні системні ресурси або через налаштовані обмеження ресурсів), операційна система може вимкнути контейнер цього Podʼа. У разі цього, контейнер, якого вимкнено ("OOMKilled"), не очищає власні правила фільтрації пакетів, які він раніше додавав під час запуску. Контейнер node-local-dns
повинен бути перезапущений (оскільки він керується як частина DaemonSet), але це призведе до короткої перерви у роботі DNS кожного разу, коли контейнер зазнає збою: правила фільтрації пакетів направляють DNS-запити до локального Podʼа, який не є справним.
Ви можете визначити прийнятне обмеження памʼяті, запустивши Podʼи node-local-dns
без обмеження
та вимірявши максимальне використання. Ви також можете налаштувати та використовувати VerticalPodAutoscaler у recommender mode, а потім перевірити його рекомендації.