Автоматическое управление DNS-записями в Kubernetes с помощью ExternalDNS

При развертывании веб-приложений в Kubernetes сервисы и Ingresses обычно применяются для того, чтобы открыть доступ к приложению по домену за пределами кластера. Это включает ручную настройку не только Ingress, но и DNS-записей провайдера, а этот процесс может быть трудоемким и подверженным ошибкам. Более того, по мере роста вашего приложения этот процесс может стать гораздо сложнее; при изменении внешнего IP-адреса необходимо соответствующим образом обновить записи DNS.

Чтобы устранить эту проблему, команда Kubernetes sig-network создала инструмент ExternalDNS, целью которого является автоматическое управление внешними записями DNS из кластера Kubernetes. После развертывания ExternalDNS работает в фоновом режиме и почти не требует дополнительной настройки. Каждый раз, когда создается или изменяется сервис или Ingress, ExternalDNS сразу обновляет записи.

В этом мануале вы научитесь устанавливать ExternalDNS в свой кластер Kubernetes через Helm и настраивать поддержку DNS-провайдера. Позже мы развернем образец веб-приложения с Ingress и попробуем использовать ExternalDNS, чтобы направить его на ваш домен. В результате у вас будет автоматизированная система управления записями DNS для сервисов и Ingress-ов.

Требования

  • Кластер Kubernetes с настроенным  kubectl по умолчанию.
  • Менеджер пакетов Helm на вашем локальном компьютере и Tiller в кластере. Для этого выполните шаги 1 и 2 мануала Установка программного обеспечения в кластер Kubernetes с помощью пакетного менеджера Helm.
  • Nginx Ingress Controller в кластере, установленный с помощью Helm (чтобы использовать ExternalDNS и ресурсы Ingress). Следуйте этому мануалу. Вам необходимо установить для свойства publishService значение true, как описано в разделе 2.
  • Ключ API (токен личного доступа) с разрешениями на чтение и запись.
  • Полностью зарегистрированное доменное имя. В этом мануале будет использоваться условный домен echo.example.com.

1: Установка ExternalDNS с помощью Helm

Сначала нужно установить ExternalDNS в свой кластер с помощью Helm и настроить его для взаимодействия с сервисом DNS вашего провайдера.

Чтобы переопределить некоторые параметры по умолчанию для чарта ExternalDNS, вам необходимо создать файл values.yaml, который вы передадите в Helm во время установки. На компьютере, который вы используете для доступа к кластеру, создайте файл:

nano externaldns-values.yaml

Добавьте в него следующие строки:

rbac:
create: true
provider: your-provider
your-provider:
apiToken: your_api_token
interval: "1m"
policy: sync # or upsert-only
# domainFilters: [ 'example.com' ]

В первом блоке включается создание манифеста RBAC (управление доступом на основе ролей), которое обязательно должно быть включено в кластерах Kubernetes с поддержкой RBAC. В следующей строке устанавливается DNS-провайдер. Затем в следующем блоке вам нужно указать свой API токен провайдера, заменив your_api_token.

Следующая строка устанавливает интервал, с которым ExternalDNS будет запрашивать изменения в Ingress-ах и сервисах. Вы можете установить меньшее значение, чтобы быстрее распространять изменения в DNS.

Параметр policy определяет, что может делать ExternalDNS: только вставлять записи DNS (upsert-only) или создавать и удалять их по мере необходимости (sync). К счастью, начиная с версии 0.3, ExternalDNS поддерживает собственность, создавая сопровождающие записи TXT , в которых он хранит информацию о доменах и ограничивает их область действия.

Параметр domainFilters используется для ограничения доменов, которыми может управлять ExternalDNS. Вы можете раскомментировать его и ввести свои домены в виде массива строк, но это не обязательно.

Когда вы закончите редактирование, сохраните и закройте файл.

Теперь установите ExternalDNS в кластер, выполнив следующую команду:

helm install stable/external-dns --name external-dns -f externaldns-values.yaml

Вывод команды будет выглядеть примерно так:

NAME:   external-dns
LAST DEPLOYED: ...
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Pod(related)
NAME                           READY  STATUS             RESTARTS  AGE
external-dns-69c545655f-xqjjf  0/1    ContainerCreating  0         0s
==> v1/Secret
NAME          TYPE    DATA  AGE
external-dns  Opaque  1     0s
==> v1/Service
NAME          TYPE       CLUSTER-IP    EXTERNAL-IP  PORT(S)   AGE
external-dns  ClusterIP  10.245.47.69  <none>       7979/TCP  0s
==> v1/ServiceAccount
NAME          SECRETS  AGE
external-dns  1        0s
==> v1beta1/ClusterRole
NAME          AGE
external-dns  0s
==> v1beta1/ClusterRoleBinding
NAME          AGE
external-dns  0s
==> v1beta1/Deployment
NAME          READY  UP-TO-DATE  AVAILABLE  AGE
external-dns  0/1    1           0          0s
NOTES:
...

Вы можете проверить создание ExternalDNS при помощи команды:

kubectl --namespace=default get pods -l "app=external-dns,release=external-dns" -w
NAME                            READY   STATUS              RESTARTS   AGE
external-dns-69bfcf8ccb-7j4hp   0/1     ContainerCreating   0          3s

Вы установили ExternalDNS в свой кластер Kubernetes. Далее мы развернем образец веб-приложения и откроем к нему доступ с помощью Nginx Ingress, а потом ExternalDNS автоматически направит домен на соответствующий балансировщик нагрузки.

2: Развертывание веб-приложения и настройка доступа к нему

