Updated: 2020-06-17
I’ll be using a helm chart to install external-dns on my Kubernetes GKE cluster.
Create zone
Create GCP service account
Create a GCP service account to enable an account to edit Cloud DNS.
export PROJECT_NAME=[YOUR_PROJECT_NAME]
# create service account
gcloud iam service-accounts create k8s-external-dns \
--display-name="Service Account to support ACME DNS-01 challenge." \
--project=$PROJECT_NAME
# create service account key
# this will also download the json key
gcloud iam service-accounts keys create ./credentials.json \
--iam-account=k8s-external-dns@$PROJECT_NAME.iam.gserviceaccount.com \
--project=$PROJECT_NAME
# give dns admin permissions
gcloud projects add-iam-policy-binding $PROJECT_NAME \
--member=serviceAccount:k8s-external-dns@$PROJECT_NAME.iam.gserviceaccount.com \
--role=roles/dns.admin
Create secret from GCP service account
kubectl create secret generic external-dns \
--from-file=./credentials.json \
--namespace=itsmetommy
Add repo
helm repo add bitnami https://charts.bitnami.com/bitnami
Update repo
helm repo update
Create namespace
kubectl create ns external-dns
Install
- domainFilters – used for limiting the domains that ExternalDNS can manage
- registry=txt – TXT Registry Identifier
- txtOwnerId=k8s – Prefix to create a TXT record with a name following the pattern prefix.<CNAME record>
- sources – K8s resources type to be observed for new DNS entries by ExternalDNS (I added istio-gateway)
IMPORTANT: Make sure that the txtOwnerId is unique when managing the same zone, otherwise DNS records will be deleted and re-added constantly. Basically external-dns will be syncing from multiple locations.
helm install external-dns \
--set provider=google \
--set google.serviceAccountSecret=external-dns \
--set policy=sync \
--set registry=txt \
--set txtOwnerId=k8s-itsmetommy \
--set rbac.create=true \
--set domainFilters={your-doamin.com} \
--set sources="{ingress,istio-gateway,service}" \
-n external-dns \
bitnami/external-dns
Ingress
Single domain.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: your-domain.com
Multiple domains.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: foo.your-domain.com,bar.your-domain.com
Service
kubectl annotate service nginx "external-dns.alpha.kubernetes.io/hostname=tommy.itsmetommy.io."
OR
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: your-domain.com.
Logs
kubectl logs -f `kubectl get pods -n external-dns -o jsonpath="{.items[0].metadata.name}"` -n external-dns
Uninstall
helm delete external-dns -n external-dns
Errors
Error 1
kubectl logs external-dns-d46d86697-4nxlw
time="2019-06-12T04:51:45Z" level=fatal msg="google: error getting credentials using GOOGLE_APPLICATION_CREDENTIALS environment variable: open /etc/secrets/service-account/credentials.json: no such file or directory"
Fix.
Make sure your key name is credentials.json.
kubectl create secret generic external-dns \
--from-file=./credentials.json \
--namespace=external-dns
Or edit the existing secret directly.
kubectl edit secret generic external-dns -n external-dns
Error 2
helm install external-dns \
--set provider=google \
--set google.serviceAccountSecret=external-dns \
--set policy=sync \
--set registry=txt \
--set txtOwnerId=k8s \
--set rbac.create=true \
--set domainFilters=your-domain.com \
--set sources="{ingress,istio-gateway,service}" \
-n external-dns \
bitnami/external-dns
Error: render error in "external-dns/templates/deployment.yaml": template: external-dns/templates/deployment.yaml:35:27: executing "external-dns/templates/deployment.yaml" at <.Values.domainFilters>: range can't iterate over your-domain.com
Fix.
Use brackets { }.
--set domainFilters={your-domain.com} \