Lab: etcd Cluster¶
Pairs with: Consensus & Raft, CAP Theorem
A real 3-node etcd cluster — literally the "CP" example in CAP Theorem's database table. Kill a minority of nodes and writes keep working; kill a majority and writes cleanly refuse (never corrupt). Then run the exact --consistency=serializable vs. default-linearizable comparison that table describes.
docker-compose.yml¶
name: labs-etcd
x-etcd-common: &etcd-common
image: gcr.io/etcd-development/etcd:v3.5.17
environment: &etcd-common-env
ETCD_INITIAL_CLUSTER: etcd1=http://etcd1:2380,etcd2=http://etcd2:2380,etcd3=http://etcd3:2380
ETCD_INITIAL_CLUSTER_STATE: new
ETCD_INITIAL_CLUSTER_TOKEN: labs-etcd-token
ETCD_LISTEN_PEER_URLS: http://0.0.0.0:2380
ETCD_LISTEN_CLIENT_URLS: http://0.0.0.0:2379
services:
etcd1:
<<: *etcd-common
hostname: etcd1
environment:
<<: *etcd-common-env
ETCD_NAME: etcd1
ETCD_INITIAL_ADVERTISE_PEER_URLS: http://etcd1:2380
ETCD_ADVERTISE_CLIENT_URLS: http://etcd1:2379
ports:
- "12379:2379"
healthcheck:
test: ["CMD", "etcdctl", "--endpoints=http://localhost:2379", "endpoint", "health"]
interval: 5s
timeout: 5s
retries: 20
etcd2:
<<: *etcd-common
hostname: etcd2
environment:
<<: *etcd-common-env
ETCD_NAME: etcd2
ETCD_INITIAL_ADVERTISE_PEER_URLS: http://etcd2:2380
ETCD_ADVERTISE_CLIENT_URLS: http://etcd2:2379
ports:
- "22379:2379"
healthcheck:
test: ["CMD", "etcdctl", "--endpoints=http://localhost:2379", "endpoint", "health"]
interval: 5s
timeout: 5s
retries: 20
etcd3:
<<: *etcd-common
hostname: etcd3
environment:
<<: *etcd-common-env
ETCD_NAME: etcd3
ETCD_INITIAL_ADVERTISE_PEER_URLS: http://etcd3:2380
ETCD_ADVERTISE_CLIENT_URLS: http://etcd3:2379
ports:
- "32379:2379"
healthcheck:
test: ["CMD", "etcdctl", "--endpoints=http://localhost:2379", "endpoint", "health"]
interval: 5s
timeout: 5s
retries: 20
Exercises¶
The full walkthrough (find the leader, kill a minority, kill a majority, compare serializable vs. linearizable reads without quorum) lives in the lab's README: