Patroni auf nebula

Mit den richtigen Zutaten ist es natürlich möglich einen Patroni-Cluster aufzubauen, der sich über mehrere völlig unabhängige Cloud-Umgebungen erstreckt.

Und die Zutaten kennen wir schon: Ein funktionierender Consul-Cluster (idealerweise auch über mehrere unabhängige Cloud-Umgebungen hinweg aufgebaut) und nebula:

GitHub - slackhq/nebula: A scalable overlay networking tool with a focus on performance, simplicity and security
A scalable overlay networking tool with a focus on performance, simplicity and security - slackhq/nebula

bzw. die "managed" Variante von defined.net:

Defined Networking
Nebula Overlay Networks: Extend network access with on-demand, encrypted tunnels between any hosts on any network. Defined Networking is the company behind the Nebula open-source project.

Sowohl bei den Consul Servern, die den Cluster bilden, als auch auf den Consul Clients, die auf den Patroni-Nodes installiert werden, muß darauf geachtet werden, die verschiedenen Dienste an das Netzwerkinterface des Overlay-Netzes zu binden.

bind_addr      = "{{ GetInterfaceIP \"nebula1\" }}"
advertise_addr = "{{ GetInterfaceIP \"nebula1\" }}"
client_addr    = "{{ GetInterfaceIP \"nebula1\" }}"

addresses {
   http     = "{{ GetInterfaceIP \"nebula1\" }}"
   https    = "{{ GetInterfaceIP \"nebula1\" }}"
   grpc     = "{{ GetInterfaceIP \"nebula1\" }}"
}

Da der Cluster in verschiedenen Cloud-Umgebungen aufgebaut wird, ist ein automatisches Cloud Auto Join leider nicht möglich.

Für die Patroni-Konfiguration ist es sinnvoll, den Namen des Knotens so zu wählen, dass die jeweilige Cloud-Umgebung daraus hervorgeht.

Auch in der Patroni-Konfiguration müssen die Dienste an das Netzwerkinterface des Overlay-Netzes gebunden werden:

scope: patroni42
namespace: terra42
name: prod1-postgresql-0

restapi:
  listen: 10.21.20.53:8008
  connect_address: 10.21.20.53:8008

consul:
  host: 10.21.20.53:8500
  register_service: true
  cacert: /etc/consul/certificates/ca.pem
  cert: /etc/consul/certificates/cert.pem
  key: /etc/consul/certificates/private_key.pem
  dc: de-west

bootstrap:
  dcs:
   ttl: 30
   loop_wait: 10

[...]

pg_hba:  # Add following lines to pg_hba.conf after running 'initdb'
- host replication replicator 127.0.0.1/32 md5
- host replication replicator 10.21.20.0/24 md5
- host all all 0.0.0.0/0 md5
- local all pmm md5

[...]

postgresql:
  listen: "*:5432"
  connect_address: 10.21.20.53:5432
  data_dir: /var/lib/postgresql/data

[...]

Natürlich müssen die entsprechenden Ports auch in der Nebula-Konfiguration bzw. in der defined-Role freigegeben werden:

[...]

firewall:
  outbound_action: drop
  inbound_action: drop

  conntrack:
    tcp_timeout: 12m
    udp_timeout: 3m
    default_timeout: 10m

  outbound:
    - port: any
      proto: any
      host: any

  inbound:
    - port: any
      proto: icmp
      host: any

    - port: 8600
      proto: tcp
      host: any

[...]

    - port: 5432
      proto: tcp
      host: any

    - port: 8008
      proto: tcp
      host: any

Beim Start von Patroni baut sich dann der Cluster auf:

postgres@postgresql-0:~$ patronictl -c patroni.yml list
+ Cluster: patroni42 (7550685979936816804) --+-----------+----+-----------+
| Member             | Host        | Role    | State     | TL | Lag in MB |
+--------------------+-------------+---------+-----------+----+-----------+
| prod1-postgresql-0 | 10.21.20.53 | Leader  | running   |  2 |           |
| prod4-postgresql-0 | 10.21.20.54 | Replica | streaming |  2 |         0 |
+--------------------+-------------+---------+-----------+----+-----------+

Für die Datenbank-Clients ist der Status des Clusters jederzeit per Consul-DNS zu erkennen, da Patroni den Dienst ja automatisch im Consul registiert hat:

root@triton-consul-0:~# consul catalog services -tags
consul         
patroni42      master,primary,replica
postgres@postgresql-0:~$ dig +short @10.21.20.53 -p 8600 consul.service.consul
10.21.20.50
10.21.20.52
10.21.20.51
postgres@postgresql-0:~$ dig +short @10.21.20.53 -p 8600 primary.patroni42.service.consul
10.21.20.53
postgres@postgresql-0:~$ dig +short @10.21.20.53 -p 8600 replica.patroni42.service.consul
10.21.20.54

Ich empfehle, DNS lokal so zu konfigurieren, dass Anfragen an die Domain "service.consul." immer an den lokalen Consul Client umgeleitet werden. Die Consul Dokumentation enthält dafür die entsprechenden Anleitungen. Ich hatte das unter "systemd-resolved vs. split-horizon DNS" auch schon beschrieben.

Natürlich kann und sollte man auch in so einem Setup dann "Percona Monitoring and Management - PMM" (inzwischen schon in der Version 3.4.0 erschienen) einsetzen, um einen Einblick in die Vorgänge im Cluster zu bekommen.