Облако
Установка и использование ExternalDNS
Что такое ExternalDNS
ExternalDNS автоматически создаёт и удаляет DNS-записи в EdgeCenter DNS, когда вы создаёте или удаляете сервисы (Service LoadBalancer) и ресурсы Ingress в кластере Kubernetes. Работает как контроллер внутри кластера совместно с webhook-компонентом в одном поде.
Требования
Перед началом установки убедитесь, что выполнены следующие условия:
- kubectl установлен и настроен для подключения к вашему кластеру MKaaS (см. «Подключиться к кластеру Managed Kubernetes»)
- Helm 3.x установлен
- У вашей учётной записи есть права на создание пространств имён (namespace), секретов (Secret) и развёртываний (Deployment) в кластере
- Кластер Managed Kubernetes создан и доступен
Подготовительные шаги
Шаг 1. Получите API-токен EdgeCenter
ExternalDNS использует EdgeCenter DNS API для управления записями. Для этого нужен постоянный API-токен.
- Войдите в личный кабинет EdgeCenter.
- Перейдите в раздел Профиль → API-токены.
- Создайте новый токен.
- Сохраните токен — он понадобится при установке.
Шаг 2. Убедитесь, что DNS сервис подключен и DNS-зона существует
ExternalDNS управляет только теми зонами, которые уже существуют в вашем аккаунте EdgeCenter DNS. Новые зоны он не создаёт.
- Перейдите в личный кабинет EdgeCenter → DNS.
- Подключите DNS сервис, если он еще не подключен.
- Убедитесь, что нужная зона (например, example.com) добавлена.
- Если зоны нет — создайте её через Личный кабинет, API или Terraform.
Установка
1. Namespace и секрет
kubectl create ns external-dns
kubectl create secret generic external-dns-webhook-secrets \
--namespace external-dns \
--from-literal=api-token=ВАШ_ТОКЕН2. Helm-репозиторий
helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/
helm repo update
3. Файл конфигурации
Создайте external-dns-ec-values.yaml. Замените cloud.example.com на вашу зону, my-cluster-id — на уникальный идентификатор кластера.
resources:
requests: { cpu: 50m, memory: 64Mi }
limits: { cpu: 200m, memory: 256Mi }
webhook:
enabled: true
securityContext:
runAsUser: 65532
runAsGroup: 65532
runAsNonRoot: true
provider:
name: webhook
webhook:
image:
repository: ghcr.io/edge-center/external-dns-ec-webhook
tag: v1.0.0
pullPolicy: IfNotPresent
env:
- name: EC_API_URL
value: "https://api.edgecenter.ru/dns"
- name: EC_API_TOKEN
valueFrom:
secretKeyRef:
name: external-dns-webhook-secrets
key: api-token
- name: EC_DRY_RUN
value: "false"
- name: EC_WEBHOOK_SERVER_ADDR
value: ":8080"
service:
port: 8080
extraArgs:
- "--webhook-provider-url=http://localhost:8080"
annotationFilter: "external-dns/edgecenter in (true)"
domainFilters:
- "cloud.example.com"
sources:
- service
- ingress
policy: sync
txtOwnerId: "my-cluster-id"
logLevel: info
interval: 30s
registry: txt
metrics:
enabled: true
Примечание: txtOwnerId должен быть уникальным для каждого кластера. Одинаковые значения приведут к конфликтам записей.
4. Установка
helm upgrade --install external-dns external-dns/external-dns \
--version 1.19.0 \
--namespace external-dns \
--create-namespace \
-f external-dns-ec-values.yaml
5. Проверка
kubectl -n external-dns get all
kubectl -n external-dns logs -l app.kubernetes.io/name=external-dns -c external-dns --tail=50
Под должен быть в статусе Running с двумя контейнерами.
Использование
Добавьте аннотации к сервису или ресурсу Ingress, чтобы ExternalDNS создал DNS-запись.
Как формируются записи
ExternalDNS берёт два элемента из манифестов Kubernetes.
Имя записи (hostname):
- Аннотация `external-dns.alpha.kubernetes.io/hostname` для Service (LoadBalancer).
- Поле `spec.rules[].host` для Ingress.
Целевой адрес (target):
- Поле `status.loadBalancer.ingress` — заполняется автоматически после назначения адреса облачным провайдером.
Тип записи:
- A-запись (если target — IP) или CNAME (если target — hostname).
Внутренний и внешний LoadBalancer
ExternalDNS не различает внутренний (internal) и внешний (external) LoadBalancer. Он использует данные, которые уже отражены в статусе Kubernetes. Для LoadBalancer-сервиса это обычно значения из `spec.externalIPs`, а если их нет, то из `status.loadBalancer.ingress[].ip` или `hostname`. Он одинаково читает поле `status.loadBalancer.ingress` в обоих случаях.
Тип балансировщика:
Внешний (по умолчанию): публичный IP (например, `185.12.34.56`). A-запись доступна из интернета. Основной сценарий.
Внутренний (internal): приватный IP (например, `10.0.1.15`). A-запись резолвится публично, но подключиться можно только из внутренней сети (VPC/VPN).
Service LoadBalancer
apiVersion: v1
kind: Service
metadata:
name: my-app
annotations:
external-dns/edgecenter: "true"
external-dns.alpha.kubernetes.io/hostname: my-app.cloud.example.com
spec:
type: LoadBalancer
selector: { app: my-app }
ports:
- port: 80
targetPort: 8080
Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
external-dns/edgecenter: "true"
spec:
ingressClassName: nginx
rules:
- host: my-app.cloud.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: { name: my-app, port: { number: 80 } }
Дополнительные аннотации
TTL записи: external-dns.alpha.kubernetes.io/ttl: "300"
Диагностика
Если записи не появляются, проверьте по порядку:
Аннотация external-dns/edgecenter: "true" присутствует.
Домен совпадает с domainFilters.
DNS-зона существует в аккаунте EdgeCenter.
Логи ExternalDNS:
kubectl -n external-dns logs -l app.kubernetes.io/name=external-dns -c external-dns --tail=100
Логи Webhook:
kubectl -n external-dns logs -l app.kubernetes.io/name=external-dns -c webhook --tail=50
Проверка DNS:
dig my-app.cloud.example.com
Удаление
helm delete -n external-dns external-dns
kubectl delete secret external-dns-webhook-secrets -n external-dns
kubectl delete ns external-dns
См. также
ExternalDNS: https://github.com/kubernetes-sigs/external-dns
EdgeCenter webhook: https://github.com/Edge-Center/external-dns-ec-webhook
EdgeCenter DNS API: https://api.edgecenter.ru/docs/dns