Como faço para configurar o ExternalDNS com o Amazon EKS?

6 minuto de leitura
0

Quero configurar o ExternalDNS com o Amazon Elastic Kubernetes Service (Amazon EKS).

Breve descrição

O ExternalDNS é um pod executado no cluster do Amazon EKS. Para usar o ExternalDNS como um plug-in com o Amazon EKS, configure as permissões do AWS Identity and Access Management (IAM). Essas permissões devem permitir que o Amazon EKS acesse o Amazon Route 53.

Observação: antes de iniciar a resolução a seguir, certifique-se de que existam um nome de domínio e uma zona hospedada do Route 53.

Resolução

Configurar as permissões do IAM e implantar o ExternalDNS

1.    Configure as permissões do IAM para conceder ao pod ExternalDNS permissões para criar, atualizar e excluir registros do Route 53 em sua conta da AWS.

Política do IAM:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "route53:ChangeResourceRecordSets"
      ],
      "Resource": [
        "arn:aws:route53:::hostedzone/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "route53:ListHostedZones",
        "route53:ListResourceRecordSets"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

Observação: também é possível ajustar a política anterior para permitir atualizações em IDs explícitos de zona hospedada.

2.    Use a política anterior para criar uma função do IAM para a conta de serviço:

eksctl create iamserviceaccount --name SERVICE_ACCOUNT_NAME --namespace NAMESPACE --cluster CLUSTER_NAME --attach-policy-arn IAM_POLICY_ARN --approve

Observação: substitua SERVICE_ACCOUNT_NAME pelo nome da conta de serviço, NAMESPACE pelo namespace, CLUSTER_NAME pelo nome do cluster e IAM_POLICY_ARN pelo ARN da política do IAM.

Para verificar o nome da conta de serviço, execute o seguinte comando:

kubectl get sa

Exemplo de saída:

NAME           SECRETS   AGE
default        1         23h
external-dns   1         23h

No exemplo de saída anterior, external-dns é o nome que foi dado à conta de serviço quando ela foi criada.

3.    Implante o ExternalDNS.

Verifique se o RBAC está ativado em seu cluster Amazon EKS:

kubectl api-versions | grep rbac.authorization.k8s.io

Observação: antes de aplicar os seguintes manifestos, verifique a versão mais recente do ExternalDNS (no site do GitHub).

Execute o seguinte comando:

kubectl apply DEPLOYMENT_MANIFEST_FILE_NAME.yaml

Observação: substitua DEPLOYMENT_MANIFEST_FILE_NAME pelo nome do arquivo do manifesto de implantação.

Se o RBAC estiver ativado, use o seguinte manifesto para implantar o ExternalDNS:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: external-dns
rules:
- apiGroups: [""]
  resources: ["services","endpoints","pods"]
  verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: external-dns-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
- kind: ServiceAccount
  name: external-dns
  namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-dns
  template:
    metadata:
      labels:
        app: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: k8s.gcr.io/external-dns/external-dns:v0.10.2
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=external-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
        - --provider=aws
        - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
        - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
        - --registry=txt
        - --txt-owner-id=my-hostedzone-identifier
      securityContext:
        fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files

Se o RBAC não estiver ativado, use o seguinte manifesto para implantar o ExternalDNS:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-dns
  template:
    metadata:
      labels:
        app: external-dns
    spec:
      containers:
      - name: external-dns
        image: k8s.gcr.io/external-dns/external-dns:v0.10.2
        args:
        - --source=service
        - --source=ingress
        - --domain-filter= <Your_R53_Domain_Name>  # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
        - --provider=aws
        - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
        - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
        - --registry=txt
        - --txt-owner-id=<Your_R53_HostedZone_Id>

4.    Confirme se a implantação foi bem-sucedida:

kubectl get deployments

Exemplo de saída:

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
external-dns   1/1     1            1           85m

Também é possível verificar os logs para confirmar se os registros estão atualizados:

kubectl logs external-dns-9f85d8d5b-sx5fg

Exemplo de saída:

....
....
time="2022-02-10T20:22:02Z" level=info msg="Instantiating new Kubernetes client"
time="2022-02-10T20:22:02Z" level=info msg="Using inCluster-config based on serviceaccount-token"
time="2022-02-10T20:22:02Z" level=info msg="Created Kubernetes client https://10.100.0.1:443"
time="2022-02-10T20:22:09Z" level=info msg="Applying provider record filter for domains: [<yourdomainname>.com. .<yourdomainname>.com.]"
time="2022-02-10T20:22:09Z" level=info msg="All records are already up to date"
....
....

Confirmar se o ExternalDNS está funcionando

1.    Crie um serviço exposto como LoadBalancer e que possa ser encaminhado externamente por meio do nome de domínio hospedado no Route 53:

kubectl apply SERVICE_MANIFEST_FILE_NAME.yaml

Observação: substitua SERVICE_MANIFEST_FILE_NAME pelo nome do arquivo do manifesto de serviço.

Manifesto:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  annotations:
    external-dns.alpha.kubernetes.io/hostname: DOMAIN_NAME
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: LoadBalancer
  selector:
    app: nginx

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx
          name: nginx
          ports:
            - containerPort: 80
              name: http

Observação: substitua DOMAIN_NAME pelo nome do domínio.

2.    Verifique se o serviço NGINX foi criado com o tipo LoadBalancer:

kubectl get svc

Exemplo de saída:

NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                              PORT(S)        AGE
kubernetes   ClusterIP      10.100.0.1      <none>                                                                   443/TCP        26h
nginx        LoadBalancer   10.100.234.77   a1ef09255d52049f487e05b4f74faea6-954147917.us-west-1.elb.amazonaws.com   80:30792/TCP   74m

Observação: o serviço cria automaticamente um registro do Route 53 para a zona hospedada.

Verifique os logs para confirmar se o registro do Route 53 foi criado:

kubectl logs external-dns-9f85d8d5b-sx5fg

Exemplo de saída:

...
...
...
time="2022-02-10T21:22:43Z" level=info msg="Applying provider record filter for domains: [<domainname>.com. .<domainname>.com.]"
time="2022-02-10T21:22:43Z" level=info msg="Desired change: CREATE <domainname>.com A [Id: /hostedzone/Z01155763Q6AN7CEI3AP6]"
time="2022-02-10T21:22:43Z" level=info msg="Desired change: CREATE <domainname>.com TXT [Id: /hostedzone/Z01155763Q6AN7CEI3AP6]"
time="2022-02-10T21:22:43Z" level=info msg="2 record(s) in zone xxx.com. [Id: /hostedzone/Z01155763Q6AN7CEI3AP6] were successfully updated"
time="2022-02-10T21:23:43Z" level=info msg="Applying provider record filter for domains: [<domainname>.com. .<domainname>.com.]"
time="2022-02-10T21:23:43Z" level=info msg="All records are already up to date"
...
...
...

Para obter mais informações e exemplos de ExternalDNS, consulte Configurar o ExternalDNS para serviços na AWS (no site do GitHub) e Configurar o ExternalDNS (no site do Kubernetes).


AWS OFICIAL
AWS OFICIALAtualizada há um ano