There's now a MetaKube Accelerator building block available for external DNS.
To eliminate the burden of having to manage your DNS zone manually, you may use external DNS with your MetaKube cluster and a compatible DNS provider (e.g. Amazon Route53, OpenStack Designate etc.). In this tutorial we will demo how to setup and use ExternalDNS with both Amazon Route53 and OpenStack Designate.
For other external DNS providers please check the official docs.
This example describes how to set up ExternalDNS for usage within a Kubernetes cluster using OpenStack Designate DNS.
Before setting up ExternalDNS you will need to set up API access to OpenStack and create a DNS Zone.
All domain names that ExternalDNS is going to create must belong to one of DNS zones created in advance. Here is an example of how to create example.com
DNS zone:
openstack zone create --email dns-admin@example.com example.com.
It is important to manually create all the zones that are going to be used for kubernetes entities (ExternalDNS sources) before starting ExternalDNS.
For more details on how to use Designate follow our documentation
To deploy ExternalDNS, copy the following text block into the file values.yaml
. We need this file to pass our DNS configuration to the helm chart. Please make sure to check all of the fields with the place holder "changeme". You will need to add your OpenStack credentials.
## Use Syseleven hosted image for designate to work properly until upstream PR for record update bug (https://github.com/kubernetes-incubator/external-dns/pull/1136)
## is merged.
image:
name: syseleven/external-dns
tag: v0.5.15-1-g810bbeaa
## This controls which types of resource external-dns should 'watch' for new
## DNS entries.
sources:
- service
- ingress
## The DNS provider where the DNS records will be created (options: aws, google, inmemory, azure, rfc2136 )
provider: designate
# OpenStack credentials are set through environment variables
extraEnv:
- name: OS_PROJECT_NAME
value: <changeme>
- name: OS_USER_DOMAIN_NAME
value: <changeme>
- name: OS_USERNAME
value: <changeme>
- name: OS_PASSWORD
value: <changeme>
- name: OS_AUTH_URL
value: <changeme>
- name: OS_REGION_NAME
value: <changeme>
## Limit possible target zones by domain suffixes (optional)
domainFilters: []
## Limit possible target zones by zone id (optional)
zoneIdFilters: []
# Filter sources managed by external-dns via annotation using label selector semantics (default: all sources)
annotationFilter: ""
## Adjust the interval for DNS updates
interval: "1m"
# Registry to use for ownership (txt or noop)
registry: "txt"
# When using the TXT registry, a name that identifies this instance of ExternalDNS
txtOwnerId: "changeme"
## Modify how DNS records are sychronized between sources and providers (options: sync, upsert-only )
policy: upsert-only
# Verbosity of the logs (options: panic, debug, info, warn, error, fatal)
logLevel: info
## CPU and Memory limit and request for external-dns
resources:
limits:
memory: 50Mi
requests:
memory: 50Mi
cpu: 10m
rbac:
create: true
Login to your AWS account and create a user named external-dns. You can find useful help on how to accomplish this here:
You can find additional information about attaching policies to IAM users here:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"*"
]
}
]
}
For manual deployment of ExternalDNS copy the following text block into the file values.yaml
. We need this file to pass our DNS configuration to the helm chart. Please make sure to check all of the fields with the place holder "changeme". You will need to add your access key and the secret key of the user you created earlier.
## External DNS
image:
name: registry.opensource.zalan.do/teapot/external-dns
tag: v0.5.14
## This controls which types of resource external-dns should 'watch' for new
## DNS entries.
sources:
- service
- ingress
## The DNS provider where the DNS records will be created (options: aws, google, inmemory, azure, rfc2136 )
provider: aws
# AWS Access keys to inject as environment variables
aws:
secretKey: "changeme"
accessKey: "changeme"
# pre external-dns 0.5.9 home dir should be `/root/.aws`
credentialsPath: "/.aws"
roleArn: ""
region: "eu-central-1"
# Filter for zones of this type (optional, options: public, private)
zoneType: "public"
## Limit possible target zones by domain suffixes (optional)
domainFilters: []
## Limit possible target zones by zone id (optional)
zoneIdFilters: []
# Filter sources managed by external-dns via annotation using label selector semantics (default: all sources)
annotationFilter: ""
## Adjust the interval for DNS updates
interval: "1m"
# Registry to use for ownership (txt or noop)
registry: "txt"
# When using the TXT registry, a name that identifies this instance of ExternalDNS
txtOwnerId: "changeme"
## Modify how DNS records are sychronized between sources and providers (options: sync, upsert-only )
policy: upsert-only
# Verbosity of the logs (options: panic, debug, info, warn, error, fatal)
logLevel: info
## CPU and Memory limit and request for external-dns
resources:
limits:
memory: 50Mi
requests:
memory: 50Mi
cpu: 10m
rbac:
create: true
Update your helm repositories
helm repo update
Install the external dns helm chart in the external-dns namespace
helm upgrade --install external-dns --namespace=external-dns -f values.yaml stable/external-dns
When the provider is successfully deployed, you can create a new LoadBalancer service the DNS entries will be created automatically for the domain configured with the external-dns.alpha.kubernetes.io/hostname
annotation.
$ cat <<EOF | kubectl apply --namespace=external-dns -f -
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: <loadbalancer.example.com>
spec:
type: LoadBalancer
ports:
- port: 80
name: http
targetPort: 80
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
EOF
When the loadbalancer was successfully created, you should be able to visit the domain <loadbalancer.example.com>
after a short time.
$ curl -I <loadbalancer.example.com>
HTTP/1 200
[...]
This also works seamlessly with Ingress resources. To test this
$ cat <<EOF | kubectl apply --namespace=external-dns -f -
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
spec:
ports:
- port: 80
name: http
targetPort: 80
selector:
app: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-dns
annotations:
spec:
ingressClassName: nginx
rules:
- host: <ingress.example.com>
http:
paths:
- backend:
service:
name: nginx-ingress
port:
number: 80
pathType: ImplementationSpecific
EOF`
and visit the page <ingress.example.com>
.
If you do not plan to continue using the external DNS provider, just delete the external-dns
namespace
$ kubectl delete namesapce external-dns
namespace "external-dns" deleted
If the policy
config option from the external-dns helm chart above is set to upsert-only
, you also need to delete the DNS entries <loadbalancer.example.com>
and <ingress.example.com>
from you hosted zone on Route53.