Multi-Region DC/OS on Azure using the Universal Installer

ENTERPRISE

Guide for DC/OS on Azure using the Universal Installer adding a remote region.

This guide expects that you already have a running DC/OS cluster based on Universal Installer 0.3. To learn more about running DC/OS with the Universal Installer have a look into the Guide for DC/OS on Azure using the Universal Installer.

You will learn how to place additional infrastructure into an Azure remote region. Remote regions will be connected to each other by using the peering functionality of Azure VNETs.

Prerequisites

  • A running DC/OS Enterprise cluster set up with Universal Installer 0.2 modules
  • A subnet range for your remote region

Getting started with remote region

We expect your already running DC/OS clusters main.tf will look similar to this example. To deploy a remote region we have to do some changes to your main.tf

  1. provider "azurerm" {
  2. features {}
  3. }
  4. # Used to determine your public IP for forwarding rules
  5. data "http" "whatismyip" {
  6. url = "http://whatismyip.akamai.com/"
  7. }
  8. module "dcos" {
  9. source = "dcos-terraform/dcos/aws"
  10. version = "~> 0.3.0"
  11. providers = {
  12. azurerm = azurerm
  13. }
  14. location = "West US"
  15. avset_platform_fault_domain_count = 3
  16. cluster_name = "my-dcos-demo"
  17. ssh_public_key_file = "<path-to-public-key-file>"
  18. admin_ips = ["${data.http.whatismyip.body}/32"]
  19. num_masters = 3
  20. num_private_agents = 2
  21. num_public_agents = 1
  22. dcos_version = ""
  23. dcos_variant = "ee"
  24. dcos_license_key_contents = "${file("./license.txt")}"
  25. # Make sure to set your credentials if you do not want the default EE
  26. # dcos_superuser_username = "superuser-name"
  27. # dcos_superuser_password_hash = "${file("./dcos_superuser_password_hash.sha512")}"
  28. dcos_instance_os = "centos_7.6"
  29. }
  30. output "masters-ips" {
  31. value = module.dcos.masters-ips
  32. }
  33. output "cluster-address" {
  34. value = module.dcos.masters-loadbalancer
  35. }
  36. output "public-agents-loadbalancer" {
  37. value = module.dcos.public-agents-loadbalancer
  38. }

Shared config options

To create the remote region and its infrastructure we will use the same underlying modules as in our master region. This also means there will be some information needed for both infrastructures like cluster_name, admin_ips and ssh_public_key_file. To make the operation easier you should define local variables in your main.tf that will be used in every module.

  1. #...
  2. // lets define variables which are shared between all regions
  3. locals {
  4. ssh_public_key_file = "~/.ssh/id_rsa.pub"
  5. cluster_name = "my-dcos-demo"
  6. admin_ips = ["${data.http.whatismyip.body}/32"]
  7. }
  8. #...

Internal subnetworks

Part of the shared information is which internal subnets are used in your infrastructure. If you did not specify subnet_range, terraform uses the default which is 172.12.0.0/16. The remote region we want to specify needs its own subnet.

IMPORTANT: You should not take 172.17.0.0/16, it is dockers internal network default which will lead to problems.

To have a clear separation between our master and our remote regions we will take 10.128.0.0/16 as our remote regions subnet. Also, we will use a map variable to assign the networks to regions. This will make it easier when adding additional regions in the future.

The locals section will now look like this

  1. #...
  2. // lets define variables which are shared between all regions
  3. locals {
  4. ssh_public_key_file = "~/.ssh/id_rsa.pub"
  5. cluster_name = "my-dcos-demo"
  6. admin_ips = ["${data.http.whatismyip.body}/32"]
  7. region_networks = {
  8. // dont use 172.17/26 as its used by docker.
  9. "master" = "172.12.0.0/16" // this is the default
  10. "West US 2" = "10.128.0.0/16"
  11. }
  12. }
  13. #...

The remote region

