Clustering

Observera

Denna funktion är för närvarande en teknisk förhandsgranskning med följande tillfälliga begränsningar:

  • Om ett kluster går förlorat (quorum går förlorat) är det enda sättet att återhämta sig fabriksåterställning + återställning. Se till att säkerhetskopiera ofta. Framtida versioner kommer att innehålla metoder för att återställa data på disk.

  • Aktiv/passiv installation för att stödja kluster med två noder, antingen genom att använda etcd Learner eller Mirror, är ännu inte tillgänglig.

  • Systemtid mellan noder måste synkroniseras manuellt för tillfället. En framtida version kommer att innehålla automatisk klocksynkronisering.

NetHSM 4.0 och framåt stöder klustring för att synkronisera data direkt mellan flera NetHSM. Detta stödjer hög frekvens av nyckelgenereringar, hög tillgänglighet och lastbalansering. Ett NetHSM-kluster är baserat på etcd som använder Raft konsensusalgoritm för stark konsistens. Detta säkerställer att data (t.ex. nycklar) är korrekta i alla NetHSM:er vid alla tidpunkter.

Innan du sätter upp ett NetHSM-kluster bör du bekanta dig med denna teknik och dess begränsningar för att undvika oavsiktliga avbrott och dataförlust. Förutom det här dokumentet kan du även läsa etcd:s dokumentation.

Operational Redundancy

Vi kallar ”nod” för en NetHSM som förväntas ingå i ett kluster. Ett kluster med N noder fortsätter att fungera så länge som minst (N/2)+1 noder är friska och nåbara. Den minimala mängden friska, nåbara noder kallas quorum.

Detta innebär följande scenarier.

En nod går ner och Quorum uppnås ändå

I ett kluster med tre noder fortsätter de två andra noderna att fungera och hantera förfrågningar om en nod misslyckas (kraschar eller blir oåtkomlig på grund av nätverksförhållanden).

Om den felande noden fortfarande är frisk (t.ex. om det bara var ett nätverksproblem) kommer den inte att fungera när den är isolerad (inte ens skrivskyddad).

Men om noden återhämtar sig kommer den att återsynkroniseras med resten av klustret och bli funktionsduglig igen, utan att förlora data.

Om den aldrig återhämtar sig måste den tas bort från klustret (se nästa avsnitt), fabriksåterställas och gå igenom join-processen igen från början.

En nätverksdelning inträffar och kvorum uppnås fortfarande

Detta är bara en generalisering av det föregående scenariot. I ett kluster med 5 noder där t.ex. 3 noder befinner sig på en fysisk plats A och 2 noder på en annan plats B, skulle ett nätverksproblem som isolerar A och B innebära följande:

  • De 3 noderna på plats A uppfyller kravet på kvorum (3 i det här fallet), så de fortsätter att fungera.

  • De 2 noderna på plats B är inte uppfyller quorum (fortfarande 3), så de kommer att sluta fungera (även skrivskyddade).

  • Om nätverksproblemet är löst kommer de två noderna att ansluta sig till de tre andra noderna.

Quorum är varaktigt förlorat

Ett fel som leder till att alla undergrupper i klustret förlorar kvorum gör att klustret och dess data går helt förlorade, såvida inte felet åtgärdas. I så fall måste noderna fabriksåterställas och en säkerhetskopia måste återställas.

Detta kan t.ex. hända om en enda nod går sönder i ett kluster med 2 noder (där kvorum är 2). I den här situationen kan den felande noden inte tas bort från klustret i efterhand, eftersom den kvarvarande friska noden redan är ur funktion eftersom den har förlorat kvorum.

Därför rekommenderas det att alltid ha ett udda antal noder i ett kluster och att säkerhetskopiera ofta.

För att förtydliga är ** tillfälligt förlorat kvorum (t.ex. om du startar om alla noder i ett kluster tillsammans, eller om ett tillfälligt nätverksfel isolerar noder) inte ett problem: när tillräckligt många noder har återanslutits (utan att behöva återanslutas manuellt) för att nå kvorum kommer klustret att återuppta sin normala drift. Endast permanenta fel, t.ex. nätverksdelningar, felkonfigurationer i nätverket, autentiseringsproblem eller maskinvarufel, kräver manuell åtgärd.

