Aws-external-dns

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску

Постановка задачи

Задача: есть некоторый базовый домен mydomain.tld, который лежит на серверах AWS в Route53
Требуется при разворачивании приложения в EKS автоматически создавать записи типа CNAME и
направлять их на балансировщик (Ingress или другой, но пока Ingress), при запуске экземпляра приложения, например для
экземпляра staging создать записи

  • backend.staging.mydomain.tld
  • frontend.staging.mydomain.tld
  • что-то-еще.staging.mydomain.tld

Имя экземпляра приложения staging может быть произвольным

Решение

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"

Icon-caution.gif

В интиерентаах пишут что нужно отдельно включать OIDC командой

eksctl utils associate-iam-oidc-provider --region=us-east-2 --cluster=education-eks-1o3RFCvh --approve

но возможно эта информация уже устарела или зависит от того как именно создавался кластер

External DNS

External DNS это код который работает внутри кластера 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




external-dns будет обрабатывать только те ресурсы, у которых аннотация external-dns.alpha.kubernetes.io/controller совпадает с указанной в параметре --controller. Остальные Ingress, даже с нужными доменами, игнорируются.

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