Before we start changing values within the dcos module we will append the infrastructure definition of the remote region to your main.tf. In our example case we only want to have private agents in our remote region, and both private and public agents can be put in a remote region.

IMPORTANT: Running master instances in remote regions is not supported.

To only start private agents we will set num_bootstrap = 0, num_masters = 0 and num_public_agents = 0.

Another important topic to mention is naming. To distinguish between instances of your main and your remote region we introduced the name_prefix variable which allows you to add a prefix to the name of every resource. In this example we set the name_prefix to the short name of the remote region.

In the following example you will also find the shared config options being used in the module call referenced by e.g. local.ssh_public_key_file.

  1. #...
  2. module "dcos-wus2" {
  3. source = "dcos-terraform/infrastructure/azurerm"
  4. version = "~> 0.3.0"
  5. providers = {
  6. azurerm = azurerm
  7. }
  8. location = "West US 2"
  9. avset_platform_fault_domain_count = 2
  10. subnet_range = local.region_networks["West US 2"]
  11. admin_ips = local.admin_ips
  12. name_prefix = "wus2"
  13. cluster_name = local.cluster_name
  14. num_bootstrap = 0
  15. num_masters = 0
  16. num_private_agents = 1
  17. num_public_agents = 0
  18. ssh_public_key_file = local.ssh_public_key_file
  19. }

Peering to the main DC/OS region

We now need to establish a connection between the two infrastructures. The Universal Installer provides a module for this task. In this module we reference data from both infrastructures the main region holding DC/OS masters and the remote region holding your remote private agents.

The only information this module needs to receive is the output of our dcos and dcos-wus2 modules. We will append this module to the end of your main.tf

Here is the example vnet-peering-section

  1. #...
  2. module "vnet-connection-master-wus2" {
  3. source = "dcos-terraform/vnet-peering/azurerm"
  4. version = "~> 0.3.0"
  5. providers = {
  6. azurerm = azurerm
  7. }
  8. cluster_name = local.cluster_name
  9. local_region_network = "master"
  10. local_resource_group_name = module.dcos.infrastructure.resource_group_name
  11. local_vnet_name = module.dcos.infrastructure.vnet_name
  12. local_vnet_id = module.dcos.infrastructure.vnet_id
  13. remote_region_network = "wus2"
  14. remote_resource_group_name = module.dcos-wus2.resource_group_name
  15. remote_vnet_name = module.dcos-wus2.vnet_name
  16. remote_vnet_id = module.dcos-wus2.vnet_id
  17. }

Changes to dcos module

