Zum Hauptinhalt springen
Version: Weekly Build

Mehrere Rechenzentren: Installation

Bevor du beginnst

Eine Konfiguration und ein Vault pro Rechenzentrum, vorbereitet wie in Mehrere Rechenzentren: Konfiguration beschrieben, sowie die Infrastruktur jedes Rechenzentrums — privates Netz, Knoten, Datenträger, reservierte Adressen, DNS — vorbereitet genau wie für eine Installation mit einem einzelnen Rechenzentrum.

Jedes Rechenzentrum wird durch einen eigenen oms install codesphere-Lauf gegen seine eigene Konfigurationsdatei installiert. Es gibt keinen einzelnen Befehl, der die gesamte Installation durchführt.

Installationsreihenfolge

Installiere das Rechenzentrum, das PostgreSQL betreibt, zuerst vollständig, und installiere niemals zwei Rechenzentren parallel. Seine Installation legt die Datenbank, die Rollen und das Schema an, die jedes andere Rechenzentrum weiterverwendet. Ein Rechenzentrum, das gegen eine noch nicht existierende Datenbank installiert wird, scheitert am ersten Service, der sich verbindet; zwei gleichzeitige Installationen konkurrieren um dieselben Rollen und Schema-Migrationen.

"Vollständig" heißt, dass die Installation erfolgreich zurückgekehrt ist und die Prüfungen unter Die Installation verifizieren für dieses Rechenzentrum bestehen.

Die Dateien anlegen

Jedes Rechenzentrum wird üblicherweise von seiner eigenen Jumpbox aus betrieben, und genau diese Topologie setzt der Rest dieser Seite voraus. Jede Jumpbox hält dann eine Konfiguration, ein Secrets-Verzeichnis, eine age-Identität und ein Vault — unter denselben Pfaden, denn es sind verschiedene Maschinen:

jumpbox 1 (data center 1) jumpbox 2 (data center 2)
/etc/codesphere/config.yaml /etc/codesphere/config.yaml
/etc/codesphere/secrets/ /etc/codesphere/secrets/
age_key.txt age_key.txt (its own identity)
prod.vault.yaml prod.vault.yaml (derived from jumpbox 1's)
install -d -m 0700 /etc/codesphere/secrets # on each jumpbox

Nichts an der Installation verlangt eine Jumpbox pro Rechenzentrum — verlangt wird, dass keine zwei Rechenzentren aus einem Secrets-Verzeichnis installiert werden. Betreibt eine einzelne Jumpbox die gesamte Installation, gib jedem Rechenzentrum dort seine eigene Konfigurationsdatei und sein eigenes Verzeichnis, und verwende diese Pfade überall dort, wo auf dieser Seite /etc/codesphere/config.yaml oder /etc/codesphere/secrets steht:

/etc/codesphere/config.yaml /etc/codesphere/config-dc2.yaml
/etc/codesphere/secrets/ /etc/codesphere/secrets-dc2/

Ein gemeinsames Verzeichnis zerstört das Vault des ersten Rechenzentrums stillschweigend, siehe Seine eigene Konfiguration.

Das Vault des zweiten Rechenzentrums ableiten

Das Vault von Rechenzentrum 2 muss die geteilten Einträge von Rechenzentrum 1 byte-identisch tragen und seine eigenen rechenzentrumsspezifischen Einträge enthalten. Leite es ab, statt eines von Grund auf zu erzeugen: kopieren, alles entfernen, was zu den Clustern von Rechenzentrum 1 gehört, und oms genau das neu erzeugen lassen.

Beginne auf Jumpbox 2, mit ihrer eigenen age-Identität. Ihr öffentlicher Empfänger ist das, wofür Jumpbox 1 das Ergebnis verschlüsselt — so ist das abgeleitete Vault während der Übertragung nie lesbar und der Klartext verlässt Jumpbox 1 nie:

# On jumpbox 2.
install -d -m 0700 /etc/codesphere/secrets
age-keygen -o /etc/codesphere/secrets/age_key.txt
chmod 0600 /etc/codesphere/secrets/age_key.txt
age-keygen -y /etc/codesphere/secrets/age_key.txt # age1... — take this along
# On jumpbox 1.
umask 077

# 1. Data center 1's vault as a starting point.
SOPS_AGE_KEY_FILE=/etc/codesphere/secrets/age_key.txt \
sops --decrypt /etc/codesphere/secrets/prod.vault.yaml > /tmp/dc2.vault.yaml

# 2. Drop everything that belongs to data center 1's clusters.
yq -i 'del(.secrets[] | select(.name | test("^(ceph|csi|rgw)")))' /tmp/dc2.vault.yaml
yq -i 'del(.secrets[] | select(.name == "selfSignedCaKeyPem"
or .name == "kubeConfig"
or .name == "acmeEabMacKey"
or .name == "privNixSigningKey"
or .name == "pubNixSigningKey"))' /tmp/dc2.vault.yaml

