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 Netzwerk, Nodes, Disks, reservierte Adressen, DNS — genau so vorbereitet wie bei einer Installation mit nur einem 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 zuerst das Rechenzentrum, das PostgreSQL hostet, vollständig, und installiere niemals zwei Rechenzentren parallel. Dessen Installation erstellt die Datenbank, die Rollen und das Schema, das jedes andere Rechenzentrum wiederverwendet. Ein Rechenzentrum, das gegen eine Datenbank installiert wird, die noch nicht existiert, schlägt beim ersten Service fehl, der sich verbindet; zwei gleichzeitige Installationen laufen sich bei denselben Rollen und Schema-Migrationen in die Quere.

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

Die Dateien anlegen​

Jedes Rechenzentrum wird üblicherweise von seiner eigenen Jumpbox aus betrieben, was auch die Topologie ist, von der der Rest dieser Seite ausgeht. Jede Jumpbox enthält dann eine Konfiguration, ein Secrets-Verzeichnis, eine age-Identität und einen Vault — unter denselben Pfaden, weil es unterschiedliche Maschinen sind:

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 erfordert eine Jumpbox pro Rechenzentrum — was erforderlich ist, ist, dass keine zwei Rechenzentren aus einem Secrets-Verzeichnis installiert werden. Wenn eine einzelne Jumpbox die gesamte Installation steuert, gib jedem Rechenzentrum seine eigene Konfigurationsdatei und sein eigenes Verzeichnis dort und verwende diese Pfade überall dort, wo diese Seite /etc/codesphere/config.yaml oder /etc/codesphere/secrets schreibt:

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

Das gemeinsame Nutzen eines Verzeichnisses zerstört stillschweigend den Vault des ersten Rechenzentrums, siehe seine eigene Konfiguration.

Den Vault des zweiten Rechenzentrums ableiten​

Der Vault von Rechenzentrum 2 muss die gemeinsamen Einträge von Rechenzentrum 1 byte-identisch sowie seine eigenen rechenzentrumsspezifischen Einträge enthalten. Leite ihn ab, anstatt einen von Grund auf neu zu erzeugen: kopiere, entferne, was zu den Clustern von Rechenzentrum 1 gehört, und lass oms genau diese neu generieren.

Prüfe zunächst, ob der Vault von Rechenzentrum 1 bereits openFgaPresharedKey enthält. Vaults, die erstellt wurden, bevor oms diesen Schlüssel generierte, tun dies nicht, und ein abgeleiteter Vault ohne ihn erhält im Schritt oms update install-config unten einen neuen, anderen Schlüssel — was jeden OpenFGA-Aufruf von Rechenzentrum 2 aus zunichtemacht. Der Befehl gibt entweder den Namen des Eintrags oder nichts aus:

# On jumpbox 1.
SOPS_AGE_KEY_FILE=/etc/codesphere/secrets/age_key.txt \
sops --decrypt /etc/codesphere/secrets/prod.vault.yaml \
| yq '.secrets[] | select(.name == "openFgaPresharedKey") | .name'

Wenn nichts ausgegeben wird, führe zunächst oms update install-config auf Jumpbox 1 aus, wie in Das erste Rechenzentrum konfigurieren gezeigt.

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

# 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 == "acmeCustomDomainsEabMacKey"
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 einzigen gemeinsam genutzten Jumpbox ist das eine Maschine und ein Schritt weniger: Überspringe die Übertragung und verschlüssele direkt nach /etc/codesphere/secrets-dc2/prod.vault.yaml, unter Verwendung der eigenen age-Identität dieses Verzeichnisses.

cephSshPrivateKey wird zusammen mit den anderen ceph*-Namen entfernt, muss aber, anders als die Ceph- Cluster-Zugangsdaten, vor der Installation wieder vorhanden sein — der Installer benötigt ihn, um die Ceph-Hosts von Rechenzentrum 2 zu erreichen. selfSignedCaKeyPem ebenso. Das Neugenerieren beider, zusammen mit den dazugehörigen Konfigurationsfeldern, ist das, was der nächste Schritt tut.

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

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
customDomainsEabKeyId: '' # likewise, for custom-domain certificates

Lass dann auf Jumpbox 2 oms das Fehlende ergänzen. Es generiert jedes fehlende Secret und schreibt das dazugehörige Konfigurationsfeld, sodass die beiden Hälften nie inkonsistent zueinander sein 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

Es meldet, was es hinzufügen wird, und fragt vor dem Schreiben nach; --yes bestätigt im Voraus.