Mer information finns i etcd:s VANLIGA FRÅGOR.

Kluster med 2 noder

Ett aktivt/passivt kluster med två noder stöds inte ännu, men kommer att läggas till i en framtida version. Vi rekommenderar att du inför en tredje nod, antingen en tredje NetHSM eller ett etcd-”vittne” som kan användas på vilken värd som helst. Se nästa avsnitt ”Vittne”.

Vittne

Klustrets natur med etcd gör det mer tillförlitligt ju fler noder det finns i klustret. Som förklaras i avsnittet Operational Redundancy bör kluster helst ha minst 3 noder för att ha utrymme att misslyckas, eftersom ett kluster med 2 noder kommer att misslyckas helt om bara en misslyckas.

Funktionen är dock utformad så att du inte behöver lägga till en fullständig, riktig NetHSM-enhet i ditt kluster för att nå ett stabilt antal noder. Istället kan du själv distribuera och lägga till en ”vittnes”-nod. En sådan nod är bara en instans av etcd som körs på den maskin du väljer (eller i en container) och är ansluten till klustret. Den kommer att identifieras som en normal nod av de riktiga enheterna i klustret och ta emot alla data och uppdateringar från enheterna (men du kommer naturligtvis inte att kunna utföra några HSM-operationer med den - den lagrar bara data).

Security Considerations

Vittnesnoden (eller någon med tillgång till den) har direkt tillgång till lagringsbackend för alla noder i klustret (t.ex. kan du dumpa alla poster och motsvarande värden med etcdctl get "/" "0").

Med undantag för konfigurationsversionen (/config/version, som alltid ska vara ”1”) är dock alla värden krypterade (med antingen en enhetsnyckel för nodspecifika värden eller domännycklar för andra), vilket säkerställer sekretessen för känsliga data.

Observera dock att en illasinnad nod kan:

  • skriva skräp som värde för en post i lagret, vilket leder till att noder misslyckas med att dekryptera det (vilket kan leda till krasch för vissa systemposter).

  • lista postnamn som användare, namnområden och nycklar, som du kan betrakta som känsliga.

Vad som delas mellan noderna

Att ha ett kluster av NetHSM:er innebär att de flesta data delas mellan dem. Alla tillägg, ändringar eller borttagningar av nycklar, användare eller namnrymder på en nod återspeglas så småningom på alla de andra. I allmänhet kommer alla operationer som ändrar tillstånd att ändra tillstånd för alla noder. Detta inkluderar åtgärden backup restore som fungerar som vanligt.

I följande avsnitt beskrivs vilka data som är helt lokala, vilka data som lagras i det delade etcd-lagret men som förblir nodspecifika och vilka data som är helt delade mellan noderna.

Inte lagrad i etcd

enhetsnyckel för varje nod lagras endast lokalt och delas aldrig mellan noderna.

Lagrad i etcd men Node-specifik

Följande data lagras i etcd i olika scopes för varje nod. Den är därför tillgänglig för varje nod men inte enhetlig mellan noderna (varje nod kan ha ett annat värde för denna data).

Configuration:

  • TLS certificates

  • clock configuration

  • network configuration

  • logging configuration

  • unattended boot configuration

  • upplåsningssalt (så att varje nod har sin egen lösenfras för upplåsning)

  • låst domännyckel

Observera att även om varje nod har sin egen version av den låsta domännyckeln (eftersom varje nod låser den med sin egen enhetsnyckel eller upplåsningspassfras), delas den underliggande domännyckeln **** mellan noderna (för åtkomst till deras delade HSM-data, t.ex. nycklar).

Lagrad i etcd och delad

Alla följande data lagras i etcd i det globala omfånget, så att de är enhetliga över alla noder i ett kluster:

HSM-data:

  • keys

  • users

  • namespaces

Configuration:

  • konfig/domänbutik version

  • Cluster CA (används för att autentisera noder över hela klustret)

  • backup passphrase and backup salt

