Toen ik voor het eerst een “productie” Kubernetes cluster opzette, had ik één control plane node. Het werkte prima totdat het niet meer werkte — een kapotte disk haalde het hele cluster neer. Elke pod, elke service, alles. Die dag leerde me wat “single point of failure” echt betekent.

Kubernetes High Availability is niet optioneel voor productie. Maar er is een keuze die veel mensen in verwarring brengt: draai je etcd op je control plane nodes (stacked), of op aparte dedicated nodes (external)? Laat me beide benaderingen uitleggen.

Wat is etcd en Waarom Doet Het Ertoe?

etcd is Kubernetes’ brein. Het is een gedistribueerde key-value store die alle cluster state bevat: pod definities, secrets, configmaps, service accounts — alles. Als je kubectl apply doet, eindigt het in etcd.

Als etcd sterft, is je cluster hersendood. De API server kan niet functioneren, controllers kunnen geen state reconcilen, niets werkt. Daarom bepaalt etcd beschikbaarheid direct de cluster beschikbaarheid.

etcd gebruikt het Raft consensus algoritme, dat een quorum (meerderheid) van nodes vereist om te functioneren. Met 3 etcd nodes kun je er 1 verliezen. Met 5 kun je er 2 verliezen. Verlies quorum, en etcd wordt read-only totdat nodes herstellen.

Stacked etcd: De Simpele Aanpak

In een stacked topologie draait etcd op elke control plane node naast de API server, controller manager en scheduler.

flowchart TD
    subgraph stacked["Stacked etcd Topologie"]
        subgraph CP1["Control Plane Node 1"]
            API1["API Server"]
            Ctrl1["Controller"]
            Sched1["Scheduler"]
            etcd1["etcd"]
        end
        subgraph CP2["Control Plane Node 2"]
            API2["API Server"]
            Ctrl2["Controller"]
            Sched2["Scheduler"]
            etcd2["etcd"]
        end
        subgraph CP3["Control Plane Node 3"]
            API3["API Server"]
            Ctrl3["Controller"]
            Sched3["Scheduler"]
            etcd3["etcd"]
        end
    end

Voordelen van Stacked etcd

Eenvoud: Minder nodes om te beheren. Drie nodes geven je een volledig HA control plane met etcd quorum.

Kosten: De helft van de infrastructuur vergeleken met external etcd. Voor homelabs en kleinere deployments telt dit.

Makkelijker setup: kubeadm, k3s en de meeste installers defaulten naar stacked omdat het simpeler is. kubeadm init met --control-plane-endpoint en je bent klaar.

Gekoppelde lifecycle: Control plane en etcd schalen samen. Voeg een control plane node toe, krijg automatisch een etcd member.

Nadelen van Stacked etcd

Gekoppelde failure: Als een node sterft, verlies je zowel een control plane component ALS een etcd member. De blast radius is groter.

Resource contention: etcd is gevoelig voor disk latency. Als je API server de disk hamert tijdens een grote list operatie, kan etcd heartbeats missen en leader election triggeren.

Schaal beperkingen: Je wilt misschien 5 API servers maar slechts 3 etcd members (of andersom). Stacked topologie dwingt ze te matchen.

External etcd: De Ontkoppelde Aanpak

External etcd draait op dedicated nodes, volledig gescheiden van het control plane.

flowchart TD
    subgraph external["External etcd Topologie"]
        subgraph etcd_cluster["etcd Cluster"]
            E1["etcd Node 1"]
            E2["etcd Node 2"]
            E3["etcd Node 3"]
        end
        etcd_cluster --> control_plane
        subgraph control_plane["Control Plane Nodes"]
            subgraph CP1["Control Plane 1"]
                API1["API Server<br/>Controller<br/>Scheduler"]
            end
            subgraph CP2["Control Plane 2"]
                API2["API Server<br/>Controller<br/>Scheduler"]
            end
            subgraph CP3["Control Plane 3"]
                API3["API Server<br/>Controller<br/>Scheduler"]
            end
        end
    end

Voordelen van External etcd

Geïsoleerde failures: Een control plane node die sterft beïnvloedt etcd quorum niet. Een etcd node die sterft beïnvloedt API server beschikbaarheid niet.

Onafhankelijke schaling: Draai 3 etcd members en 5 API servers, of wat je workload ook nodig heeft.

Geoptimaliseerde resources: Dediceer snelle SSDs aan etcd nodes. Geef API servers meer RAM. Elk component krijgt wat het nodig heeft.

Makkelijker etcd onderhoud: Backup, restore en upgrade etcd zonder het control plane aan te raken.

Nadelen van External etcd

Complexiteit: Meer nodes, meer bewegende delen, meer netwerkpaden om te beveiligen.