# 3. Encrypt to jumpbox 2's recipient and hand it over.
sops --encrypt --age age1... /tmp/dc2.vault.yaml > /tmp/dc2.vault.enc.yaml
shred -u /tmp/dc2.vault.yaml
scp /tmp/dc2.vault.enc.yaml jumpbox2:/etc/codesphere/secrets/prod.vault.yaml
shred -u /tmp/dc2.vault.enc.yaml

Auf einer einzelnen gemeinsamen Jumpbox ist das eine Maschine und ein Schritt weniger: lass die Übertragung weg und verschlüssele direkt nach /etc/codesphere/secrets-dc2/prod.vault.yaml, mit der age-Identität dieses Verzeichnisses.

cephSshPrivateKey wird zusammen mit den übrigen ceph*-Namen entfernt, muss aber — anders als die Ceph-Cluster-Zugangsdaten — vor der Installation wieder vorhanden sein: der Installer braucht ihn, um die Ceph-Hosts von Rechenzentrum 2 zu erreichen. Für selfSignedCaKeyPem gilt dasselbe. Beide neu zu erzeugen, zusammen mit den zugehörigen Konfigurationsfeldern, ist genau das, was der nächste Schritt tut.

Kopiere die config.yaml von Rechenzentrum 1 auf Jumpbox 2 und passe sie zur Konfiguration von Rechenzentrum 2 an, wie in Mehrere Rechenzentren: Konfiguration beschrieben — einschließlich des Leerens der drei Felder, deren Schlüssel du gerade entfernt hast:

cluster:
certificates:
ca:
certPem: '' # regenerated with selfSignedCaKeyPem
ceph:
cephAdmSshKey:
publicKey: '' # regenerated with cephSshPrivateKey
codesphere:
certIssuer:
acme:
eabKeyId: '' # only if you use ACME with external account binding

Lass anschließend auf Jumpbox 2 oms ergänzen, was fehlt. Es erzeugt jedes fehlende Secret und schreibt das zugehörige Konfigurationsfeld, sodass die beiden Hälften nie auseinanderlaufen können:

SOPS_AGE_KEY_FILE=/etc/codesphere/secrets/age_key.txt \
oms update install-config \
--config /etc/codesphere/config.yaml \
--vault /etc/codesphere/secrets/prod.vault.yaml

Der Befehl zeigt an, was er hinzufügen will, und fragt vor dem Schreiben nach; --yes stimmt vorab zu.

warnung

Setze SOPS_AGE_KEY_FILE wie oben für das Vault, an dem du gerade arbeitest. Die Variable hat Vorrang vor der Identität neben dem Vault; auf einer gemeinsamen Jumpbox verschlüsselt ein von Rechenzentrum 1 übriggebliebener Wert das Vault von Rechenzentrum 2 also für den Empfänger von Rechenzentrum 1 — und eine Jumpbox, die nur ihren eigenen Schlüssel hat, kann es dann nicht mehr lesen.

Ein External Account Binding lässt sich nicht lokal neu erzeugen: hole ein neues von deiner ACME-CA und setze acmeEabMacKey und codesphere.certIssuer.acme.eabKeyId gemeinsam.

Validiere zum Schluss das Dateipaar jedes Rechenzentrums, wie unter Vor der Installation beschrieben.

Die Installationen durchführen

Rechenzentrum 1 zuerst, von Jumpbox 1 aus, und erst danach Rechenzentrum 2 von Jumpbox 2 aus. Der Befehl ist auf beiden derselbe — jede Jumpbox hält nur die Dateien ihres eigenen Rechenzentrums:

# On jumpbox 1: the data center that hosts PostgreSQL. Must finish and verify first.
# Then the same command on jumpbox 2.
oms install codesphere \
-c /etc/codesphere/config.yaml \
-k /etc/codesphere/secrets/age_key.txt \
--vault /etc/codesphere/secrets/prod.vault.yaml \
-p codesphere-<version>-installer-lite.tar.gz \
-s load-container-images

Rechenzentrum 2 braucht postgres nicht auf der Kommandozeile — operations.skip in seiner Konfiguration trägt es bereits, und genau das verhindert, dass ein manueller Lauf einer Kollegin den geteilten Server anfasst. Jeder andere Schritt läuft in jedem Rechenzentrum.

warnung