Observera att för närvarande kan versionen av config/domänlagret endast vara version 1 (om din programvaruversion stöder klustring är det vad du har). Se avsnittet `Software Updates in Clusters” för mer information om säkerheten vid installation av programuppdateringar i ett kluster.

Creating a Cluster

Varje kluster startar från början med en enda nod. Nya noder kommer att ansluta sig till klustret en efter en.

Preparing Nodes

Nätverkstrafiken mellan noderna krypteras och autentiseras med hjälp av deras TLS-certifikat.

Alla noder som förväntas ingå i samma kluster måste först installera en gemensam certifikatutfärdare (CA) som gör det möjligt för dem att verifiera att andra noder är legitima.

I det följande utgår vi från att alla noder är nyligen provisionerade och i drift.

Networking

Nodes must first be reconfigured with their expected final network configuration using the /config/network endpoint (refer to the API documentation).

Skapa och installera en certifikatutfärdare

Användare bör skapa en CA på sina egna sätt och enligt sina egna operativa begränsningar, och se till att den tillåter åtminstone keyCertSign nyckelanvändning.

En minimal CA kan t.ex. skapas med openssl:

$ openssl genrsa -out CA.key 2048 # create a key
$ openssl req -x509 -new -nodes -key CA.key -sha256 -days 1825 -out CA.pem -addext keyUsage=critical,keyCertSign

Denna CA måste nu installeras på varje nod.

To do this, first generate a Certificate Signing Request (CSR) from the node with the /config/tls/csr.pem endpoint (refer to the API documentation).

Observera

För att kunna autentisera noder på rätt sätt förväntar sig klusterbackend (etcd) att varje nod har ett certifikat med ett korrekt ifyllt SAN-fält (Subject Alt Names). I synnerhet måste noder som förväntas nås endast via sin IP ha ett korrekt IP-SAN i sitt certifikat. IP-SAN kan begäras för CSR genom att prefixera ”IP:” till namnen, som i openssl:

"subjectAltNames": [ "normalname.org", "IP:192.168.1.1" ]

Med den erhållna CSR:n (låt oss kalla den nethsm.csr) kan vi sedan generera ett certifikat för den, klart att installeras. Till exempel med openssl:

$ openssl x509 -req -days 1825 -in nethsm.csr -CA CA.pem -copy_extensions copy \
    -CAkey CA.key -out new_cert.pem -set_serial 01 -sha256

Then install the obtained new_cert.pem with the /config/tls/cert.pem endpoint (refer to the API documentation).

Slutligen kan certifikatutfärdaren (CA.pem) nu installeras med slutpunkten /config/tls/cluster-ca.pem (se API-dokumentation). Detta är endast möjligt när det installerade TLS-certifikatet är signerat av det. I annat fall kommer åtgärden att avvisas.

Observera

Denna process måste upprepas för varje nod.

Klocksynkronisering

Se till att varje nod har försetts med en korrekt systemtid. Om inte, justera deras klockor med slutpunkten /config/time.

Adding a New Node

Att lägga till en nod i ett kluster görs i två steg:

  • registrera tillägget till klustret (via någon av dess medlemmar)

  • tala om för den nya noden att ansluta sig

Configure a Backup Passphrase

Kontrollera först att en säkerhetskopierad lösenfras har konfigurerats på den nod som ska användas för att registrera en ny deltagare (se API-dokumentationen för slutpunkten /config/backup-passphrase).

Registrering av en ny nod

Varning

När en nod registreras införs omedelbart en ny nod i klustret, vilket ändrar tröskelvärdet för kvorum, även om noden inte har anslutit sig ännu. Detta kan göra de befintliga noderna obrukbara tills den nya noden faktiskt har anslutit sig. Se API-dokumentation och avsnittet Operational Redundancy i det här dokumentet.

Ha till hands IP-adressen för den nod som ska ansluta sig. Den fullständiga URL (även kallad peer URL i etcd terminologi) för den noden kommer att vara https://<IP_of_node>:2380 (t.ex. https://192.168.1.1:2380). Porten måste vara 2380, så se till att alla brandväggar mellan noderna tillåter TCP-trafik på den porten.

Du kan dubbelkolla att webbadressen är korrekt genom att anropa GET /cluster/members på den nod som förväntas ansluta sig. Detta bör bara lista en medlem: sig själv.

Registrera sedan den förväntade URL:en på en befintlig nod i klustret (om du inte har ett kluster ännu gör du detta på den NetHSM som kommer att fungera som klustrets första nod). Detta görs med hjälp av slutpunkten POST /cluster/members (se API-dokumentation), genom att skicka en JSON-kropp som innehåller URL:en.

Om det lyckas returneras formulärets JSON-text:

{
  "members": [
    {
      "name": "",
      "urls": [
        "https://172.22.1.3:2380"
      ]
    },
    {
      "name": "9ZVNM2MNWP",
      "urls": [
        "https://172.22.1.2:2380"
      ]
    }
  ],
  "joinerKit": "eyJiYWNrdXBfc2FsdCI6IkVlUzNPOEhHSEc5NnlNRktrdG1NZmc9PSIsInVubG9ja19zYWx0IjoiU3phMkEvYW13NlhxVWsrdHZMMmFubm5SZFlWd2ZQUjdpZ3IxK1RSdTdVaU14dmh3d0x2NWIvYVNkY2c9IiwibG9ja2VkX2RvbWFpbl9rZXkiOiIyMnNGVlkyelhQUVZ6S1pQenI3MmkwTk1WM3lmQ2k5dGwzeDhUbGtuOXM0WjFOd3JoZkRQTFZIVHp1WVl0YkQxaVZCMlovV3JHUHJlMXlwN0t4U0w4WkxjY2ZUTmUzcFg0WXE4YXNlY0wwREhXNGlIaXlPMlZnPT0ifQ=="
}

som innehåller information som är nödvändig för att den nya noden ska kunna ansluta sig till klustret. Framför allt listas alla medlemmar i klustret (där medlemmen med ett tomt namn är den nya medlemmen). Den innehåller också domännyckeln som krypteras med både upplåsnings- och säkerhetskopieringslösenfrasen - så en säkerhetskopieringslösenfras måste ha konfigurerats tidigare.

Spara det svaret till nästa steg.

Att faktiskt ansluta till klustret

Ta svaret från det sista steget och lägg till ett fält backupPassphrase som innehåller säkerhetskopieringslösenordet för den nod som den nya deltagaren registrerades på, och skicka dessa data till ett anrop till POST /cluster/join (se API-dokumentation) på den nod som förväntas ansluta.

Förutsatt att både klustret och noden kan nå varandra, kommer detta att genomföra den faktiska anslutningen och radera data på den nya anslutningen för att istället synkronisera dess tillstånd med klustrets.

Beroende på nätverks- och klusterförhållandena kan den här åtgärden ta några tiotals sekunder. Om denna operation misslyckas omedelbart (t.ex. om klustret inte var nåbart eller om autentiseringen misslyckades), kommer nodens tillstånd inte att raderas och anslutningen kommer att återställas. Men så snart en första anslutning lyckas är denna operation slutgiltig och kan endast återställas genom en fabriksåterställning.

Om denna anslutning lyckas hamnar noden i ett Locked-tillstånd och måste låsas upp med upplåsningspassfrasen för den nod som användes för registrering. Efteråt kan upplåsningslösenfrasen ändras (upplåsningslösenfraser förblir nodspecifika och delas inte mellan noder).

Observera

Även efter att joinningen har lyckats kan det, om klustrets databas är stor eller om klustret är upptaget, ta en viss tid för den nya joinaren att synkronisera sitt tillstånd helt och hållet. Under den tiden kan alla noder (i synnerhet den nya joinern) vara mindre responsiva eller inte alls responsiva. Särskilt den nya joinern kan initialt returnera fel när man försöker låsa upp den till exempel. I så fall kan du ge det lite tid och försöka igen.

Adding a Witness Node

Prepare a Witness

Du behöver en miljö med etcd v3.6 tillgänglig, med en IPv4-adress (minst) som kan nås av de andra medlemmarna i ditt kluster. TCP-trafik till och från port 2380 måste vara tillåten.

Skapa en tom katalog där etcd kommer att lagra sina data och skriv ner sökvägen (vi använder /var/etcd/data). Se till att den användare som ska starta processen har behörighet att läsa och skriva till katalogen.

Överför det CA-certifikat som används för att autentisera noderna i klustret till maskinen. Du bör ha skapat ett sådant i avsnittet Skapa och installera en CA. Vi kommer att lagra det i /var/etcd/CA.pem.

Du måste sedan skapa ett certifikat för vittnet och signera det med certifikatutfärdaren så att det kan kommunicera med sina kollegor. Detta kan till exempel göras genom openssl:

# Create a key
$ openssl genrsa -out witness.key 2048
# Create a CSR with a SAN that corresponds to the witness's IP or hostname
$ openssl req -new -sha256 -key own.key -subj "/C=US/ST=CA/O=MyOrg, Inc./CN=witness" \
    -addext "subjectAltName=IP:172.22.1.3" --out witness.csr
# Sign it
$ openssl x509 -req -days 1825 -in witness.csr -CA CA.pem -copy_extensions copy \
    -CAkey CA.key -out witness.pem -set_serial 01 -sha256

Lagra de resulterande witness.key och witness.pem även i /var/etcd.

Register Witness to Cluster

Följ de vanliga instruktionerna i avsnittet Registering a New Node för att meddela det befintliga klustret att en ny medlem har lagts till med de angivna URL-adresserna.

Skriv ner svaret från klustret: det ska innehålla en lista över klustermedlemmar och ett ”joiner kit” (du behöver inte den här delen).

Configure etcd

Till skillnad från NetHSM som automatiskt väljer ett nodnamn för sig själva (med hjälp av enhets-ID), måste du välja ett namn för varje vittne du lägger till, och se till att namnen är unika. Vi kommer att använda ”witness1” i följande exempel.

Med NetHSM:s svar på registrering av vittnet, förbered variabler av formuläret:

export ETCD_NAME="witness1"
export ETCD_DATA_DIR="/var/etcd/data"
export ETCD_INITIAL_CLUSTER="peer1=url1,peer1=url2,peer2=url1,peer2=url2,..."
export ETCD_INITIAL_ADVERTISE_PEER_URLS="my_url1,my_url2,..."

Om du antar att svaret från NetHSM lagras i en fil response.json kan du generera dessa två sista variabler automatiskt med följande uttryck jq:

export ETCD_INITIAL_CLUSTER=$(jq --raw-output '[.members[] | ["\(if .name == "" then "witness1" else .name end)=\(.urls[])"]] | flatten | join(",")' < response.json)
export ETCD_INITIAL_ADVERTISE_PEER_URLS=$(jq --raw-output '.members[] | select(.name=="") | .urls | join(",")' < response.json)

Med det exempelsvar som ges i avsnittet Registering a New Node kommer du till exempel att ha:

ETCD_NAME="witness1"
ETCD_DATA_DIR="/var/etcd/data"
ETCD_INITIAL_CLUSTER="witness1=https://172.22.1.3:2380,9ZVNM2MNWP=https://172.22.1.2:2380"
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://172.22.1.3:2380"

Slutligen skapar du en etcd.conf.yml-fil med hjälp av den mallfil som finns i docs/etcd_witness.conf.template:

$ envsubst < NETHSM_ROOT/docs/etcd_witness.conf.template > /var/etcd/witness.conf.yml
$ cat witness.conf.yml

Detta bör ge dig en fil av formuläret:

name: witness1
data-dir: /var/etcd/data
log-level: warn
log-format: console

listen-peer-urls: https://0.0.0.0:2380
listen-client-urls: http://localhost:2379

initial-advertise-peer-urls: https://172.22.1.3:2380
advertise-client-urls: http://localhost:2379
initial-cluster: witness1=https://172.22.1.3:2380,9ZVNM2MNWP=https://172.22.1.2:2380
initial-cluster-state: 'existing'

peer-transport-security:
  cert-file: witness.pem
  key-file: witness.key
  client-cert-auth: true
  trusted-ca-file: CA.pem
  skip-client-san-verification: true

Start etcd

Starta etcd på önskat sätt (manuellt, systemd tjänst, container, etc.) och peka på den konfigurationsfil som skapades i föregående steg:

$ cd /var/etcd
$ etcd --config-file witness.conf.yml

Du bör se den starta, ansluta sig till klustret och komma ikapp med data. Efter en tid bör du kunna kontrollera att den är frisk med klienten etcdctl:

etcdctl get /config/version

Denna nyckel ska finnas och innehålla ”1”.

Se till att den här processen fortsätter att köras, eftersom den nu är en riktig medlem av ditt kluster. Om du behöver ta bort den måste du först ta bort den från klustret på rätt sätt (se det dedikerade avsnittet). Om dess nåbara IP ändras ska du uppdatera dess URL från klustret.

Operating a Cluster

Säkerhetskopiering och återställning

Säkerhetskopieringen fungerar på samma sätt som utan ett kluster och kan begäras från vilken nod som helst i klustret. Den säkerhetskopierar data för hela klustret, inklusive nodspecifika fält (dessa ignoreras dock om du inte återställer säkerhetskopian på en icke-provisionerad nod).

En säkerhetskopia som har gjorts på ett kluster kan återställas på samma kluster, även om vissa noder har lagts till eller tagits bort sedan dess. Sådana återställningar som görs på operativa kluster påverkar inte konfigurationsvärden (endast nycklar, användare, namnområden), precis som alla andra partiella återställningar.

Om du återställer en säkerhetskopia på en icke-provisionerad nod återställs de nodspecifika fälten (t.ex. nätverkskonfiguration, certifikat osv.) för den nod som användes för att skapa säkerhetskopian.

Återställning av en stor säkerhetskopia kan överbelasta klustret under en tid, medan den nod som utför återställningen vidarebefordrar ändringar till de andra.

Denna åtgärd är fortfarande kompatibel med säkerhetskopior som gjorts på tidigare versioner av NetHSM.

Observera

Om man på en nod A återställer en säkerhetskopia som gjorts på en annan nod Z med en annan domännyckel kommer A:s domännyckel att skrivas om korrekt, precis som tidigare. Men om A var i ett kluster med noden B kommer B att bli obrukbar eftersom Z:s domännyckel inte återställs på B.

Med andra ord ska du bara utföra en återställning i ett kluster med säkerhetskopior som har gjorts i samma kluster (även om noder kan ha tagits bort eller lagts till sedan dess). Om du vill återställa en utländsk säkerhetskopia på en nod måste du först ta bort den från klustret på ett säkert sätt, sedan fabriksåterställa den och återställa säkerhetskopian.

Ta bort en nod på ett rent sätt

Så länge någon del av klustret fortfarande är beslutsmässigt kan vilken som helst av dess medlemmar användas för att ta bort en annan nod från klustret, oavsett om denna nod redan är onåbar eller förväntas bli det.

Du måste först veta ID:t för den nod du vill ta bort, genom att lista alla noder via GET /cluster/members och leta efter rätt nod.

Sedan kan den tas bort genom att anropa DELETE /cluster/members/<id>. Om noden i fråga fortfarande var frisk kommer detta att isolera den från resten av klustret och göra den obrukbar.

Software Updates in Clusters

Framtida uppdateringar kommer att markeras som ”klustersäkra” (detta bör vara majoriteten) eller ”klusterosäkra”.

Klustersäkra uppdateringar kan tillämpas på noder som ingår i ett kluster utan att de först tas bort från klustret. Men som med alla åtgärder bör du se till att göra detta på en nod i taget och i ett kluster där borttagandet av en nod inte går under kvorumet (t.ex. om uppdateringen misslyckas).

Uppdateringar som inte är säkra i kluster måste tillämpas på isolerade noder. Du bör demontera klustret (ta bort noderna en efter en), fabriksåterställa alla noder utom en, tillämpa uppdateringen på alla noder och sedan få alla återställda noder att ansluta sig till den återstående noden.

Se till att göra en säkerhetskopia före sådana operationer.

Omkonfigurering av ett befintligt kluster

Changing the Cluster CA

Ett befintligt kluster (med två eller fler noder) kan inte ändra sin klustercertifikatutfärdare medan det är i drift. Om du behöver ändra detta certifikat: välj en nod, ta bort alla andra noder, uppdatera certifikatutfärdaren och låt sedan de andra medlemmarna ansluta sig igen.

Changing the Network Configuration of Nodes

Om du ändrar nätverkskonfigurationen för en nod (t.ex. ändrar dess IP) kommer de andra noderna automatiskt att informeras om uppdateringen. Du bör dock se till att du bara utför sådana uppdateringar på en enda nod i taget och i ett kluster där kvorum inte förloras om den noden försvinner.