At this point its time to do changes to your dcos module so it knows about the remote region and is able to install the remote agents.

  1. Choose a subnet range. In general this change is not needed but we wanted to make your example pretty specific.

    subnet_range = "local.region_networks["master"]

  2. Change the cluster_name. As this is a shared resource we will make use of the local variable.

    cluster_name = "local.cluster_name

  3. List the SSH key. This is also a shared resource and we can make use of the local variable

    ssh_public_key_file = "local.ssh_public_key_file

  4. Add the admin IPs following the same pattern.

    `admin_ips = local.admin_ips

  5. Add the private agents. This nearly the most important new variable. This tells the DC/OS installation module which other agents need to be installed.

    additional_private_agent_ips = module.dcos-wus2.private_agents.private_ips

Example dcos module

After the changes above got applied your dcos module should look like this

  1. module "dcos" {
  2. source = "dcos-terraform/dcos/azurerm"
  3. version = "~> 0.3.0"
  4. providers = {
  5. azure = "azure"
  6. }
  7. location = "West US"
  8. avset_platform_fault_domain_count = 3
  9. subnet_range = local.region_networks["master"]
  10. cluster_name = local.cluster_name
  11. ssh_public_key_file = local.ssh_public_key_file
  12. admin_ips = local.admin_ips
  13. num_masters = 3
  14. num_private_agents = 2
  15. num_public_agents = 1
  16. dcos_version = ""
  17. dcos_variant = "ee"
  18. dcos_license_key_contents = "${file("./license.txt")}"
  19. # Make sure to set your credentials if you do not want the default EE
  20. # dcos_superuser_username = "superuser-name"
  21. # dcos_superuser_password_hash = "${file("./dcos_superuser_password_hash.sha512")}"
  22. dcos_instance_os = "centos_7.6"
  23. additional_private_agent_ips = module.dcos-wus2.private_agents.private_ips
  24. }

Full main.tf example

Here is the complete main.tf you should see once you completed this guide.

  1. provider "azurerm" {
  2. features {}
  3. }
  4. # Used to determine your public IP for forwarding rules
  5. data "http" "whatismyip" {
  6. url = "http://whatismyip.akamai.com/"
  7. }
  8. // lets define variables which are shared between all regions
  9. locals {
  10. ssh_public_key_file = "~/.ssh/id_rsa.pub"
  11. cluster_name = "my-dcos-demo"
  12. admin_ips = ["${data.http.whatismyip.body}/32"]
  13. region_networks = {
  14. // dont use 172.17/26 as its used by docker.
  15. "master" = "172.12.0.0/16" // this is the default
  16. "West US 2" = "172.13.0.0/16"
  17. }
  18. }
  19. module "dcos" {
  20. source = "dcos-terraform/dcos/azurerm"
  21. version = "~> 0.3.0"
  22. providers = {
  23. azurerm = azurerm
  24. }
  25. location = "West US"
  26. avset_platform_fault_domain_count = 3
  27. subnet_range = local.region_networks["master"]
  28. cluster_name = local.cluster_name
  29. ssh_public_key_file = local.ssh_public_key_file
  30. admin_ips = local.admin_ips
  31. num_masters = 3
  32. num_private_agents = 2
  33. num_public_agents = 1
  34. dcos_version = ""
  35. dcos_variant = "ee"
  36. dcos_license_key_contents = "${file("./license.txt")}"
  37. # Make sure to set your credentials if you do not want the default EE
  38. # dcos_superuser_username = "superuser-name"
  39. # dcos_superuser_password_hash = "${file("./dcos_superuser_password_hash.sha512")}"
  40. dcos_instance_os = "centos_7.6"
  41. additional_private_agent_ips = module.dcos-usw2.private_agents_private_ips
  42. }
  43. output "masters-ips" {
  44. value = module.dcos.masters-ips
  45. }
  46. output "cluster-address" {
  47. value = module.dcos.masters-loadbalancer
  48. }
  49. output "public-agents-loadbalancer" {
  50. value = module.dcos.public-agents-loadbalancer
  51. }
  52. module "dcos-usw2" {
  53. source = "dcos-terraform/infrastructure/azurerm"
  54. version = "~> 0.3.0"
  55. providers = {
  56. azurerm = azurerm
  57. }
  58. location = "West US 2"
  59. avset_platform_fault_domain_count = 2
  60. subnet_range = local.region_networks["West US 2"]
  61. admin_ips = local.admin_ips
  62. name_prefix = "usw2"
  63. cluster_name = local.cluster_name
  64. num_bootstrap = 0
  65. num_masters = 0
  66. num_private_agents = 1
  67. num_public_agents = 0
  68. ssh_public_key_file = local.ssh_public_key_file
  69. }
  70. module "vnet-connection-master-usw2" {
  71. source = "dcos-terraform/vnet-peering/azurerm"
  72. version = "~> 0.3.0"
  73. providers = {
  74. azurerm = azurerm
  75. }
  76. cluster_name = local.cluster_name
  77. local_region_network = "master"
  78. local_resource_group_name = module.dcos.infrastructure_resource_group_name
  79. local_vnet_name = module.dcos.infrastructure_vnet_name
  80. local_vnet_id = module.dcos.infrastructure_vnet_id
  81. remote_region_network = "usw2"
  82. remote_resource_group_name = module.dcos-usw2.resource_group_name
  83. remote_vnet_name = module.dcos-usw2.vnet_name
  84. remote_vnet_id = module.dcos-usw2.vnet_id
  85. }