AZ-Kopplung bei Triton

Wenn man mehrere availability zones pro Region und möglicherweise sogar mehrere Regionen eines Cloud-Service betreibt, sollen Kunden natürlich in allen Rechenzentren VMs und/oder Container ausrollen können. Um dies zu erreichen, müssen die Kundeninformationen (insbesondere die Credentials) natürlich in jedem Rechenzentrum verfügbar sein. Dazu wird für den ufds-Dienst von Triton (der i. W. ein LDAP-Server ist) eine Replikationsbeziehung aufgesetzt. Dabei gibt es nur einen Master ufds-Dienst, an den alle anderen Regionen als Slaves angehängt werden.

Bevor man die Kopplung durchführen kann, müssen sich die zu koppelnden ufds-Instanzen netzwerktechnisch erreichen können. Ist das gewährleistet, kann auf dem Headnode des Slave Data Centers folgendes Kommando aufgerufen werden:

[root@headnode (my-dc-3) ~]# sdc-ufds-m2s  
---------------------------------------------------------------
Warning:
This command will delete all existing UFDS data and reconfigure
UFDS as a slave.
 
Ensure that the SAPI zone is up-to-date before proceeding.
---------------------------------------------------------------
Enter 'y' to continue: y
UFDS master IP address: 10.65.69.29
Deleting local UFDS data
ldap_delete: No such object (32)
        matched DN: o=smartdc
        additional info: region=GT, o=smartdc
Setting up UFDS replicator
Waiting for SAPI to update the replicator configuration...
Waiting for SAPI to update the replicator configuration...
Waiting for SAPI to update the replicator configuration...
Waiting for SAPI to update the replicator configuration...
Waiting for SAPI to update the replicator configuration...
Waiting for SAPI to update the replicator configuration...
Waiting for SAPI to update the replicator configuration...
There are 199 changelog entries to be replicated
Waiting for the admin user to be replicated (0%)...
Re-loading local amon probe data
adding new entry "amonprobegroup=789fe866-1156-c52b-a8b0-f37f6cf18d5a, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
 
adding new entry "amonprobegroup=d82c2eb0-688d-e998-d9ab-d56bd77037dd, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
 
adding new entry "amonprobe=a3771535-b618-ec81-f188-d8ce6710b2e3, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
 
adding new entry "amonprobegroup=1eebd6cc-bde1-47f6-9a68-b8276d094837, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
 
adding new entry "amonprobe=7a1b6eca-d186-e325-ef1e-a0f6f127df74, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
                         
adding new entry "amonprobe=7f2db04b-f277-e3b7-8249-daca75a2d6be, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
                       
adding new entry "amonprobe=00bab3bf-eb71-ed5c-85fb-f12118dc8fde, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
                      
adding new entry "amonprobegroup=9ddf7871-76f7-4572-883c-b4551e8ae751, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"

adding new entry "amonprobe=799311a9-f3bc-c6f3-8dac-b3e4e3bc3b39, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
 
adding new entry "amonprobe=16d71d13-3b56-6738-dd64-b4eba69a9fde, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"

adding new entry "amonprobe=1dc103ea-3bf4-cbc8-c199-9d8c1f0a2de7, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
                                                                       [...]
                                                                       
adding new entry "amonprobegroup=232a168a-dc45-4e4b-a38f-eb81c3192182, uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc"
 
Downloading SAPI metadata to /var/tmp/metadata.json

Verifying local ufds at 127.0.0.1

Verifying remote ufds at 10.65.69.29

Datacenter information not found in ufds.  Need to load data...

Reconciling local data

ldap_add: Already exists (68)
    matched DN: o=smartdc
    additional info: ou=users, o=smartdc
ldap_add: Already exists (68)
    matched DN: o=smartdc
    additional info: ou=groups, o=smartdc

[...]

ldap_add: Already exists (68)
    matched DN: o=smartdc
    additional info: uuid=930896af-bf8c-48d4-885c-6573a94b1853, ou=users, o=smartdc
ldap_add: Already exists (68)
    matched DN: o=smartdc
    additional info: cn=operators, ou=groups, o=smartdc
Reconciling (possible) remote data
Done with reconciliation.
Updating config files
Done
[root@headnode (my-dc-3) ~]#

Nachdem die Kopplung erfolgreich durchgeführt wurde, kann dann noch der public ssh key der ufds zone (des Slave Data Centers) dem admin user des Master Data Centers hinzugefügt werden. Auch dieses Kommando wird auf dem Head Node des Slave Data Centers aufgerufen:

headnode# sdc-useradm add-key admin /zones/$(sdc-vmname cloudapi)/root/root/.ssh/sdc.id_rsa.pub

