Skip to content

Commit 302b23d

Browse files
committed
Add support for dynamic DNS updates
Passing the update key to `dns_update_key` will cause each node (including the dedicated loadbalancer if used) to register with the specified DNS servers.
1 parent fb981f5 commit 302b23d

11 files changed

Lines changed: 263 additions & 8 deletions

README.adoc

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ connected by a private _software defined network_ (SDN) which can be
2525
implemented either with http://openvswitch.org/[OpenVSwitch] or https://github.com/coreos/flannel[Flannel].
2626

2727
A _bastion server_ is used to control the host and service
28-
configuration. It can also run local DNS services as
29-
needed. The host and service configuration is run using
30-
https://www.ansible.com/[Ansible] playbooks executed from the bastion host.
28+
configuration. The host and service configuration is run using
29+
https://www.ansible.com/[Ansible] playbooks executed from the bastion
30+
host.
3131

3232
_Bastion server_, _master nodes_ and _infra nodes_ is also given a _floating IP_
3333
address on the public network. This provides direct access to the
@@ -68,6 +68,28 @@ inter-node communication).
6868

6969
CentOS and RHEL are the only tested distros for now.
7070

71+
=== DNS Server
72+
73+
The OpenShift installer requires that all nodes be reachable via their
74+
hostnames. Since OpenStack does not currently provide an internal name
75+
resolution, this needs to be done with an external DNS service that
76+
all nodes use via the `dns_nameserver` parameter.
77+
78+
In a production deployment this would be your existing DNS, but if you
79+
don't have the ability to update it to add new name records, you will
80+
have to deploy one yourself.
81+
82+
We have provided a separate repository that can deploy a DNS server
83+
suitable for OpenShift:
84+
85+
https://github.com/openshift/openshift-ansible-contrib/tree/master/reference-architecture/osp-dns
86+
87+
NOTE: If your DNS supports dynamic updates via RFC 2136, you can pass
88+
the update key to the Heat stack and all nodes will register
89+
themselves as they come up. Otherwise, you will have to update your
90+
DNS records manually.
91+
92+
7193
=== Red Hat Software Repositories
7294

7395
When installing OpenShift Container Platform on RHEL the OpenShift and
@@ -480,6 +502,17 @@ The above DNS records should be set on the DNS server authoritative for the
480502
domain used in OpenShift cluster (`example.com` in the example above).
481503
====
482504

505+
506+
=== Dynamic DNS Updates
507+
508+
If your DNS servers support dynamic updates (as defined in RFC 2136),
509+
you can pass the update key in the `dns_update_key` parameter and each
510+
node will register its internal IP address to all the DNS servers in
511+
the `dns_nameserver` list.
512+
513+
You will still need to set the API and wildcard entries, though.
514+
515+
483516
== Retrieving the CA certificate
484517

485518
You can retrieve the CA certificate that was generated during the OpenShift

fragments/add_dns_record.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
# Update the DNS server with a record for this host
3+
4+
set -eu
5+
set -x
6+
set -o pipefail
7+
8+
DNS_UPDATE_KEY="%DNS_UPDATE_KEY%"
9+
10+
if [ -z "$DNS_UPDATE_KEY" ]; then
11+
echo "Skipping the DNS update because the key is empty."
12+
exit
13+
fi
14+
15+
if yum info python-dns; then
16+
retry yum -y install python-dns
17+
else
18+
retry yum -y install python2-dns
19+
fi
20+
21+
HOSTNAME="$(hostname --fqdn)"
22+
23+
for DNS_SERVER in "%DNS_SERVERS%"; do
24+
# NOTE: the dot after the hostname is necessary
25+
/usr/local/bin/update_dns -s "$DNS_SERVER" -k "$DNS_UPDATE_KEY" "$HOSTNAME." "%IP_ADDRESS%"
26+
done

