Aws-external-dns: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
| Строка 229: | Строка 229: | ||
... |
... |
||
</PRE> |
</PRE> |
||
| + | |||
| + | =Дополнительно проверить= |
||
| + | * Для домашней лабы - интеграцию с Mikrotk (Вроде бы заявлено) |
||
Версия 12:08, 9 июня 2025
Постановка задачи
Задача: есть некоторый базовый домен mydomain.tld, который лежит на серверах AWS в Route53
Требуется при разворачивании приложения в EKS автоматически создавать записи типа CNAME и
направлять их на балансировщик (Ingress или другой, в перспективе ALB но пока Ingress),
при запуске экземпляра приложения, например для
экземпляра staging создать записи
backend.staging.mydomain.tldfrontend.staging.mydomain.tldчто-то-еще.staging.mydomain.tld
Имя экземпляра приложения staging может быть произвольным
Обзор решения
- Создать роль которая разрешает модификацию DNS
- Создать политику Trust Policy — это специальный документ JSON, который определяет, кто имеет право "представлять" IAM роль, то есть использовать её права.
Она не определяет, что роль может делать. Она определяет, кто может её использовать. Например:
- EC2-инстанс
- Lambda-функция
- Конкретный экзкмпляр Kubernetes пода (через запуск пода от имени Service Account) через OIDC
- Роль привязывается к trust policy
- Создается сераисный аккаунт с аннотацией
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-sa
namespace: my-namespace
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/MyEksIamRole
Который будет обладать всеми правами прописанными в полиси
- Под этим аккаунтом запускается POD который следит за ДНС и вносит изменения при необходимости
IAM Policy
Для начала потребуется создать политику следующего вида:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ExternalDNSAccess",
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/Z1038XXXXXXXXXXXXXXX",
"arn:aws:route53:::hostedzone/Z0235XXXXXXXXXXXXXXX"
]
},
{
"Effect": "Allow",
"Action": "route53:ListHostedZones",
"Resource": "*"
}
]
}
В том пример присутствуют две записи:
"arn:aws:route53:::hostedzone/Z1038XXXXXXXXXXXXXXX", "arn:aws:route53:::hostedzone/Z0235XXXXXXXXXXXXXXX"
так как приложение использует более чем одну зону.
Для получения Id (Z1038XXXXXXXXXXXXXXX в примере) для домена mydomain.tld использовать комманду
aws route53 list-hosted-zones-by-name | jq '.HostedZones[] | select(.Name=="mydomain.tld") | .Id'
Создание IAM Role
Далее требуется создать роль (которая далее будет привязана к Service Account).
Пример роли (в web console я не нашл как вставить сразу json но результат можно посмотреть в таком виде и сравнить с желаемым):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::54XXXXXXXXXX:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/5918A6B3305CXXXXXXXXXXXXXXXXXXXX"
},
"Condition": {
"StringEquals": {
"oidc.eks.us-east-1.amazonaws.com/id/5918A6B3305CXXXXXXXXXXXXXXXXXXXX:sub": [
"system:serviceaccount:external-dns:external-dns"
],
"oidc.eks.us-east-1.amazonaws.com/id/5918A6B3305CXXXXXXXXXXXXXXXXXXXX:aud": [
"sts.amazonaws.com"
]
}
}
}
]
}
Значения
arn:aws:iam::54XXXXXXXXXXэто ID аккаунтаoidc.eks.us-east-1.amazonaws.com/id/5918A6B3305CXXXXXXXXXXXXXXXXXXXXкак правильно называется это значение,
я не знаю, но получить его можно следующей коммандой:
aws eks describe-cluster --name education-eks-1o3RFCvh --query "cluster.identity.oidc.issuer"
education-eks-1o3RFCvhэто имя кластера
Вывод команды будет примерно таким:
"https://oidc.eks.us-east-1.amazonaws.com/id/5918A6B3305CXXXXXXXXXXXXXXXXXXXX"
|
В интиерентаах пишут что нужно отдельно включать OIDC командой eksctl utils associate-iam-oidc-provider --region=us-east-2 --cluster=education-eks-1o3RFCvh --approve но возможно эта информация уже устарела или зависит от того как именно создавался кластер |
Привязка политики к роли
Я "накликал" это в Web Console :(
External DNS
ExternalDNS это код который работает внутри кластера k8s от имени сервисного аккаунта,
связанного с IAM ролью и за счет этого получает все права, которые есть у роли
Подготовительная работа
Добавить репозиторий
helm repo add bitnami https://charts.bitnami.com/bitnami
При желании для изучения можно скачать чарт:
helm pull bitnami/external-dns
Создать отдельный namespace (опционально - но лучше конечно создавать):
kubectl create namespace external-dns
Подготовить конфигурационный файл SERVICE-ACCOUNT-external-dns.yaml для сервисного аккаунта следующего содержания:
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
namespace: external-dns
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::54XXXXXXXXXX:role/ExternalDNSServiceAccountRole
В этом файле ключевой является аннотация:
arn:aws:iam::54XXXXXXXXXX:role/ExternalDNSServiceAccountRole- это ссылка на созданную IAM ROLE с правами работы с DNS
Создать Service Account
kubectl apply -f SERVICE-ACCOUNT-external-dns.yaml serviceaccount/external-dns created
|
ExternalDNS будет обрабатывать только те ресурсы, у которых аннотация |
Установка
Устанавлить External DNS с нужными параметрами
helm upgrade \
--install external-dns bitnami/external-dns \
--namespace external-dns \
--set serviceAccount.name=external-dns \
--set serviceAccount.create=false \
--set provider=aws \
--set sources={ingress} \
--set domainFilters[0]=mydomain.tld \
--set domainFilters[1]=myseconddomain.tld \
--set policy=upsert-only \
--set registry=txt \
--set txtOwnerId=external-dns \
--set logLevel=debug
serviceAccount.name=external-dns- использовать предсозданныйService AccountserviceAccount.create=false- не создаватьService Accountпри установке chartprovider=aws- очевидноsources={ingress}- смотреть на домены только наIngress(это массив, его элементы можно перечислить, я не уверен что это елинственно-возможный синтаксис)domainFilters[0]=mydomain.tld- оционально, разрешить работу только с 2 зонами (это тоже массив)domainFilters[1]=myseconddomain.tldpolicy=upsert-onlyнасколько я понимаю, эта опция означает "не удалять", другими словами при удаленииIngressзапись останется (вероятно это более безопасный вариант?)registry=txttxtOwnerId=external-dnslogLevel=debug(options: panic, debug, info, warning, error, fatal, trace)
|
Нигде в документации толком не сказано, что за опция |
Настройка Ingress
Настройка Ingress сводится к казанию правильной аннотации
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
...
external-dns.alpha.kubernetes.io/controller: dns-controller
...
Дополнительно проверить
- Для домашней лабы - интеграцию с Mikrotk (Вроде бы заявлено)