external-dns/docs/tutorials/rfc2136.md

302 lines
8.7 KiB
Markdown

# Configuring RFC2136 provider
This tutorial describes how to use the RFC2136 with either BIND or Windows DNS.
## Using with BIND
To use external-dns with BIND: generate/procure a key, configure DNS and add a
deployment of external-dns.
### Server credentials:
- RFC2136 was developed for and tested with
[BIND](https://www.isc.org/downloads/bind/) DNS server. This documentation
assumes that you already have a configured and working server. If you don't,
please check BIND documents or tutorials.
- If your DNS is provided for you, ask for a TSIG key authorized to update and
transfer the zone you wish to update. The key will look something like below.
Skip the next steps wrt BIND setup.
```text
key "externaldns-key" {
algorithm hmac-sha256;
secret "96Ah/a2g0/nLeFGK+d/0tzQcccf9hCEIy34PoXX2Qg8=";
};
```
- If you are your own DNS administrator create a TSIG key. Use
`tsig-keygen -a hmac-sha256 externaldns` or on older distributions
`dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST externaldns`. You will end up with
a key printed to standard out like above (or in the case of dnssec-keygen in a
file called `Kexternaldns......key`).
### BIND Configuration:
If you do not administer your own DNS, skip to RFC provider configuration
- Edit your named.conf file (or appropriate included file) and add/change the
following.
- Make sure You are listening on the right interfaces. At least whatever
interface external-dns will be communicating over and the interface that
faces the internet.
- Add the key that you generated/was given to you above. Copy paste the four
lines that you got (not the same as the example key) into your file.
- Create a zone for kubernetes. If you already have a zone, skip to the next
step. (I put the zone in it's own subdirectory because named,
which shouldn't be running as root, needs to create a journal file and the
default zone directory isn't writeable by named).
```text
zone "k8s.example.org" {
type master;
file "/etc/bind/pri/k8s/k8s.zone";
};
```
- Add your key to both transfer and update. For instance with our previous
zone.
```text
zone "k8s.example.org" {
type master;
file "/etc/bind/pri/k8s/k8s.zone";
allow-transfer {
key "externaldns-key";
};
update-policy {
grant externaldns-key zonesub ANY;
};
};
```
- Create a zone file (k8s.zone):
```text
$TTL 60 ; 1 minute
k8s.example.org IN SOA k8s.example.org. root.k8s.example.org. (
16 ; serial
60 ; refresh (1 minute)
60 ; retry (1 minute)
60 ; expire (1 minute)
60 ; minimum (1 minute)
)
NS ns.k8s.example.org.
ns A 123.456.789.012
```
- Reload (or restart) named
### Using external-dns
To use external-dns add an ingress or a LoadBalancer service with a host that
is part of the domain-filter. For example both of the following would produce
A records.
```text
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: svc.example.org
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: nginx
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: ingress.example.org
http:
paths:
- path: /
backend:
serviceName: my-service
servicePort: 8000
```
### Custom TTL
The default DNS record TTL (Time-To-Live) is 0 seconds. You can customize this value by setting the annotation `external-dns.alpha.kubernetes.io/ttl`. e.g., modify the service manifest YAML file above:
```
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: nginx.external-dns-test.my-org.com
external-dns.alpha.kubernetes.io/ttl: 60
spec:
...
```
This will set the DNS record's TTL to 60 seconds.
A default TTL for all records can be set using the the flag with a time in seconds, minutes or hours, such as `--rfc2136-min-ttl=60s`
There are other annotation that can affect the generation of DNS records, but these are beyond the scope of this
tutorial and are covered in the main documentation.
### Test with external-dns installed on local machine (optional)
You may install external-dns and test on a local machine by running:
```external-dns --txt-owner-id k8s --provider rfc2136 --rfc2136-host=192.168.0.1 --rfc2136-port=53 --rfc2136-zone=k8s.example.org --rfc2136-tsig-secret=96Ah/a2g0/nLeFGK+d/0tzQcccf9hCEIy34PoXX2Qg8= --rfc2136-tsig-secret-alg=hmac-sha256 --rfc2136-tsig-keyname=externaldns-key --rfc2136-tsig-axfr --source ingress --once --domain-filter=k8s.example.org --dry-run```
- host should be the IP of your master DNS server.
- tsig-secret should be changed to match your secret.
- tsig-keyname needs to match the keyname you used (if you changed it).
- domain-filter can be used as shown to filter the domains you wish to update.
### RFC2136 provider configuration:
In order to use external-dns with your cluster you need to add a deployment
with access to your ingress and service resources. The following are two
example manifests with and without RBAC respectively.
- With RBAC:
```text
apiVersion: v1
kind: Namespace
metadata:
name: external-dns
labels:
name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: external-dns
namespace: external-dns
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- pods
- nodes
verbs:
- get
- watch
- list
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
namespace: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
namespace: external-dns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: external-dns
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: external-dns
spec:
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.7.3
args:
- --txt-owner-id=k8s
- --provider=rfc2136
- --rfc2136-host=192.168.0.1
- --rfc2136-port=53
- --rfc2136-zone=k8s.example.org
- --rfc2136-tsig-secret=96Ah/a2g0/nLeFGK+d/0tzQcccf9hCEIy34PoXX2Qg8=
- --rfc2136-tsig-secret-alg=hmac-sha256
- --rfc2136-tsig-keyname=externaldns-key
- --rfc2136-tsig-axfr
- --source=ingress
- --domain-filter=k8s.example.org
```
- Without RBAC:
```text
apiVersion: v1
kind: Namespace
metadata:
name: external-dns
labels:
name: external-dns
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: external-dns
spec:
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.7.3
args:
- --txt-owner-id=k8s
- --provider=rfc2136
- --rfc2136-host=192.168.0.1
- --rfc2136-port=53
- --rfc2136-zone=k8s.example.org
- --rfc2136-tsig-secret=96Ah/a2g0/nLeFGK+d/0tzQcccf9hCEIy34PoXX2Qg8=
- --rfc2136-tsig-secret-alg=hmac-sha256
- --rfc2136-tsig-keyname=externaldns-key
- --rfc2136-tsig-axfr
- --source=ingress
- --domain-filter=k8s.example.org
```
## Microsoft DNS
While `external-dns` was not developed or tested against Microsoft DNS, it can be configured to work against it. YMMV.
### DNS-side configuration
1. Create a DNS zone
2. Enable insecure dynamic updates for the zone
3. Enable Zone Transfers from all servers
### `external-dns` configuration
You'll want to configure `external-dns` similarly to the following:
```text
...
- --provider=rfc2136
- --rfc2136-host=192.168.0.1
- --rfc2136-port=53
- --rfc2136-zone=k8s.example.org
- --rfc2136-insecure
- --rfc2136-tsig-axfr # needed to enable zone transfers, which is required for deletion of records.
...
```
Since Microsoft DNS does not support secure updates via TSIG, this will let `external-dns` make insecure updates. Do this at your own risk.