fragments/update_dns.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python
2+
#
3+
# Add an A record to a DNS server via RFC 2136 dynamic update
4+
#
5+
6+
from __future__ import print_function
7+
8+
import os,sys
9+
from argparse import ArgumentParser
10+
11+
# python2-dns
12+
import dns.query
13+
import dns.tsigkeyring
14+
import dns.update
15+
import dns.rcode
16+
17+
18+
def add_a_record(server, zone, key, name, address, ttl=300):
19+
20+
# make input zones absolute
21+
#zone = zone + '.' if not zone.endswith('.')
22+
keyring = dns.tsigkeyring.from_text({'update-key': key})
23+
update = dns.update.Update(zone, keyring=keyring)
24+
update.replace(name, ttl, 'a', address)
25+
response = dns.query.tcp(update, server)
26+
return response
27+
28+
29+
if __name__ == "__main__":
30+
31+
def process_arguments():
32+
parser = ArgumentParser()
33+
parser.add_argument("-s", "--server", type=str, default="127.0.0.1")
34+
parser.add_argument("-z", "--zone", type=str, default="example.com")
35+
parser.add_argument("-k", "--key", type=str, default=os.getenv("DNS_KEY"))
36+
parser.add_argument("name", type=str)
37+
parser.add_argument("address", type=str)
38+
parser.add_argument("-t", "--ttl", type=str, default=300)
39+
return parser.parse_args()
40+
41+
opts = process_arguments()
42+
r = add_a_record(opts.server, opts.zone, opts.key, opts.name, opts.address, opts.ttl)
43+
44+
if r.rcode() != dns.rcode.NOERROR:
45+
print("ERROR: update failed: {}".format(dns.rcode.to_text(r.rcode())))
46+
sys.exit(r.rcode())
47+

infra.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ parameters:
220220
description: List of docker repository URLs which will be installed on each node, if a repo is insecure use '#insecure' suffix.
221221
default: ''
222222

223+
dns_servers:
224+
type: comma_delimited_list
225+
description: address of dns nameservers reachable in your environment
226+
227+
dns_update_key:
228+
type: string
229+
hidden: true
230+
223231
resources:
224232

225233
# Create a network connection on the internal communications network
@@ -295,6 +303,7 @@ resources:
295303
- config: {get_resource: set_extra_repos}
296304
- config: {get_resource: set_extra_docker_repos}
297305
- config: {get_resource: host_update}
306+
- config: {get_resource: add_dns_record}
298307
- config: {get_resource: infra_boot}
299308

300309
# Compose the short hostname and fully qualified domain name for the new host
@@ -329,6 +338,9 @@ resources:
329338
- path: /usr/local/bin/retry
330339
permissions: 0755
331340
content: {get_file: fragments/retry.sh}
341+
- path: /usr/local/bin/update_dns
342+
permissions: 0755
343+
content: {get_file: fragments/update_dns.py}
332344
- path: /etc/sysconfig/network-scripts/ifcfg-eth1
333345
content:
334346
str_replace:
@@ -393,6 +405,17 @@ resources:
393405
$SYSTEM_UPDATE: {get_param: system_update}
394406
template: {get_file: fragments/host-update.sh}
395407

408+
add_dns_record:
409+
type: OS::Heat::SoftwareConfig
410+
properties:
411+
config:
412+
str_replace:
413+
params:
414+
'%DNS_SERVERS%': {list_join: [" ", {get_param: dns_servers}]}
415+
'%DNS_UPDATE_KEY%': {get_param: dns_update_key}
416+
'%IP_ADDRESS%': {get_attr: [port, fixed_ips, 0, ip_address]}
417+
template: {get_file: fragments/add_dns_record.sh}
418+
396419
# Prepare the host to run Docker and Ansible for OpenShift install and config
397420
infra_boot:
398421
type: OS::Heat::SoftwareConfig

loadbalancer_dedicated.yaml

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ parameters:
114114
floatingip_id:
115115
type: string
116116

117+
floatingip:
118+
type: string
119+
117120
fixed_network:
118121
description: >
119122
The name or ID of the internal network
@@ -158,6 +161,14 @@ parameters:
158161
description: Top level stack name.
159162
type: string
160163

164+
dns_servers:
165+
type: comma_delimited_list
166+
description: address of dns nameservers reachable in your environment
167+
168+
dns_update_key:
169+
type: string
170+
hidden: true
171+
161172
resources:
162173
floating_ip_assoc:
163174
type: OS::Neutron::FloatingIPAssociation
@@ -226,6 +237,7 @@ resources:
226237
- config: {get_resource: set_extra_repos}
227238
- config: {get_resource: set_extra_docker_repos}
228239
- config: {get_resource: host_update}
240+
- config: {get_resource: add_dns_record}
229241
- config: {get_resource: lb_boot}
230242

231243
# Compose the FQDN and set the hostname in the cloud-init data structure
@@ -256,6 +268,9 @@ resources:
256268
- path: /usr/bin/retry
257269
permissions: 0755
258270
content: {get_file: fragments/retry.sh}
271+
- path: /usr/local/bin/update_dns
272+
permissions: 0755
273+
content: {get_file: fragments/update_dns.py}
259274
- path: /usr/local/share/openshift-on-openstack/common_functions.sh
260275
permissions: 0755
261276
content:
@@ -318,13 +333,25 @@ resources:
318333
config:
319334
get_file: fragments/host-update.sh
320335

