DEV Community

Alex Spinov
Alex Spinov

Posted on

etcd Has a Free API — The Distributed Key-Value Store Behind Kubernetes

etcd is the distributed key-value store that powers Kubernetes. Every K8s cluster uses etcd to store its entire state — pods, services, configs, secrets. But etcd is useful far beyond Kubernetes.

Free, open source, CNCF graduated. Used by CoreDNS, Rook, and M3.

Why Use etcd?

  • Strong consistency — Raft consensus, linearizable reads
  • Watch mechanism — real-time notifications on key changes
  • Distributed locking — leader election and mutual exclusion
  • TTL keys — auto-expiring entries for service discovery
  • gRPC + HTTP — both protocols supported

Quick Setup

1. Install

# Docker
docker run -d -p 2379:2379 -p 2380:2380 --name etcd \
  quay.io/coreos/etcd:v3.5.12 \
  /usr/local/bin/etcd --advertise-client-urls http://0.0.0.0:2379 --listen-client-urls http://0.0.0.0:2379

# Install etcdctl
brew install etcd
Enter fullscreen mode Exit fullscreen mode

2. Basic Key-Value Operations

# PUT
etcdctl put mykey "hello world"
curl -s -X POST http://localhost:2379/v3/kv/put \
  -d '{"key": "'$(echo -n mykey | base64)'", "value": "'$(echo -n "hello world" | base64)'"}' | jq

# GET
etcdctl get mykey
curl -s -X POST http://localhost:2379/v3/kv/range \
  -d '{"key": "'$(echo -n mykey | base64)'"}' | jq '.kvs[] | {key: (.key | @base64d), value: (.value | @base64d)}'

# GET with prefix (all keys starting with "app/")
etcdctl get --prefix "app/"
curl -s -X POST http://localhost:2379/v3/kv/range \
  -d '{"key": "'$(echo -n 'app/' | base64)'", "range_end": "'$(echo -n 'app0' | base64)'"}' | jq

# DELETE
etcdctl del mykey
curl -s -X POST http://localhost:2379/v3/kv/deleterange \
  -d '{"key": "'$(echo -n mykey | base64)'"}' | jq
Enter fullscreen mode Exit fullscreen mode

3. Watch for Changes

# CLI watch
etcdctl watch --prefix "config/"

# In another terminal
etcdctl put config/db_host "postgres.internal"
etcdctl put config/cache_ttl "300"
Enter fullscreen mode Exit fullscreen mode

4. Leases (TTL Keys)

# Create a 60-second lease
LEASE=$(etcdctl lease grant 60 | grep -oP 'ID \K[a-f0-9]+')

# Attach key to lease (auto-expires)
etcdctl put --lease=$LEASE "service/worker-1" "alive"

# Keep alive (heartbeat)
etcdctl lease keep-alive $LEASE
Enter fullscreen mode Exit fullscreen mode

5. Cluster Health

etcdctl endpoint health
etcdctl endpoint status --write-out=table

curl -s http://localhost:2379/health | jq
curl -s http://localhost:2379/v3/maintenance/status -X POST -d '{}' | jq
Enter fullscreen mode Exit fullscreen mode

Python Example

import etcd3

client = etcd3.client(host='localhost', port=2379)

# Put/Get
client.put('config/app_name', 'My Scraper')
value, metadata = client.get('config/app_name')
print(f"Value: {value.decode()}")

# List all keys with prefix
for value, metadata in client.get_prefix('config/'):
    print(f"{metadata.key.decode()} = {value.decode()}")

# Watch for changes
watch_iter, cancel = client.watch_prefix('config/')
for event in watch_iter:
    print(f"Changed: {event.key.decode()} = {event.value.decode()}")
Enter fullscreen mode Exit fullscreen mode

Key HTTP Endpoints

Endpoint Method Description
/v3/kv/put POST Put key-value
/v3/kv/range POST Get key(s)
/v3/kv/deleterange POST Delete key(s)
/v3/watch POST Watch for changes
/v3/lease/grant POST Create lease
/v3/lease/keepalive POST Renew lease
/v3/maintenance/status POST Cluster status
/health GET Health check

Need custom data extraction or scraping solution? I build production-grade scrapers for any website. Email: Spinov001@gmail.com | My Apify Actors

Top comments (0)