Настройка NodeLocal DNS Cache
Чтобы снизить нагрузку по DNS-запросам в кластере Managed Service for Kubernetes, включите NodeLocal DNS Cache.
Совет
Если кластер Managed Service for Kubernetes содержит более 50 узлов, используйте автоматическое масштабирование DNS.
По умолчанию поды отправляют запросы к сервису kube-dns
. В поле nameserver
в /etc/resolv.conf
установлено значение ClusterIp
сервиса kube-dns
. Для того, чтобы установить соединение с ClusterIP
, используется iptables
При включении NodeLocal DNS Cache в кластере Managed Service for Kubernetes разворачивается DaemonSetnode-local-dns
). Поды пользователя теперь отправляют запросы к агенту на своем узле Managed Service for Kubernetes.
Если запрос в кеше агента, он возвращает прямой ответ. В ином случае создается TCP-соединение с kube-dns
ClusterIP
. По умолчанию кеширующий агент делает cache-miss запросы к kube-dns
для DNS-зоны кластера Managed Service for Kubernetes cluster.local
.
С помощью такого плана удается избежать правил DNAT, connection tracking
Чтобы настроить кеширование запросов DNS:
- Установите NodeLocal DNS.
- Измените конфигурацию NodeLocal DNS Cache.
- Выполните DNS-запросы.
- Настройте трафик через NodeLocal DNS.
- Проверьте логи.
Если созданные ресурсы вам больше не нужны, удалите их.
Перед началом работы
Создайте инфраструктуру
-
Создайте облачную сеть и подсеть.
-
Создайте сервисный аккаунт с ролью
editor
. -
Создайте группы безопасности для кластера Managed Service for Kubernetes и входящих в него групп узлов.
Важно
От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.
-
Создайте кластер Managed Service for Kubernetes и группу узлов с публичным доступом в интернет и с группами безопасности, подготовленными ранее.
-
Если у вас еще нет Terraform, установите его.
-
Получите данные для аутентификации. Вы можете добавить их в переменные окружения или указать далее в файле с настройками провайдера.
-
Настройте и инициализируйте провайдер. Чтобы не создавать конфигурационный файл с настройками провайдера вручную, скачайте его
. -
Поместите конфигурационный файл в отдельную рабочую директорию и укажите значения параметров. Если данные для аутентификации не были добавлены в переменные окружения, укажите их в конфигурационном файле.
-
Скачайте в ту же рабочую директорию файл конфигурации кластера Managed Service for Kubernetes k8s-node-local-dns.tf
. В файле описаны:-
Сеть.
-
Кластер Managed Service for Kubernetes.
-
Сервисный аккаунт, необходимый для работы кластера и группы узлов Managed Service for Kubernetes.
-
Группы безопасности, которые содержат необходимые правила для кластера Managed Service for Kubernetes и входящих в него групп узлов.
Важно
От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.
-
-
Укажите в файле конфигурации:
- Идентификатор каталога.
- Версии Kubernetes для кластера и групп узлов Managed Service for Kubernetes.
- CIDR кластера Managed Service for Kubernetes.
- Имя сервисного аккаунта кластера Managed Service for Kubernetes.
-
Проверьте корректность файлов конфигурации Terraform с помощью команды:
terraform validate
Если в файлах конфигурации есть ошибки, Terraform на них укажет.
-
Создайте необходимую инфраструктуру:
-
Выполните команду для просмотра планируемых изменений:
terraform plan
Если конфигурации ресурсов описаны верно, в терминале отобразится список изменяемых ресурсов и их параметров. Это проверочный этап: ресурсы не будут изменены.
-
Если вас устраивают планируемые изменения, внесите их:
-
Выполните команду:
terraform apply
-
Подтвердите изменение ресурсов.
-
Дождитесь завершения операции.
-
В указанном каталоге будут созданы все требуемые ресурсы. Проверить появление ресурсов и их настройки можно в консоли управления
. -
Подготовьте окружение
-
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
По умолчанию используется каталог, указанный в профиле CLI. Вы можете указать другой каталог с помощью параметра
--folder-name
или--folder-id
. -
Установите kubectl
и настройте его на работу с созданным кластером.
Установите NodeLocal DNS
Установите NodeLocal DNS с помощью Cloud Marketplace, как описано в инструкции.
-
Узнайте IP-адрес сервиса
kube-dns
:kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}
-
Создайте файл
node-local-dns.yaml
. В настройках DaemonSetnode-local-dns
укажите IP-адрес сервисаkube-dns
:node-local-dns.yaml
# Copyright 2018 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Modified for Yandex Cloud Usage --- apiVersion: v1 kind: ServiceAccount metadata: name: node-local-dns namespace: kube-system labels: --- apiVersion: v1 kind: Service metadata: name: kube-dns-upstream namespace: kube-system labels: k8s-app: kube-dns kubernetes.io/name: "KubeDNSUpstream" spec: ports: - name: dns port: 53 protocol: UDP targetPort: 53 - name: dns-tcp port: 53 protocol: TCP targetPort: 53 selector: k8s-app: kube-dns --- apiVersion: v1 kind: ConfigMap metadata: name: node-local-dns namespace: kube-system labels: data: Corefile: | cluster.local:53 { errors cache { success 9984 30 denial 9984 5 } reload loop bind 169.254.20.10 <IP-адрес_сервиса_kube-dns> forward . __PILLAR__CLUSTER__DNS__ { prefer_udp } prometheus :9253 health 169.254.20.10:8080 } in-addr.arpa:53 { errors cache 30 reload loop bind 169.254.20.10 <IP-адрес_сервиса_kube-dns> forward . __PILLAR__CLUSTER__DNS__ { prefer_udp } prometheus :9253 } ip6.arpa:53 { errors cache 30 reload loop bind 169.254.20.10 <IP-адрес_сервиса_kube-dns> forward . __PILLAR__CLUSTER__DNS__ { prefer_udp } prometheus :9253 } .:53 { errors cache 30 reload loop bind 169.254.20.10 <IP-адрес_сервиса_kube-dns> forward . __PILLAR__UPSTREAM__SERVERS__ { prefer_udp } prometheus :9253 } --- apiVersion: apps/v1 kind: DaemonSet metadata: name: node-local-dns namespace: kube-system labels: k8s-app: node-local-dns spec: updateStrategy: rollingUpdate: maxUnavailable: 10% selector: matchLabels: k8s-app: node-local-dns template: metadata: labels: k8s-app: node-local-dns annotations: prometheus.io/port: "9253" prometheus.io/scrape: "true" spec: priorityClassName: system-node-critical serviceAccountName: node-local-dns hostNetwork: true dnsPolicy: Default # Don't use cluster DNS. tolerations: - key: "CriticalAddonsOnly" operator: "Exists" - effect: "NoExecute" operator: "Exists" - effect: "NoSchedule" operator: "Exists" containers: - name: node-cache image: registry.k8s.io/dns/k8s-dns-node-cache:1.17.0 resources: requests: cpu: 25m memory: 5Mi args: [ "-localip", "169.254.20.10,<IP-адрес_сервиса_kube-dns>", "-conf", "/etc/Corefile", "-upstreamsvc", "kube-dns-upstream" ] securityContext: privileged: true ports: - containerPort: 53 name: dns protocol: UDP - containerPort: 53 name: dns-tcp protocol: TCP - containerPort: 9253 name: metrics protocol: TCP livenessProbe: httpGet: host: 169.254.20.10 path: /health port: 8080 initialDelaySeconds: 60 timeoutSeconds: 5 volumeMounts: - mountPath: /run/xtables.lock name: xtables-lock readOnly: false - name: config-volume mountPath: /etc/coredns - name: kube-dns-config mountPath: /etc/kube-dns volumes: - name: xtables-lock hostPath: path: /run/xtables.lock type: FileOrCreate - name: kube-dns-config configMap: name: kube-dns optional: true - name: config-volume configMap: name: node-local-dns items: - key: Corefile path: Corefile.base --- # A headless service is a service with a service IP but instead of load-balancing it will return the IPs of our associated Pods. # We use this to expose metrics to Prometheus. apiVersion: v1 kind: Service metadata: annotations: prometheus.io/port: "9253" prometheus.io/scrape: "true" labels: k8s-app: node-local-dns name: node-local-dns namespace: kube-system spec: clusterIP: None ports: - name: metrics port: 9253 targetPort: 9253 selector: k8s-app: node-local-dns
-
Создайте ресурсы для NodeLocal DNS:
kubectl apply -f node-local-dns.yaml
Результат:
serviceaccount/node-local-dns created service/kube-dns-upstream created configmap/node-local-dns created daemonset.apps/node-local-dns created service/node-local-dns created
-
Убедитесь, что DaemonSet успешно развернут и запущен:
kubectl get ds -l k8s-app=node-local-dns -n kube-system
Результат:
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE node-local-dns 3 3 3 3 3 <none> 24m
Измените конфигурацию NodeLocal DNS Cache
Чтобы изменить конфигурацию, отредактируйте соответствующий configmap
. Например, чтобы включить логи DNS-запросов для зоны cluster.local
:
-
Выполните команду:
kubectl -n kube-system edit configmap node-local-dns
-
Добавьте строку
log
в конфигурацию зоныcluster.local
:... apiVersion: v1 data: Corefile: | cluster.local:53 { log errors cache { success 9984 30 denial 9984 5 } ...
-
Сохраните изменения.
Результат:
configmap/node-local-dns edited
Обновление конфигурации может занять несколько минут.
Выполните DNS-запросы
Чтобы выполнить тестовые запросы
-
Запустите под:
kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
Результат:
pod/dnsutils created
-
Убедитесь, что под перешел в состояние
Running
:kubectl get pods dnsutils
Результат:
NAME READY STATUS RESTARTS AGE dnsutils 1/1 Running 0 26m
-
Подключитесь к поду:
kubectl exec -i -t dnsutils -- sh
-
Получите IP-адрес локального DNS-кеша:
nslookup kubernetes.default
Результат:
Server: <IP-адрес_kube-dns> Address: <IP-адрес_kube-dns>#53 Name: kubernetes.default.svc.cluster.local Address: 10.96.128.1
-
Выполните запросы:
dig +short @169.254.20.10 www.com dig +short @<IP-адрес_сервиса_kube-dns> example.com
Результат:
# dig +short @169.254.20.10 www.com 52.128.23.153 # dig +short @<IP-адрес_kube-dns> example.com 93.184.216.34
После запуска
node-local-dns
правила iptables настраиваются так, что по обоим адресам (<IP-адрес_сервиса_kube-dns>:53
и169.254.20.10:53
) отвечает local DNS .К
kube-dns
можно обращаться по адресуClusterIp
сервисаkube-dns-upstream
. Этот адрес может понадобиться, чтобы настроить перенаправление запросов.
Настройте трафик через NodeLocal DNS
-
Создайте под для настройки сетевого трафика:
kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: dnschange namespace: default spec: priorityClassName: system-node-critical hostNetwork: true dnsPolicy: Default hostPID: true tolerations: - key: "CriticalAddonsOnly" operator: "Exists" - effect: "NoExecute" operator: "Exists" - effect: "NoSchedule" operator: "Exists" containers: - name: dnschange image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 tty: true stdin: true securityContext: privileged: true command: - nsenter - --target - "1" - --mount - --uts - --ipc - --net - --pid - -- - sleep - "infinity" imagePullPolicy: IfNotPresent restartPolicy: Always EOF
-
Подключитесь к созданному поду
dnschange
:kubectl exec -it dnschange -- sh
-
Откройте файл
/etc/default/kubelet
в контейнере для редактирования:vi /etc/default/kubelet
-
В файле добавьте к значению переменной
KUBELET_OPTS
параметр--cluster-dns=169.254.20.10
(адрес кеша NodeLocal DNS):KUBELET_OPTS="--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig.conf --cert-dir=/var/lib/kubelet/pki/ --cloud-provider=external --config=/home/kubernetes/kubelet-config.yaml --kubeconfig=/etc/kubernetes/ kubelet-kubeconfig.conf --resolv-conf=/run/systemd/resolve/resolv.conf --v=2 --cluster-dns=169.254.20.10"
-
Сохраните файл и выполните команду перезапуска компонента
kubelet
:systemctl daemon-reload && systemctl restart kubelet
Затем выйдите из режима контейнера командой
exit
. -
Удалите под
dnschange
:kubectl delete pod dnschange
-
Чтобы все поды начали работать через NodeLocal DNS, перезапустите их, например, командой:
kubectl get deployments --all-namespaces | \ tail +2 | \ awk '{ cmd=sprintf("kubectl rollout restart deployment -n %s %s", $1, $2) ; system(cmd) }'
-
Выполните команду:
kubectl edit deployment <имя_развертывания_пода>
-
Замените в спецификации пода, в ключе
spec.template.spec
, настройкуdnsPolicy: ClusterFirst
на блок:dnsPolicy: "None" dnsConfig: nameservers: - 169.254.20.10 searches: - default.svc.cluster.local - svc.cluster.local - cluster.local - ru-central1.internal - internal - my.dns.search.suffix options: - name: ndots value: "5"
Проверьте логи
Выполните команду:
kubectl logs --namespace=kube-system -l k8s-app=node-local-dns -f
Чтобы остановить вывод лога на экран, нажмите Ctrl + C.
Результат:
...
[INFO] 10.112.128.7:50527 - 41658 "A IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR qr,aa,rd 106 0.000097538s
[INFO] 10.112.128.7:44256 - 26847 "AAAA IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR qr,aa,rd 147 0.057075876s
...
Остановите DaemonSet
Чтобы выключить DaemonSet NodeLocal DNS Cache, выполните команду:
kubectl delete -f node-local-dns.yaml
Результат:
serviceaccount "node-local-dns" deleted
service "kube-dns-upstream" deleted
configmap "node-local-dns" deleted
daemonset.apps "node-local-dns" deleted
service "node-local-dns" deleted
Удалите созданные ресурсы
Удалите ресурсы, которые вы больше не будете использовать, чтобы за них не списывалась плата:
-
Удалите ресурсы в зависимости от способа их создания:
ВручнуюTerraform-
В терминале перейдите в директорию с планом инфраструктуры.
Важно
Убедитесь, что в директории нет Terraform-манифестов с ресурсами, которые вы хотите сохранить. Terraform удаляет все ресурсы, которые были созданы с помощью манифестов в текущей директории.
-
Удалите ресурсы:
-
Выполните команду:
terraform destroy
-
Подтвердите удаление ресурсов и дождитесь завершения операции.
Все ресурсы, которые были описаны в Terraform-манифестах, будут удалены.
-
-
-
Если для доступа к кластеру Managed Service for Kubernetes или узлам использовались статические публичные IP-адреса, освободите и удалите их.