Skip to content

etcd Architecture Deep Dive — Quorum, Replication, Watch Mechanism, Compaction

Tại Sao Cần Hiểu etcd Internals

Đa số Kubernetes engineers chỉ biết etcd là "key-value store mà Kubernetes dùng". Tuy nhiên, hiểu cách etcd vận hành giúp:

  1. Gỡ lỗi state inconsistencies — Khi dữ liệu ở etcd sai với deployed state
  2. Dự đoán failure modes — Biết etcd quorum cần bao nhiêu nodes, tránh single-point-of-failure
  3. Tune performance — Watch connection limits, compaction schedule ảnh hưởng latency
  4. Capacity planning — Biết object size limits, write throughput ceiling

Raft Consensus Algorithm — Foundation

etcd dựa trên Raft, distributed consensus algorithm. Hiểu Raft rất quan trọng để hiểu etcd.

Core Concept: State Machine Replication

Mong Đợi: Tất cả nodes trong etcd cluster duy trì TRẠNG THÁI GIỐNG HỆT

Cơ Chế: Sao chép mỗi ghi → tất cả nodes áp dụng cùng thứ tự

       Client ghi giá trị X

       Ghi cho leader

       Leader broadcasts "append entry X" cho followers

       Followers nhận, persist vào disk, ack

       Leader chờ majority ack (quorum)

       Leader commits X tới state machine

       Leader thông báo followers: "commit X"

       Tất cả followers áp dụng X tới state machine

       Nhất quán đạt được ✓

Quorum Requirement

etcd luôn cần đa số (>50%) nodes hoạt động:

Kích thước Cluster   Quorum tối thiểu   Dung sai
─────────────────────────────────────
1              1            0 nodes fail
3              2            1 node fail
5              3            2 nodes fail
7              4            3 nodes fail

Ảnh hưởng:

  • 1-node cluster: bất kỳ fail = downtime (tránh!)
  • 3-node cluster: HA điển hình, dung sai 1 fail
  • 5-node cluster: dung sai 2 fail (đắt tiền, hiếm cần)

Tại sao số lẻ?: Quorum cho 4-node = 3, giống 5-node. Tốt hơn dùng 3 hoặc 5.

Leader Election

Bất kỳ lúc nào, etcd cluster có đúng 1 leader:

┌────────────────────────────────────┐
│ Leader                             │
│ - Nhận client writes           │
│ - Broadcasts cho followers          │
│ - Commits khi majority acks       │
└────────────────────────────────────┘

Followers:
- Sao chép leader state
- Forward client writes cho leader
- Kích hoạt bầu chọn mới nếu leader chết

Leader được bầu chọn: ~150-300ms (tunable)

GKE context: etcd leader được bầu chọn tự động bởi GCP, không cần can thiệp thủ công.


Replication Mechanics

Log Replication

etcd maintains replicated log — ordered list of write operations:

Leader Log:
┌──────────────────────────────────────┐
│ [1] PUT /pods/pod1 → data1          │
│ [2] PUT /services/svc1 → data2      │
│ [3] DELETE /configmaps/cfg1 → -     │
│ [4] PUT /pods/pod2 → data3          │
│ (uncommitted ↓)                      │
│ [5] PUT /services/svc2 → data4      │
│ [6] (pending replication)            │
└──────────────────────────────────────┘

Followers replicate same log, apply same order

Snapshots Cho Efficiency

etcd không giữ infinite log. Định kỳ:

Log entries 1-1000 → Snapshot
├─ Tất cả entries áp dụng state machine
├─ Take snapshot trạng thái cuối
└─ Discard old log entries

Kết quả:
- Log giữ kích thước quản lý được
- New followers catchup nhanh qua snapshot
- Faster recovery từ crashes

GKE etcd compaction: ~mỗi 6 giờ (tunable)

Consistency During Replication

Đảm bảo quan trọng: Followers áp dụng entries trong thứ tự giống hệt như leader:

yaml
# Leader có
[ PUT key1=A ]
[ PUT key1=B ]

# Followers sẽ LUÔN thấy theo thứ tự này
# Không bao giờ key1=B rồi key1=A

# Đảm bảo thứ tự này là điều cần thiết cho nhất quán

Watch Mechanism — Event Streaming

Cách Watch Hoạt Động (High Level)

Watch là subscriber pattern — clients đăng ký để nhận events:

Client:
    kubectl get pods --watch

    Mở HTTP connection

    Gửi: WATCH /pods

    API Server:
         Forwards tới etcd

         Mở watch subscription

    etcd:
         Streams ADDED/MODIFIED/DELETED events
         ├─ Object X thêm → ADDED event
         ├─ Object X cập nhật → MODIFIED event
         └─ Object X xóa → DELETED event
         
    Events chảy lại cho client in real-time

Watch Caching Trong API Server

Không phải mỗi watch trực tiếp từ etcd. API Server duy trì watch cache:

Nhiều Clients watching /pods
    ├─ Watch 1 (client A)
    ├─ Watch 2 (client B)
    └─ Watch 3 (client C)

        API Server Watch Cache
        (shared subscription tới etcd)

        Single etcd watch
        (multiplexed upstream)

Efficiency:

  • Một etcd watch cho 100 API clients
  • Significant reduction etcd watch connections

Latency:

  • etcd → API Server cache: <10ms điển hình
  • API Server → client: <100ms

Watch Nhất Quán & Thứ Tự

Rất quan trọng: watch events được deliver theo thứ tự:

Nếu Pod spec cập nhật: field1=A → field1=B

Client sẽ thấy:
1. MODIFIED event (field1=A)
2. MODIFIED event (field1=B)

KHÔNG bao giờ out-of-order hoặc bỏ qua

Watch Connection Kết Nối Lại

