Migrating DNS Hosting

This step is a part of the service nodes migration to Azure.

DNS hosting migration is carried out in several maintenance (migration) windows, the number of which is equal to the number of name servers.

During migration, the propagation of DNS zones to target servers is performed using the following scripts:

Note: Hereinafter, dns_sync.py will be used to mean "the corresponding migration script".

Prerequisites

The prerequisites from the General Migration Procedure are fulfilled.

Migration Procedure

To ensure zero downtime of the DNS service, migrate each DNS server within a single separate maintenance window by performing these steps:

Note: For each name server migration, step 1 can be performed before the migration window.

  • Step 1. Prepare a new virtual machine (VM) with the same name and new IPs (Azure).
  • Step 2. Unregister the source DNS server (On-Premise).
  • Step 3. Configure the target DNS server on the VM prepared in step 1 (Azure).

Removing and configuring a new name server requires updating the DNS hosting resource type configuration using the "circular motion" principle illustrated in the example below. The "circular motion" principle is used because CloudBlue Commerce does not allow removing the first name server from the DNS hosting resource type, but allows changes to any name server.

Step 1. Prepare a New VM with a New IP (Azure)

  1. Create a VM in Azure with a private IP address (Exclusive IP).
  2. Assign a public IP (Shared IP) to the VM.
  3. To ensure that the VM can be registered in CloudBlue Commerce, create a temporary virtual networking interface on the VM and assign the public IP from step 2 to it:

    modprobe -r dummy
    modprobe -a dummy
    ip link set name <INTERFACE_NAME> dev dummy0
    ifconfig <INTERFACE_NAME> <NAMESERVER_PUBLIC_IP>/32

    where:

    • <INTERFACE_NAME> is an arbitrary unused name for the virtual interface, for example: eth10;
    • <NAMESERVER_PUBLIC_IP> is the new public IP address of the Azure VM.
  4. For the VM, check inbound and outbound access to the Internet.
  5. To prepare the VM for registration in CloudBlue Commerce, set up sudores for the user that will be used for registering the VM in CloudBlue Commerce:

    # vim /etc/sudoers.d/waagent
    <USER> ALL=(ALL) NOPASSWD: ALL

    where: <USER> is the username of the user that will be used for registering the VM in CloudBlue Commerce.