Von einer gemeinsamen Jumpbox aus richtet jeder Lauf -c, -k und --vault auf einen anderen Satz Dateien: drei Flags, drei Gelegenheiten, sie zu verwechseln. Das --vault von Rechenzentrum 1 für Rechenzentrum 2 wiederzuverwenden beschädigt das Vault von Rechenzentrum 1; sein -c wiederzuverwenden installiert die Knoten von Rechenzentrum 2 mit der Identität von Rechenzentrum 1. oms install codesphere gibt eine Warnung aus, wenn Konfiguration und Vault nicht zusammenpassen — ignoriere sie nicht:

Warning: config secrets.baseDir (/etc/codesphere/secrets) does not match the directory of --vault (/etc/codesphere/secrets-dc2)

Sichere jede Konfiguration, jedes verschlüsselte Vault und jede age-Identität in einem freigegebenen Secret-Store. Ohne die age-Identität lässt sich ihr Rechenzentrum weder wiederherstellen noch aktualisieren.

Die Installation verifizieren

Führe zuerst in jedem Rechenzentrum die üblichen Prüfungen für ein einzelnes Rechenzentrum durch (siehe Den Installer ausführen), danach die vier Prüfungen unten.

Jedes Cluster steht für sich

Auf einem Control-Plane-Knoten jedes Rechenzentrums:

/etc/codesphere/deps/kubernetes/files/k0s kubectl get nodes -o wide

Die Knotenliste muss zu kubernetes.controlPlanes und kubernetes.workers dieses Rechenzentrums passen. Liefern beide Befehle dieselbe Liste, zeigen die beiden Konfigurationen auf ein Cluster — prüfe kubernetes.apiServerHost und den Eintrag kubeConfig in jedem Vault.

Auch die Ceph-Cluster müssen getrennt sein. Ihre FSIDs müssen sich unterscheiden:

grep fsid /etc/ceph/ceph.conf # on each data center's Ceph master

Zwei identische FSIDs bedeuten, dass sich die Rechenzentren ein secrets.baseDir geteilt haben und eine Installation die Ceph-Zugangsdaten der anderen überschrieben hat.

Beide Rechenzentren kennen die vollständige Topologie

Auf einem Control-Plane-Knoten jedes Rechenzentrums:

/etc/codesphere/deps/kubernetes/files/k0s kubectl -n codesphere \
get configmap -l codesphere.com/purpose=config \
-o jsonpath='{.items[0].data.dataCenters}'

Jedes Cluster muss dieselbe availableDcs-Liste melden — jedes Rechenzentrum der Installation — mit currentDc auf seiner eigenen dataCenter.id. Eine Liste, die nur das lokale Rechenzentrum enthält, bedeutet, dass dataCenters in dieser Konfiguration fehlt.

Beide Rechenzentren schreiben in dieselbe Datenbank

Lege in jedem Rechenzentrum einen Workspace an und frage dann den geteilten Server ab. Jede Workspace-Zeile trägt die ID des Rechenzentrums, in dem sie läuft; je eine Zeile pro Rechenzentrum ist also nur möglich, wenn beide Cluster in dieselbe Datenbank schreiben:

psql "host=10.10.0.10 port=5432 dbname=codesphere user=postgres sslmode=verify-full" \
-c 'select data_center_id, count(*)
from "workspaceService".workspaces
group by data_center_id
order by data_center_id;'
data_center_id | count
----------------+-------
1 | 1
2 | 1

Fehlen die Workspaces von Rechenzentrum 2, sprechen dessen Services mit einer anderen Datenbank — prüfe postgres.serverAddress in seiner Konfiguration. (codesphere ist der Standardname der Datenbank; nutze postgres.database, falls die Konfiguration ihn überschreibt.)

Eine Sitzung überschreitet Rechenzentrumsgrenzen

Die Ende-zu-Ende-Prüfung, und diejenige, die einen abweichenden tokenPrivateKey oder einen fehlenden <dc-id>.<codesphere.domain>-DNS-Eintrag aufdeckt:

  1. Melde dich unter https://cs.example.com an.
  2. Wechsle in der Auswahl zum anderen Rechenzentrum. Wird nur eines angeboten, geh zurück zur Topologie-Prüfung oben.
  3. Lege dort einen Workspace an und öffne ihn, ohne dich erneut anzumelden.
  4. Öffne darin ein Terminal und erreiche ihn per SSH unter seinem Namen *.<dc-id>.ssh.<base-domain>.

Eine Weiterleitung zurück zur Anmeldeseite in Schritt 3 bedeutet, dass sich die Token-Schlüssel zwischen den Rechenzentren unterscheiden. Ein Verbindungsfehler, bevor irgendeine Oberfläche erscheint, bedeutet, dass <dc-id>.cs.example.com fehlt oder auf das falsche Gateway zeigt.