Khi watch connection bị rơi (network interrupt, server restart):

Client:
    Connection bị rơi

    Thử kết nối lại

    Gửi WATCH /pods tại resourceVersion=N

    API Server:
    "Gửi cho tôi events từ version N"

    Streams buffered events

    Tiếp tục live stream

Buffering: API Server buffer ~1000s events nếu client tạm disconnect


Compaction — Maintaining Database Size

Vấn Đề: Unbounded Growth

Không có compaction, etcd database liên tục grow:

Time 0: PUT key1=A    (version 1)
Time 1: PUT key1=B    (version 2)
Time 2: PUT key1=C    (version 3)
Time 3: PUT key1=D    (version 4)
...
Time 1000000: PUT key1=LATEST  (version 1000000)

Database lưu tất cả versions!
Disk usage: không giới hạn
Recovery speed: chậm (replay tất cả versions)

Compaction Operation

Compaction removes old revisions:

bash
# Triggering compaction (GKE does automatically)
etcdctl compact 100000
# Keep revisions > 100000, discard older

# Result:
# Database size reduced
# Can't read old versions anymore
# Faster recovery

GKE automatic compaction: ~mỗi 6 giờ, giữ lại 1 giờ lịch sử cuối

Side Effects of Compaction

⚠️ Quan Trọng: Sau compaction, old revisions không còn truy cập được:

bash
# Điều này sẽ fail post-compaction
etcdctl get key1 --rev=50000
# LỖI: revision 50000 không có sẵn

# Điều này hoạt động
etcdctl get key1 --rev=150000  # > compaction revision

Watch ảnh hưởng:

  • Nếu client watches từ revision 50000 sau-compaction
  • etcdctl không thể fulfill (revision xóa)
  • etcdctl returns: "watch revision quá cũ"
  • Client phải kết nối lại với revision hiện tại

Key & Value Size Constraints

Per-Key Limits

LimitValueImpact
Max key size~512 KBetcd key paths not typically hit limit
Max value size~1 MBConfigMaps/Secrets > 1MB = reject
Total db sizeConfigurableDefault: unlimited, limited by disk

Ảnh Hưởng Cho Kubernetes

yaml
# ❌ Sẽ từ chối - ConfigMap quá lớn
apiVersion: v1
kind: ConfigMap
metadata:
  name: huge-config
data:
  large-file: |
    [... 10 MB dữ liệu ...]  # TỪ CHỐI

# Giải pháp: Lưu trong object storage, chỉ tham chiếu
apiVersion: v1
kind: ConfigMap
metadata:
  name: config-ref
data:
  storage-url: gs://bucket/file

Kích Thước Database etcd

bash
# Kiểm tra kích thước database etcd (GKE)
kubectl exec -n kube-system etcd-server -- \
  du -sh /var/lib/etcd

# Giá trị điển hình:
# Small cluster: 100 MB - 1 GB
# Medium cluster: 1 GB - 10 GB  
# Large cluster: 10 GB - 100 GB

Performance Characteristics

Write Latency

Typical latency per write:
├─ Network latency to leader: 5 ms
├─ Disk fsync (persistent): 10 ms
├─ Leader commits: 5 ms
├─ Response back to client: 5 ms
└─ Total: ~25 ms (p50), ~100 ms (p99)

Write Throughput

etcd bottleneck typically disk I/O:

Single leader can handle:
- Typical writes: ~1000 writes/sec
- Peak writes: ~5000 writes/sec (unsustainable)

Throughput limits:
- Storage IOPS capacity
- Network bandwidth
- Quorum replication latency

Watch Latency

Event latency:
- etcd detects change: immediate
- Broadcasts to followers: <5ms
- API Server buffers: <10ms
- Client receives: <100ms total

Failure Modes & Recovery

Node Failure Impact

3-node cluster:
├─ Node 1 fails: Cluster operational (2/3 quorum)
├─ Node 2 fails: Cluster operational (2/3 quorum)
└─ Nodes 1,2 fail: Cluster DOWN (need 2/3)

Data loss: Zero (quorum always preserved)

Leader Failure

Leader crash:

Time 0: Leader crashes

Time 100-200ms: Followers detect (heartbeat missing)

Time 300ms: New leader elected

Time 400ms: Cluster operational again

Client impact: Pending writes get re-executed, consistency maintained

Network Partition

Network partition:
├─ Partition 1: 2 nodes (includes leader)
├─ Partition 2: 1 node

Partition 1: Quorum intact → OPERATIONAL
Partition 2: No quorum → READ-ONLY (or rejected)

When healed: Partition 2 catches up automatically

Production Best Practices

Cluster Size

Recommendation:

  • 3-node: Default production (tolerate 1 failure)
  • 5-node: Use if frequent updates (faster catchup dari snapshots)
  • 1-node: Development only

Monitoring

bash
# Critical metrics
etcd_server_has_leader  # Should always be 1
etcd_server_leader_changes_seen_total  # Should increase slowly
etcd_disk_backend_commit_duration_seconds  # Should be <50ms
etcd_server_proposals_failed_total  # Should be 0

Backup Strategy

GKE manages backups automatically, tapi validate:

bash
# Verify backups
gcloud container backups describe <backup> \
  --format="table(name, state, create_time)"

# Test restore monthly

Reference Dokumentasi


Summary

  • Raft consensus: etcd basis, guarantees consistency across replicas
  • Quorum requirement: Odd-sized clusters, 3-node typical
  • Replication log: Maintains ordering of all operations
  • Watch mechanism: Efficient event streaming via caching layer
  • Compaction: Removes old revisions, improves performance but affects revision history
  • Performance: ~1000 writes/sec ceiling, latency ~25ms median
  • Failure recovery: Automatic leader election, transparent client failover