¿Cómo configuro ExternalDNS con Amazon EKS?

Última actualización: 01-03-2022

Quiero configurar ExternalDNS con mi Amazon Elastic Kubernetes Service (Amazon EKS).

Descripción breve

ExternalDNS es un pod que se ejecuta en el clúster de Amazon EKS. Para utilizar ExternalDNS como complemento con su Amazon EKS, debe configurar los permisos de AWS Identity and Access Management (IAM) para permitir que Amazon EKS acceda a Amazon Route 53.

Nota: Asegúrese de que existan un nombre de dominio y una zona alojada de Route 53.

Resolución

Configure los permisos de IAM e implemente ExternalDNS

1.    Configure los permisos de IAM para otorgar al pod ExternalDNS permisos para crear, actualizar y eliminar registros de Route 53 en su cuenta de AWS.

Política de IAM:

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

Nota: También puede ajustar la política anterior para permitir las actualizaciones de los ID de zona alojada explícitos.

2.    Cree un rol de IAM para la cuenta de servicio mediante la política anterior:

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

Nota: Reemplace SERVICE_ACCOUNT_NAME por el nombre de su cuenta de servicio, NAMESPACE por su espacio de nombres, CLUSTER_NAME por el nombre de su clúster e IAM_POLICY_ARN por el ARN de su política de IAM.

Para comprobar el nombre de su cuenta de servicio, ejecute el siguiente comando:

kubectl get sa

Resultado de ejemplo:

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

En el resultado del ejemplo anterior, external-dns es el nombre que se le dio a la cuenta de servicio cuando se creó.

3.    Implemente ExternalDNS.

Compruebe si el control de acceso basado en roles (RBAC) está habilitado en su clúster de Amazon EKS:

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

Nota: Antes de aplicar los siguientes manifiestos, busque la última versión de ExternalDNS (desde el sitio web de GitHub).

Ejecute el siguiente comando:

kubectl apply DEPLOYMENT_MANIFEST_FILE_NAME.yaml

Nota: Reemplace DEPLOYMENT_MANIFEST_FILE_NAME por el nombre del archivo de manifiesto de implementación.

Si el RBAC está habilitado, utilice el siguiente manifiesto para implementar 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

Si el RBAC no está habilitado, utilice el siguiente manifiesto para implementar 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.    Compruebe que la implementación se haya realizado correctamente:

kubectl get deployments

Resultado de ejemplo:

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

También puede revisar los registros para comprobar que estén actualizados:

kubectl logs external-dns-9f85d8d5b-sx5fg

Resultado de ejemplo:

....
....
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"
....
....

Compruebe que ExternalDNS esté funcionando

1.    Cree un servicio que se exponga como LoadBalancer y que se pueda dirigir externamente a través del nombre de dominio que se aloja en Route 53:

kubectl apply SERVICE_MANIFEST_FILE_NAME.yaml

Nota: Reemplace SERVICE_MANIFEST_FILE_NAME por el nombre del archivo de manifiesto de servicio.

Manifiesto:

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

Nota: Reemplace DOMAIN_NAME por el nombre de su dominio.

2.    Compruebe que el servicio NGINX se haya creado con el tipo LoadBalancer:

kubectl get svc

Resultado de ejemplo:

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

Nota: El servicio crea automáticamente un registro de Route 53 para la zona alojada.

Revise los registros para comprobar que se haya creado el registro de Route 53:

kubectl logs external-dns-9f85d8d5b-sx5fg

Resultado de ejemplo:

...
...
...
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 obtener más información sobre cómo configurar y verificar ExternalDNS, consulte Configurar ExternalDNS para los servicios en AWS (en el sitio web de GitHub).


¿Le resultó útil este artículo?


¿Necesita asistencia técnica o con la facturación?