В этом разделе мы развернем в кластере фиктивное веб-приложение, а затем откроем его с помощью Ingress. Затем мы подготовим ExternalDNS к автоматической настройке DNS-записей. В итоге у вас будут DNS записи для вашего домена, указывающие на балансировщик нагрузки Ingress.

В качестве тестового веб-приложениея мы используем http-echo от Hashicorp. Это in-memory веб-сервер, который возвращает отправленное вами сообщение. Хранить его манифесты Kubernetes можно в файле echo.yaml. Создайте его и откройте в редакторе:

nano echo.yaml

Добавьте следующие строки в этот файл:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: echo-ingress
spec:
rules:
- host: echo.example.com
http:
paths:
- backend:
serviceName: echo
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: echo
spec:
ports:
- port: 80
targetPort: 5678
selector:
app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo
spec:
selector:
matchLabels:
app: echo
replicas: 3
template:
metadata:
labels:
app: echo
spec:
containers:
- name: echo
image: hashicorp/http-echo
args:
- "-text=Echo!"
ports:
- containerPort: 5678

В этой конфигурации вы определяете развертывание, Ingress и сервис. Развертывание состоит из трех реплик приложения http-echo с переданным пользовательским сообщением (Echo!). Сервис разрешает доступ к модулям в Развертывании через порт 80. Ingress открывает доступ к сервису по вашему домену.

Замените echo.example.com своим доменом, затем сохраните и закройте файл.

Теперь вам не нужно вручную настраивать DNS-записи для домена. ExternalDNS сделает это автоматически, как только вы примените конфигурацию к Kubernetes.

Чтобы применить конфигурацию, выполните следующую команду:

kubectl create -f echo.yaml

Вы увидите следующий вывод:

ingress.extensions/echo-ingress created
service/echo created
deployment.apps/echo created

Вам нужно будет немного подождать, пока ExternalDNS заметит изменения и создаст соответствующие записи. Настройка interval в чарте Helm определяет продолжительность времени, в течение которого вам нужно ожидать создания записи DNS. В values.yaml интервал по умолчанию – 1 минута.

Откройте панель управления своего облачного провайдера и убедитесь, что у вас появилась запись TXT.

По истечении указанного промежутка времени используйте curl:

curl echo.example.com

Если все правильно, вы увидите следующий вывод:

Echo!

Это сообщение подтверждает, что вы настроили ExternalDNS и создали необходимые DNS-записи для работы балансировщика нагрузки контроллера Ingress. Если вы видите сообщение об ошибке, подождите еще немного. Также можно попробовать получить доступ к своему домену через браузер, где вы должны увидеть это сообщение.

Вы протестировали ExternalDNS, развернув образец приложения через Ingress. Вы также можете найти новые записи DNS в панели управления хостинга.

3: Открытие доступа к приложению через сервис (опционально)

В этом дополнительном разделе вместо Ingress мы используем сервис с ExternalDNS. ExternalDNS позволяет открывать DNS-серверам доступ к разным ресурсам Kubernetes. Использование сервисов аналогично процессу Ingress-а, нужно только немного отладить конфигурацию для этого ресурса.

Примечание: После выполнения этого раздела только что созданные вами DNS записи будут удалены.

Поскольку вы будете настраивать сервис, содержащийся в echo.yaml, вам больше не понадобится echo-ingress. Удалите его:

kubectl delete ing echo-ingress
ingress.extensions/echo-ingress deleted

ExternalDNS удалит существующие записи DNS, созданные на предыдущем этапе. В оставшейся части мануала вы можете использовать тот же домен, который вы использовали ранее.

Далее откройте файл echo.yaml для редактирования:

nano echo.yaml

Замените текущее содержимое этого файла следующими строками:

apiVersion: v1
kind: Service
metadata:
name: echo
annotations:

external-dns.alpha.kubernetes.io/hostname: echo.example.com

spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 5678
selector:
app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo
spec:
selector:
matchLabels:
app: echo
replicas: 3
template:
metadata:
labels:
app: echo
spec:
containers:
- name: echo
image: hashicorp/http-echo
args:
- "-text=Echo!"
ports:
- containerPort: 5678

Вы удалили Ingress из предыдущей настройки и изменили тип сервиса на LoadBalancer. Кроме того, вы добавили аннотацию, указав доменное имя для ExternalDNS.

Примените изменения к кластеру, выполнив следующую команду:

kubectl apply -f echo.yaml

В выводе появится:

service/echo configured
deployment.apps/echo configured

Вы можете наблюдать, как к балансировщику нагрузки сервиса появляется доступ, запустив команду:

kubectl get svc echo -w

Вы увидите похожий вывод:

NAME   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
echo   LoadBalancer   10.245.81.235   <pending>     80:31814/TCP   8s
...

Как и прежде, вам нужно будет немного подождать, пока создадутся и распространятся записи DNS. Как только это будет сделано, запустите curl на указанный вами домен:

curl echo.example.com

Вывод будет таким же, как на предыдущем этапе:

Echo!

Если вы получили ошибку, подождите немного дольше или попробуйте другой домен. Поскольку в клиентских системах записи DNS кэшируются, для фактического распространения изменений может потребоваться больше времени.

Итак, вы создали сервис типа LoadBalancer и направили ее на свое доменное имя, используя ExternalDNS.

Заключение

ExternalDNS работает в фоновом режиме и упрощает работу в кластере. Ваш кластер Kubernetes только что стал основным доверенным источником надежных данных о доменах. Вам больше не придется обновлять DNS-записи вручную.

Tags: , , , , , ,