Ein Rechenzentrum zu einer laufenden Installation hinzufügen

Das bestehende Rechenzentrum läuft durchgehend weiter; es braucht am Ende eine Konfigurationsänderung und einen erneuten Lauf seiner Plattform-Installation.

  1. Planen. Wähle eine ungenutzte dataCenter.id und einen dataCenter.name, der sich von jedem bestehenden unterscheidet. Reserviere seine drei externen Adressen.

  2. Infrastruktur vorbereiten wie für eine Installation mit einem einzelnen Rechenzentrum — einschließlich seiner eigenen Jumpbox und der Erreichbarkeit des bestehenden PostgreSQL-Servers von seinen Knoten aus über TCP 5432.

  3. Konfiguration und Vault ableiten von denen des bestehenden Rechenzentrums, wie oben. Das ist es, was die geteilten Rollen und Token-Schlüssel hinüberträgt.

  4. DNS aktualisieren. Ergänze die Einträge des neuen Rechenzentrums — und die <dc-id>.<codesphere.domain>-Einträge des bestehenden Rechenzentrums, die eine Installation mit einem einzelnen Rechenzentrum nie brauchte. Prüfe sie von außerhalb des privaten Netzes.

  5. Das neue Rechenzentrum installieren, von seiner eigenen Jumpbox aus. Das bestehende betreibt PostgreSQL bereits und ist bereits vollständig, die Reihenfolgeregel ist also erfüllt.

  6. Die Konfiguration des bestehenden Rechenzentrums aktualisieren um die dataCenters-Liste mit beiden Rechenzentren und defaultDataCenterId, dann seine Plattform erneut ausrollen:

    oms install codesphere \
    -c /etc/codesphere/config.yaml \
    -k /etc/codesphere/secrets/age_key.txt \
    --vault /etc/codesphere/secrets/prod.vault.yaml \
    -p codesphere-<version>-installer-lite.tar.gz \
    -s copy-dependencies,extract-dependencies,load-container-images,docker,postgres,ceph,kubernetes

    Soll das neue Rechenzentrum die geteilte OpenFGA-Instanz betreiben, setze zusätzlich codesphere.openFga.apiUrl in der Konfiguration des bestehenden Rechenzentrums.

  7. Verifizieren mit den Prüfungen oben. Beide Cluster müssen nun beide Rechenzentren melden.

warnung

Schritt 6 wird leicht aufgeschoben und leicht vergessen. Sein Fehlen ist in jeder Gesundheitsprüfung unsichtbar: beide Cluster sind grün, beide bedienen ihre eigenen Workspaces, und das einzige Symptom ist, dass die Nutzenden des bestehenden Rechenzentrums das neue nie in der Auswahl sehen.

Auf GCP testen

Zur Evaluierung stellt oms beta bootstrap-gcp --multi-dc eine vollständige Installation mit zwei Rechenzentren in einem GCP-Projekt bereit und wendet alles auf dieser Seite automatisch an:

oms beta bootstrap-gcp \
--project-name multidc-test \
--billing-account "$BILLING_ACCOUNT" \
--base-domain oms-testing.example.com \
--multi-dc \
--datacenter-name multidc \
--install-version <version>

Die Rechenzentren teilen sich VPC und PostgreSQL-VM des Projekts sowie — anders als ein Produktivaufbau — eine einzelne Jumpbox; jedes erhält seine eigenen drei Ceph-Knoten, drei k0s-Knoten und drei statischen Adressen. Die Ressourcen von Rechenzentrum 2 tragen deshalb das Suffix -dc2, darunter /etc/codesphere/config-dc2.yaml und /etc/codesphere/secrets-dc2/ auf dieser Jumpbox — die oben beschriebene Ablage für eine gemeinsame Jumpbox.

Zwei Rechenzentren bedeuten 14 VMs (~100 vCPUs) und 6 regionale statische Adressen, die Quotas der Region müssen also meist zuerst erhöht werden. --multi-dc lässt sich nicht mit --datacenter-id kombinieren — die IDs werden abgeleitet (1 und 2), weil sie die rechenzentrumsspezifischen Domains bestimmen. Der Bootstrap bedient Workspaces unter <dc-id>.ws.<base-domain> und SSH unter *.<dc-id>.ssh.cs.<base-domain> statt nach dem Schema der Beispiele auf dieser Seite; nur die DNS-Einträge und workspaceHostingBaseDomain müssen zueinander passen.

oms beta bootstrap-gcp ist nicht für den Produktivbetrieb gedacht. Die vollständige Flag-Liste steht in der bootstrap-gcp-Dokumentation.