Kosten: Dubbel het aantal nodes voor de control plane tier.

Netwerk afhankelijkheid: Het API server naar etcd pad wordt kritiek. Netwerkproblemen daartussen breken alles.

Setup overhead: kubeadm vereist handmatige etcd cluster setup voor het initialiseren van het control plane.

Wanneer Welke Gebruiken

Kies Stacked etcd Wanneer:

  • Kleine tot medium clusters: Onder 100 nodes is stacked meestal prima
  • Homelab of development: Minder nodes betekent minder stroom, minder kosten
  • Team eenvoud: Je team heeft niet veel ervaring met etcd operations
  • Managed Kubernetes: EKS, GKE, AKS regelen dit toch voor je

Kies External etcd Wanneer:

  • Grote clusters: 100+ nodes betekent meer API server load, meer etcd writes
  • Strikte SLAs: Wanneer je gekoppelde failures niet kunt veroorloven
  • Gemixte workloads: Je moet control plane en etcd onafhankelijk schalen
  • etcd expertise: Je team weet hoe etcd clusters te opereren

Stacked HA Opzetten met kubeadm

Hier is de praktische setup voor stacked HA:

# Op eerste control plane node
kubeadm init \
  --control-plane-endpoint "loadbalancer.example.com:6443" \
  --upload-certs

# Bewaar de join commands voor andere control planes
# Join extra control plane nodes
kubeadm join loadbalancer.example.com:6443 \
  --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash> \
  --control-plane \
  --certificate-key <cert-key>

De sleutel is --control-plane-endpoint — dit moet naar een load balancer voor je API servers wijzen, niet een enkel node IP.

External etcd Opzetten

Voor external etcd bootstrap je eerst het etcd cluster:

# Op elke etcd node, configureer etcd
cat > /etc/etcd/etcd.conf.yaml << EOF
name: etcd-1
data-dir: /var/lib/etcd
initial-cluster-state: new
initial-cluster: etcd-1=https://10.0.0.1:2380,etcd-2=https://10.0.0.2:2380,etcd-3=https://10.0.0.3:2380
listen-peer-urls: https://10.0.0.1:2380
listen-client-urls: https://10.0.0.1:2379,https://127.0.0.1:2379
advertise-client-urls: https://10.0.0.1:2379
initial-advertise-peer-urls: https://10.0.0.1:2380
client-transport-security:
  cert-file: /etc/etcd/pki/server.crt
  key-file: /etc/etcd/pki/server.key
  trusted-ca-file: /etc/etcd/pki/ca.crt
peer-transport-security:
  cert-file: /etc/etcd/pki/peer.crt
  key-file: /etc/etcd/pki/peer.key
  trusted-ca-file: /etc/etcd/pki/ca.crt
EOF

Wijs dan kubeadm naar het externe cluster:

# kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
etcd:
  external:
    endpoints:
      - https://10.0.0.1:2379
      - https://10.0.0.2:2379
      - https://10.0.0.3:2379
    caFile: /etc/kubernetes/pki/etcd/ca.crt
    certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt
    keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key

Wat Over K3s?

K3s defaultt naar embedded etcd (stacked) met een simpelere setup:

# Eerste server
curl -sfL https://get.k3s.io | sh -s - server --cluster-init

# Extra servers
curl -sfL https://get.k3s.io | sh -s - server \
  --server https://first-server:6443 \
  --token <token>

K3s ondersteunt ook externe databases (MySQL, PostgreSQL) als etcd alternatief, wat handig kan zijn als je die databases al draait.

Mijn Aanbeveling

Voor de meeste use cases, begin met stacked etcd. Het is simpeler, goedkoper, en voor clusters onder 100 nodes met redelijke workloads werkt het prima.

Ga naar external etcd wanneer je:

  • etcd performance problemen ervaart
  • Onafhankelijke schaling nodig hebt
  • Strikte beschikbaarheidseisen hebt die de complexiteit rechtvaardigen

Ik draai stacked etcd in mijn homelab op drie control plane nodes. Het heeft node failures, netwerkproblemen en de occasionele “oeps ik reboottte de verkeerde server” overleefd. Stacked betekent niet fragiel — het betekent gekoppeld.

Het belangrijkste is niet stacked vs external. Het is minstens drie control plane nodes met etcd hebben. Eén node is geen HA. Twee nodes is erger dan één (je hebt majority quorum nodig, en 2/2 - 1 = 1, wat betekent dat je geen nodes kunt verliezen).

Drie nodes. Dat is het minimum voor echte HA.


Kubernetes HA gaat over failures overleven, niet voorkomen. Failures zullen gebeuren. De vraag is of je cluster ze overleeft.