Step 2. Remove the Source Name Server with the Old IP (On-Premise)

  1. Check the DNS hosting consistency:

    python dns_sync.py --check --from=<REMOVED_SERVICE_ID> --to=<SERVICE_ID_X>,<SERVICE_ID_Y>,<REMOVED_SERVICE_ID>

    where:

    • <REMOVED_SERVICE_ID> is the ID of the DNS service that you want to remove;
    • <SERVICE_ID_X> and <SERVICE_ID_Y> are the IDs of the DNS services that you want to keep.

    Note: The DNS service IDs can be found at: PCP > Operations > Services > Domains > DNS > Nameservers.

    Example:

    In this example, the on-premise DNS service IDs are 10, 11, and 12, and the Azure DNS service IDs are 13, 14, and 15.

    # Migration window 1
    python dns_sync.py --check --from=10 --to=10,11,12

    # Migration window 2
    python dns_sync.py --check --from=11 --to=11,12,13

    # Migration window 3
    python dns_sync.py --check --from=12 --to=12,13,14

    Where dns_sync.py is the corresponding migration script.

  2. For each brand, determine whether or not DNS branding is used:

    Find the brand name for the source DNS service at

    System > Settings > Brands > click a brand name > Service Branding > DNS Branding > DNS Server

  3. For each brand with DNS branding follow these steps:
    1. Choose a temporary IP for the source DNS service:

      Find the IP of a DNS service that will not be deleted in the current migration window. For example, for the first migration window, the IP of the second DNS service can be chosen in the example below.

    2. Find the system-created A-record for the source DNS service brand name:

      Go to Services > Domains > click the brand domain > DNS > DNS Records > find the record.

    3. Create a temporary A-record based on the system-created record but with the chosen temporary IP:

      Go to Services > Domains > click the brand domain > DNS > DNS Records > click Add New DNS Record and complete the fields:

      • DNS Record Type: A
      • Domain: <the brand name of the source DNS service>
      • IP address: <the chosen temporary IP>
      • TTL > Custom: 360
    4. For the source DNS service brand, disable the system-created A-record:

      Go to Services > Domains > click the brand domain > DNS > DNS Records > click the record > click Deactivate.

  4. Un-register the source name server from the domain registrar’s system (for example, OpenSRS).

    Important: To properly un-register the name server from the registrar’s system, please refer to the registrar’s documentation. DNS propagation takes time (specified by the registrar) before taking effect. Wait until the DNS propagation is completed before going to the next step).

  5. Remove the source name server from DNS hosting Resource Type:

    Go to Products > Resources > the DNS hosting resource type > the Activation Parameters tab > remove the source name server.

    See the example below.

  6. Synchronize name servers for all domains using the corresponding synchronization script:

    python dns_sync.py --check --from=<REMOVED_SERVICE_ID> --to=<SERVICE_ID_X>,<SERVICE_ID_Y>
    python dns_sync.py --sync --from=<REMOVED_SERVICE_ID> --to=<SERVICE_ID_X>,<SERVICE_ID_Y>

    where:

    • <REMOVED_SERVICE_ID> is the ID of the DNS service that you want to remove;
    • <SERVICE_ID_X> and <SERVICE_ID_Y> are the IDs of the DNS services that you want to keep.

    Example (continued):

    In this example, the on-premise DNS service IDs are 10, 11, and 12, and the Azure DNS service IDs are 13, 14, and 15.

    # Migration window 1
    python dns_sync.py --check --from=10 --to=11,12
    python dns_sync.py --sync --from=10 --to=11,12

    # Migration window 2
    python dns_sync.py --check --from=11 --to=12,13
    python dns_sync.py --sync --from=11 --to=12,13

    # Migration window 3
    python dns_sync.py --check --from=12 --to=13,14
    python dns_sync.py --sync --from=12 --to=13,14

    Note: For troubleshooting, please see In Case of Synchronization Interruption and In Case of Synchronization Error.

  7. Remove the source DNS from each of the reverse DNS zones:

    Go to Services > Domains > DNS > Reverse DNS Zones > click a zone > Zone Info > select and remove the source DNS. Repeat for all reverse zones.

  8. Remove the DNS service from the source name server node:

    1. Go to Infrastructure > PPM Group Operations > click Create new PPM group operation > Deinstallation > select the corresponding DNS host > select the necessary DNS service > complete the removal.
    2. Check the task queue to make sure that the tasks with the name "Deinstall DNS..." are completed.
  9. Remove the source name server node from the on-premise CloudBlue Commerce installation:

    Go to Infrastructure > Service Nodes > select the corresponding DNS host > click Delete.

In Case of Synchronization Interruption

To restart the synchronization process after interruption, re-launch the dns_sync.py script in the following way:

python dns_sync.py --sync --from=<REMOVED_SERVICE_ID> --to=<SERVICE_ID_X>,<SERVICE_ID_Y> --initial-domain-id=<DOMAIN_ID>

where:

  • <DOMAIN_ID> is the ID of the domain at which the synchronization was interrupted (can be found in the synchronization script log at /var/log/pa/dns_sync.log).
  • <REMOVED_SERVICE_ID> is the ID of the DNS service you want to remove.
  • <SERVICE_ID_X> and <SERVICE_ID_Y> are the IDs of the DNS services that you want to keep.

For example:

python dns_sync.py --sync --from=12 --to=13,14 --initial-domain-id=1234

In Case of Synchronization Error

The DNS synchronization script may return the following error:

2020-02-04 10:14:01.589 [ERROR] DNS configuration is not completed for migration to service ns2 (3)
2020-02-04 10:14:01.589 [ERROR] Service template: 2, Resource type: DNS Hosting (1000012), Owner: 1, Domains: 1

Where '2' is the service template ID.

To eliminate the error, remove DNS customizations from the service templates mentioned in the error:

  1. Repeat the following steps for all affected service templates:
    1. In PCP, go to Operations > Products > Service Templates. Click the necessary service template. Switch to the Parameters tab.
    2. Click Edit. For the Nameservers parameter, select Use default value.
  2. After all customizations are changed to defaults, rerun the synchronization script.

