/etc/resolv.conf для Kubernetes pods, опція ndots:5, як це може негативно позначитися на продуктивності програми

/etc/resolv.conf для Kubernetes pods, опція ndots:5, як це може негативно позначитися на продуктивності програми

Нещодавно ми запустили Kubernetes 1.9 на AWS за допомогою Kops. Вчора, під час плавного викочування нового трафіку на найбільший з наших кластерів Kubernetes, я почав помічати незвичайні помилки дозволу імен DNS, залоговані нашим додатком.

На GitHub досить довго про це говорилитому я теж вирішив розібратися. У результаті я зрозумів, що в нашому випадку це викликано підвищеним навантаженням kube-dns и dnsmasq. Найцікавішим і найновішим для мене виявилася сама причина значного збільшення трафіку DNS-запитів. Про це і про те, що з цим робити, мій пост.

Роздільна здатність DNS всередині контейнера - як і в будь-якій системі Linux - визначається конфігураційним файлом /etc/resolv.conf. Типово Kubernetes dnsPolicy це ClusterFirst, що означає, що будь-який DNS-запит буде перенаправлений на dnsmasq, запущений у поді kube-dns всередині кластера, який, у свою чергу, перенаправить запит на додаток kube-dnsякщо ім'я закінчується суфіксом кластера, або, в іншому випадку, до DNS серверу вищого рівня.

Файл /etc/resolv.conf всередині кожного контейнера за умовчанням виглядатиме так:

nameserver 100.64.0.10
search namespace.svc.cluster.local svc.cluster.local cluster.local 
eu-west-1.compute.internal
options ndots:5

Як можна помітити, тут три директиви:

  1. Сервер імен - це IP сервісу kube-dns
  2. Вказано 4 локальні пошукові домени search
  3. Є опція ndots:5

Цікавою частиною цієї конфігурації є те, як локальні пошукові домени та налаштування ndots:5 уживаються разом. Щоб зрозуміти, необхідно розібратися, як працює дозвіл DNS для неповних імен.

Що таке повне ім'я?

Цілком певне ім'я — це ім'я, для якого не буде виконуватися локальний пошук, і ім'я вважатиметься абсолютним під час дозволу імен. За згодою, програмне забезпечення DNS вважає ім'я повністю визначеним, якщо воно закінчується точкою (.), і не повністю визначеним інакше. Тобто google.com. повністю визначено, а google.com - немає.

Як обробляється неповне ім'я?

Коли програма підключається до віддаленого хоста, вказаного в імені, роздільна здатність імен DNS зазвичай виконується за допомогою системного виклику, наприклад, getaddrinfo(). А ось якщо неповне ім'я (не закінчується на .), цікаво, чи спробує системний виклик спочатку дозволити ім'я як абсолютне, або спочатку пройде через локальні пошукові домени? Це залежить від опції ndots.

З мануалу по resolv.conf:

ndots:n

устанавливает порог для количества точек, которые должны появиться в имени, прежде чем будет сделан начальный абсолютный запрос. Значение по умолчанию для n равно 1, что означает, что если в имени есть какие-либо точки, имя будет сначала опробовано как абсолютное имя, прежде чем к нему будут добавлены какие-либо элементы списка поиска.

Це означає, що якщо для ndots задано значення 5, а ім'я містить менше 5 точок, системний виклик спробує дозволити його послідовно, спочатку пройшовши по всіх локальних пошукових доменів, і, у разі невдачі, нарешті дозволить його як абсолютне ім'я.

Чому ж ndots:5 може негативно позначитися на продуктивність програми?

Як ви розумієте, якщо ваша програма використовує багато зовнішнього трафіку, для кожного встановленого TCP-з'єднання (або, точніше, для кожного дозволеного імені) воно видаватиме 5 DNS-запитів, перш ніж ім'я буде правильно дозволено, тому що воно спочатку пройде через 4 локальних пошукових доменів, а в кінці видасть запит дозволу абсолютного імені.

На наступній діаграмі показано сумарний трафік на наших 3 модулях kube-dns до та після того, як ми переключили кілька імен хостів, налаштованих у нашому додатку, повністю визначені.

/etc/resolv.conf для Kubernetes pods, опція ndots:5, як це може негативно позначитися на продуктивності програми

На наступній діаграмі показано затримку програми до і після того, як ми переключили кілька імен хостів, налаштованих у нашому додатку, на повні (вертикальна синя лінія це розгортання):

/etc/resolv.conf для Kubernetes pods, опція ndots:5, як це може негативно позначитися на продуктивності програми

Рішення #1 - використовувати повністю певні імена

Якщо у вас мало статичних зовнішніх імен (тобто визначених у конфігурації програми), до яких ви створюєте велику кількість з'єднань, можливо, найпростіше рішення - переключити їх на певні, просто додавши. в кінці.

Це не остаточне рішення, але допомагає швидко, хай і не чисто, покращити ситуацію. Цей патч ми застосували для вирішення нашої проблеми, результати чого були показані на скріншотах вище.

Рішення #2 - кастомізація ndots в dnsConfig

У Kubernetes 1.9 в альфа режимі з'явився функціонал (бета-версія v1.10), який дозволяє краще контролювати параметри DNS через властивість подавання dnsConfig. Серед іншого він дозволяє налаштувати значення ndots для конкретного пода, тобто.

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsConfig:
    options:
      - name: ndots
        value: "1"

Джерела

Також читайте інші статті у нашому блозі:

Джерело: habr.com

Додати коментар або відгук