warnung

Setze SOPS_AGE_KEY_FILE für den Vault, an dem gerade gearbeitet wird, wie oben. Dies hat Vorrang vor der Identität neben dem Vault, sodass auf einer gemeinsam genutzten Jumpbox ein von Rechenzentrum 1 übrig gebliebener Wert den Vault von Rechenzentrum 2 für den Empfänger von Rechenzentrum 1 neu verschlüsselt — und eine Jumpbox, die nur ihren eigenen Schlüssel besitzt, kann ihn dann nicht mehr lesen.

Eine External Account Binding kann nicht lokal neu generiert werden: Besorge eine neue von deiner ACME-CA und setze acmeEabMacKey und codesphere.certIssuer.acme.eabKeyId gemeinsam. Das Gleiche gilt für acmeCustomDomainsEabMacKey und codesphere.certIssuer.acme.customDomainsEabKeyId, das eine eigene Bindung benötigt, die sich von der ersten unterscheidet.

Validiere abschließend das Dateipaar jedes Rechenzentrums, wie in Bevor du installierst beschrieben.

Die Installationen durchführen​

Zuerst Rechenzentrum 1, von Jumpbox 1 aus, und erst danach Rechenzentrum 2 von Jumpbox 2 aus. Der Befehl ist auf beiden gleich — jede Jumpbox enthä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 benötigt postgres nicht in der Kommandozeile — operations.skip in seiner Konfiguration übernimmt das, was einen Kollegen davon abhält, den gemeinsamen Server durch einen manuellen erneuten Lauf zu berühren. Jeder andere Schritt läuft in jedem Rechenzentrum.

warnung

Von einer gemeinsam genutzten Jumpbox aus zeigt jeder Lauf mit -c, -k und --vault auf einen anderen Satz von Dateien: drei Flags, drei Möglichkeiten, sie zu vertauschen. Das Wiederverwenden des --vault von Rechenzentrum 1 für Rechenzentrum 2 zerstört den Vault von Rechenzentrum 1; das Wiederverwenden seines -c installiert die Nodes von Rechenzentrum 2 mit der Identität von Rechenzentrum 1. oms install codesphere protokolliert eine Warnung, wenn die Konfiguration und der Vault nicht übereinstimmen — ignoriere sie nicht:

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

Sichere jede Konfiguration, jeden verschlüsselten Vault und jede age-Identität in einem zugelassenen Secret-Speicher. Eine age-Identität ist erforderlich, um dessen Rechenzentrum wiederherzustellen oder zu aktualisieren.

Die Installation verifizieren​

Führe zunächst die normalen Prüfungen für ein einzelnes Rechenzentrum aus (siehe Den Installer ausführen) in jedem Rechenzentrum, dann die vier unten stehenden Prüfungen.

Jeder Cluster ist eigenständig​

Auf einem Control-Plane-Node jedes Rechenzentrums:

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

Die Node-Liste muss mit den kubernetes.controlPlanes und kubernetes.workers dieses Rechenzentrums übereinstimmen. Wenn beide Befehle dieselbe Liste zurückgeben, zeigen die beiden Konfigurationen auf einen Cluster — prüfe kubernetes.apiServerHost und den kubeConfig-Eintrag in jedem Vault.

Die Ceph-Cluster müssen ebenfalls 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-Node jedes Rechenzentrums:

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

Jeder Cluster muss dieselbe availableDcs-Liste melden — jedes Rechenzentrum der Installation — mit currentDc, das auf seine eigene dataCenter.id gesetzt ist. Eine Liste, die nur das lokale Rechenzentrum enthält, bedeutet, dass dataCenters in dieser Konfiguration weggelassen wurde.

Beide Rechenzentren schreiben in dieselbe Datenbank​

Erstelle in jedem Rechenzentrum einen Workspace und frage dann den gemeinsamen Server ab. Jede Workspace- Zeile trägt die ID des Rechenzentrums, in dem sie läuft, sodass eine Zeile pro Rechenzentrum nur möglich ist, 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

Wenn die Workspaces von Rechenzentrum 2 fehlen, sprechen dessen Services mit einer anderen Datenbank — prüfe postgres.serverAddress in seiner Konfiguration. (codesphere ist der Standard- Datenbankname; verwende postgres.database, falls die Konfiguration ihn überschreibt.)