Step 3. Configure the Target Name Server with a New IP (Asure)

  1. Register in CloudBlue Commerce the VM prepared in step 1:

    1. Go to Infrastructure > Service Nodes > click Add New Node and follow the wizard.
    2. Check the tasks queue to make sure that the tasks with the name "node_registration_..." are completed.
  2. Deploy the corresponding DNS service (PowerDNS or BIND) to the VM in Azure.
    1. Go to Infrastructure > PPM Group Operations > click Create new PPM group operation > Installation > select the corresponding DNS host > select the necessary DNS service > complete the installation.
    2. Check the tasks queue to make sure that the tasks with the name "Install DNS to..." are completed.
  3. Remove the temporary virtual interface from the VM:

    ip link delete <INTERFACE_NAME>

    where:

    <INTERFACE_NAME> is the virtual interface name, for example: eth10.

  4. Allow inbound access to the DNS node port 53 from the internet by configuring the firewall for the corresponding Network security group in Azure.
  5. Check inbound internet access to the DNS server:

    dig @<NAMESERVER_PUBLIC_IP>

    where:

    <NAMESERVER_PUBLIC_IP> is the new public IP address of the DNS service on the Azure VM.

  6. Add the target name server to the DNS hosting Resource Type:

    Go to Products > Resources > DNS Hosting > the Activation Parameters tab > add the target name server. See the example below.

  7. Add the target name server to each of the reverse zones:

    Go to Services > Domains > DNS > Reverse DNS Zones > click a zone > Zone Info > add the target name server. Repeat for all reverse zones.

  8. Synchronize nameservers for all domains using the corresponding synchronization script:

    python dns_sync.py --check --from=<SERVICE_ID_X> --to=<SERVICE_ID_X>,<SERVICE_ID_Y>,<ADDED_SERVICE_ID>
    python dns_sync.py --sync --from=<SERVICE_ID_X> --to=<SERVICE_ID_X>,<SERVICE_ID_Y>,<ADDED_SERVICE_ID>

    where:

    • <SERVICE_ID_X> and <SERVICE_ID_Y> are the IDs of the existing DNS services.
    • <ADDED_SERVICE_ID> is the ID of the DNS service you want to add.

    Example (continued):

    In this example, the on-premise DNS service IDs are 10, 11, and 12, and the Azure DNS service IDs are 13, 14, and 15.

    # Migration window 1
    python dns_sync.py --check --from=11 --to=11,12,13
    python dns_sync.py --sync --from=11 --to=11,12,13

    # Migration window 2
    python dns_sync.py --check --from=12 --to=12,13,14
    python dns_sync.py --sync --from=12 --to=12,13,14

    # Migration window 3
    python dns_sync.py --check --from=13 --to=13,14,15
    python dns_sync.py --sync --from=13 --to=13,14,15

    Note: For troubleshooting, please see In Case of Synchronization Interruption.

  9. Register the name server in the registrar’s system (for example, OpenSRS).

    Important: To properly register the name server in the registrar’s system, please refer to the registrar’s documentation. DNS propagation takes time (specified by the registrar) before taking effect. Wait until the DNS propagation is completed before going to the next step.

  10. Update DNS servers for all brands with DNS branding:

    1. Find the auto-generated brand name for the target DNS service:

      Go to System > Settings > Brands > click the brand domain > Service Branding > DNS Branding > DNS Server.

    2. Replace the auto-generated brand name of the target DNS service with the brand name of the source DNS service:

      Go to System > Settings > Brands > click the brand domain > Service Branding > DNS Branding > click the vendor's service name > edit the settings.

    3. Delete the temporary manually-created A-record that you create in step 2 for the source DNS service brand:

      Go to Services > Domains > click the brand domain > DNS > DNS Records > select the A-record > click Delete.

In Case of Synchronization Interruption

To restart the synchronization process after interruption, re-launch the dns_sync.py script in the following way:

python dns_sync.py --sync --from=<REMOVED_SERVICE_ID> --to=<SERVICE_ID_X>,<SERVICE_ID_Y> --initial-domain-id=<DOMAIN_ID>

where:

  • <DOMAIN_ID> is the ID of the domain at which the synchronization was interrupted (can be found in the synchronization script log at /var/log/pa/dns_sync.log).
  • <REMOVED_SERVICE_ID> is the ID of the DNS service that you want to remove.
  • <SERVICE_ID_X> and <SERVICE_ID_Y> are the IDs of the DNS services that you want to keep.

For example:

python dns_sync.py --sync --from=13 --to=13,14,15 --initial-domain-id=1234

Example of Migrating a DNS Hosting Configuration

In this example, there are three on-premise name servers. Three maintenance windows are necessary for their migration to Azure. Following the "circular motion" principle, the name servers are migrated sequentially, one name server within a single maintenance window at a time.