OK. Offensichtlich ist es doch nicht ganz so einfach. Sicherer ist es, den public key per cut'n paste in die Adminui des Master Data Centers einzutragen. Obwohl man es aus dem Diagramm möglicherweise erkennen könnte, wird es in der Dokumentation nicht erwähnt: Auch die adminui- und die cloudapi-zone müssen mit der ufds-zone des Master Data Centers sprechen können. Ist das nicht der Fall, merkt man es als erstes beim Healthcheck: cloudapi ist unhealthy:

[root@headnode (my-dc-3) ~]# sdcadm check-health cloudapi
INSTANCE                              SERVICE   HOSTNAME  ALIAS      HEALTHY           
d171be53-a922-4f14-86bd-10e8ac1c33e2  cloudapi  headnode  cloudapi0  false             
1a1d3a3a-d9c5-11e3-b6ed-70e2840736be  global    headnode  global     true              
d171be53-a922-4f14-86bd-10e8ac1c33e2 ping check to 10.65.70.35 failed with HTTP code 503
sdcadm check-health: error: Some instances appear unhealthy
[root@headnode (my-dc-3) ~]# sdc-healthcheck |grep -i error                            
cloudapi                             running         -                    error

An dieser Stelle hilft dann aber doch wieder die Dokumentation weiter. Wir lernen, dass es "zone-specific checks" gibt. Im Fall von cloudapi wird sdc-listdatacenters aufgerufen. Der Aufruf (und die Antwort) auf dem Master Data Center sieht ungefähr so aus:

[root@99e7294e-9885-4c43-8921-4cb7fa1f13d7 (my-dc-2:cloudapi0) /opt/smartdc/cloudapi/etc]# sdc-listdatacenters --account admin  --keyId 5c:b7:25:ef:ec:b4:f3:d3:67:b5:35:5a:c2:3c:b7:88 --url https://cloudapi.my-dc-2.cns.tgos.de
{                                          
  "my-dc-2": "https://cloudapi.my-dc-2.srv.tgos.de"                                    
}                                          
[root@99e7294e-9885-4c43-8921-4cb7fa1f13d7 (my-dc-2:cloudapi0) /opt/smartdc/cloudapi/etc]#

Im Slave sieht es derzeit so aus:

[root@d171be53-a922-4f14-86bd-10e8ac1c33e2 (my-dc-3:cloudapi0) ~]# sdc-listdatacenters --account admin --keyId cf:3d:8f:ff:f8:49:2f:61:5b:b0:5a:3f:03:93:97:db --url https://cloudapi.my-dc-3.cns.tgos.de
sdc-listdatacenters: error (ServiceUnavailable): CloudAPI service is currently unavailable
[root@d171be53-a922-4f14-86bd-10e8ac1c33e2 (my-dc-3:cloudapi0) ~]#

Und das ist auch genau die Fehlermeldung, die wir bekommen, wenn wir derzeit von aussen auf die cloudapi zugreifen wollen:

root@d4305de1-0cd7-c690-83c2-c47542f5512a:~# triton ls -l
triton instance list: error (ServiceUnavailable): CloudAPI service is currently unavailable
root@d4305de1-0cd7-c690-83c2-c47542f5512a:~#

Sobald die Netzwerkverbindung hergestellt ist, sieht es besser aus (wir möchten über das Admin-Netzwerk kommunizieren, deswegen haben wir in cloudapi und adminui jeweils eine Host-Route zur ufds-zone hinzugefügt (10.65.69.29)):

root@d4305de1-0cd7-c690-83c2-c47542f5512a:~# triton ls -l
ID                                    NAME             IMG                    BRAND  PACKAGE    STATE    FLAGS  PRIMARYIP    CREATED
d4305de1-0cd7-c690-83c2-c47542f5512a  ubuntu-dev       ubuntu-16.04@20170403  lx     sample-2G  running  -      10.65.71.11  2017-08-02T08:38:23.979Z
c526fe6e-517e-ee0b-a18e-f2db578a50f7  hungry_rosalind  cb41ecfc               lx     sample-1G  running  DF     10.65.71.12  2017-08-07T07:46:22.032Z

Und auch die Healthchecks sehen wieder gut aus:

[root@headnode (my-dc-3) ~]# sdcadm check-health cloudapi
INSTANCE                              SERVICE   HOSTNAME  ALIAS      HEALTHY
d171be53-a922-4f14-86bd-10e8ac1c33e2  cloudapi  headnode  cloudapi0  true
1a1d3a3a-d9c5-11e3-b6ed-70e2840736be  global    headnode  global     true
[root@headnode (my-dc-3) ~]#

Damit sind jetzt aber nur die ufds-Instanzen sowie die Cloudapis der Slave-Datacenter mit dem Master-Datacenter "verheiratet". Damit kann man schonmal auf eine einheitliche Userbasis zurückgreifen.

Um jetzt auch eine verteilte Manta-Installation hinzubekommen, müssen einige Vorbedingungen erfüllt sein. Zunächst müssen Region und DNS-Domain über alle AZs gleich sein. Das kann man gut an der binder-Konfiguration sehen:

[root@4a9baf47-34ec-4a84-9af5-548e1036f4dc (my-dc-1:binder0) /opt/smartdc/binder/etc]# less config.json
{
    "dnsDomain": "srv.tgos.de",
    "datacenterName": "my-dc-1",
    "recursion": {
        "regionName": "my-dc",
        "datacenterName": "my-dc-1",
        "dnsDomain": "srv.tgos.de",
        "ufds": {
            "url": "ldaps://ufds.my-dc-1.srv.tgos.de",
            "bindDN": "cn=root",
            "bindPassword": "secret",
            "cache": {
                "size": 5000,
                "expiry": 60
            },
            "maxConnections": 1,
            "retry": {
                "initialDelay": 1000,
                "retries": 3
            },
            "clientTimeout": 120000,
            "connectTimeout": 3000
        }
    }
}

Nur die Namen der Datacenter sollten sich natürlich unterscheiden. Weitere Vorbedingungen (aus einer Mail von Dave Pacheco):

There are also a few pieces of multi-DC setup that are not well-documented:
- Triton needs to be configured with cross-DC routes and DNS (see https://smartos.org/bugview/HEAD-2334)
- SAPI needs to be configured for multi-DC mode with a master (see https://smartos.org/bugview/SAPI-283, https://smartos.org/bugview/MANTA-3053)
- The `manta-shardadm` step must be run in the DC with the SAPI master (see https://smartos.org/bugview/MANTA-3055)
- You probably want to configure MUSKIE_MULTI_DC (see https://smartos.org/bugview/MANTA-3105)

Ich habe in den binder-Zonen der verschiedenen AZs jeweils Routen in die Admin-Netze der anderen AZs eingerichtet. Die ufds-Kopplung und die Kommunikation zwischen cloudapi und ufds erfolgt über das externe Interface. Um SAPI für den multi-DC Modus zu konfigurieren, habe ich zunächst ebenfalls die Routen zu den jeweils anderen Admin-Netzen in den sapi- und moray-Zonen gesetzt. Danach können sich alle sapi- und moray-Zonen über das Admin-Netz pingen. Danach wird nach der Anleitung aus dem oben genannten Ticket, die Konfiguration durchgeführt, um SAPI auf multi-DC Modus zu schalten:

[root@headnode (my-dc-3) ~]# sapi_svc=$(sdc-sapi /services?name=sapi | json -Ha uuid)
[root@headnode (my-dc-3) ~]# echo $sapi_svc
920f853e-8016-410a-8a96-88edcc17d57f       
[root@headnode (my-dc-3) ~]# sapiadm update $sapi_svc metadata.MASTER_MORAY_IP=moray.my-dc-2.srv.tgos.de
[root@headnode (my-dc-3) ~]# sapiadm update $sapi_svc metadata.MASTER_MORAY_PORT=2020
[root@headnode (my-dc-3) ~]# 
 
[root@headnode (my-dc-1) ~]# sapi_svc=$(sdc-sapi /services?name=sapi | json -Ha uuid) 
[root@headnode (my-dc-1) ~]# echo $sapi_svc
acd45d7d-de74-401f-a6cd-adefabded8d5       
[root@headnode (my-dc-1) ~]# sapiadm update $sapi_svc metadata.MASTER_MORAY_IP=moray.my-dc-2.srv.tgos.de               
[root@headnode (my-dc-1) ~]# sapiadm update $sapi_svc metadata.MASTER_MORAY_PORT=2020  
[root@headnode (my-dc-1) ~]#

Wichtig! Das Manta-Setup danach zunächst in der Manta-Zone des Master-DC beginnen. Fängt man in einem der Slave-DCs an, wird der poseidon-User mehrmals angelegt. Das führt dazu, dass dann der Manta-Hashring nicht mehr gespeichert werden kann. Manta-Init deshalb immer im DC mit der Primary SAPI ausführen.

Damit die Kommunikation der bereits ausgerollten Zonen (in Triton) mit den Zonen funktioniert, die beim Manta-Deployment ausgerollt werden, benötigen noch weitere Triton-Zonen zusätzliche Routen: imgapi, cnapi, vmapi.

Um  MUSKIE_MULTI_DC zu konfigurieren, muss man wie folgt vorgehen:

headnode $ app_uuid="$(sdc-sapi /applications?name=manta | json -Ha uuid)"
headnode $ echo '{ "metadata": { "MUSKIE_MULTI_DC": true } }' | \
    sapiadm update "$app_uuid"

Danach muss man noch alle Muskie-Dienste in jedem Datacenter einmal durchstarten:

headnode $ manta-oneach -s webapi 'svcadm restart "*muskie*"'

Ich bin allerdings nicht sicher, ob das vor oder nach dem eigentlichen Deployment passieren sollte. Im aktualisierten Manta Operator's Guide sieht es so aus, als wäre der Schritt nach dem Deployment durchzuführen (vorher gibt es ja auch keine muskie-Dienste zum durchstarten).