Eine Sitzung überspannt Rechenzentren​

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

  1. Melde dich unter https://cs.example.com an.
  2. Wechsle in der Auswahl zum anderen Rechenzentrum. Wenn die Auswahl nur eines anbietet, gehe zur obigen Topologieprüfung zurück.
  3. Erstelle und öffne dort einen Workspace, ohne dich erneut anzumelden.
  4. Öffne darin ein Terminal und erreiche es per SSH unter seinem Namen *.<dc-id>.ssh.<base-domain>.

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

Den OpenFGA-Preshared-Key in einer laufenden Installation teilen​

Eine Installation, die eingerichtet wurde, bevor oms openFgaPresharedKey generierte, hat in keinem Vault einen Schlüssel. Eine, bei der der Schlüssel durch Ausführen von oms update install-config auf jeder Jumpbox hinzugefügt wurde, hat in jedem einen anderen Schlüssel. Vergleiche die Vaults per Hash, damit der Schlüssel niemals in einem Terminal erscheint:

# On every jumpbox.
SOPS_AGE_KEY_FILE=/etc/codesphere/secrets/age_key.txt \
sops --decrypt /etc/codesphere/secrets/prod.vault.yaml \
| yq '.secrets[] | select(.name == "openFgaPresharedKey") | .fields.password' \
| sha256sum

Derselbe Hash überall bedeutet, dass nichts zu tun ist. e3b0c442… ist der Hash eines leeren Werts: dieser Vault hat keinen Schlüssel.

warnung

Behebe dies nicht, indem du oms update install-config auf den Jumpboxes ausführst, denen der Schlüssel fehlt. Jeder Lauf generiert seinen eigenen Zufallswert, sodass die Rechenzentren am Ende unterschiedliche Schlüssel haben und OpenFGA alle bis auf einen ablehnt.

Übernimm den Wert aus dem Vault des Rechenzentrums, das OpenFGA bereitstellt. Wenn dieser Vault ebenfalls keinen Schlüssel hat, generiere dort einen, im selben Format, das oms verwendet:

openssl rand -hex 32

Schreibe diesen Wert in jeden Vault, dem er fehlt oder der einen anderen enthält. sops edit entschlüsselt den Vault nur im Editor und verschlüsselt ihn beim Speichern erneut:

SOPS_AGE_KEY_FILE=/etc/codesphere/secrets/age_key.txt \
sops edit /etc/codesphere/secrets/prod.vault.yaml
secrets:
# ... existing entries
- name: openFgaPresharedKey
fields:
password: <the 64 hexadecimal characters>

Rolle ihn dann aus, Rechenzentrum für Rechenzentrum: zuerst jedes Rechenzentrum, das OpenFGA nur aufruft, zuletzt das, das es bereitstellt.

  1. Wende dessen Plattform erneut an mit oms install codesphere, wobei die Infrastruktur- Schritte übersprungen werden, wie in Schritt 6 von Ein Rechenzentrum zu einer laufenden Installation hinzufügen. Dies synchronisiert den Vault in den Cluster. In dem Rechenzentrum, das OpenFGA bereitstellt, schaltet dies auch die Authentifizierung von OpenFGA ein, falls sie aus war.

  2. Erzwinge, dass der Schlüssel aus dem Vault ausgelesen wird. Die ExternalSecrets, die ihn in die Services und in OpenFGA kopieren, lesen den Vault nur alle 24 Stunden neu ein:

    # On a control plane node of that data center.
    KUBECTL="/etc/codesphere/deps/kubernetes/files/k0s kubectl"
    $KUBECTL -n codesphere get externalsecret -o name | grep openfga-token \
    | xargs -I{} $KUBECTL -n codesphere annotate {} force-sync="$(date +%s)" --overwrite
    # Only in the data center that deploys OpenFGA:
    $KUBECTL -n openfga annotate externalsecret openfga-preshared-keys \
    force-sync="$(date +%s)" --overwrite
  3. Starte neu, was den Schlüssel liest. Die Services und OpenFGA lesen ihn nur beim Start ein:

    $KUBECTL -n codesphere rollout restart deployment
    # Only in the data center that deploys OpenFGA:
    $KUBECTL -n openfga rollout restart deployment
warnung

In dem Rechenzentrum, das OpenFGA bereitstellt, schlagen Autorisierungsprüfungen von dem Moment an fehl, in dem Schritt 1 die Authentifizierung einschaltet, bis Schritt 3 die Services neu gestartet hat. Führe die drei Schritte dort unmittelbar nacheinander aus.