The name server configuration is performed at: Provider Control Panel > Operations panel > Products > Resources > the DNS Hosting resource type > the Activation Parameters tab.

The first name server The second name server The third name server
ns1.example.com ns2.example.com ns3.example.com

 

Table 1. Migration window 1: DNS hosting configuration

  Migration procedure The first name server The second name server The third name server
1. Prepare target ns1 (Azure) ns1.example.com (On-Premises) ns2.example.com (On-Premises) ns3.example.com (On-Premises)
2. Remove source ns1 (On-Premises) ns2.example.com (On-Premises) ns3.example.com (On-Premises) ---
3. Configure target ns1 (Azure) ns2.example.com (On-Premises) ns3.example.com (On-Premises) ns1.example.com (Azure) (NEW)

 

Table 2. Migration window 2: DNS hosting configuration

  Migration procedure The first name server The second name server The third name server
1. Prepare target ns2 (Azure) ns2.example.com (On-Premises) ns3.example.com (On-Premises) ns1.example.com (Azure)
2. Remove source ns2 (On-Premises) ns3.example.com (On-Premises) ns1.example.com (Azure) ---
3. Configure target ns2 (Azure) ns3.example.com (On-Premises) ns1.example.com (Azure) ns2.example.com (Azure) (NEW)

 

Table 3. Migration window 3: DNS hosting configuration

  Migration procedure The first name server The second name server The third name server
1. Prepare target ns3 (Azure) ns3.example.com (On-Premises) ns1.example.com (Azure) ns2.example.com (Azure)
2. Remove source ns3 (On-Premises) ns1.example.com (Azure) ns2.example.com (Azure) ---
3. Configure target ns3 (Azure) ns1.example.com (Azure) ns2.example.com (Azure) ns3.example.com (Azure) (NEW)

Know Issues

Issue 1: "issue. incorrect path in dns hosting rt in subs_resources"

oss=> select * from subs_resources where rt_instance_id = 264167;
rt_instance_id | sub_id | sub_limit | curr_usage | own_usage | rt_id | last_update | path
----------------+---------+-----------+------------+-----------+---------+----------------------------+-------------
264167 | 1006635 | -1 | 1 | 1 | 1000150 | 2018-06-06 13:18:56.894-04 | nullx264167
(1 row)

Workaround:

  1. Find the reseller transaction (RT):

    oss=> select * from subs_resources where sub_id = 1002924 and rt_id=1000150;
    rt_instance_id | sub_id | sub_limit | curr_usage | own_usage | rt_id | last_update | path
    ----------------+---------+-----------+------------+-----------+---------+----------------------------+----------------
    169210 | 1002924 | -1 | 2 | 2 | 1000150 | 2018-12-17 07:23:53.559-05 | x10x150x169210
    (1 row)
  2. Update the path:

    oss=> begin;
    BEGIN
    oss=> update subs_resources set path='x10x150x169210x264167' where rt_instance_id = 264167;
    UPDATE 1
    oss=> commit;
    COMMIT
    oss=>

Issue 2: "some domains with external dns hosting still have hosting_id in db"

oss=> select * from dns_zones where hosting_id = 9;
zone_id | mbox | refresh | retry | expire | min_ttl | ns1_name | ns2_name | ns3_name | name | hosting_id | external_master_ip
---------+--------------------+---------+-------+---------+---------+---------------------+---------------------+---------------------+-----------------+------------+--------------------
339 | person1@mail.example.com | 14400 | 7200 | 2419200 | 3600 | ns1.example.com | ns2.example.com | ns3.example.com | net.apstestaast | 9 |
525 | person2@mail.example.com | 14400 | 7200 | 2419200 | 3600 | ns1.example.com | ns2.example.com | ns3.example.com | me.www | 9 |
1945 | person3@mail.example.com | 14400 | 7200 | 2419200 | 3600 | ns1.example.com | ns2.example.com | ns3.example.com | com.testup72 | 9 |
(3 rows)

Such domains prevent removal of name servers. Also it is impossible to switch them to internal hosting in the UI.

Workaround:

Apply the following fix in the database:

oss=> update dns_zones set ns1_name='ns4.external.example.com', ns2_name='ns5.external.example.com', ns3_name='ns6.external.example.com', hosting_id=165 where hosting_id=9;
UPDATE 3