Nomad Multi-Region Federation

Ich hatte ja schonmal einen Artikel zum diesem Thema geschrieben. Dort wurde schon beschrieben, wie zwei Nomad/Consul-Installationen in zwei verschiedenen Cloud-Umgebungen (AWS und GCP) per Terraform installiert und "föderiert" wurden.

Voraussetzung für dieses Konstrukt war aber, dass beide Cloud-Umgebungen vorher per VPN verbunden werden mussten.

Jetzt ist der Plan, so ein Konstrukt ohne weitere Nutzung von Diensten der unterliegenden Cloud-Umgebungen aufzubauen.

Wie man zwei Consul-Installationen verbindet hatte ich schon in "Consul Datacenter Federation" beschrieben.

Leider (oder zum Glück) unterscheiden sich die verschiedenen Hashicorp Produkte an der ein oder anderen Stelle - deshalb waren die Erfahrungen bei Consul nicht 1:1 auf Nomad zu übertragen. Denn dort haben wir ähnliche Probleme wie bei Consul.

Auch bei Nomad müssen wir erzwingen, dass für die Kommunikation der Server untereinander die öffentliche Adresse verwendet wird. Bei Nomad wird dazu die advertise Anweisung in der Server-Konfiguration benutzt. In meinem Template sieht das jetzt so aus:

advertise {
  # Defaults to the first private IP address.
  http = "{{ GetInterfaceIP \"ens3\" }}" # must be reachable by Nomad CLI clients
  rpc  = "{{ GetInterfaceIP \"ens3\" }}" # must be reachable by Nomad client nodes
  serf = "${floatingip}"                 # must be reachable by Nomad server nodes
}

ports {
  http = 4646
  rpc  = 4647
  serf = 4648
}

Die ${floatingip} wird dabei aus der entsprechenden Ressource von Terraform befüllt:

content = templatefile("${path.module}/templates/nomad.hcl.tpl", {
        datacenter_name = var.config.datacenter_name,
        domain_name = var.config.domain_name,
        os_domain_name = var.config.os_domain_name,
        node_name = "nomad-${count.index}",
        bootstrap_expect = var.config.server_replicas,
#       nomad_encryption_key = random_id.nomad_encryption_key.b64_std,
        nomad_encryption_key = var.config.nomad_encryption_key,
        upstream_dns_servers = var.config.dns_servers,
        auth_url = "${var.auth_url}",
        user_name = "${var.user_name}",
        password = "${var.password}",
        os_region = "${var.config.os_region}",
        floatingip = "${element(openstack_networking_floatingip_v2.nomad_flip.*.address, count.index)}",
    })
    destination = "/etc/nomad/nomad.hcl"

Damit lassen sich die beteiligten Nomad Datacenter bzw. Regionen problemlos "verheiraten":

debian@nomad-2:~$ nomad server members
Name           Address         Port  Status  Leader  Raft Version  Build  Datacenter  Region
nomad-0.prod2  194.64.176.147  4648  alive   false   3             1.7.2  prod2       prod2
nomad-1.prod2  194.64.176.22   4648  alive   false   3             1.7.2  prod2       prod2
nomad-2.prod2  194.64.176.226  4648  alive   true    3             1.7.2  prod2       prod2
nomad-0.prod3  194.64.177.186  4648  alive   false   3             1.7.2  prod3       prod3
nomad-1.prod3  194.64.177.219  4648  alive   true    3             1.7.2  prod3       prod3
nomad-2.prod3  194.64.177.44   4648  alive   false   3             1.7.2  prod3       prod3

Jetzt fehlt noch das Aufsetzen des Consul Service Mesh ohne Kubernetes. Zum Glück gibt es auch dazu schon Informationen von Guy Barros, der dazu schon einen Medium-Artikel und ein Youtube-Video gemacht hat:

Er hat natürlich auch ein GitHub-Repository, in welchem sich dazu wertvolle Informationen finden. Mal sehen, ob wir es hinbekommen, damit eine sinnvolle Applikation in zwei unabhängigen Cloud-Umgebungen möglichst ausfallsicher auszurollen. Dazu dann mehr, sobald das auch läuft.