Skip to content

Commit 6d67b8f

Browse files
beaglesclaude
andcommitted
Support migration windows for BIND9
The IPs for the BIND9 servers may be in external registries or in other DNS configuration for zone delegation via glue records. This change is part of a series to verify the steps to maintaining records in both the RHOSO system and the legacy system to allow a staged migration of DNS infrastructure. Documentation is enhanced to: - Update the procedure for maintaining a migration window with legacy BIND9 servers, including a reference to additional steps after the standard adoption. - Add tasks to configure and enable the Designate service, including creating a LoadBalancer service for mDNS zone transfers. - Refine task names for clarity and removed unnecessary steps related to external binds secret verification. - Improve the patch file creation process for Designate CR to include necessary configurations for legacy BIND9 integration. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c2642cf commit 6d67b8f

8 files changed

Lines changed: 478 additions & 0 deletions

File tree

docs_dev/assemblies/development_environment.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@ done
514514
515515
oc delete --wait=false pod ovn-copy-data || true
516516
oc delete --wait=false pod mariadb-copy-data || true
517+
oc delete secret designate-external-binds || true
518+
oc delete service designate-external-master || true
517519
oc delete secret osp-secret || true
518520
----
519521

docs_user/modules/proc_adopting-the-dns-service.adoc

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
[role="_abstract"]
77
To adopt the {dns_first_ref}, you patch an existing `OpenStackControlPlane` custom resource (CR) where the {dns_service} is disabled. The patch starts the service with the configuration parameters that are provided by the {rhos_prev_long} ({OpenStackShort}) environment.
88

9+
[NOTE]
10+
====
11+
If your {rhos_prev_long} deployment uses BIND9 servers that you want to serve DNS during and after adoption, you can include them as external back ends with the new operator-managed BIND9 instances. In this staged migration model, both the legacy BIND9 servers and the new cluster-hosted BIND9 StatefulSet serve the same pool concurrently. This avoids a disruptive DNS switchover and allows external DNS registries and delegations to be updated to reference the new nameservers later.
12+
After completing the standard adoption procedure, see xref:maintaining-a-migration-window-with-legacy-bind9-servers_{context}[Maintaining a migration window with legacy BIND9 servers] for the additional steps required to enable this transition window.
13+
====
14+
915
.Procedure
1016