Ein Rechenzentrum zu einer laufenden Installation hinzufügen​

Das bestehende Rechenzentrum läuft während des gesamten Vorgangs weiter; es benötigt eine Konfigurationsaktualisierung und am Ende einen erneuten Lauf der Plattforminstallation.

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

  2. Bereite seine Infrastruktur vor, wie bei einer Installation mit nur einem Rechenzentrum — einschließlich einer eigenen Jumpbox und der Konnektivität von seinen Nodes zum bestehenden PostgreSQL-Server über TCP 5432.

  3. Leite seine Konfiguration und seinen Vault ab von denen des bestehenden Rechenzentrums, wie oben. Das ist der Weg, wie die gemeinsamen Rollen und Token-Schlüssel übertragen werden. Ein bestehendes Rechenzentrum stammt oft aus einer Zeit vor openFgaPresharedKey; die Prüfung am Anfang dieses Abschnitts erkennt das.

  4. Aktualisiere DNS. Füge die Einträge des neuen Rechenzentrums hinzu — sowie die <dc-id>.<codesphere.domain>- Einträge des bestehenden Rechenzentrums und den Eintrag für das expose.host von OpenFGA, die eine Installation mit nur einem Rechenzentrum nie benötigte. Verifiziere sie von außerhalb des privaten Netzwerks.

  5. Installiere das neue Rechenzentrum von seiner eigenen Jumpbox aus. Das bestehende hostet bereits PostgreSQL und ist bereits vollständig, sodass die Reihenfolgeregel erfüllt ist.

  6. Aktualisiere die Konfiguration des bestehenden Rechenzentrums mit der dataCenters-Liste, die beide Rechenzentren enthält, und defaultDataCenterId, und wende dann seine Plattform erneut an:

    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

    Wenn das neue Rechenzentrum das gemeinsame OpenFGA betreiben soll, setze auch codesphere.openFga.apiUrl in der Konfiguration des bestehenden Rechenzentrums.

    Wenn openFgaPresharedKey in Schritt 3 nur zum Vault dieses Rechenzentrums hinzugefügt wurde, schaltet diese erneute Anwendung dessen OpenFGA-Authentifizierung ein. Folge unmittelbar mit den Schritten 2 und 3 aus Den OpenFGA-Preshared-Key in einer laufenden Installation teilen.

  7. Verifiziere mit den obigen Prüfungen. Beide Cluster müssen jetzt beide Rechenzentren melden.

warnung

Schritt 6 lässt sich leicht aufschieben und leicht vergessen. Sein Fehlen ist in keiner Gesundheitsprüfung sichtbar: beide Cluster sind grün, beide bedienen ihre eigenen Workspaces, und das einzige Symptom ist, dass Benutzer des bestehenden Rechenzentrums das neue nie in der Auswahl sehen.

Auf GCP testen​

Zu Evaluierungszwecken stellt oms beta bootstrap-gcp --multi-dc eine vollständige Zwei-Rechenzentren-Installation in einem GCP-Projekt bereit und wendet dabei automatisch alles auf dieser Seite 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 die VPC, die PostgreSQL-VM des Projekts und — anders als bei einem Produktionssetup — eine einzige Jumpbox; jedes erhält seine eigenen drei Ceph-Nodes, drei k0s-Nodes und drei statische Adressen. Die Ressourcen von Rechenzentrum 2 tragen daher ein -dc2-Suffix, einschließlich /etc/codesphere/config-dc2.yaml und /etc/codesphere/secrets-dc2/ auf dieser Jumpbox, was dem oben beschriebenen Layout mit gemeinsam genutzter Jumpbox entspricht.

Zwei Rechenzentren bedeuten 14 VMs (~100 vCPUs) und 6 regionale statische Adressen, sodass die Kontingente der Region üblicherweise zuerst erhöht werden müssen. --multi-dc kann nicht mit --datacenter-id kombiniert werden — die IDs werden abgeleitet (1 und 2), weil sie die rechenzentrumsspezifischen Domains steuern. Das Bootstrap bedient Workspaces unter <dc-id>.ws.<base-domain> und SSH unter *.<dc-id>.ssh.cs.<base-domain>, statt dem in den Beispielen dieser Seite verwendeten Schema; nur die DNS-Einträge und workspaceHostingBaseDomain müssen miteinander übereinstimmen.

oms beta bootstrap-gcp ist nicht für den Produktivbetrieb bestimmt. Siehe die bootstrap-gcp-Dokumentation für die vollständige Liste der Flags.