336+
add_dns_record:
337+
type: OS::Heat::SoftwareConfig
338+
properties:
339+
config:
340+
str_replace:
341+
params:
342+
'%DNS_SERVERS%': {list_join: [" ", {get_param: dns_servers}]}
343+
'%DNS_UPDATE_KEY%': {get_param: dns_update_key}
344+
'%IP_ADDRESS%': {get_param: floatingip}
345+
template: {get_file: fragments/add_dns_record.sh}
346+
347+
321348
# Prepare the host for SSH access for ansible
322349
lb_boot:
323350
type: OS::Heat::SoftwareConfig
324351
properties:
325352
config:
326353
str_replace:
327-
params:
354+
params: {}
328355
template: {get_file: fragments/lb-boot.sh}
329356

330357
node_cleanup:

loadbalancer_external.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ parameters:
116116
floatingip_id:
117117
type: string
118118

119+
floatingip:
120+
type: string
121+
119122
fixed_network:
120123
description: >
121124
The name or ID of the internal network
@@ -156,6 +159,14 @@ parameters:
156159
The name or ID of the bastion instance.
157160
default: ''
158161

162+
dns_servers:
163+
type: comma_delimited_list
164+
description: address of dns nameservers reachable in your environment
165+
166+
dns_update_key:
167+
type: string
168+
hidden: true
169+
159170
outputs:
160171
console_url:
161172
description: URL of the OpenShift web console

loadbalancer_neutron.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ parameters:
115115
floatingip_id:
116116
type: string
117117

118+
floatingip:
119+
type: string
120+
118121
fixed_network:
119122
description: >
120123
The name or ID of the internal network
@@ -149,6 +152,14 @@ parameters:
149152
The name or ID of the bastion instance.
150153
default: ''
151154

155+
dns_servers:
156+
type: comma_delimited_list
157+
description: address of dns nameservers reachable in your environment
158+
159+
dns_update_key:
160+
type: string
161+
hidden: true
162+
152163
resources:
153164
lb:
154165
type: OS::Neutron::LoadBalancer

loadbalancer_none.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ parameters:
112112
floatingip_id:
113113
type: string
114114

115+
floatingip:
116+
type: string
117+
115118
fixed_network:
116119
description: >
117120
The name or ID of the internal network
@@ -160,6 +163,14 @@ parameters:
160163
The name or ID of the bastion instance.
161164
default: ''
162165

166+
dns_servers:
167+
type: comma_delimited_list
168+
description: address of dns nameservers reachable in your environment
169+
170+
dns_update_key:
171+
type: string
172+
hidden: true
173+
163174
outputs:
164175
console_url:
165176
description: URL of the OpenShift web console

master.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,14 @@ parameters:
213213
description: List of docker repository URLs which will be installed on each node, if a repo is insecure use '#insecure' suffix.
214214
default: ''
215215

216+
dns_servers:
217+
type: comma_delimited_list
218+
description: address of dns nameservers reachable in your environment
219+
220+
dns_update_key:
221+
type: string
222+
hidden: true
223+
216224
resources:
217225

218226
# Create a network connection on the internal communications network
@@ -287,6 +295,7 @@ resources:
287295
- config: {get_resource: set_extra_repos}
288296
- config: {get_resource: set_extra_docker_repos}
289297
- config: {get_resource: host_update}
298+
- config: {get_resource: add_dns_record}
290299
- config: {get_resource: master_boot}
291300

292301
# Compose the short hostname and fully qualified domain name for the new host
@@ -321,6 +330,9 @@ resources:
321330
- path: /usr/local/bin/retry
322331
permissions: 0755
323332
content: {get_file: fragments/retry.sh}
333+
- path: /usr/local/bin/update_dns
334+
permissions: 0755
335+
content: {get_file: fragments/update_dns.py}
324336
- path: /etc/sysconfig/network-scripts/ifcfg-eth1
325337
content:
326338
str_replace:
@@ -385,6 +397,17 @@ resources:
385397
$SYSTEM_UPDATE: {get_param: system_update}
386398
template: {get_file: fragments/host-update.sh}
387399

400+
add_dns_record:
401+
type: OS::Heat::SoftwareConfig
402+
properties:
403+
config:
404+
str_replace:
405+
params:
406+
'%DNS_SERVERS%': {list_join: [" ", {get_param: dns_servers}]}
407+
'%DNS_UPDATE_KEY%': {get_param: dns_update_key}
408+
'%IP_ADDRESS%': {get_attr: [port, fixed_ips, 0, ip_address]}
409+
template: {get_file: fragments/add_dns_record.sh}
410+
388411
# Prepare the host to run Docker and Ansible for OpenShift install and config
389412
master_boot:
390413
type: OS::Heat::SoftwareConfig

0 commit comments

Comments
 (0)