¿Cómo configuro ExternalDNS con Amazon EKS?
Última actualización: 01/02/2023
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 usar ExternalDNS como complemento con Amazon EKS, configure los permisos de AWS Identity and Access Management (IAM). Estos permisos deben permitir el acceso de Amazon EKS a Amazon Route 53.
Nota: Antes de iniciar la siguiente resolución, asegúrese de que exista 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. Utilice la política anterior para crear un rol de IAM para la cuenta de servicio:
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á activado 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á activado, 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á activado, 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 y ejemplos de ExternalDNS, consulte Configuración de ExternalDNS para servicios en AWS (en el sitio web de GitHub) y Configuración de ExternalDNS (en el sitio web de Kubernetes).
¿Le resultó útil este artículo?
¿Necesita asistencia técnica o con la facturación?