Categories
Kubernetes

Kubernetes: Automated DNS with External-DNS on GKE

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

Install

  • policy: upsert-only or sync
  • The domainFilters parameter is used for limiting the domains that ExternalDNS can manage.
helm install \
  --namespace itsmetommy \
  --name external-dns \
  --set provider=google \
  --set google.project=$PROJECT_NAME \
  --set google.serviceAccountSecret=external-dns \
  --set policy=sync \
  --set registry=txt \
  --set txtOwnerId=k8s \
  --set domainFilters={itsmetommy.io} \
  --set rbac.create=true \
  stable/external-dns

Ingress

Single domain.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    external-dns.alpha.kubernetes.io/hostname: tommy.itsmetommy.io

Multiple domains.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    external-dns.alpha.kubernetes.io/hostname: tommy1.itsmetommy.io,tommy2.itsmetommy.io

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: tommy.itsmetommy.io.

Logs

kubectl logs `kubectl get pods | grep external-dns | awk '{print $1}'`

Uninstall

helm delete external-dns; helm del --purge 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=itsmetommy

Or edit the existing secret directly.

kubectl edit secret generic external-dns

Error 2

helm install \
  --namespace itsmetommy \
  --name external-dns \
  --set provider=google \
  --set google.project=$PROJECT_NAME \
  --set google.serviceAccountSecret=external-dns \
  --set policy=upsert-only \
  --set registry=txt \
  --set txtOwnerId=k8s \
  --set domainFilters=itsmetommy.io \
  --set rbac.create=true \
  stable/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 itsmetommy.io

Fix.

Use brackets { }.

  --set domainFilters={itsmetommy.io} \