1117
. Create an alias for the `openstack` command:
@@ -320,3 +326,240 @@ $ oc patch openstackcontrolplane openstack --type=merge --patch-file /tmp/design
320326
----
321327
$ oc wait --for condition=Ready --timeout=600s designate.designate.openstack.org/designate
322328
----
329+
330+
[id="maintaining-a-migration-window-with-legacy-bind9-servers_{context}"]
331+
== Maintaining a migration window with legacy BIND9 servers
332+
[role="_abstract"]
333+
334+
A complete immediate switchover of all DNS servers to {rhos_long} requires all DNS clients to be updated with the new addresses of the DNS servers. This may be DNS registry entries, `glue records` in other DNS zone tables or configuration in OpenStack servers. In deployments where this cannot be done immediately, this procedure configures the existing DNS servers to be used and updated until all references to them can be migrated to the {rhos_long} DNS services.
335+
336+
If your {rhos_prev_long} deployment uses BIND9 servers that should continue serving DNS during adoption, follow this procedure after completing the standard {dns_service} adoption. The designate worker sends RNDC commands and DNS NOTIFY messages to the legacy servers, which pull zone data from the mDNS service through AXFR on port 5354.
337+
338+
.Procedure
339+
340+
. Extract RNDC credentials from each legacy {rhos_prev_long} Controller that runs BIND9 and create the `designate-external-binds` secret. Run the following script from the adoption host:
341+
+
342+
----
343+
$ binddata_file=/tmp/binddata.yaml
344+
$ rm $binddata_file
345+
$ for i in {1..3}; do
346+
SSH_CMD=CONTROLLER${i}_SSH
347+
if [ ! -z "${!SSH_CMD}" ]; then
348+
echo "Extracting RNDC credentials from controller $i"
349+
RNDC_SECRET=$(${!SSH_CMD} sudo grep secret /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf | awk '{gsub(/"/, "", $2); gsub(/;/, "", $2); print $2}')
350+
RNDC_KEYNAME=$(${!SSH_CMD} sudo grep '^key' /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf | awk '{gsub(/"/, "", $2); print $2}' | cut -f 1)
351+
RNDC_ALGORITHM=$(${!SSH_CMD} sudo grep algorithm /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf | awk '{gsub(/;/, "", $2); print $2}')
352+
CONTROLLER_IP=$(${!SSH_CMD} sudo grep 'internal_api\"' /etc/puppet/hieradata/net_ip_map.json | awk '{gsub(/"/, "", $2); gsub(/,/, "", $2); print $2}')
353+
cat << BINDATACR >> "$binddata_file"
354+
- name: controller-$i
355+
address: $CONTROLLER_IP
356+
rndcsecret: $RNDC_SECRET
357+
rndckeyname: $RNDC_KEYNAME
358+
rndcalgorithm: $RNDC_ALGORITHM
359+
BINDATACR
360+
fi
361+
done
362+
$ if [ -s "$binddata_file" ]; then
363+
external_binds_secret_file=/tmp/external_binds_secret.yaml
364+
cat << EOSECRETC > "$external_binds_secret_file"
365+
apiVersion: v1
366+
kind: Secret
367+
metadata:
368+
name: designate-external-binds
369+
namespace: openstack
370+
type: Opaque
371+
stringData:
372+
default: |
373+
$(cat "$binddata_file")
374+
EOSECRETC
375+
oc apply -f "$external_binds_secret_file"
376+
fi
377+
----
378+
+
379+
where:
380+
`CONTROLLER1_SSH`, `CONTROLLER2_SSH`, and `CONTROLLER3_SSH`::
381+
Specifies the SSH connection variables for each legacy Controller that runs BIND9. The script extracts credentials from each available Controller and automatically creates and applies the `designate-external-binds` secret in the `openstack` namespace.
382+
383+
. Reconfigure the legacy BIND9 instances to accept RNDC connections and zone transfers from the new {rhos_long} deployment. On each legacy Controller, modify the BIND9 configuration. Because the `options` and `controls` blocks cannot be reopened, use the following commands to add the required configuration in-place:
384+
+
385+
386+
[subs="+quotes"]
387+
----
388+
$ INTERNALAPI_CIDR=<internalapi_subnet>
389+
$ for i in {1..3}; do
390+
SSH_CMD=CONTROLLER${i}_SSH
391+
if [ ! -z "${!SSH_CMD}" ]; then
392+
echo "Reconfiguring bind on controller $i"
393+
CONTROLLER_IP=$(${!SSH_CMD} sudo grep 'internal_api\"' /etc/puppet/hieradata/net_ip_map.json | awk '{gsub(/"/, "", $2); gsub(/,/, "", $2); print $2}')
394+
${!SSH_CMD} cp -n /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf.pre-adoption-backup
395+
${!SSH_CMD} "sed -i 's:inet [0-9.]* allow { [0-9./]*; }:inet ${CONTROLLER_IP} allow { ${INTERNALAPI_CIDR}; }:' /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf"
396+
${!SSH_CMD} cp -n /var/lib/config-data/ansible-generated/designate/etc/named/options.conf /var/lib/config-data/ansible-generated/designate/etc/named/options.conf.pre-adoption-backup
397+
${!SSH_CMD} "sed -i 's:allow.notify.*};:allow-notify { $INTERNALAPI_CIDR; };:' /var/lib/config-data/ansible-generated/designate/etc/named/options.conf"
398+
${!SSH_CMD} "sed -i '/allow.transfer:/d' /var/lib/config-data/ansible-generated/designate/etc/named/options.conf"
399+
${!SSH_CMD} "sed -i '/^options {/,/^};/{
400+
/^};/ i\\\tallow-transfer { '"$INTERNALAPI_CIDR"'; };
401+
}' /var/lib/config-data/ansible-generated/designate/etc/named/options.conf"
402+
done
403+
----
404+
+
405+
where:
406+
407+
`CONTROLLER_IP`::
408+
Specifies the `internalapi` IP address of the legacy Controller. You can be retrieve this from `/etc/puppet/hieradata/net_ip_map.json` on each Controller.
409+
410+
`internalapi_subnet`::
411+
Specifies the `internalapi` subnet in CIDR notation, for example `172.17.0.0/24`.
412+
This is a CIDR range represents the network from which RHOSO designate worker
413+
pods send requests.
414+
415+
+
416+
[NOTE]
417+
====
418+
The `sed` commands in the shell script example are directed at default deployments. If customizations are made to the deployment, either modify these commands or perform the modifications directly.
419+
====
420+
421+
+
422+
Reload the BIND9 configuration:
423+
+
424+
----
425+
$ systemctl restart desginate-designatebackendbind9
426+
----
427+
+
428+
[NOTE]
429+
====
430+
You can edit the BIND9 configuration directly because the legacy {OpenStackPreviousInstaller} control plane is being decommissioned and no longer manages these files.
431+
====
432+
433+
. Open the firewall on each legacy Controller to allow RNDC and DNS traffic from the {rhos_long} pods:
434+
+
435+
[subs="+quotes"]
436+
----
437+
$ firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<internalapi_subnet>" port port="953" protocol="tcp" accept'
438+
$ firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<internalapi_subnet>" port port="53" protocol="tcp" accept'
439+
$ firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="<internalapi_subnet>" port port="53" protocol="udp" accept'
440+
$ firewall-cmd --reload
441+
----
442+
443+
. Create a LoadBalancer service to expose the mDNS service on the internalapi
444+
network so that the legacy BIND9 servers can perform AXFR zone transfers:
445+
+
446+
----
447+
$ cat << EOF_CAT > /tmp/designate-external-mdns-svc.yaml
448+
apiVersion: v1
449+
kind: Service
450+
metadata:
451+
namespace: openstack
452+
name: designate-external-master
453+
labels:
454+
service: designate-mdns
455+
designate.openstack.org/external_master: "true"
456+
annotations:
457+
core.openstack.org/ingress_create: "false"
458+
metallb.io/ip-allocated-from-pool: internalapi
459+
metallb.universe.tf/address-pool: internalapi
460+
metallb.universe.tf/allow-shared-ip: internalapi
461+
metallb.universe.tf/loadBalancerIPs: 172.17.0.80
462+
designate.openstack.org/external_pool: default
463+
spec:
464+
selector:
465+
service: designate-mdns
466+
ports:
467+
- name: dns-tcp
468+
port: 5354
469+
protocol: TCP
470+
targetPort: 5354
471+
- name: dns
472+
port: 5354
473+
protocol: UDP
474+
targetPort: 5354
475+
ipFamilies:
476+
- IPv4
477+
ipFamilyPolicy: SingleStack
478+
externalTrafficPolicy: Cluster
479+
internalTrafficPolicy: Cluster
480+
type: LoadBalancer
481+
EOF_CAT
482+
$ oc apply -f /tmp/designate-external-mdns-svc.yaml
483+
----
484+
485+
. Patch the {dns_service} custom resource to reference the external binds secret and connect the worker to the internalapi network so it can connect to the external BIND9 servers.
486+
+
487+
----
488+
$ oc patch openstackcontrolplane openstack --type=merge --patch '
489+
spec:
490+
designate:
491+
template:
492+
externalBindsSecret: designate-external-binds
493+
designateWorker:
494+
networkAttachments:
495+
- designate
496+
- internalapi
497+
'
498+
----
499+
500+
. Wait for the {dns_service} to reconcile:
501+
+
502+
----
503+
$ oc wait --for condition=Ready --timeout=300s designate.designate.openstack.org/designate
504+
----
505+
506+
. Verify that the external BIND9 targets are included in the pool configuration:
507+
+
508+
----
509+
$ oc get configmap designate-pools-yaml-config-map -o jsonpath='{.data.pools\.yaml}' | grep -A5 'external-bind9'
510+
----
511+
+
512+
The output should list the external BIND9 servers you configured in the external binds secret.
513+
514+
. Verify RNDC connectivity from the designate worker pods to the legacy BIND9 servers:
515+
+
516+
[subs="+quotes"]
517+
----
518+
$ oc exec -it $(oc get pods -l service=designate-worker -o name | head -1) -- \
519+
rndc -s <controller_internalapi_ip> -k /etc/designate/rndc-keys/default-rndc-0 status
520+
----
521+
+
522+
where:
523+
524+
`<controller_internalapi_ip>`::
525+
Specifies the internalapi IP address of a legacy BIND9 server.
526+
+
527+
A successful response indicates that the designate worker can manage the external BIND9 server.
528+
529+
.Next steps
530+
When external DNS registries and delegations are updated to reference the new nameservers, remove the legacy servers from the pool. For more information, see xref:completing-the-bind9-migration_{context}[Completing the BIND9 migration].
531+
532+
[id="completing-the-bind9-migration_{context}"]
533+
== Completing the BIND9 migration
534+
535+
After external DNS registries and delegations have been updated to reference
536+
the new {rhos_long} nameservers, remove the legacy BIND9 servers from the
537+
{dns_service} pool to complete the BIND9 migration.
538+
539+
.Procedure
540+
541+
. Remove the external binds secret reference from the {dns_service} custom resource:
542+
+
543+
----
544+
$ oc patch openstackcontrolplane openstack --type=json --patch '
545+
[{"op": "remove", "path": "/spec/designate/template/externalBindsSecret"}]
546+
'
547+
----
548+
549+
. Wait for the {dns_service} to reconcile:
550+
+
551+
----
552+
$ oc wait --for condition=Ready --timeout=300s designate.designate.openstack.org/designate
553+
----
554+
555+
. Delete the external binds secret:
556+
+
557+
----
558+
$ oc delete secret designate-external-binds -n openstack
559+
----
560+
561+
. Delete the mDNS LoadBalancer service:
562+
+
563+
----
564+
$ oc delete service designate-external-master -n openstack
565+
----
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
designate_adoption: false
2+
designate_external: false
23
designate_retry_delay: 5
4+
designate_external_bind_controllers: []
5+
designate_external_binds: []
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
- name: Extract RNDC credentials from legacy controllers
2+
ansible.builtin.shell: |
3+
{{ shell_header }}
4+
{{ oc_header }}
5+
6+
echo "Extracting BIND9 data from legacy controllers"
7+
binddata_file=/tmp/binddata.yaml
8+
rm -f $binddata_file
9+
for i in {1..3}; do
10+
SSH_CMD=CONTROLLER${i}_SSH
11+
if [ ! -z "${!SSH_CMD}" ]; then
12+
echo "Extracting RNDC credentials from controller $i"
13+
RNDC_SECRET=$(${!SSH_CMD} sudo grep secret /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf | awk '{gsub(/"/, "", $2); gsub(/;/, "", $2); print $2}')
14+
RNDC_KEYNAME=$(${!SSH_CMD} sudo grep '^key' /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf | awk '{gsub(/"/, "", $2); print $2}' | cut -f 1)
15+
RNDC_ALGORITHM=$(${!SSH_CMD} sudo grep algorithm /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf | awk '{gsub(/;/, "", $2); print $2}')
16+
CONTROLLER_IP=$(${!SSH_CMD} sudo grep 'internal_api\"' /etc/puppet/hieradata/net_ip_map.json | awk '{gsub(/"/, "", $2); gsub(/,/, "", $2); print $2}')
17+
echo "address: $CONTROLLER_IP"
18+
echo "rndcsecret: $RNDC_SECRET"
19+
echo "rndckeyname: $RNDC_KEYNAME"
20+
echo "rndcalgorithm: $RNDC_ALGORITHM"
21+
22+
cat << BINDATACR >> "$binddata_file"
23+
- name: controller-$i
24+
address: $CONTROLLER_IP
25+
rndcsecret: $RNDC_SECRET
26+
rndckeyname: $RNDC_KEYNAME
27+
rndcalgorithm: $RNDC_ALGORITHM
28+
BINDATACR
29+
fi
30+
done
31+
32+
if [ -s "$binddata_file" ]; then
33+
external_binds_secret_file=/tmp/external_binds_secret.yaml
34+
cat << EOSECRETC > "$external_binds_secret_file"
35+
apiVersion: v1
36+
kind: Secret
37+
metadata:
38+
name: designate-external-binds
39+
namespace: openstack
40+
type: Opaque
41+
stringData:
42+
default: |
43+
$(cat "$binddata_file")
44+
EOSECRETC
45+
46+
oc apply -f "$external_binds_secret_file"
47+
fi
48+
49+
- name: Reconfigure Legacy BIND9 instances to talk with Designate on Internal API network.
50+
ansible.builtin.shell: |
51+
{{ shell_header }}
52+
{{ oc_header }}
53+
echo "Configuring BIND9 to integrate via internalapi"
54+
INTERNALAPI_CIDR="{{ internalapi_cidr }}"
55+
for i in {1..3}; do
56+
SSH_CMD=CONTROLLER${i}_SSH
57+
if [ ! -z "${!SSH_CMD}" ]; then
58+
echo "Reconfiguring bind on controller $i"
59+
CONTROLLER_IP=$(${!SSH_CMD} sudo grep 'internal_api\"' /etc/puppet/hieradata/net_ip_map.json | awk '{gsub(/"/, "", $2); gsub(/,/, "", $2); print $2}')
60+
${!SSH_CMD} cp -n /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf.pre-adoption-backup
61+
${!SSH_CMD} "sed -i 's:inet [0-9.]* allow { [0-9./]*; }:inet ${CONTROLLER_IP} allow { ${INTERNALAPI_CIDR}; }:' /var/lib/config-data/ansible-generated/designate/etc/named/rndc.conf"
62+
${!SSH_CMD} cp -n /var/lib/config-data/ansible-generated/designate/etc/named/options.conf /var/lib/config-data/ansible-generated/designate/etc/named/options.conf.pre-adoption-backup
63+
${!SSH_CMD} "sed -i 's:allow.notify.*};:allow-notify { $INTERNALAPI_CIDR; };:' /var/lib/config-data/ansible-generated/designate/etc/named/options.conf"
64+
${!SSH_CMD} "sed -i '/allow.transfer:/d' /var/lib/config-data/ansible-generated/designate/etc/named/options.conf"
65+
${!SSH_CMD} "sed '/^options {/,/^};/{
66+
/^};/ i\\\tallow-transfer { '"$INTERNALAPI_CIDR"'; };
67+
}' /var/lib/config-data/ansible-generated/designate/etc/named/options.conf"
68+
echo "Restarting bind on controller $i"
69+
${!SSH_CMD} systemctl restart designate-designatebackendbind9
70+
fi
71+
done
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
- name: Patch Designate CR to reference external binds secret and add internalapi network to the designate workers.
2+
ansible.builtin.shell: |
3+
{{ shell_header }}
4+
{{ oc_header }}
5+
6+
oc patch openstackcontrolplane openstack --type=merge --patch '
7+
spec:
8+
designate:
9+
template:
10+
externalBindsSecret: designate-external-binds
11+
designateWorker:
12+
networkAttachments:
13+
- designate
14+
- internalapi
15+
'
16+
register: designate_external_patch_results
17+
changed_when: true
18+
failed_when: designate_external_patch_results.rc != 0
19+
20+
- name: Wait for the designate service to reconcile after external binds patch
21+
ansible.builtin.shell: |
22+
{{ shell_header }}
23+
{{ oc_header }}
24+
25+
oc wait --for condition=Ready --timeout=300s designates.designate.openstack.org/designate
26+
register: designate_external_ready_result
27+
until: designate_external_ready_result is success
28+
retries: 60
29+
delay: "{{ designate_retry_delay }}"
30+
31+
- name: Verify external BIND9 targets are in pool configuration
32+
ansible.builtin.shell: |
33+
{{ shell_header }}
34+
{{ oc_header }}
35+
36+
oc get configmap designate-pools-yaml-config-map -o jsonpath='{.data.pools\.yaml}' | grep -A5 'external-bind9'
37+
register: external_bind9_pool_check
38+
changed_when: false
39+
failed_when: external_bind9_pool_check.rc != 0

0 commit comments

Comments
 (0)