etcd v3 uses gRPC for its messaging protocol. The etcd project includes a gRPC-based Go client and a command line utility, etcdctl, for communicating with an etcd cluster through gRPC. For languages with no gRPC support, etcd provides a JSON gRPC gateway. This gateway serves a RESTful proxy that translates HTTP/JSON requests into gRPC messages.

Using gRPC gateway

The gateway accepts a JSON mapping for etcd’s protocol buffer message definitions. Note that key and value fields are defined as byte arrays and therefore must be base64 encoded in JSON. The following examples use curl, but any HTTP/JSON client should work all the same.

Notes

gRPC gateway endpoint has changed since etcd v3.3:

  • etcd v3.2 or before uses only [CLIENT-URL]/v3alpha/*.
  • etcd v3.3 uses [CLIENT-URL]/v3beta/ while keeping [CLIENT-URL]/v3alpha/.
  • etcd v3.4 uses [CLIENT-URL]/v3/ while keeping [CLIENT-URL]/v3beta/.
    • [CLIENT-URL]/v3alpha/* is deprecated.
  • etcd v3.5 or later uses only [CLIENT-URL]/v3/*.
    • [CLIENT-URL]/v3beta/* is deprecated.gRPC-gateway does not support authentication using TLS Common Name.

Put and get keys

Use the /v3/kv/range and /v3/kv/put services to read and write keys:

  1. <<COMMENT
  2. https://www.base64encode.org/
  3. foo is 'Zm9v' in Base64
  4. bar is 'YmFy'
  5. COMMENT
  6. curl -L http://localhost:2379/v3/kv/put \
  7. -X POST -d '{"key": "Zm9v", "value": "YmFy"}'
  8. # {"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"2","raft_term":"3"}}
  9. curl -L http://localhost:2379/v3/kv/range \
  10. -X POST -d '{"key": "Zm9v"}'
  11. # {"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"2","raft_term":"3"},"kvs":[{"key":"Zm9v","create_revision":"2","mod_revision":"2","version":"1","value":"YmFy"}],"count":"1"}
  12. # get all keys prefixed with "foo"
  13. curl -L http://localhost:2379/v3/kv/range \
  14. -X POST -d '{"key": "Zm9v", "range_end": "Zm9w"}'
  15. # {"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"2","raft_term":"3"},"kvs":[{"key":"Zm9v","create_revision":"2","mod_revision":"2","version":"1","value":"YmFy"}],"count":"1"}

Watch keys

Use the /v3/watch service to watch keys:

  1. curl -N http://localhost:2379/v3/watch \
  2. -X POST -d '{"create_request": {"key":"Zm9v"} }' &
  3. # {"result":{"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"1","raft_term":"2"},"created":true}}
  4. curl -L http://localhost:2379/v3/kv/put \
  5. -X POST -d '{"key": "Zm9v", "value": "YmFy"}' >/dev/null 2>&1
  6. # {"result":{"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"2","raft_term":"2"},"events":[{"kv":{"key":"Zm9v","create_revision":"2","mod_revision":"2","version":"1","value":"YmFy"}}]}}

Transactions

Issue a transaction with /v3/kv/txn:

  1. # target CREATE
  2. curl -L http://localhost:2379/v3/kv/txn \
  3. -X POST \
  4. -d '{"compare":[{"target":"CREATE","key":"Zm9v","createRevision":"2"}],"success":[{"requestPut":{"key":"Zm9v","value":"YmFy"}}]}'
  5. # {"header":{"cluster_id":"12585971608760269493","member_id":"13847567121247652255","revision":"3","raft_term":"2"},"succeeded":true,"responses":[{"response_put":{"header":{"revision":"3"}}}]}
  1. # target VERSION
  2. curl -L http://localhost:2379/v3/kv/txn \
  3. -X POST \
  4. -d '{"compare":[{"version":"4","result":"EQUAL","target":"VERSION","key":"Zm9v"}],"success":[{"requestRange":{"key":"Zm9v"}}]}'
  5. # {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"6","raft_term":"3"},"succeeded":true,"responses":[{"response_range":{"header":{"revision":"6"},"kvs":[{"key":"Zm9v","create_revision":"2","mod_revision":"6","version":"4","value":"YmF6"}],"count":"1"}}]}

Authentication

Set up authentication with the /v3/auth service:

  1. # create root user
  2. curl -L http://localhost:2379/v3/auth/user/add \
  3. -X POST -d '{"name": "root", "password": "pass"}'
  4. # {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"}}
  5. # create root role
  6. curl -L http://localhost:2379/v3/auth/role/add \
  7. -X POST -d '{"name": "root"}'
  8. # {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"}}
  9. # grant root role
  10. curl -L http://localhost:2379/v3/auth/user/grant \
  11. -X POST -d '{"user": "root", "role": "root"}'
  12. # {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"}}
  13. # enable auth
  14. curl -L http://localhost:2379/v3/auth/enable -X POST -d '{}'
  15. # {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"}}

Authenticate with etcd for an authentication token using /v3/auth/authenticate:

  1. # get the auth token for the root user
  2. curl -L http://localhost:2379/v3/auth/authenticate \
  3. -X POST -d '{"name": "root", "password": "pass"}'
  4. # {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1","raft_term":"2"},"token":"sssvIpwfnLAcWAQH.9"}

Set the Authorization header to the authentication token to fetch a key using authentication credentials:

  1. curl -L http://localhost:2379/v3/kv/put \
  2. -H 'Authorization : sssvIpwfnLAcWAQH.9' \
  3. -X POST -d '{"key": "Zm9v", "value": "YmFy"}'
  4. # {"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"2","raft_term":"2"}}

Swagger

Generated Swagger API definitions can be found at rpc.swagger.json.