Compare commits
87 Commits
Author | SHA1 | Date | |
---|---|---|---|
92e3895214 | |||
b12a52b0fd | |||
9fa4002787 | |||
5686c33e4b | |||
6fd2dfdebc | |||
896ce1668c | |||
0520b4cd24 | |||
6ee6f72c48 | |||
b4dd519a63 | |||
a98fff84e7 | |||
973cfbebda | |||
00d1d34cf8 | |||
fcf81fd6bf | |||
0678329cd6 | |||
9a0e0c2eae | |||
3e4d57c37d | |||
d30e764b2d | |||
b5b7c78f1b | |||
ee1c07c3d4 | |||
67c5d4dfd2 | |||
3afcbd6f83 | |||
8fed61b2eb | |||
c8d386e18c | |||
2b6a44b7b0 | |||
8069d08b96 | |||
5074235254 | |||
f59bddd74b | |||
58f035844c | |||
f83774b4cd | |||
12c32137a8 | |||
fce4cf4dc8 | |||
06a72b2702 | |||
fbaef05885 | |||
31a94d28e3 | |||
88660a303f | |||
53c74dbd0b | |||
8a8af60fad | |||
7de19fefe8 | |||
7750f387b0 | |||
e33ab24442 | |||
fce2c1eeaf | |||
6a3bb93305 | |||
21455d2f3b | |||
51bb4220c5 | |||
d8c506923f | |||
5d778f85ca | |||
02697ca725 | |||
bd693c7069 | |||
52c90cdcfb | |||
a88b22ac0a | |||
e93f8b8a12 | |||
86e616c6e9 | |||
5ae55a2c0d | |||
62ce6eef7b | |||
7df4f5c804 | |||
461c24e899 | |||
6d90d03bf0 | |||
9995e80a2c | |||
229405f113 | |||
b3f2a998d4 | |||
8436e901e9 | |||
c03f5cb941 | |||
0cb90e4bea | |||
df83b1b34e | |||
f2bef04009 | |||
02198336f6 | |||
0c9a226e0e | |||
5bd1d420bb | |||
a1cb5cb768 | |||
acba49fe81 | |||
e3c902228b | |||
52a2d143d2 | |||
f53d550a79 | |||
63b799b891 | |||
697883fb8c | |||
f794f87f26 | |||
0847986d4a | |||
9ea80c6ac1 | |||
02fb648abf | |||
4c9e1686b1 | |||
0fb9362c5c | |||
9481945228 | |||
e13b09e4d9 | |||
78e0149f41 | |||
4c86ab4868 | |||
59327bab47 | |||
62ed1ebf03 |
8
.github/ISSUE_TEMPLATE.md
vendored
8
.github/ISSUE_TEMPLATE.md
vendored
@ -1,8 +0,0 @@
|
||||
# Bug reporting
|
||||
|
||||
A good bug report has some very specific qualities, so please read over our short document on
|
||||
[reporting bugs][report_bugs] before you submit your bug report.
|
||||
|
||||
To ask a question, go ahead and ignore this.
|
||||
|
||||
[report_bugs]: ../Documentation/reporting_bugs.md
|
5
.github/PULL_REQUEST_TEMPLATE.md
vendored
5
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,5 +0,0 @@
|
||||
# Contributing guidelines
|
||||
|
||||
Please read our [contribution workflow][contributing] before submitting a pull request.
|
||||
|
||||
[contributing]: ../CONTRIBUTING.md#contribution-flow
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,5 +9,3 @@
|
||||
*.swp
|
||||
/hack/insta-discovery/.env
|
||||
*.test
|
||||
tools/functional-tester/docker/bin
|
||||
hack/tls-setup/certs
|
||||
|
2
.header
2
.header
@ -1,4 +1,4 @@
|
||||
// Copyright 2016 The etcd Authors
|
||||
// Copyright 2014 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
53
.travis.yml
53
.travis.yml
@ -1,55 +1,12 @@
|
||||
dist: trusty
|
||||
language: go
|
||||
go_import_path: github.com/coreos/etcd
|
||||
sudo: false
|
||||
|
||||
go:
|
||||
- 1.6
|
||||
- tip
|
||||
- 1.4
|
||||
|
||||
env:
|
||||
global:
|
||||
- GO15VENDOREXPERIMENT=1
|
||||
matrix:
|
||||
- TARGET=amd64
|
||||
- TARGET=arm64
|
||||
- TARGET=arm
|
||||
- TARGET=ppc64le
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- go: tip
|
||||
exclude:
|
||||
- go: 1.6
|
||||
env: TARGET=arm64
|
||||
- go: tip
|
||||
env: TARGET=arm
|
||||
- go: tip
|
||||
env: TARGET=arm64
|
||||
- go: tip
|
||||
env: TARGET=ppc64le
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libpcap-dev
|
||||
- libaspell-dev
|
||||
- libhunspell-dev
|
||||
|
||||
before_install:
|
||||
- go get -v github.com/chzchzchz/goword
|
||||
- go get -v honnef.co/go/simple/cmd/gosimple
|
||||
- go get -v honnef.co/go/unused/cmd/unused
|
||||
|
||||
# disable godep restore override
|
||||
install:
|
||||
- pushd cmd/ && go get -t -v ./... && popd
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get golang.org/x/tools/cmd/vet
|
||||
- go get github.com/barakmich/go-nyet
|
||||
|
||||
script:
|
||||
- >
|
||||
if [ "${TARGET}" == "amd64" ]; then
|
||||
GOARCH="${TARGET}" ./test;
|
||||
else
|
||||
GOARCH="${TARGET}" ./build;
|
||||
fi
|
||||
- INTEGRATION=y ./test
|
||||
|
@ -1,6 +1,6 @@
|
||||
# How to contribute
|
||||
|
||||
etcd is Apache 2.0 licensed and accepts contributions via GitHub pull requests. This document outlines some of the conventions on commit message formatting, contact points for developers and other resources to make getting your contribution into etcd easier.
|
||||
etcd is Apache 2.0 licensed and accepts contributions via Github pull requests. This document outlines some of the conventions on commit message formatting, contact points for developers and other resources to make getting your contribution into etcd easier.
|
||||
|
||||
# Email and chat
|
||||
|
||||
@ -12,14 +12,6 @@ etcd is Apache 2.0 licensed and accepts contributions via GitHub pull requests.
|
||||
- Fork the repository on GitHub
|
||||
- Read the README.md for build instructions
|
||||
|
||||
## Reporting bugs and creating issues
|
||||
|
||||
Reporting bugs is one of the best ways to contribute. However, a good bug report
|
||||
has some very specific qualities, so please read over our short document on
|
||||
[reporting bugs](https://github.com/coreos/etcd/blob/master/Documentation/reporting_bugs.md)
|
||||
before you submit your bug report. This document might contain links known
|
||||
issues, another good reason to take a look there, before reporting your bug.
|
||||
|
||||
## Contribution flow
|
||||
|
||||
This is a rough outline of what a contributor's workflow looks like:
|
||||
@ -35,11 +27,11 @@ Thanks for your contributions!
|
||||
|
||||
### Code style
|
||||
|
||||
The coding style suggested by the Golang community is used in etcd. See the [style doc](https://github.com/golang/go/wiki/CodeReviewComments) for details.
|
||||
The coding style suggested by the Golang community is used in etcd. See the [style doc](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) for details.
|
||||
|
||||
Please follow this style to make etcd easy to review, maintain and develop.
|
||||
|
||||
### Format of the commit message
|
||||
### Format of the Commit Message
|
||||
|
||||
We follow a rough convention for commit messages that is designed to answer two
|
||||
questions: what changed and why. The subject line should feature the what and
|
||||
|
@ -1,6 +1,2 @@
|
||||
FROM golang
|
||||
ADD . /go/src/github.com/coreos/etcd
|
||||
ADD cmd/vendor /go/src/github.com/coreos/etcd/vendor
|
||||
RUN go install github.com/coreos/etcd
|
||||
EXPOSE 2379 2380
|
||||
ENTRYPOINT ["etcd"]
|
||||
FROM golang:onbuild
|
||||
EXPOSE 4001 7001 2379 2380
|
||||
|
@ -1,10 +0,0 @@
|
||||
FROM alpine:latest
|
||||
|
||||
ADD etcd /usr/local/bin/
|
||||
ADD etcdctl /usr/local/bin/
|
||||
RUN mkdir -p /var/etcd/
|
||||
|
||||
EXPOSE 2379 2380
|
||||
|
||||
# Define default command.
|
||||
CMD ["/usr/local/bin/etcd"]
|
@ -1,108 +1,40 @@
|
||||
# Administration
|
||||
## Administration
|
||||
|
||||
## Data Directory
|
||||
### Data Directory
|
||||
|
||||
### Lifecycle
|
||||
#### Lifecycle
|
||||
|
||||
When first started, etcd stores its configuration into a data directory specified by the data-dir configuration parameter.
|
||||
Configuration is stored in the write ahead log and includes: the local member ID, cluster ID, and initial cluster configuration.
|
||||
The write ahead log and snapshot files are used during member operation and to recover after a restart.
|
||||
|
||||
Having a dedicated disk to store wal files can improve the throughput and stabilize the cluster.
|
||||
It is highly recommended to dedicate a wal disk and set `--wal-dir` to point to a directory on that device for a production cluster deployment.
|
||||
|
||||
If a member’s data directory is ever lost or corrupted then the user should [remove][remove-a-member] the etcd member from the cluster using `etcdctl` tool.
|
||||
If a member’s data directory is ever lost or corrupted then the user should remove the etcd member from the cluster via the [members API][members-api].
|
||||
|
||||
A user should avoid restarting an etcd member with a data directory from an out-of-date backup.
|
||||
Using an out-of-date data directory can lead to inconsistency as the member had agreed to store information via raft then re-joins saying it needs that information again.
|
||||
For maximum safety, if an etcd member suffers any sort of data corruption or loss, it must be removed from the cluster.
|
||||
Once removed the member can be re-added with an empty data directory.
|
||||
|
||||
### Contents
|
||||
[members-api]: https://github.com/coreos/etcd/blob/master/Documentation/other_apis.md#members-api
|
||||
|
||||
#### Contents
|
||||
|
||||
The data directory has two sub-directories in it:
|
||||
|
||||
1. wal: write ahead log files are stored here. For details see the [wal package documentation][wal-pkg]
|
||||
2. snap: log snapshots are stored here. For details see the [snap package documentation][snap-pkg]
|
||||
|
||||
If `--wal-dir` flag is set, etcd will write the write ahead log files to the specified directory instead of data directory.
|
||||
[wal-pkg]: http://godoc.org/github.com/coreos/etcd/wal
|
||||
[snap-pkg]: http://godoc.org/github.com/coreos/etcd/snap
|
||||
|
||||
## Cluster Management
|
||||
### Cluster Management
|
||||
|
||||
### Lifecycle
|
||||
#### Lifecycle
|
||||
|
||||
If you are spinning up multiple clusters for testing it is recommended that you specify a unique initial-cluster-token for the different clusters.
|
||||
This can protect you from cluster corruption in case of mis-configuration because two members started with different cluster tokens will refuse members from each other.
|
||||
|
||||
### Monitoring
|
||||
|
||||
It is important to monitor your production etcd cluster for healthy information and runtime metrics.
|
||||
|
||||
#### Health Monitoring
|
||||
|
||||
At lowest level, etcd exposes health information via HTTP at `/health` in JSON format. If it returns `{"health": "true"}`, then the cluster is healthy. Please note the `/health` endpoint is still an experimental one as in etcd 2.2.
|
||||
|
||||
```
|
||||
$ curl -L http://127.0.0.1:2379/health
|
||||
|
||||
{"health": "true"}
|
||||
```
|
||||
|
||||
You can also use etcdctl to check the cluster-wide health information. It will contact all the members of the cluster and collect the health information for you.
|
||||
|
||||
```
|
||||
$./etcdctl cluster-health
|
||||
member 8211f1d0f64f3269 is healthy: got healthy result from http://127.0.0.1:12379
|
||||
member 91bc3c398fb3c146 is healthy: got healthy result from http://127.0.0.1:22379
|
||||
member fd422379fda50e48 is healthy: got healthy result from http://127.0.0.1:32379
|
||||
cluster is healthy
|
||||
```
|
||||
|
||||
#### Runtime Metrics
|
||||
|
||||
etcd uses [Prometheus][prometheus] for metrics reporting in the server. You can read more through the runtime metrics [doc][metrics].
|
||||
|
||||
### Debugging
|
||||
|
||||
Debugging a distributed system can be difficult. etcd provides several ways to make debug
|
||||
easier.
|
||||
|
||||
#### Enabling Debug Logging
|
||||
|
||||
When you want to debug etcd without stopping it, you can enable debug logging at runtime.
|
||||
etcd exposes logging configuration at `/config/local/log`.
|
||||
|
||||
```
|
||||
$ curl http://127.0.0.1:2379/config/local/log -XPUT -d '{"Level":"DEBUG"}'
|
||||
$ # debug logging enabled
|
||||
$
|
||||
$ curl http://127.0.0.1:2379/config/local/log -XPUT -d '{"Level":"INFO"}'
|
||||
$ # debug logging disabled
|
||||
```
|
||||
|
||||
#### Debugging Variables
|
||||
|
||||
Debug variables are exposed for real-time debugging purposes. Developers who are familiar with etcd can utilize these variables to debug unexpected behavior. etcd exposes debug variables via HTTP at `/debug/vars` in JSON format. The debug variables contains
|
||||
`cmdline`, `file_descriptor_limit`, `memstats` and `raft.status`.
|
||||
|
||||
`cmdline` is the command line arguments passed into etcd.
|
||||
|
||||
`file_descriptor_limit` is the max number of file descriptors etcd can utilize.
|
||||
|
||||
`memstats` is explained in detail in the [Go runtime documentation][golang-memstats].
|
||||
|
||||
`raft.status` is useful when you want to debug low level raft issues if you are familiar with raft internals. In most cases, you do not need to check `raft.status`.
|
||||
|
||||
```json
|
||||
{
|
||||
"cmdline": ["./etcd"],
|
||||
"file_descriptor_limit": 0,
|
||||
"memstats": {"Alloc":4105744,"TotalAlloc":42337320,"Sys":12560632,"...":"..."},
|
||||
"raft.status": {"id":"ce2a822cea30bfca","term":5,"vote":"ce2a822cea30bfca","commit":23509,"lead":"ce2a822cea30bfca","raftState":"StateLeader","progress":{"ce2a822cea30bfca":{"match":23509,"next":23510,"state":"ProgressStateProbe"}}}
|
||||
}
|
||||
```
|
||||
|
||||
### Optimal Cluster Size
|
||||
#### Optimal Cluster Size
|
||||
|
||||
The recommended etcd cluster size is 3, 5 or 7, which is decided by the fault tolerance requirement. A 7-member cluster can provide enough fault tolerance in most cases. While larger cluster provides better fault tolerance the write performance reduces since data needs to be replicated to more machines.
|
||||
|
||||
@ -113,8 +45,7 @@ It is recommended to have an odd number of members in a cluster. Having an odd c
|
||||
| Cluster Size | Majority | Failure Tolerance |
|
||||
|--------------|------------|-------------------|
|
||||
| 1 | 1 | 0 |
|
||||
| 2 | 2 | 0 |
|
||||
| 3 | 2 | **1** |
|
||||
| 3 | 2 | 1 |
|
||||
| 4 | 3 | 1 |
|
||||
| 5 | 3 | **2** |
|
||||
| 6 | 4 | 2 |
|
||||
@ -126,7 +57,7 @@ As you can see, adding another member to bring the size of cluster up to an odd
|
||||
|
||||
#### Changing Cluster Size
|
||||
|
||||
After your cluster is up and running, adding or removing members is done via [runtime reconfiguration][runtime-reconfig], which allows the cluster to be modified without downtime. The `etcdctl` tool has `member list`, `member add` and `member remove` commands to complete this process.
|
||||
After your cluster is up and running, adding or removing members is done via [runtime reconfiguration](runtime-configuration.md), which allows the cluster to be modified without downtime. The `etcdctl` tool has a `member list`, `member add` and `member remove` commands to complete this process.
|
||||
|
||||
### Member Migration
|
||||
|
||||
@ -134,10 +65,10 @@ When there is a scheduled machine maintenance or retirement, you might want to m
|
||||
|
||||
The data directory contains all the data to recover a member to its point-in-time state. To migrate a member:
|
||||
|
||||
* Stop the member process.
|
||||
* Copy the data directory of the now-idle member to the new machine.
|
||||
* Update the peer URLs for the replaced member to reflect the new machine according to the [runtime reconfiguration instructions][update-a-member].
|
||||
* Start etcd on the new machine, using the same configuration and the copy of the data directory.
|
||||
* Stop the member process
|
||||
* Copy the data directory of the now-idle member to the new machine
|
||||
* Update the peer URLs for that member to reflect the new machine according to the [member api] [change peer url]
|
||||
* Start etcd on the new machine, using the same configuration and the copy of the data directory
|
||||
|
||||
This example will walk you through the process of migrating the infra1 member to a new machine:
|
||||
|
||||
@ -147,11 +78,11 @@ This example will walk you through the process of migrating the infra1 member to
|
||||
|infra1|10.0.1.11:2380|
|
||||
|infra2|10.0.1.12:2380|
|
||||
|
||||
```sh
|
||||
$ export ETCDCTL_ENDPOINT=http://10.0.1.10:2379,http://10.0.1.11:2379,http://10.0.1.12:2379
|
||||
```
|
||||
$ export ETCDCTL_PEERS=http://10.0.1.10:2379,http://10.0.1.11:2379,http://10.0.1.12:2379
|
||||
```
|
||||
|
||||
```sh
|
||||
```
|
||||
$ etcdctl member list
|
||||
84194f7c5edd8b37: name=infra0 peerURLs=http://10.0.1.10:2380 clientURLs=http://127.0.0.1:2379,http://10.0.1.10:2379
|
||||
b4db3bf5e495e255: name=infra1 peerURLs=http://10.0.1.11:2380 clientURLs=http://127.0.0.1:2379,http://10.0.1.11:2379
|
||||
@ -160,57 +91,53 @@ bc1083c870280d44: name=infra2 peerURLs=http://10.0.1.12:2380 clientURLs=http://1
|
||||
|
||||
#### Stop the member etcd process
|
||||
|
||||
```sh
|
||||
$ ssh 10.0.1.11
|
||||
```
|
||||
$ ssh core@10.0.1.11
|
||||
```
|
||||
|
||||
```sh
|
||||
$ kill `pgrep etcd`
|
||||
```
|
||||
$ sudo systemctl stop etcd
|
||||
```
|
||||
|
||||
#### Copy the data directory of the now-idle member to the new machine
|
||||
|
||||
```
|
||||
$ tar -cvzf infra1.etcd.tar.gz %data_dir%
|
||||
$ tar -cvzf node1.etcd.tar.gz /var/lib/etcd/node1.etcd
|
||||
```
|
||||
|
||||
```sh
|
||||
$ scp infra1.etcd.tar.gz 10.0.1.13:~/
|
||||
```
|
||||
$ scp node1.etcd.tar.gz core@10.0.1.13:~/
|
||||
```
|
||||
|
||||
#### Update the peer URLs for that member to reflect the new machine
|
||||
|
||||
```sh
|
||||
```
|
||||
$ curl http://10.0.1.10:2379/v2/members/b4db3bf5e495e255 -XPUT \
|
||||
-H "Content-Type: application/json" -d '{"peerURLs":["http://10.0.1.13:2380"]}'
|
||||
```
|
||||
|
||||
Or use `etcdctl member update` command
|
||||
|
||||
```sh
|
||||
$ etcdctl member update b4db3bf5e495e255 http://10.0.1.13:2380
|
||||
```
|
||||
|
||||
#### Start etcd on the new machine, using the same configuration and the copy of the data directory
|
||||
|
||||
```sh
|
||||
$ ssh 10.0.1.13
|
||||
```
|
||||
|
||||
```sh
|
||||
$ tar -xzvf infra1.etcd.tar.gz -C %data_dir%
|
||||
$ ssh core@10.0.1.13
|
||||
```
|
||||
|
||||
```
|
||||
etcd -name infra1 \
|
||||
$ tar -xzvf node1.etcd.tar.gz -C /var/lib/etcd
|
||||
```
|
||||
|
||||
```
|
||||
etcd -name node1 \
|
||||
-listen-peer-urls http://10.0.1.13:2380 \
|
||||
-listen-client-urls http://10.0.1.13:2379,http://127.0.0.1:2379 \
|
||||
-advertise-client-urls http://10.0.1.13:2379,http://127.0.0.1:2379
|
||||
```
|
||||
|
||||
[change peer url]: https://github.com/coreos/etcd/blob/master/Documentation/other_apis.md#change-the-peer-urls-of-a-member
|
||||
|
||||
### Disaster Recovery
|
||||
|
||||
etcd is designed to be resilient to machine failures. An etcd cluster can automatically recover from any number of temporary failures (for example, machine reboots), and a cluster of N members can tolerate up to _(N-1)/2_ permanent failures (where a member can no longer access the cluster, due to hardware failure or disk corruption). However, in extreme circumstances, a cluster might permanently lose enough members such that quorum is irrevocably lost. For example, if a three-node cluster suffered two simultaneous and unrecoverable machine failures, it would be normally impossible for the cluster to restore quorum and continue functioning.
|
||||
etcd is designed to be resilient to machine failures. An etcd cluster can automatically recover from any number of temporary failures (for example, machine reboots), and a cluster of N members can tolerate up to _(N/2)-1_ permanent failures (where a member can no longer access the cluster, due to hardware failure or disk corruption). However, in extreme circumstances, a cluster might permanently lose enough members such that quorum is irrevocably lost. For example, if a three-node cluster suffered two simultaneous and unrecoverable machine failures, it would be normally impossible for the cluster to restore quorum and continue functioning.
|
||||
|
||||
To recover from such scenarios, etcd provides functionality to backup and restore the datastore and recreate the cluster without data loss.
|
||||
|
||||
@ -218,14 +145,12 @@ To recover from such scenarios, etcd provides functionality to backup and restor
|
||||
|
||||
**NB:** Windows users must stop etcd before running the backup command.
|
||||
|
||||
The first step of the recovery is to backup the data directory and wal directory, if stored separately, on a functioning etcd node. To do this, use the `etcdctl backup` command, passing in the original data (and wal) directory used by etcd. For example:
|
||||
The first step of the recovery is to backup the data directory on a functioning etcd node. To do this, use the `etcdctl backup` command, passing in the original data directory used by etcd. For example:
|
||||
|
||||
```sh
|
||||
etcdctl backup \
|
||||
--data-dir %data_dir% \
|
||||
[--wal-dir %wal_dir%] \
|
||||
--backup-dir %backup_data_dir%
|
||||
[--backup-wal-dir %backup_wal_dir%]
|
||||
--data-dir /var/lib/etcd \
|
||||
--backup-dir /tmp/etcd_backup
|
||||
```
|
||||
|
||||
This command will rewrite some of the metadata contained in the backup (specifically, the node ID and cluster ID), which means that the node will lose its former identity. In order to recreate a cluster from the backup, you will need to start a new, single-node cluster. The metadata is rewritten to prevent the new node from inadvertently being joined onto an existing cluster.
|
||||
@ -236,37 +161,33 @@ To restore a backup using the procedure created above, start etcd with the `-for
|
||||
|
||||
```sh
|
||||
etcd \
|
||||
-data-dir=%backup_data_dir% \
|
||||
[-wal-dir=%backup_wal_dir%] \
|
||||
-data-dir=/tmp/etcd_backup \
|
||||
-force-new-cluster \
|
||||
...
|
||||
```
|
||||
|
||||
Now etcd should be available on this node and serving the original datastore.
|
||||
|
||||
Once you have verified that etcd has started successfully, shut it down and move the data and wal, if stored separately, back to the previous location (you may wish to make another copy as well to be safe):
|
||||
Once you have verified that etcd has started successfully, shut it down and move the data back to the previous location (you may wish to make another copy as well to be safe):
|
||||
|
||||
```sh
|
||||
pkill etcd
|
||||
rm -fr %data_dir%
|
||||
rm -fr %wal_dir%
|
||||
mv %backup_data_dir% %data_dir%
|
||||
mv %backup_wal_dir% %wal_dir%
|
||||
rm -fr /var/lib/etcd
|
||||
mv /tmp/etcd_backup /var/lib/etcd
|
||||
etcd \
|
||||
-data-dir=%data_dir% \
|
||||
[-wal-dir=%wal_dir%] \
|
||||
-data-dir=/var/lib/etcd \
|
||||
...
|
||||
```
|
||||
|
||||
#### Restoring the cluster
|
||||
|
||||
Now that the node is running successfully, [change its advertised peer URLs][update-a-member], as the `--force-new-cluster` option has set the peer URL to the default listening on localhost.
|
||||
Now that the node is running successfully, you should [change its advertised peer URLs](other_apis.md#change-the-peer-urls-of-a-member), as the `--force-new-cluster` has set the peer URL to the default (listening on localhost).
|
||||
|
||||
You can then add more nodes to the cluster and restore resiliency. See the [add a new member][add-a-member] guide for more details. **NB:** If you are trying to restore your cluster using old failed etcd nodes, please make sure you have stopped old etcd instances and removed their old data directories specified by the data-dir configuration parameter.
|
||||
You can then add more nodes to the cluster and restore resiliency. See the [runtime configuration](runtime-configuration.md) guide for more details.
|
||||
|
||||
### Client Request Timeout
|
||||
|
||||
etcd sets different timeouts for various types of client requests. The timeout value is not tunable now, which will be improved soon (https://github.com/coreos/etcd/issues/2038).
|
||||
etcd sets different timeouts for various types of client requests. The timeout value is not tunable now, which will be improved soon(https://github.com/coreos/etcd/issues/2038).
|
||||
|
||||
#### Get requests
|
||||
|
||||
@ -288,23 +209,3 @@ If the request times out, it indicates two possibilities:
|
||||
2. the majority of the cluster is not functioning.
|
||||
|
||||
If timeout happens several times continuously, administrators should check status of cluster and resolve it as soon as possible.
|
||||
|
||||
### Best Practices
|
||||
|
||||
#### Maximum OS threads
|
||||
|
||||
By default, etcd uses the default configuration of the Go 1.4 runtime, which means that at most one operating system thread will be used to execute code simultaneously. (Note that this default behavior [has changed in Go 1.5][golang1.5-runtime]).
|
||||
|
||||
When using etcd in heavy-load scenarios on machines with multiple cores it will usually be desirable to increase the number of threads that etcd can utilize. To do this, simply set the environment variable GOMAXPROCS to the desired number when starting etcd. For more information on this variable, see the [Go runtime documentation][golang-runtime].
|
||||
|
||||
[add-a-member]: runtime-configuration.md#add-a-new-member
|
||||
[golang1.5-runtime]: https://golang.org/doc/go1.5#runtime
|
||||
[golang-memstats]: https://golang.org/pkg/runtime/#MemStats
|
||||
[golang-runtime]: https://golang.org/pkg/runtime
|
||||
[metrics]: metrics.md
|
||||
[prometheus]: http://prometheus.io/
|
||||
[remove-a-member]: runtime-configuration.md#remove-a-member
|
||||
[runtime-reconfig]: runtime-configuration.md#cluster-reconfiguration-operations
|
||||
[snap-pkg]: http://godoc.org/github.com/coreos/etcd/snap
|
||||
[update-a-member]: runtime-configuration.md#update-a-member
|
||||
[wal-pkg]: http://godoc.org/github.com/coreos/etcd/wal
|
@ -78,9 +78,12 @@ X-Raft-Index: 5398
|
||||
X-Raft-Term: 1
|
||||
```
|
||||
|
||||
* `X-Etcd-Index` is the current etcd index as explained above. When request is a watch on key space, `X-Etcd-Index` is the current etcd index when the watch starts, which means that the watched event may happen after `X-Etcd-Index`.
|
||||
* `X-Raft-Index` is similar to the etcd index but is for the underlying raft protocol.
|
||||
* `X-Raft-Term` is an integer that will increase whenever an etcd master election happens in the cluster. If this number is increasing rapidly, you may need to tune the election timeout. See the [tuning][tuning] section for details.
|
||||
- `X-Etcd-Index` is the current etcd index as explained above.
|
||||
- `X-Raft-Index` is similar to the etcd index but is for the underlying raft protocol
|
||||
- `X-Raft-Term` is an integer that will increase whenever an etcd master election happens in the cluster. If this number is increasing rapidly, you may need to tune the election timeout. See the [tuning][tuning] section for details.
|
||||
|
||||
[tuning]: #tuning
|
||||
|
||||
|
||||
### Get the value of a key
|
||||
|
||||
@ -231,51 +234,6 @@ curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -d ttl= -d prevExist=t
|
||||
}
|
||||
```
|
||||
|
||||
### Refreshing key TTL
|
||||
|
||||
Keys in etcd can be refreshed without notifying current watchers.
|
||||
|
||||
This can be achieved by setting the refresh to true when updating a TTL.
|
||||
|
||||
You cannot update the value of a key when refreshing it.
|
||||
|
||||
```sh
|
||||
curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -d ttl=5
|
||||
curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d ttl=5 -d refresh=true -d prevExist=true
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "set",
|
||||
"node": {
|
||||
"createdIndex": 5,
|
||||
"expiration": "2013-12-04T12:01:21.874888581-08:00",
|
||||
"key": "/foo",
|
||||
"modifiedIndex": 5,
|
||||
"ttl": 5,
|
||||
"value": "bar"
|
||||
}
|
||||
}
|
||||
{
|
||||
"action":"update",
|
||||
"node":{
|
||||
"key":"/foo",
|
||||
"value":"bar",
|
||||
"expiration": "2013-12-04T12:01:26.874888581-08:00",
|
||||
"ttl":5,
|
||||
"modifiedIndex":6,
|
||||
"createdIndex":5
|
||||
},
|
||||
"prevNode":{
|
||||
"key":"/foo",
|
||||
"value":"bar",
|
||||
"expiration":"2013-12-04T12:01:21.874888581-08:00",
|
||||
"ttl":3,
|
||||
"modifiedIndex":5,
|
||||
"createdIndex":5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Waiting for a change
|
||||
|
||||
@ -319,7 +277,7 @@ The first terminal should get the notification and return with the same response
|
||||
However, the watch command can do more than this.
|
||||
Using the index, we can watch for commands that have happened in the past.
|
||||
This is useful for ensuring you don't miss events between watch commands.
|
||||
Typically, we watch again from the `modifiedIndex` + 1 of the node we got.
|
||||
Typically, we watch again from the (modifiedIndex + 1) of the node we got.
|
||||
|
||||
Let's try to watch for the set command of index 7 again:
|
||||
|
||||
@ -329,81 +287,48 @@ curl 'http://127.0.0.1:2379/v2/keys/foo?wait=true&waitIndex=7'
|
||||
|
||||
The watch command returns immediately with the same response as previously.
|
||||
|
||||
If we were to restart the watch from index 8 with:
|
||||
|
||||
```sh
|
||||
curl 'http://127.0.0.1:2379/v2/keys/foo?wait=true&waitIndex=8'
|
||||
```
|
||||
|
||||
Then even if etcd is on index 9 or 800, the first event to occur to the `/foo`
|
||||
key between 8 and the current index will be returned.
|
||||
|
||||
**Note**: etcd only keeps the responses of the most recent 1000 events across all etcd keys.
|
||||
It is recommended to send the response to another thread to process immediately
|
||||
instead of blocking the watch while processing the result.
|
||||
|
||||
#### Watch from cleared event index
|
||||
|
||||
If we miss all the 1000 events, we need to recover the current state of the
|
||||
watching key space through a get and then start to watch from the
|
||||
`X-Etcd-Index` + 1.
|
||||
watching key space. First, We do a get and then start to watch from the (etcdIndex + 1).
|
||||
|
||||
For example, we set `/other="bar"` for 2000 times and try to wait from index 8.
|
||||
For example, we set `/foo="bar"` for 2000 times and tries to wait from index 7.
|
||||
|
||||
```sh
|
||||
curl 'http://127.0.0.1:2379/v2/keys/foo?wait=true&waitIndex=8'
|
||||
curl 'http://127.0.0.1:2379/v2/keys/foo?wait=true&waitIndex=7'
|
||||
```
|
||||
|
||||
We get the index is outdated response, since we miss the 1000 events kept in etcd.
|
||||
|
||||
```
|
||||
{"errorCode":401,"message":"The event in requested index is outdated and cleared","cause":"the requested history has been cleared [1008/8]","index":2007}
|
||||
{"errorCode":401,"message":"The event in requested index is outdated and cleared","cause":"the requested history has been cleared [1003/7]","index":2002}
|
||||
```
|
||||
|
||||
To start watch, first we need to fetch the current state of key `/foo`:
|
||||
|
||||
To start watch, first we need to fetch the current state of key `/foo` and the etcdIndex.
|
||||
```sh
|
||||
curl 'http://127.0.0.1:2379/v2/keys/foo' -vv
|
||||
```
|
||||
|
||||
```
|
||||
< HTTP/1.1 200 OK
|
||||
< Content-Type: application/json
|
||||
< X-Etcd-Cluster-Id: 7e27652122e8b2ae
|
||||
< X-Etcd-Index: 2007
|
||||
< X-Etcd-Index: 2002
|
||||
< X-Raft-Index: 2615
|
||||
< X-Raft-Term: 2
|
||||
< Date: Mon, 05 Jan 2015 18:54:43 GMT
|
||||
< Transfer-Encoding: chunked
|
||||
<
|
||||
{"action":"get","node":{"key":"/foo","value":"bar","modifiedIndex":7,"createdIndex":7}}
|
||||
{"action":"get","node":{"key":"/foo","value":"","modifiedIndex":2002,"createdIndex":2002}}
|
||||
```
|
||||
|
||||
Unlike watches we use the `X-Etcd-Index` + 1 of the response as a `waitIndex`
|
||||
instead of the node's `modifiedIndex` + 1 for two reasons:
|
||||
|
||||
1. The `X-Etcd-Index` is always greater than or equal to the `modifiedIndex` when
|
||||
getting a key because `X-Etcd-Index` is the current etcd index, and the `modifiedIndex`
|
||||
is the index of an event already stored in etcd.
|
||||
2. None of the events represented by indexes between `modifiedIndex` and
|
||||
`X-Etcd-Index` will be related to the key being fetched.
|
||||
|
||||
Using the `modifiedIndex` + 1 is functionally equivalent for subsequent
|
||||
watches, but since it is smaller than the `X-Etcd-Index` + 1, we may receive a
|
||||
`401 EventIndexCleared` error immediately.
|
||||
|
||||
So the first watch after the get should be:
|
||||
The `X-Etcd-Index` is important. It is the index when we got the value of `/foo`.
|
||||
So we can watch again from the (`X-Etcd-Index` + 1) without missing an event after the last get.
|
||||
|
||||
```sh
|
||||
curl 'http://127.0.0.1:2379/v2/keys/foo?wait=true&waitIndex=2008'
|
||||
curl 'http://127.0.0.1:2379/v2/keys/foo?wait=true&waitIndex=2003'
|
||||
```
|
||||
|
||||
#### Connection being closed prematurely
|
||||
|
||||
The server may close a long polling connection before emitting any events.
|
||||
This can happen due to a timeout or the server being shutdown.
|
||||
Since the HTTP header is sent immediately upon accepting the connection, the response will be seen as empty: `200 OK` and empty body.
|
||||
The clients should be prepared to deal with this scenario and retry the watch.
|
||||
|
||||
### Atomically Creating In-Order Keys
|
||||
|
||||
@ -422,7 +347,7 @@ curl http://127.0.0.1:2379/v2/keys/queue -XPOST -d value=Job1
|
||||
"action": "create",
|
||||
"node": {
|
||||
"createdIndex": 6,
|
||||
"key": "/queue/00000000000000000006",
|
||||
"key": "/queue/6",
|
||||
"modifiedIndex": 6,
|
||||
"value": "Job1"
|
||||
}
|
||||
@ -441,7 +366,7 @@ curl http://127.0.0.1:2379/v2/keys/queue -XPOST -d value=Job2
|
||||
"action": "create",
|
||||
"node": {
|
||||
"createdIndex": 29,
|
||||
"key": "/queue/00000000000000000029",
|
||||
"key": "/queue/29",
|
||||
"modifiedIndex": 29,
|
||||
"value": "Job2"
|
||||
}
|
||||
@ -465,13 +390,13 @@ curl -s 'http://127.0.0.1:2379/v2/keys/queue?recursive=true&sorted=true'
|
||||
"nodes": [
|
||||
{
|
||||
"createdIndex": 2,
|
||||
"key": "/queue/00000000000000000002",
|
||||
"key": "/queue/2",
|
||||
"modifiedIndex": 2,
|
||||
"value": "Job1"
|
||||
},
|
||||
{
|
||||
"createdIndex": 3,
|
||||
"key": "/queue/00000000000000000003",
|
||||
"key": "/queue/3",
|
||||
"modifiedIndex": 3,
|
||||
"value": "Job2"
|
||||
}
|
||||
@ -514,7 +439,7 @@ curl http://127.0.0.1:2379/v2/keys/dir -XPUT -d ttl=30 -d dir=true -d prevExist=
|
||||
Keys that are under this directory work as usual, but when the directory expires, a watcher on a key under the directory will get an expire event:
|
||||
|
||||
```sh
|
||||
curl 'http://127.0.0.1:2379/v2/keys/dir?wait=true'
|
||||
curl 'http://127.0.0.1:2379/v2/keys/dir/asdf?wait=true'
|
||||
```
|
||||
|
||||
```json
|
||||
@ -542,15 +467,13 @@ etcd can be used as a centralized coordination service in a cluster, and `Compar
|
||||
|
||||
This command will set the value of a key only if the client-provided conditions are equal to the current conditions.
|
||||
|
||||
*Note that `CompareAndSwap` does not work with [directories][directories]. If an attempt is made to `CompareAndSwap` a directory, a 102 "Not a file" error will be returned.*
|
||||
|
||||
The current comparable conditions are:
|
||||
|
||||
1. `prevValue` - checks the previous value of the key.
|
||||
|
||||
2. `prevIndex` - checks the previous modifiedIndex of the key.
|
||||
|
||||
3. `prevExist` - checks existence of the key: if `prevExist` is true, it is an `update` request; if `prevExist` is `false`, it is a `create` request.
|
||||
3. `prevExist` - checks existence of the key: if `prevExist` is true, it is an `update` request; if prevExist is `false`, it is a `create` request.
|
||||
|
||||
Here is a simple example.
|
||||
Let's create a key-value pair first: `foo=one`.
|
||||
@ -629,8 +552,6 @@ We successfully changed the value from "one" to "two" since we gave the correct
|
||||
|
||||
This command will delete a key only if the client-provided conditions are equal to the current conditions.
|
||||
|
||||
*Note that `CompareAndDelete` does not work with [directories]. If an attempt is made to `CompareAndDelete` a directory, a 102 "Not a file" error will be returned.*
|
||||
|
||||
The current comparable conditions are:
|
||||
|
||||
1. `prevValue` - checks the previous value of the key.
|
||||
@ -949,7 +870,7 @@ Here we see the `/message` key but our hidden `/_message` key is not returned.
|
||||
|
||||
### Setting a key from a file
|
||||
|
||||
You can also use etcd to store small configuration files, JSON documents, XML documents, etc directly.
|
||||
You can also use etcd to store small configuration files, json documents, XML documents, etc directly.
|
||||
For example you can use curl to upload a simple text file and encode it:
|
||||
|
||||
```
|
||||
@ -1094,7 +1015,6 @@ curl http://127.0.0.1:2379/v2/stats/self
|
||||
### Store Statistics
|
||||
|
||||
The store statistics include information about the operations that this node has handled.
|
||||
Note that v2 `store Statistics` is stored in-memory. When a member stops, store statistics will reset on restart.
|
||||
|
||||
Operations that modify the store's state like create, delete, set and update are seen by the entire cluster and the number will increase on all nodes.
|
||||
Operations like get and watch are node local and will only be seen on this node.
|
||||
@ -1124,8 +1044,6 @@ curl http://127.0.0.1:2379/v2/stats/store
|
||||
|
||||
## Cluster Config
|
||||
|
||||
See the [members API][members-api] for details on the cluster management.
|
||||
See the [other etcd APIs][other-apis] for details on the cluster management.
|
||||
|
||||
[directories]: #listing-a-directory
|
||||
[members-api]: members_api.md
|
||||
[tuning]: tuning.md
|
||||
[other-apis]: https://github.com/coreos/etcd/blob/master/Documentation/other_apis.md
|
@ -1,10 +1,10 @@
|
||||
# Backward Compatibility
|
||||
### Backward Compatibility
|
||||
|
||||
The main goal of etcd 2.0 release is to improve cluster safety around bootstrapping and dynamic reconfiguration. To do this, we deprecated the old error-prone APIs and provide a new set of APIs.
|
||||
|
||||
The other main focus of this release was a more reliable Raft implementation, but as this change is internal it should not have any notable effects to users.
|
||||
|
||||
## Command Line Flags Changes
|
||||
#### Command Line Flags Changes
|
||||
|
||||
The major flag changes are to mostly related to bootstrapping. The `initial-*` flags provide an improved way to specify the required criteria to start the cluster. The advertised URLs now support a list of values instead of a single value, which allows etcd users to gracefully migrate to the new set of IANA-assigned ports (2379/client and 2380/peers) while maintaining backward compatibility with the old ports.
|
||||
|
||||
@ -18,32 +18,35 @@ The major flag changes are to mostly related to bootstrapping. The `initial-*` f
|
||||
- `-peer-election-timeout` is replaced by `-election-timeout`.
|
||||
|
||||
The documentation of new command line flags can be found at
|
||||
https://github.com/coreos/etcd/blob/master/Documentation/v2/configuration.md.
|
||||
https://github.com/coreos/etcd/blob/master/Documentation/configuration.md.
|
||||
|
||||
## Data Directory Naming
|
||||
#### Data Dir
|
||||
- Default data dir location has changed from {$hostname}.etcd to {name}.etcd.
|
||||
|
||||
The default data dir location has changed from {$hostname}.etcd to {name}.etcd.
|
||||
- The disk format within the data dir has changed. etcd 2.0 should be able to auto upgrade the old data format. Instructions on doing so manually are in the [migration tool doc][migrationtooldoc].
|
||||
|
||||
## Key-Value API
|
||||
[migrationtooldoc]: https://github.com/coreos/etcd/blob/master/Documentation/0_4_migration_tool.md
|
||||
|
||||
### Read consistency flag
|
||||
#### Key-Value API
|
||||
|
||||
##### Read consistency flag
|
||||
|
||||
The consistent flag for read operations is removed in etcd 2.0.0. The normal read operations provides the same consistency guarantees with the 0.4.6 read operations with consistent flag set.
|
||||
|
||||
The read consistency guarantees are:
|
||||
|
||||
The consistent read guarantees the sequential consistency within one client that talks to one etcd server. Read/Write from one client to one etcd member should be observed in order. If one client write a value to an etcd server successfully, it should be able to get the value out of the server immediately.
|
||||
The consistent read guarantees the sequential consistency within one client that talks to one etcd server. Read/Write from one client to one etcd member should be observed in order. If one client write a value to a etcd server successfully, it should be able to get the value out of the server immediately.
|
||||
|
||||
Each etcd member will proxy the request to leader and only return the result to user after the result is applied on the local member. Thus after the write succeed, the user is guaranteed to see the value on the member it sent the request to.
|
||||
|
||||
Reads do not provide linearizability. If you want linearizable read, you need to set quorum option to true.
|
||||
Reads do not provide linearizability. If you want linearizabilable read, you need to set quorum option to true.
|
||||
|
||||
**Previous behavior**
|
||||
|
||||
We added an option for a consistent read in the old version of etcd since etcd 0.x redirects the write request to the leader. When the user get back the result from the leader, the member it sent the request to originally might not apply the write request yet. With the consistent flag set to true, the client will always send read request to the leader. So one client should be able to see its last write when consistent=true is enabled. There is no order guarantees among different clients.
|
||||
|
||||
|
||||
## Standby
|
||||
#### Standby
|
||||
|
||||
etcd 0.4’s standby mode has been deprecated. [Proxy mode][proxymode] is introduced to solve a subset of problems standby was solving.
|
||||
|
||||
@ -51,21 +54,21 @@ Standby mode was intended for large clusters that had a subset of the members ac
|
||||
|
||||
Proxy mode in 2.0 will provide similar functionality, and with improved control over which machines act as proxies due to the operator specifically configuring them. Proxies also support read only or read/write modes for increased security and durability.
|
||||
|
||||
[proxymode]: proxy.md
|
||||
[proxymode]: https://github.com/coreos/etcd/blob/master/Documentation/proxy.md
|
||||
|
||||
## Discovery Service
|
||||
#### Discovery Service
|
||||
|
||||
A size key needs to be provided inside a [discovery token][discoverytoken].
|
||||
[discoverytoken]: clustering.md#custom-etcd-discovery-service
|
||||
[discoverytoken]: https://github.com/coreos/etcd/blob/master/Documentation/clustering.md#custom-etcd-discovery-service
|
||||
|
||||
## HTTP Admin API
|
||||
#### HTTP Admin API
|
||||
|
||||
`v2/admin` on peer url and `v2/keys/_etcd` are unified under the new [v2/members API][members-api] to better explain which machines are part of an etcd cluster, and to simplify the keyspace for all your use cases.
|
||||
`v2/admin` on peer url and `v2/keys/_etcd` are unified under the new [v2/member API][memberapi] to better explain which machines are part of an etcd cluster, and to simplify the keyspace for all your use cases.
|
||||
|
||||
[members-api]: members_api.md
|
||||
[memberapi]: https://github.com/coreos/etcd/blob/master/Documentation/other_apis.md
|
||||
|
||||
## HTTP Key Value API
|
||||
- The follower can now transparently proxy write requests to the leader. Clients will no longer see 307 redirections to the leader from etcd.
|
||||
#### HTTP Key Value API
|
||||
- The follower can now transparently proxy write equests to the leader. Clients will no longer see 307 redirections to the leader from etcd.
|
||||
|
||||
- Expiration time is in UTC instead of local time.
|
||||
|
@ -1,18 +0,0 @@
|
||||
# Benchmarks
|
||||
|
||||
etcd benchmarks will be published regularly and tracked for each release below:
|
||||
|
||||
- [etcd v2.1.0-alpha][2.1]
|
||||
- [etcd v2.2.0-rc][2.2]
|
||||
- [etcd v3 demo][3.0]
|
||||
|
||||
# Memory Usage Benchmarks
|
||||
|
||||
It records expected memory usage in different scenarios.
|
||||
|
||||
- [etcd v2.2.0-rc][2.2-mem]
|
||||
|
||||
[2.1]: etcd-2-1-0-alpha-benchmarks.md
|
||||
[2.2]: etcd-2-2-0-rc-benchmarks.md
|
||||
[2.2-mem]: etcd-2-2-0-rc-memory-benchmarks.md
|
||||
[3.0]: etcd-3-demo-benchmarks.md
|
@ -1,52 +0,0 @@
|
||||
## Physical machines
|
||||
|
||||
GCE n1-highcpu-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted under /var/lib/etcd
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 1.8 GB memory
|
||||
- 2x CPUs
|
||||
- etcd version 2.1.0 alpha
|
||||
|
||||
## etcd Cluster
|
||||
|
||||
3 etcd members, each runs on a single machine
|
||||
|
||||
## Testing
|
||||
|
||||
Bootstrap another machine and use the [boom HTTP benchmark tool][boom] to send requests to each etcd member. Check the [benchmark hacking guide][hack-benchmark] for detailed instructions.
|
||||
|
||||
## Performance
|
||||
|
||||
### reading one single key
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | read QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|--------------------|----------|---------------|
|
||||
| 64 | 1 | leader only | 1534 | 0.7 |
|
||||
| 64 | 64 | leader only | 10125 | 9.1 |
|
||||
| 64 | 256 | leader only | 13892 | 27.1 |
|
||||
| 256 | 1 | leader only | 1530 | 0.8 |
|
||||
| 256 | 64 | leader only | 10106 | 10.1 |
|
||||
| 256 | 256 | leader only | 14667 | 27.0 |
|
||||
| 64 | 64 | all servers | 24200 | 3.9 |
|
||||
| 64 | 256 | all servers | 33300 | 11.8 |
|
||||
| 256 | 64 | all servers | 24800 | 3.9 |
|
||||
| 256 | 256 | all servers | 33000 | 11.5 |
|
||||
|
||||
### writing one single key
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | write QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|--------------------|-----------|---------------|
|
||||
| 64 | 1 | leader only | 60 | 21.4 |
|
||||
| 64 | 64 | leader only | 1742 | 46.8 |
|
||||
| 64 | 256 | leader only | 3982 | 90.5 |
|
||||
| 256 | 1 | leader only | 58 | 20.3 |
|
||||
| 256 | 64 | leader only | 1770 | 47.8 |
|
||||
| 256 | 256 | leader only | 4157 | 105.3 |
|
||||
| 64 | 64 | all servers | 1028 | 123.4 |
|
||||
| 64 | 256 | all servers | 3260 | 123.8 |
|
||||
| 256 | 64 | all servers | 1033 | 121.5 |
|
||||
| 256 | 256 | all servers | 3061 | 119.3 |
|
||||
|
||||
[boom]: https://github.com/rakyll/boom
|
||||
[hack-benchmark]: /hack/benchmark/
|
@ -1,69 +0,0 @@
|
||||
# Benchmarking etcd v2.2.0
|
||||
|
||||
## Physical Machines
|
||||
|
||||
GCE n1-highcpu-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted as etcd data directory
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 1.8 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## etcd Cluster
|
||||
|
||||
3 etcd 2.2.0 members, each runs on a single machine.
|
||||
|
||||
Detailed versions:
|
||||
|
||||
```
|
||||
etcd Version: 2.2.0
|
||||
Git SHA: e4561dd
|
||||
Go Version: go1.5
|
||||
Go OS/Arch: linux/amd64
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Bootstrap another machine, outside of the etcd cluster, and run the [`boom` HTTP benchmark tool](https://github.com/rakyll/boom) with a connection reuse patch to send requests to each etcd cluster member. See the [benchmark instructions](../../hack/benchmark/) for the patch and the steps to reproduce our procedures.
|
||||
|
||||
The performance is calulated through results of 100 benchmark rounds.
|
||||
|
||||
## Performance
|
||||
|
||||
### Single Key Read Performance
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | average read QPS | read QPS stddev | average 90th Percentile Latency (ms) | latency stddev |
|
||||
|-------------------|-------------------|--------------------|------------------|-----------------|--------------------------------------|----------------|
|
||||
| 64 | 1 | leader only | 2303 | 200 | 0.49 | 0.06 |
|
||||
| 64 | 64 | leader only | 15048 | 685 | 7.60 | 0.46 |
|
||||
| 64 | 256 | leader only | 14508 | 434 | 29.76 | 1.05 |
|
||||
| 256 | 1 | leader only | 2162 | 214 | 0.52 | 0.06 |
|
||||
| 256 | 64 | leader only | 14789 | 792 | 7.69| 0.48 |
|
||||
| 256 | 256 | leader only | 14424 | 512 | 29.92 | 1.42 |
|
||||
| 64 | 64 | all servers | 45752 | 2048 | 2.47 | 0.14 |
|
||||
| 64 | 256 | all servers | 46592 | 1273 | 10.14 | 0.59 |
|
||||
| 256 | 64 | all servers | 45332 | 1847 | 2.48| 0.12 |
|
||||
| 256 | 256 | all servers | 46485 | 1340 | 10.18 | 0.74 |
|
||||
|
||||
### Single Key Write Performance
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | average write QPS | write QPS stddev | average 90th Percentile Latency (ms) | latency stddev |
|
||||
|-------------------|-------------------|--------------------|------------------|-----------------|--------------------------------------|----------------|
|
||||
| 64 | 1 | leader only | 55 | 4 | 24.51 | 13.26 |
|
||||
| 64 | 64 | leader only | 2139 | 125 | 35.23 | 3.40 |
|
||||
| 64 | 256 | leader only | 4581 | 581 | 70.53 | 10.22 |
|
||||
| 256 | 1 | leader only | 56 | 4 | 22.37| 4.33 |
|
||||
| 256 | 64 | leader only | 2052 | 151 | 36.83 | 4.20 |
|
||||
| 256 | 256 | leader only | 4442 | 560 | 71.59 | 10.03 |
|
||||
| 64 | 64 | all servers | 1625 | 85 | 58.51 | 5.14 |
|
||||
| 64 | 256 | all servers | 4461 | 298 | 89.47 | 36.48 |
|
||||
| 256 | 64 | all servers | 1599 | 94 | 60.11| 6.43 |
|
||||
| 256 | 256 | all servers | 4315 | 193 | 88.98 | 7.01 |
|
||||
|
||||
## Performance Changes
|
||||
|
||||
- Because etcd now records metrics for each API call, read QPS performance seems to see a minor decrease in most scenarios. This minimal performance impact was judged a reasonable investment for the breadth of monitoring and debugging information returned.
|
||||
|
||||
- Write QPS to cluster leaders seems to be increased by a small margin. This is because the main loop and entry apply loops were decoupled in the etcd raft logic, eliminating several blocks between them.
|
||||
|
||||
- Write QPS to all members seems to be increased by a significant margin, because followers now receive the latest commit index sooner, and commit proposals more quickly.
|
@ -1,72 +0,0 @@
|
||||
## Physical machines
|
||||
|
||||
GCE n1-highcpu-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted under /var/lib/etcd
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 1.8 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## etcd Cluster
|
||||
|
||||
3 etcd 2.2.0-rc members, each runs on a single machine.
|
||||
|
||||
Detailed versions:
|
||||
|
||||
```
|
||||
etcd Version: 2.2.0-alpha.1+git
|
||||
Git SHA: 59a5a7e
|
||||
Go Version: go1.4.2
|
||||
Go OS/Arch: linux/amd64
|
||||
```
|
||||
|
||||
Also, we use 3 etcd 2.1.0 alpha-stage members to form cluster to get base performance. etcd's commit head is at [c7146bd5][c7146bd5], which is the same as the one that we use in [etcd 2.1 benchmark][etcd-2.1-benchmark].
|
||||
|
||||
## Testing
|
||||
|
||||
Bootstrap another machine and use the [boom HTTP benchmark tool][boom] to send requests to each etcd member. Check the [benchmark hacking guide][hack-benchmark] for detailed instructions.
|
||||
|
||||
## Performance
|
||||
|
||||
### reading one single key
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | read QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|--------------------|----------|---------------|
|
||||
| 64 | 1 | leader only | 2804 (-5%) | 0.4 (+0%) |
|
||||
| 64 | 64 | leader only | 17816 (+0%) | 5.7 (-6%) |
|
||||
| 64 | 256 | leader only | 18667 (-6%) | 20.4 (+2%) |
|
||||
| 256 | 1 | leader only | 2181 (-15%) | 0.5 (+25%) |
|
||||
| 256 | 64 | leader only | 17435 (-7%) | 6.0 (+9%) |
|
||||
| 256 | 256 | leader only | 18180 (-8%) | 21.3 (+3%) |
|
||||
| 64 | 64 | all servers | 46965 (-4%) | 2.1 (+0%) |
|
||||
| 64 | 256 | all servers | 55286 (-6%) | 7.4 (+6%) |
|
||||
| 256 | 64 | all servers | 46603 (-6%) | 2.1 (+5%) |
|
||||
| 256 | 256 | all servers | 55291 (-6%) | 7.3 (+4%) |
|
||||
|
||||
### writing one single key
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | write QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|--------------------|-----------|---------------|
|
||||
| 64 | 1 | leader only | 76 (+22%) | 19.4 (-15%) |
|
||||
| 64 | 64 | leader only | 2461 (+45%) | 31.8 (-32%) |
|
||||
| 64 | 256 | leader only | 4275 (+1%) | 69.6 (-10%) |
|
||||
| 256 | 1 | leader only | 64 (+20%) | 16.7 (-30%) |
|
||||
| 256 | 64 | leader only | 2385 (+30%) | 31.5 (-19%) |
|
||||
| 256 | 256 | leader only | 4353 (-3%) | 74.0 (+9%) |
|
||||
| 64 | 64 | all servers | 2005 (+81%) | 49.8 (-55%) |
|
||||
| 64 | 256 | all servers | 4868 (+35%) | 81.5 (-40%) |
|
||||
| 256 | 64 | all servers | 1925 (+72%) | 47.7 (-59%) |
|
||||
| 256 | 256 | all servers | 4975 (+36%) | 70.3 (-36%) |
|
||||
|
||||
### performance changes explanation
|
||||
|
||||
- read QPS in most scenarios is decreased by 5~8%. The reason is that etcd records store metrics for each store operation. The metrics is important for monitoring and debugging, so this is acceptable.
|
||||
|
||||
- write QPS to leader is increased by 20~30%. This is because we decouple raft main loop and entry apply loop, which avoids them blocking each other.
|
||||
|
||||
- write QPS to all servers is increased by 30~80% because follower could receive latest commit index earlier and commit proposals faster.
|
||||
|
||||
[boom]: https://github.com/rakyll/boom
|
||||
[c7146bd5]: https://github.com/coreos/etcd/commits/c7146bd5f2c73716091262edc638401bb8229144
|
||||
[etcd-2.1-benchmark]: etcd-2-1-0-alpha-benchmarks.md
|
||||
[hack-benchmark]: /hack/benchmark/
|
@ -1,47 +0,0 @@
|
||||
## Physical machine
|
||||
|
||||
GCE n1-standard-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted under /var/lib/etcd
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 7.5 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## etcd
|
||||
|
||||
```
|
||||
etcd Version: 2.2.0-rc.0+git
|
||||
Git SHA: 103cb5c
|
||||
Go Version: go1.5
|
||||
Go OS/Arch: linux/amd64
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Start 3-member etcd cluster, each of which uses 2 cores.
|
||||
|
||||
The length of key name is always 64 bytes, which is a reasonable length of average key bytes.
|
||||
|
||||
## Memory Maximal Usage
|
||||
|
||||
- etcd may use maximal memory if one follower is dead and the leader keeps sending snapshots.
|
||||
- `max RSS` is the maximal memory usage recorded in 3 runs.
|
||||
|
||||
| value bytes | key number | data size(MB) | max RSS(MB) | max RSS/data rate on leader |
|
||||
|-------------|-------------|---------------|-------------|-----------------------------|
|
||||
| 128 | 50000 | 6 | 433 | 72x |
|
||||
| 128 | 100000 | 12 | 659 | 54x |
|
||||
| 128 | 200000 | 24 | 1466 | 61x |
|
||||
| 1024 | 50000 | 48 | 1253 | 26x |
|
||||
| 1024 | 100000 | 96 | 2344 | 24x |
|
||||
| 1024 | 200000 | 192 | 4361 | 22x |
|
||||
|
||||
## Data Size Threshold
|
||||
|
||||
- When etcd reaches data size threshold, it may trigger leader election easily and drop part of proposals.
|
||||
- At most cases, etcd cluster should work smoothly if it doesn't hit the threshold. If it doesn't work well due to insufficient resources, you need to decrease its data size.
|
||||
|
||||
| value bytes | key number limitation | suggested data size threshold(MB) | consumed RSS(MB) |
|
||||
|-------------|-----------------------|-----------------------------------|------------------|
|
||||
| 128 | 400K | 48 | 2400 |
|
||||
| 1024 | 300K | 292 | 6500 |
|
@ -1,42 +0,0 @@
|
||||
## Physical machines
|
||||
|
||||
GCE n1-highcpu-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted under /var/lib/etcd
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 1.8 GB memory
|
||||
- 2x CPUs
|
||||
- etcd version 2.2.0
|
||||
|
||||
## etcd Cluster
|
||||
|
||||
1 etcd member running in v3 demo mode
|
||||
|
||||
## Testing
|
||||
|
||||
Use [etcd v3 benchmark tool][etcd-v3-benchmark].
|
||||
|
||||
## Performance
|
||||
|
||||
### reading one single key
|
||||
|
||||
| key size in bytes | number of clients | read QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|----------|---------------|
|
||||
| 256 | 1 | 2716 | 0.4 |
|
||||
| 256 | 64 | 16623 | 6.1 |
|
||||
| 256 | 256 | 16622 | 21.7 |
|
||||
|
||||
The performance is nearly the same as the one with empty server handler.
|
||||
|
||||
### reading one single key after putting
|
||||
|
||||
| key size in bytes | number of clients | read QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|----------|---------------|
|
||||
| 256 | 1 | 2269 | 0.5 |
|
||||
| 256 | 64 | 13582 | 8.6 |
|
||||
| 256 | 256 | 13262 | 47.5 |
|
||||
|
||||
The performance with empty server handler is not affected by one put. So the
|
||||
performance downgrade should be caused by storage package.
|
||||
|
||||
[etcd-v3-benchmark]: /tools/benchmark/
|
@ -1,77 +0,0 @@
|
||||
# Watch Memory Usage Benchmark
|
||||
|
||||
*NOTE*: The watch features are under active development, and their memory usage may change as that development progresses. We do not expect it to significantly increase beyond the figures stated below.
|
||||
|
||||
A primary goal of etcd is supporting a very large number of watchers doing a massively large amount of watching. etcd aims to support O(10k) clients, O(100K) watch streams (O(10) streams per client) and O(10M) total watchings (O(100) watching per stream). The memory consumed by each individual watching accounts for the largest portion of etcd's overall usage, and is therefore the focus of current and future optimizations.
|
||||
|
||||
|
||||
Three related components of etcd watch consume physical memory: each `grpc.Conn`, each watch stream, and each instance of the watching activity. `grpc.Conn` maintains the actual TCP connection and other gRPC connection state. Each `grpc.Conn` consumes O(10kb) of memory, and might have multiple watch streams attached.
|
||||
|
||||
Each watch stream is an independent HTTP2 connection which consumes another O(10kb) of memory.
|
||||
Multiple watchings might share one watch stream.
|
||||
|
||||
Watching is the actual struct that tracks the changes on the key-value store. Each watching should only consume < O(1kb).
|
||||
|
||||
```
|
||||
+-------+
|
||||
| watch |
|
||||
+---------> | foo |
|
||||
| +-------+
|
||||
+------+-----+
|
||||
| stream |
|
||||
+--------------> | |
|
||||
| +------+-----+ +-------+
|
||||
| | | watch |
|
||||
| +---------> | bar |
|
||||
+-----+------+ +-------+
|
||||
| | +------------+
|
||||
| conn +-------> | stream |
|
||||
| | | |
|
||||
+-----+------+ +------------+
|
||||
|
|
||||
|
|
||||
|
|
||||
| +------------+
|
||||
+--------------> | stream |
|
||||
| |
|
||||
+------------+
|
||||
```
|
||||
|
||||
The theoretical memory consumption of watch can be approximated with the formula:
|
||||
`memory = c1 * number_of_conn + c2 * avg_number_of_stream_per_conn + c3 * avg_number_of_watch_stream`
|
||||
|
||||
## Testing Environment
|
||||
|
||||
etcd version
|
||||
- git head https://github.com/coreos/etcd/commit/185097ffaa627b909007e772c175e8fefac17af3
|
||||
|
||||
GCE n1-standard-2 machine type
|
||||
- 7.5 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## Overall memory usage
|
||||
|
||||
The overall memory usage captures how much [RSS][rss] etcd consumes with the client watchers. While the result may vary by as much as 10%, it is still meaningful, since the goal is to learn about the rough memory usage and the pattern of allocations.
|
||||
|
||||
With the benchmark result, we can calculate roughly that `c1 = 17kb`, `c2 = 18kb` and `c3 = 350bytes`. So each additional client connection consumes 17kb of memory and each additional stream consumes 18kb of memory, and each additional watching only cause 350bytes. A single etcd server can maintain millions of watchings with a few GB of memory in normal case.
|
||||
|
||||
|
||||
| clients | streams per client | watchings per stream | total watching | memory usage |
|
||||
|---------|---------|-----------|----------------|--------------|
|
||||
| 1k | 1 | 1 | 1k | 50MB |
|
||||
| 2k | 1 | 1 | 2k | 90MB |
|
||||
| 5k | 1 | 1 | 5k | 200MB |
|
||||
| 1k | 10 | 1 | 10k | 217MB |
|
||||
| 2k | 10 | 1 | 20k | 417MB |
|
||||
| 5k | 10 | 1 | 50k | 980MB |
|
||||
| 1k | 50 | 1 | 50k | 1001MB |
|
||||
| 2k | 50 | 1 | 100k | 1960MB |
|
||||
| 5k | 50 | 1 | 250k | 4700MB |
|
||||
| 1k | 50 | 10 | 500k | 1171MB |
|
||||
| 2k | 50 | 10 | 1M | 2371MB |
|
||||
| 5k | 50 | 10 | 2.5M | 5710MB |
|
||||
| 1k | 50 | 100 | 5M | 2380MB |
|
||||
| 2k | 50 | 100 | 10M | 4672MB |
|
||||
| 5k | 50 | 100 | 25M | *OOM* |
|
||||
|
||||
[rss]: https://en.wikipedia.org/wiki/Resident_set_size
|
@ -1,98 +0,0 @@
|
||||
# Storage Memory Usage Benchmark
|
||||
|
||||
<!---todo: link storage to storage design doc-->
|
||||
Two components of etcd storage consume physical memory. The etcd process allocates an *in-memory index* to speed key lookup. The process's *page cache*, managed by the operating system, stores recently-accessed data from disk for quick re-use.
|
||||
|
||||
The in-memory index holds all the keys in a [B-tree][btree] data structure, along with pointers to the on-disk data (the values). Each key in the B-tree may contain multiple pointers, pointing to different versions of its values. The theoretical memory consumption of the in-memory index can hence be approximated with the formula:
|
||||
|
||||
`N * (c1 + avg_key_size) + N * (avg_versions_of_key) * (c2 + size_of_pointer)`
|
||||
|
||||
where `c1` is the key metadata overhead and `c2` is the version metadata overhead.
|
||||
|
||||
The graph shows the detailed structure of the in-memory index B-tree.
|
||||
|
||||
```
|
||||
|
||||
|
||||
In mem index
|
||||
|
||||
+------------+
|
||||
| key || ... |
|
||||
+--------------+ | || |
|
||||
| | +------------+
|
||||
| | | v1 || ... |
|
||||
| disk <----------------| || | Tree Node
|
||||
| | +------------+
|
||||
| | | v2 || ... |
|
||||
| <----------------+ || |
|
||||
| | +------------+
|
||||
+--------------+ +-----+ | | |
|
||||
| | | | |
|
||||
| +------------+
|
||||
|
|
||||
|
|
||||
^
|
||||
------+
|
||||
| ... |
|
||||
| |
|
||||
+-----+
|
||||
| ... | Tree Node
|
||||
| |
|
||||
+-----+
|
||||
| ... |
|
||||
| |
|
||||
------+
|
||||
```
|
||||
|
||||
[Page cache memory][pagecache] is managed by the operating system and is not covered in detail in this document.
|
||||
|
||||
## Testing Environment
|
||||
|
||||
etcd version
|
||||
- git head https://github.com/coreos/etcd/commit/776e9fb7be7eee5e6b58ab977c8887b4fe4d48db
|
||||
|
||||
GCE n1-standard-2 machine type
|
||||
|
||||
- 7.5 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## In-memory index memory usage
|
||||
|
||||
In this test, we only benchmark the memory usage of the in-memory index. The goal is to find `c1` and `c2` mentioned above and to understand the hard limit of memory consumption of the storage.
|
||||
|
||||
We calculate the memory usage consumption via the Go runtime.ReadMemStats. We calculate the total allocated bytes difference before creating the index and after creating the index. It cannot perfectly reflect the memory usage of the in-memory index itself but can show the rough consumption pattern.
|
||||
|
||||
| N | versions | key size | memory usage |
|
||||
|------|----------|----------|--------------|
|
||||
| 100K | 1 | 64bytes | 22MB |
|
||||
| 100K | 5 | 64bytes | 39MB |
|
||||
| 1M | 1 | 64bytes | 218MB |
|
||||
| 1M | 5 | 64bytes | 432MB |
|
||||
| 100K | 1 | 256bytes | 41MB |
|
||||
| 100K | 5 | 256bytes | 65MB |
|
||||
| 1M | 1 | 256bytes | 409MB |
|
||||
| 1M | 5 | 256bytes | 506MB |
|
||||
|
||||
|
||||
Based on the result, we can calculate `c1=120bytes`, `c2=30bytes`. We only need two sets of data to calculate `c1` and `c2`, since they are the only unknown variable in the formula. The `c1=120bytes` and `c2=30bytes` are the average value of the 4 sets of `c1` and `c2` we calculated. The key metadata overhead is still relatively nontrivial (50%) for small key-value pairs. However, this is a significant improvement over the old store, which had at least 1000% overhead.
|
||||
|
||||
## Overall memory usage
|
||||
|
||||
The overall memory usage captures how much RSS etcd consumes with the storage. The value size should have very little impact on the overall memory usage of etcd, since we keep values on disk and only retain hot values in memory, managed by the OS page cache.
|
||||
|
||||
| N | versions | key size | value size | memory usage |
|
||||
|------|----------|----------|------------|--------------|
|
||||
| 100K | 1 | 64bytes | 256bytes | 40MB |
|
||||
| 100K | 5 | 64bytes | 256bytes | 89MB |
|
||||
| 1M | 1 | 64bytes | 256bytes | 470MB |
|
||||
| 1M | 5 | 64bytes | 256bytes | 880MB |
|
||||
| 100K | 1 | 64bytes | 1KB | 102MB |
|
||||
| 100K | 5 | 64bytes | 1KB | 164MB |
|
||||
| 1M | 1 | 64bytes | 1KB | 587MB |
|
||||
| 1M | 5 | 64bytes | 1KB | 836MB |
|
||||
|
||||
Based on the result, we know the value size does not significantly impact the memory consumption. There is some minor increase due to more data held in the OS page cache.
|
||||
|
||||
[btree]: https://en.wikipedia.org/wiki/B-tree
|
||||
[pagecache]: https://en.wikipedia.org/wiki/Page_cache
|
||||
|
@ -1,26 +0,0 @@
|
||||
# Branch management
|
||||
|
||||
## Guide
|
||||
|
||||
* New development occurs on the [master branch][master].
|
||||
* Master branch should always have a green build!
|
||||
* Backwards-compatible bug fixes should target the master branch and subsequently be ported to stable branches.
|
||||
* Once the master branch is ready for release, it will be tagged and become the new stable branch.
|
||||
|
||||
The etcd team has adopted a *rolling release model* and supports one stable version of etcd.
|
||||
|
||||
### Master branch
|
||||
|
||||
The `master` branch is our development branch. All new features land here first.
|
||||
|
||||
To try new and experimental features, pull `master` and play with it. Note that `master` may not be stable because new features may introduce bugs.
|
||||
|
||||
Before the release of the next stable version, feature PRs will be frozen. We will focus on the testing, bug-fix and documentation for one to two weeks.
|
||||
|
||||
### Stable branches
|
||||
|
||||
All branches with prefix `release-` are considered _stable_ branches.
|
||||
|
||||
After every minor release (http://semver.org/), we will have a new stable branch for that release. We will keep fixing the backwards-compatible bugs for the latest stable release, but not previous releases. The _patch_ release, incorporating any bug fixes, will be once every two weeks, given any patches.
|
||||
|
||||
[master]: https://github.com/coreos/etcd/tree/master
|
358
Documentation/clustering.md
Normal file
358
Documentation/clustering.md
Normal file
@ -0,0 +1,358 @@
|
||||
# Clustering Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Starting an etcd cluster statically requires that each member knows another in the cluster. In a number of cases, you might not know the IPs of your cluster members ahead of time. In these cases, you can bootstrap an etcd cluster with the help of a discovery service.
|
||||
|
||||
Once an etcd cluster is up and running, adding or removing members is done via [runtime reconfiguration](runtime-configuration.md).
|
||||
|
||||
This guide will cover the following mechanisms for bootstrapping an etcd cluster:
|
||||
|
||||
* [Static](#static)
|
||||
* [etcd Discovery](#etcd-discovery)
|
||||
* [DNS Discovery](#dns-discovery)
|
||||
|
||||
Each of the bootstrapping mechanisms will be used to create a three machine etcd cluster with the following details:
|
||||
|
||||
|Name|Address|Hostname|
|
||||
|------|---------|------------------|
|
||||
|infra0|10.0.1.10|infra0.example.com|
|
||||
|infra1|10.0.1.11|infra1.example.com|
|
||||
|infra2|10.0.1.12|infra2.example.com|
|
||||
|
||||
## Static
|
||||
|
||||
As we know the cluster members, their addresses and the size of the cluster before starting, we can use an offline bootstrap configuration by setting the `initial-cluster` flag. Each machine will get either the following command line or environment variables:
|
||||
|
||||
```
|
||||
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380"
|
||||
ETCD_INITIAL_CLUSTER_STATE=new
|
||||
```
|
||||
|
||||
```
|
||||
-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
-initial-cluster-state new
|
||||
```
|
||||
|
||||
Note that the URLs specified in `initial-cluster` are the _advertised peer URLs_, i.e. they should match the value of `initial-advertise-peer-urls` on the respective nodes.
|
||||
|
||||
If you are spinning up multiple clusters (or creating and destroying a single cluster) with same configuration for testing purpose, it is highly recommended that you specify a unique `initial-cluster-token` for the different clusters. By doing this, etcd can generate unique cluster IDs and member IDs for the clusters even if they otherwise have the exact same configuration. This can protect you from cross-cluster-interaction, which might corrupt your clusters.
|
||||
|
||||
On each machine you would start etcd with these flags:
|
||||
|
||||
```
|
||||
$ etcd -name infra0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
-listen-peer-urls http://10.0.1.10:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
-initial-cluster-state new
|
||||
```
|
||||
```
|
||||
$ etcd -name infra1 -initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
-listen-peer-urls http://10.0.1.11:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
-initial-cluster-state new
|
||||
```
|
||||
```
|
||||
$ etcd -name infra2 -initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
-listen-peer-urls http://10.0.1.12:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
-initial-cluster-state new
|
||||
```
|
||||
|
||||
The command line parameters starting with `-initial-cluster` will be ignored on subsequent runs of etcd. You are free to remove the environment variables or command line flags after the initial bootstrap process. If you need to make changes to the configuration later (for example, adding or removing members to/from the cluster), see the [runtime configuration](runtime-configuration.md) guide.
|
||||
|
||||
### Error Cases
|
||||
|
||||
In the following example, we have not included our new host in the list of enumerated nodes. If this is a new cluster, the node _must_ be added to the list of initial cluster members.
|
||||
|
||||
```
|
||||
$ etcd -name infra1 -initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
-listen-peer-urls https://10.0.1.11:2380 \
|
||||
-initial-cluster infra0=http://10.0.1.10:2380 \
|
||||
-initial-cluster-state new
|
||||
etcd: infra1 not listed in the initial cluster config
|
||||
exit 1
|
||||
```
|
||||
|
||||
In this example, we are attempting to map a node (infra0) on a different address (127.0.0.1:2380) than its enumerated address in the cluster list (10.0.1.10:2380). If this node is to listen on multiple addresses, all addresses _must_ be reflected in the "initial-cluster" configuration directive.
|
||||
|
||||
```
|
||||
$ etcd -name infra0 -initial-advertise-peer-urls http://127.0.0.1:2380 \
|
||||
-listen-peer-urls http://10.0.1.10:2380 \
|
||||
-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
-initial-cluster-state=new
|
||||
etcd: error setting up initial cluster: infra0 has different advertised URLs in the cluster and advertised peer URLs list
|
||||
exit 1
|
||||
```
|
||||
|
||||
If you configure a peer with a different set of configuration and attempt to join this cluster you will get a cluster ID mismatch and etcd will exit.
|
||||
|
||||
```
|
||||
$ etcd -name infra3 -initial-advertise-peer-urls http://10.0.1.13:2380 \
|
||||
-listen-peer-urls http://10.0.1.13:2380 \
|
||||
-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra3=http://10.0.1.13:2380 \
|
||||
-initial-cluster-state=new
|
||||
etcd: conflicting cluster ID to the target cluster (c6ab534d07e8fcc4 != bc25ea2a74fb18b0). Exiting.
|
||||
exit 1
|
||||
```
|
||||
|
||||
## Discovery
|
||||
|
||||
In a number of cases, you might not know the IPs of your cluster peers ahead of time. This is common when utilizing cloud providers or when your network uses DHCP. In these cases, rather than specifying a static configuration, you can use an existing etcd cluster to bootstrap a new one. We call this process "discovery".
|
||||
|
||||
There two methods that can be used for discovery:
|
||||
|
||||
* etcd discovery service
|
||||
* DNS SRV records
|
||||
|
||||
### etcd Discovery
|
||||
|
||||
#### Lifetime of a Discovery URL
|
||||
|
||||
A discovery URL identifies a unique etcd cluster. Instead of reusing a discovery URL, you should always create discovery URLs for new clusters.
|
||||
|
||||
Moreover, discovery URLs should ONLY be used for the initial bootstrapping of a cluster. To change cluster membership after the cluster is already running, see the [runtime reconfiguration][runtime] guide.
|
||||
|
||||
[runtime]: https://github.com/coreos/etcd/blob/master/Documentation/runtime-configuration.md
|
||||
|
||||
#### Custom etcd Discovery Service
|
||||
|
||||
Discovery uses an existing cluster to bootstrap itself. If you are using your own etcd cluster you can create a URL like so:
|
||||
|
||||
```
|
||||
$ curl -X PUT https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/_config/size -d value=3
|
||||
```
|
||||
|
||||
By setting the size key to the URL, you create a discovery URL with an expected cluster size of 3.
|
||||
|
||||
If you bootstrap an etcd cluster using discovery service with more than the expected number of etcd members, the extra etcd processes will [fall back][fall-back] to being [proxies][proxy] by default.
|
||||
|
||||
The URL you will use in this case will be `https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83` and the etcd members will use the `https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83` directory for registration as they start.
|
||||
|
||||
Now we start etcd with those relevant flags for each member:
|
||||
|
||||
```
|
||||
$ etcd -name infra0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
-listen-peer-urls http://10.0.1.10:2380 \
|
||||
-discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
```
|
||||
$ etcd -name infra1 -initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
-listen-peer-urls http://10.0.1.11:2380 \
|
||||
-discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
```
|
||||
$ etcd -name infra2 -initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
-listen-peer-urls http://10.0.1.12:2380 \
|
||||
-discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
|
||||
This will cause each member to register itself with the custom etcd discovery service and begin the cluster once all machines have been registered.
|
||||
|
||||
#### Public etcd Discovery Service
|
||||
|
||||
If you do not have access to an existing cluster, you can use the public discovery service hosted at `discovery.etcd.io`. You can create a private discovery URL using the "new" endpoint like so:
|
||||
|
||||
```
|
||||
$ curl https://discovery.etcd.io/new?size=3
|
||||
https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
This will create the cluster with an initial expected size of 3 members. If you do not specify a size, a default of 3 will be used.
|
||||
|
||||
If you bootstrap an etcd cluster using discovery service with more than the expected number of etcd members, the extra etcd processes will [fall back][fall-back] to being [proxies][proxy] by default.
|
||||
|
||||
[fall-back]: proxy.md#fallback-to-proxy-mode-with-discovery-service
|
||||
[proxy]: proxy.md
|
||||
|
||||
```
|
||||
ETCD_DISCOVERY=https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
```
|
||||
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
Now we start etcd with those relevant flags for each member:
|
||||
|
||||
```
|
||||
$ etcd -name infra0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
-listen-peer-urls http://10.0.1.10:2380 \
|
||||
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
```
|
||||
$ etcd -name infra1 -initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
-listen-peer-urls http://10.0.1.11:2380 \
|
||||
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
```
|
||||
$ etcd -name infra2 -initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
-listen-peer-urls http://10.0.1.12:2380 \
|
||||
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
This will cause each member to register itself with the discovery service and begin the cluster once all members have been registered.
|
||||
|
||||
You can use the environment variable `ETCD_DISCOVERY_PROXY` to cause etcd to use an HTTP proxy to connect to the discovery service.
|
||||
|
||||
#### Error and Warning Cases
|
||||
|
||||
##### Discovery Server Errors
|
||||
|
||||
|
||||
```
|
||||
$ etcd -name infra0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
-listen-peer-urls http://10.0.1.10:2380 \
|
||||
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
etcd: error: the cluster doesn’t have a size configuration value in https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de/_config
|
||||
exit 1
|
||||
```
|
||||
|
||||
##### User Errors
|
||||
|
||||
This error will occur if the discovery cluster already has the configured number of members, and `discovery-fallback` is explicitly disabled
|
||||
|
||||
```
|
||||
$ etcd -name infra0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
-listen-peer-urls http://10.0.1.10:2380 \
|
||||
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de \
|
||||
-discovery-fallback exit
|
||||
etcd: discovery: cluster is full
|
||||
exit 1
|
||||
```
|
||||
|
||||
##### Warnings
|
||||
|
||||
This is a harmless warning notifying you that the discovery URL will be
|
||||
ignored on this machine.
|
||||
|
||||
```
|
||||
$ etcd -name infra0 -initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
-listen-peer-urls http://10.0.1.10:2380 \
|
||||
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
etcdserver: discovery token ignored since a cluster has already been initialized. Valid log found at /var/lib/etcd
|
||||
```
|
||||
|
||||
### DNS Discovery
|
||||
|
||||
DNS [SRV records](http://www.ietf.org/rfc/rfc2052.txt) can be used as a discovery mechanism.
|
||||
The `-discovery-srv` flag can be used to set the DNS domain name where the discovery SRV records can be found.
|
||||
The following DNS SRV records are looked up in the listed order:
|
||||
|
||||
* _etcd-server-ssl._tcp.example.com
|
||||
* _etcd-server._tcp.example.com
|
||||
|
||||
If `_etcd-server-ssl._tcp.example.com` is found then etcd will attempt the bootstrapping process over SSL.
|
||||
|
||||
#### Create DNS SRV records
|
||||
|
||||
```
|
||||
$ dig +noall +answer SRV _etcd-server._tcp.example.com
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra0.example.com.
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra1.example.com.
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra2.example.com.
|
||||
```
|
||||
|
||||
```
|
||||
$ dig +noall +answer infra0.example.com infra1.example.com infra2.example.com
|
||||
infra0.example.com. 300 IN A 10.0.1.10
|
||||
infra1.example.com. 300 IN A 10.0.1.11
|
||||
infra2.example.com. 300 IN A 10.0.1.12
|
||||
```
|
||||
#### Bootstrap the etcd cluster using DNS
|
||||
|
||||
etcd cluster memebers can listen on domain names or IP address, the bootstrap process will resolve DNS A records.
|
||||
|
||||
```
|
||||
$ etcd -name infra0 \
|
||||
-discovery-srv example.com \
|
||||
-initial-advertise-peer-urls http://infra0.example.com:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster-state new \
|
||||
-advertise-client-urls http://infra0.example.com:2379 \
|
||||
-listen-client-urls http://infra0.example.com:2379 \
|
||||
-listen-peer-urls http://infra0.example.com:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd -name infra1 \
|
||||
-discovery-srv example.com \
|
||||
-initial-advertise-peer-urls http://infra1.example.com:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster-state new \
|
||||
-advertise-client-urls http://infra1.example.com:2379 \
|
||||
-listen-client-urls http://infra1.example.com:2379 \
|
||||
-listen-peer-urls http://infra1.example.com:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd -name infra2 \
|
||||
-discovery-srv example.com \
|
||||
-initial-advertise-peer-urls http://infra2.example.com:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster-state new \
|
||||
-advertise-client-urls http://infra2.example.com:2379 \
|
||||
-listen-client-urls http://infra2.example.com:2379 \
|
||||
-listen-peer-urls http://infra2.example.com:2380
|
||||
```
|
||||
|
||||
You can also bootstrap the cluster using IP addresses instead of domain names:
|
||||
|
||||
```
|
||||
$ etcd -name infra0 \
|
||||
-discovery-srv example.com \
|
||||
-initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster-state new \
|
||||
-advertise-client-urls http://10.0.1.10:2379 \
|
||||
-listen-client-urls http://10.0.1.10:2379 \
|
||||
-listen-peer-urls http://10.0.1.10:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd -name infra1 \
|
||||
-discovery-srv example.com \
|
||||
-initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster-state new \
|
||||
-advertise-client-urls http://10.0.1.11:2379 \
|
||||
-listen-client-urls http://10.0.1.11:2379 \
|
||||
-listen-peer-urls http://10.0.1.11:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd -name infra2 \
|
||||
-discovery-srv example.com \
|
||||
-initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
-initial-cluster-token etcd-cluster-1 \
|
||||
-initial-cluster-state new \
|
||||
-advertise-client-urls http://10.0.1.12:2379 \
|
||||
-listen-client-urls http://10.0.1.12:2379 \
|
||||
-listen-peer-urls http://10.0.1.12:2380
|
||||
```
|
||||
|
||||
#### etcd proxy configuration
|
||||
|
||||
DNS SRV records can also be used to configure the list of peers for an etcd server running in proxy mode:
|
||||
|
||||
```
|
||||
$ etcd --proxy on -discovery-srv example.com
|
||||
```
|
||||
|
||||
# 0.4 to 2.0+ Migration Guide
|
||||
|
||||
In etcd 2.0 we introduced the ability to listen on more than one address and to advertise multiple addresses. This makes using etcd easier when you have complex networking, such as private and public networks on various cloud providers.
|
||||
|
||||
To make understanding this feature easier, we changed the naming of some flags, but we support the old flags to make the migration from the old to new version easier.
|
||||
|
||||
|Old Flag |New Flag |Migration Behavior |
|
||||
|-----------------------|-----------------------|---------------------------------------------------------------------------------------|
|
||||
|-peer-addr |-initial-advertise-peer-urls |If specified, peer-addr will be used as the only peer URL. Error if both flags specified.|
|
||||
|-addr |-advertise-client-urls |If specified, addr will be used as the only client URL. Error if both flags specified.|
|
||||
|-peer-bind-addr |-listen-peer-urls |If specified, peer-bind-addr will be used as the only peer bind URL. Error if both flags specified.|
|
||||
|-bind-addr |-listen-client-urls |If specified, bind-addr will be used as the only client bind URL. Error if both flags specified.|
|
||||
|-peers |none |Deprecated. The -initial-cluster flag provides a similar concept with different semantics. Please read this guide on cluster startup.|
|
||||
|-peers-file |none |Deprecated. The -initial-cluster flag provides a similar concept with different semantics. Please read this guide on cluster startup.|
|
157
Documentation/configuration.md
Normal file
157
Documentation/configuration.md
Normal file
@ -0,0 +1,157 @@
|
||||
## Configuration Flags
|
||||
|
||||
etcd is configurable through command-line flags and environment variables. Options set on the command line take precedence over those from the environment.
|
||||
|
||||
The format of environment variable for flag `-my-flag` is `ETCD_MY_FLAG`. It applies to all flags.
|
||||
|
||||
To start etcd automatically using custom settings at startup in Linux, using a [systemd][systemd-intro] unit is highly recommended.
|
||||
|
||||
[systemd-intro]: http://freedesktop.org/wiki/Software/systemd/
|
||||
|
||||
### Member Flags
|
||||
|
||||
##### -name
|
||||
+ Human-readable name for this member.
|
||||
+ default: "default"
|
||||
|
||||
##### -data-dir
|
||||
+ Path to the data directory.
|
||||
+ default: "${name}.etcd"
|
||||
|
||||
##### -snapshot-count
|
||||
+ Number of committed transactions to trigger a snapshot to disk.
|
||||
+ default: "10000"
|
||||
|
||||
##### -heartbeat-interval
|
||||
+ Time (in milliseconds) of a heartbeat interval.
|
||||
+ default: "100"
|
||||
|
||||
##### -election-timeout
|
||||
+ Time (in milliseconds) for an election to timeout.
|
||||
+ default: "1000"
|
||||
|
||||
##### -listen-peer-urls
|
||||
+ List of URLs to listen on for peer traffic.
|
||||
+ default: "http://localhost:2380,http://localhost:7001"
|
||||
|
||||
##### -listen-client-urls
|
||||
+ List of URLs to listen on for client traffic.
|
||||
+ default: "http://localhost:2379,http://localhost:4001"
|
||||
|
||||
##### -max-snapshots
|
||||
+ Maximum number of snapshot files to retain (0 is unlimited)
|
||||
+ default: 5
|
||||
+ The default for users on Windows is unlimited, and manual purging down to 5 (or your preference for safety) is recommended.
|
||||
|
||||
##### -max-wals
|
||||
+ Maximum number of wal files to retain (0 is unlimited)
|
||||
+ default: 5
|
||||
+ The default for users on Windows is unlimited, and manual purging down to 5 (or your preference for safety) is recommended.
|
||||
|
||||
##### -cors
|
||||
+ Comma-separated white list of origins for CORS (cross-origin resource sharing).
|
||||
+ default: none
|
||||
|
||||
### Clustering Flags
|
||||
|
||||
`-initial` prefix flags are used in bootstrapping ([static bootstrap][build-cluster], [discovery-service bootstrap][discovery] or [runtime reconfiguration][reconfig]) a new member, and ignored when restarting an existing member.
|
||||
|
||||
`-discovery` prefix flags need to be set when using [discovery service][discovery].
|
||||
|
||||
##### -initial-advertise-peer-urls
|
||||
|
||||
+ List of this member's peer URLs to advertise to the rest of the cluster. These addresses are used for communicating etcd data around the cluster. At least one must be routable to all cluster members.
|
||||
+ default: "http://localhost:2380,http://localhost:7001"
|
||||
|
||||
##### -initial-cluster
|
||||
+ Initial cluster configuration for bootstrapping.
|
||||
+ default: "default=http://localhost:2380,default=http://localhost:7001"
|
||||
|
||||
##### -initial-cluster-state
|
||||
+ Initial cluster state ("new" or "existing"). Set to `new` for all members present during initial static or DNS bootstrapping. If this option is set to `existing`, etcd will attempt to join the existing cluster. If the wrong value is set, etcd will attempt to start but fail safely.
|
||||
+ default: "new"
|
||||
|
||||
[static bootstrap]: clustering.md#static
|
||||
|
||||
##### -initial-cluster-token
|
||||
+ Initial cluster token for the etcd cluster during bootstrap.
|
||||
+ default: "etcd-cluster"
|
||||
|
||||
##### -advertise-client-urls
|
||||
+ List of this member's client URLs to advertise to the rest of the cluster.
|
||||
+ default: "http://localhost:2379,http://localhost:4001"
|
||||
|
||||
##### -discovery
|
||||
+ Discovery URL used to bootstrap the cluster.
|
||||
+ default: none
|
||||
|
||||
##### -discovery-srv
|
||||
+ DNS srv domain used to bootstrap the cluster.
|
||||
+ default: none
|
||||
|
||||
##### -discovery-fallback
|
||||
+ Expected behavior ("exit" or "proxy") when discovery services fails.
|
||||
+ default: "proxy"
|
||||
|
||||
##### -discovery-proxy
|
||||
+ HTTP proxy to use for traffic to discovery service.
|
||||
+ default: none
|
||||
|
||||
### Proxy Flags
|
||||
|
||||
`-proxy` prefix flags configures etcd to run in [proxy mode][proxy].
|
||||
|
||||
##### -proxy
|
||||
+ Proxy mode setting ("off", "readonly" or "on").
|
||||
+ default: "off"
|
||||
|
||||
### Security Flags
|
||||
|
||||
The security flags help to [build a secure etcd cluster][security].
|
||||
|
||||
##### -ca-file
|
||||
+ Path to the client server TLS CA file.
|
||||
+ default: none
|
||||
|
||||
##### -cert-file
|
||||
+ Path to the client server TLS cert file.
|
||||
+ default: none
|
||||
|
||||
##### -key-file
|
||||
+ Path to the client server TLS key file.
|
||||
+ default: none
|
||||
|
||||
##### -peer-ca-file
|
||||
+ Path to the peer server TLS CA file.
|
||||
+ default: none
|
||||
|
||||
##### -peer-cert-file
|
||||
+ Path to the peer server TLS cert file.
|
||||
+ default: none
|
||||
|
||||
##### -peer-key-file
|
||||
+ Path to the peer server TLS key file.
|
||||
+ default: none
|
||||
|
||||
### Unsafe Flags
|
||||
|
||||
Please be CAUTIOUS when using unsafe flags because it will break the guarantees given by the consensus protocol.
|
||||
For example, it may panic if other members in the cluster are still alive.
|
||||
Follow the instructions when using these flags.
|
||||
|
||||
##### -force-new-cluster
|
||||
+ Force to create a new one-member cluster. It commits configuration changes in force to remove all existing members in the cluster and add itself. It needs to be set to [restore a backup][restore].
|
||||
+ default: false
|
||||
|
||||
### Miscellaneous Flags
|
||||
|
||||
##### -version
|
||||
+ Print the version and exit.
|
||||
+ default: false
|
||||
|
||||
[build-cluster]: https://github.com/coreos/etcd/blob/master/Documentation/clustering.md#static
|
||||
[reconfig]: https://github.com/coreos/etcd/blob/master/Documentation/runtime-configuration.md
|
||||
[discovery]: https://github.com/coreos/etcd/blob/master/Documentation/clustering.md#discovery
|
||||
[proxy]: https://github.com/coreos/etcd/blob/master/Documentation/proxy.md
|
||||
[security]: https://github.com/coreos/etcd/blob/master/Documentation/security.md
|
||||
[restore]: https://github.com/coreos/etcd/blob/master/Documentation/admin_guide.md#restoring-a-backup
|
@ -1,454 +0,0 @@
|
||||
# Demo
|
||||
|
||||
This series of examples shows the basic procedures for working with an etcd cluster.
|
||||
|
||||
## Set up a cluster
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/01_etcd_clustering_2016051001.gif" alt="01_etcd_clustering_2016050601"/>
|
||||
|
||||
On each etcd node, specify the cluster members:
|
||||
|
||||
```
|
||||
TOKEN=token-01
|
||||
CLUSTER_STATE=new
|
||||
NAME_1=machine-1
|
||||
NAME_2=machine-2
|
||||
NAME_3=machine-3
|
||||
HOST_1=10.240.0.17
|
||||
HOST_2=10.240.0.18
|
||||
HOST_3=10.240.0.19
|
||||
CLUSTER=${NAME_1}=http://${HOST_1}:2380,${NAME_2}=http://${HOST_2}:2380,${NAME_3}=http://${HOST_3}:2380
|
||||
```
|
||||
|
||||
Run this on each machine:
|
||||
|
||||
```
|
||||
# For machine 1
|
||||
THIS_NAME=${NAME_1}
|
||||
THIS_IP=${HOST_1}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
|
||||
# For machine 2
|
||||
THIS_NAME=${NAME_2}
|
||||
THIS_IP=${HOST_2}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
|
||||
# For machine 3
|
||||
THIS_NAME=${NAME_3}
|
||||
THIS_IP=${HOST_3}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
```
|
||||
|
||||
Or use our public discovery service:
|
||||
|
||||
```
|
||||
curl https://discovery.etcd.io/new?size=3
|
||||
https://discovery.etcd.io/a81b5818e67a6ea83e9d4daea5ecbc92
|
||||
|
||||
# grab this token
|
||||
TOKEN=token-01
|
||||
CLUSTER_STATE=new
|
||||
NAME_1=machine-1
|
||||
NAME_2=machine-2
|
||||
NAME_3=machine-3
|
||||
HOST_1=10.240.0.17
|
||||
HOST_2=10.240.0.18
|
||||
HOST_3=10.240.0.19
|
||||
DISCOVERY=https://discovery.etcd.io/a81b5818e67a6ea83e9d4daea5ecbc92
|
||||
|
||||
THIS_NAME=${NAME_1}
|
||||
THIS_IP=${HOST_1}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--discovery ${DISCOVERY} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
|
||||
THIS_NAME=${NAME_2}
|
||||
THIS_IP=${HOST_2}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--discovery ${DISCOVERY} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
|
||||
THIS_NAME=${NAME_3}
|
||||
THIS_IP=${HOST_3}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--discovery ${DISCOVERY} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
```
|
||||
|
||||
Now etcd is ready! To connect to etcd with etcdctl:
|
||||
|
||||
```
|
||||
export ETCDCTL_API=3
|
||||
HOST_1=10.240.0.17
|
||||
HOST_2=10.240.0.18
|
||||
HOST_3=10.240.0.19
|
||||
ENDPOINTS=$HOST_1:2379,$HOST_2:2379,$HOST_3:2379
|
||||
|
||||
etcdctl --endpoints=$ENDPOINTS member list
|
||||
```
|
||||
|
||||
|
||||
## Access etcd
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/02_etcdctl_access_etcd_2016051001.gif" alt="02_etcdctl_access_etcd_2016051001"/>
|
||||
|
||||
`put` command to write:
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS put foo "Hello World!"
|
||||
```
|
||||
|
||||
`get` to read from etcd:
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS get foo
|
||||
etcdctl --endpoints=$ENDPOINTS --write-out="json" get foo
|
||||
```
|
||||
|
||||
|
||||
## Get by prefix
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/03_etcdctl_get_by_prefix_2016050501.gif" alt="03_etcdctl_get_by_prefix_2016050501"/>
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS put web1 value1
|
||||
etcdctl --endpoints=$ENDPOINTS put web2 value2
|
||||
etcdctl --endpoints=$ENDPOINTS put web3 value3
|
||||
|
||||
etcdctl --endpoints=$ENDPOINTS get web --prefix
|
||||
```
|
||||
|
||||
|
||||
## Delete
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/04_etcdctl_delete_2016050601.gif" alt="04_etcdctl_delete_2016050601"/>
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS put key myvalue
|
||||
etcdctl --endpoints=$ENDPOINTS del key
|
||||
|
||||
etcdctl --endpoints=$ENDPOINTS put k1 value1
|
||||
etcdctl --endpoints=$ENDPOINTS put k2 value2
|
||||
etcdctl --endpoints=$ENDPOINTS del k --prefix
|
||||
```
|
||||
|
||||
|
||||
## Transactional write
|
||||
|
||||
`txn` to wrap multiple requests into one transaction:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/05_etcdctl_transaction_2016050501.gif" alt="05_etcdctl_transaction_2016050501"/>
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS put user1 bad
|
||||
etcdctl --endpoints=$ENDPOINTS txn --interactive
|
||||
|
||||
compares:
|
||||
value("user1") = "bad"
|
||||
|
||||
success requests (get, put, delete):
|
||||
del user1
|
||||
|
||||
failure requests (get, put, delete):
|
||||
put user1 good
|
||||
```
|
||||
|
||||
|
||||
## Watch
|
||||
|
||||
`watch` to get notified of future changes:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/06_etcdctl_watch_2016050501.gif" alt="06_etcdctl_watch_2016050501"/>
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS watch stock1
|
||||
etcdctl --endpoints=$ENDPOINTS put stock1 1000
|
||||
|
||||
etcdctl --endpoints=$ENDPOINTS watch stock --prefix
|
||||
etcdctl --endpoints=$ENDPOINTS put stock1 10
|
||||
etcdctl --endpoints=$ENDPOINTS put stock2 20
|
||||
```
|
||||
|
||||
|
||||
## Lease
|
||||
|
||||
`lease` to write with TTL:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/07_etcdctl_lease_2016050501.gif" alt="07_etcdctl_lease_2016050501"/>
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS lease grant 300
|
||||
# lease 2be7547fbc6a5afa granted with TTL(300s)
|
||||
|
||||
etcdctl --endpoints=$ENDPOINTS put sample value --lease=2be7547fbc6a5afa
|
||||
etcdctl --endpoints=$ENDPOINTS get sample
|
||||
|
||||
etcdctl --endpoints=$ENDPOINTS lease keep-alive 2be7547fbc6a5afa
|
||||
etcdctl --endpoints=$ENDPOINTS lease revoke 2be7547fbc6a5afa
|
||||
# or after 300 seconds
|
||||
etcdctl --endpoints=$ENDPOINTS get sample
|
||||
```
|
||||
|
||||
|
||||
## Distributed locks
|
||||
|
||||
`lock` for distributed lock:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/08_etcdctl_lock_2016050501.gif" alt="08_etcdctl_lock_2016050501"/>
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS lock mutex1
|
||||
|
||||
# another client with the same name blocks
|
||||
etcdctl --endpoints=$ENDPOINTS lock mutex1
|
||||
```
|
||||
|
||||
|
||||
## Elections
|
||||
|
||||
`elect` for leader election:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/09_etcdctl_elect_2016050501.gif" alt="09_etcdctl_elect_2016050501"/>
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS elect one p1
|
||||
|
||||
# another client with the same name blocks
|
||||
etcdctl --endpoints=$ENDPOINTS elect one p2
|
||||
```
|
||||
|
||||
|
||||
## Cluster status
|
||||
|
||||
Specify the initial cluster configuration for each machine:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/10_etcdctl_endpoint_2016050501.gif" alt="10_etcdctl_endpoint_2016050501"/>
|
||||
|
||||
```
|
||||
etcdctl --write-out=table --endpoints=$ENDPOINTS endpoint status
|
||||
|
||||
+------------------+------------------+---------+---------+-----------+-----------+------------+
|
||||
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
|
||||
+------------------+------------------+---------+---------+-----------+-----------+------------+
|
||||
| 10.240.0.17:2379 | 4917a7ab173fabe7 | 3.0.0 | 45 kB | true | 4 | 16726 |
|
||||
| 10.240.0.18:2379 | 59796ba9cd1bcd72 | 3.0.0 | 45 kB | false | 4 | 16726 |
|
||||
| 10.240.0.19:2379 | 94df724b66343e6c | 3.0.0 | 45 kB | false | 4 | 16726 |
|
||||
+------------------+------------------+---------+---------+-----------+-----------+------------+
|
||||
```
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS endpoint health
|
||||
|
||||
10.240.0.17:2379 is healthy: successfully committed proposal: took = 3.345431ms
|
||||
10.240.0.19:2379 is healthy: successfully committed proposal: took = 3.767967ms
|
||||
10.240.0.18:2379 is healthy: successfully committed proposal: took = 4.025451ms
|
||||
```
|
||||
|
||||
|
||||
## Snapshot
|
||||
|
||||
`snapshot` to save point-in-time snapshot of etcd database:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/11_etcdctl_snapshot_2016051001.gif" alt="11_etcdctl_snapshot_2016051001"/>
|
||||
|
||||
```
|
||||
etcdctl --endpoints=$ENDPOINTS snapshot save my.db
|
||||
|
||||
Snapshot saved at my.db
|
||||
```
|
||||
|
||||
```
|
||||
etcdctl --write-out=table --endpoints=$ENDPOINTS snapshot status my.db
|
||||
|
||||
+---------+----------+------------+------------+
|
||||
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
|
||||
+---------+----------+------------+------------+
|
||||
| c55e8b8 | 9 | 13 | 25 kB |
|
||||
+---------+----------+------------+------------+
|
||||
```
|
||||
|
||||
|
||||
## Migrate
|
||||
|
||||
`migrate` to transform etcd v2 to v3 data:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/12_etcdctl_migrate_2016061602.gif" alt="12_etcdctl_migrate_2016061602"/>
|
||||
|
||||
```
|
||||
# write key in etcd version 2 store
|
||||
export ETCDCTL_API=2
|
||||
etcdctl --endpoints=http://$ENDPOINT set foo bar
|
||||
|
||||
# read key in etcd v2
|
||||
etcdctl --endpoints=$ENDPOINTS --output="json" get foo
|
||||
|
||||
# stop etcd node to migrate, one by one
|
||||
|
||||
# migrate v2 data
|
||||
export ETCDCTL_API=3
|
||||
etcdctl --endpoints=$ENDPOINT migrate --data-dir="default.etcd" --wal-dir="default.etcd/member/wal"
|
||||
|
||||
# restart etcd node after migrate, one by one
|
||||
|
||||
# confirm that the key got migrated
|
||||
etcdctl --endpoints=$ENDPOINTS get /foo
|
||||
```
|
||||
|
||||
|
||||
## Member
|
||||
|
||||
`member` to add,remove,update membership:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/13_etcdctl_member_2016062301.gif" alt="13_etcdctl_member_2016062301"/>
|
||||
|
||||
```
|
||||
# For each machine
|
||||
TOKEN=my-etcd-token-1
|
||||
CLUSTER_STATE=new
|
||||
NAME_1=etcd-node-1
|
||||
NAME_2=etcd-node-2
|
||||
NAME_3=etcd-node-3
|
||||
HOST_1=10.240.0.13
|
||||
HOST_2=10.240.0.14
|
||||
HOST_3=10.240.0.15
|
||||
CLUSTER=${NAME_1}=http://${HOST_1}:2380,${NAME_2}=http://${HOST_2}:2380,${NAME_3}=http://${HOST_3}:2380
|
||||
|
||||
# For node 1
|
||||
THIS_NAME=${NAME_1}
|
||||
THIS_IP=${HOST_1}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 \
|
||||
--listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 \
|
||||
--listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} \
|
||||
--initial-cluster-token ${TOKEN}
|
||||
|
||||
# For node 2
|
||||
THIS_NAME=${NAME_2}
|
||||
THIS_IP=${HOST_2}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 \
|
||||
--listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 \
|
||||
--listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} \
|
||||
--initial-cluster-token ${TOKEN}
|
||||
|
||||
# For node 3
|
||||
THIS_NAME=${NAME_3}
|
||||
THIS_IP=${HOST_3}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 \
|
||||
--listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 \
|
||||
--listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} \
|
||||
--initial-cluster-token ${TOKEN}
|
||||
```
|
||||
|
||||
Then replace a member with `member remove` and `member add` commands:
|
||||
|
||||
```
|
||||
# get member ID
|
||||
export ETCDCTL_API=3
|
||||
HOST_1=10.240.0.13
|
||||
HOST_2=10.240.0.14
|
||||
HOST_3=10.240.0.15
|
||||
etcdctl --endpoints=${HOST_1}:2379,${HOST_2}:2379,${HOST_3}:2379 member list
|
||||
|
||||
# remove the member
|
||||
MEMBER_ID=278c654c9a6dfd3b
|
||||
etcdctl --endpoints=${HOST_1}:2379,${HOST_2}:2379,${HOST_3}:2379 \
|
||||
member remove ${MEMBER_ID}
|
||||
|
||||
# add a new member (node 4)
|
||||
export ETCDCTL_API=3
|
||||
NAME_1=etcd-node-1
|
||||
NAME_2=etcd-node-2
|
||||
NAME_4=etcd-node-4
|
||||
HOST_1=10.240.0.13
|
||||
HOST_2=10.240.0.14
|
||||
HOST_4=10.240.0.16 # new member
|
||||
etcdctl --endpoints=${HOST_1}:2379,${HOST_2}:2379 \
|
||||
member add ${NAME_4} \
|
||||
--peer-urls=http://${HOST_4}:2380
|
||||
```
|
||||
|
||||
Next, start the new member with `--initial-cluster-state existing` flag:
|
||||
|
||||
```
|
||||
# [WARNING] If the new member starts from the same disk space,
|
||||
# make sure to remove the data directory of the old member
|
||||
#
|
||||
# restart with 'existing' flag
|
||||
TOKEN=my-etcd-token-1
|
||||
CLUSTER_STATE=existing
|
||||
NAME_1=etcd-node-1
|
||||
NAME_2=etcd-node-2
|
||||
NAME_4=etcd-node-4
|
||||
HOST_1=10.240.0.13
|
||||
HOST_2=10.240.0.14
|
||||
HOST_4=10.240.0.16 # new member
|
||||
CLUSTER=${NAME_1}=http://${HOST_1}:2380,${NAME_2}=http://${HOST_2}:2380,${NAME_4}=http://${HOST_4}:2380
|
||||
|
||||
THIS_NAME=${NAME_4}
|
||||
THIS_IP=${HOST_4}
|
||||
etcd --data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 \
|
||||
--listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 \
|
||||
--listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} \
|
||||
--initial-cluster-token ${TOKEN}
|
||||
```
|
||||
|
||||
|
||||
## Auth
|
||||
|
||||
`auth`,`user`,`role` for authentication:
|
||||
|
||||
<img src="https://storage.googleapis.com/etcd/demo/14_etcdctl_auth_2016062301.gif" alt="14_etcdctl_auth_2016062301"/>
|
||||
|
||||
```
|
||||
export ETCDCTL_API=3
|
||||
ENDPOINTS=localhost:2379
|
||||
|
||||
etcdctl --endpoints=${ENDPOINTS} role add root
|
||||
etcdctl --endpoints=${ENDPOINTS} role grant-permission root readwrite foo
|
||||
etcdctl --endpoints=${ENDPOINTS} role get root
|
||||
|
||||
etcdctl --endpoints=${ENDPOINTS} user add root
|
||||
etcdctl --endpoints=${ENDPOINTS} user grant-role root root
|
||||
etcdctl --endpoints=${ENDPOINTS} user get root
|
||||
|
||||
etcdctl --endpoints=${ENDPOINTS} auth enable
|
||||
# now all client requests go through auth
|
||||
|
||||
etcdctl --endpoints=${ENDPOINTS} --user=root:123 put foo bar
|
||||
etcdctl --endpoints=${ENDPOINTS} get foo
|
||||
etcdctl --endpoints=${ENDPOINTS} --user=root:123 get foo
|
||||
etcdctl --endpoints=${ENDPOINTS} --user=root:123 get foo1
|
||||
```
|
@ -1,38 +0,0 @@
|
||||
|
||||
## Why grpc-gateway
|
||||
|
||||
etcd v3 uses [gRPC][grpc] for its messaging protocol. The etcd project includes a gRPC-based [Go client][go-client] and a command line utility, [etcdctl][etcdctl], for communicating with an etcd cluster through gRPC. For languages with no gRPC support, etcd provides a JSON [grpc-gateway][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][json-mapping] for etcd's [protocol buffer][api-ref] message definitions. Note that `key` and `value` fields are defined as byte arrays and therefore must be base64 encoded in JSON.
|
||||
|
||||
```bash
|
||||
<<COMMENT
|
||||
https://www.base64encode.org/
|
||||
foo is 'Zm9v' in Base64
|
||||
bar is 'YmFy'
|
||||
COMMENT
|
||||
|
||||
curl -L http://localhost:2379/v3alpha/kv/put \
|
||||
-X POST -d '{"key": "Zm9v", "value": "YmFy"}'
|
||||
|
||||
curl -L http://localhost:2379/v3alpha/kv/range \
|
||||
-X POST -d '{"key": "Zm9v"}'
|
||||
```
|
||||
|
||||
|
||||
## Swagger
|
||||
|
||||
Generated [Swagger][swagger] API definitions can be found at [rpc.swagger.json][swagger-doc].
|
||||
|
||||
[api-ref]: ./api_reference_v3.md
|
||||
[go-client]: https://github.com/coreos/etcd/tree/master/clientv3
|
||||
[etcdctl]: https://github.com/coreos/etcd/tree/master/etcdctl
|
||||
[grpc]: http://www.grpc.io/
|
||||
[grpc-gateway]: https://github.com/gengo/grpc-gateway
|
||||
[json-mapping]: https://developers.google.com/protocol-buffers/docs/proto3#json
|
||||
[swagger]: http://swagger.io/
|
||||
[swagger-doc]: apispec/swagger/rpc.swagger.json
|
||||
|
@ -1,826 +0,0 @@
|
||||
### etcd API Reference
|
||||
|
||||
|
||||
This is a generated documentation. Please read the proto files for more.
|
||||
|
||||
|
||||
##### service `Auth` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Method | Request Type | Response Type | Description |
|
||||
| ------ | ------------ | ------------- | ----------- |
|
||||
| AuthEnable | AuthEnableRequest | AuthEnableResponse | AuthEnable enables authentication. |
|
||||
| AuthDisable | AuthDisableRequest | AuthDisableResponse | AuthDisable disables authentication. |
|
||||
| Authenticate | AuthenticateRequest | AuthenticateResponse | Authenticate processes an authenticate request. |
|
||||
| UserAdd | AuthUserAddRequest | AuthUserAddResponse | UserAdd adds a new user. |
|
||||
| UserGet | AuthUserGetRequest | AuthUserGetResponse | UserGet gets detailed user information. |
|
||||
| UserList | AuthUserListRequest | AuthUserListResponse | UserList gets a list of all users. |
|
||||
| UserDelete | AuthUserDeleteRequest | AuthUserDeleteResponse | UserDelete deletes a specified user. |
|
||||
| UserChangePassword | AuthUserChangePasswordRequest | AuthUserChangePasswordResponse | UserChangePassword changes the password of a specified user. |
|
||||
| UserGrantRole | AuthUserGrantRoleRequest | AuthUserGrantRoleResponse | UserGrant grants a role to a specified user. |
|
||||
| UserRevokeRole | AuthUserRevokeRoleRequest | AuthUserRevokeRoleResponse | UserRevokeRole revokes a role of specified user. |
|
||||
| RoleAdd | AuthRoleAddRequest | AuthRoleAddResponse | RoleAdd adds a new role. |
|
||||
| RoleGet | AuthRoleGetRequest | AuthRoleGetResponse | RoleGet gets detailed role information. |
|
||||
| RoleList | AuthRoleListRequest | AuthRoleListResponse | RoleList gets lists of all roles. |
|
||||
| RoleDelete | AuthRoleDeleteRequest | AuthRoleDeleteResponse | RoleDelete deletes a specified role. |
|
||||
| RoleGrantPermission | AuthRoleGrantPermissionRequest | AuthRoleGrantPermissionResponse | RoleGrantPermission grants a permission of a specified key or range to a specified role. |
|
||||
| RoleRevokePermission | AuthRoleRevokePermissionRequest | AuthRoleRevokePermissionResponse | RoleRevokePermission revokes a key or range permission of a specified role. |
|
||||
|
||||
|
||||
|
||||
##### service `Cluster` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Method | Request Type | Response Type | Description |
|
||||
| ------ | ------------ | ------------- | ----------- |
|
||||
| MemberAdd | MemberAddRequest | MemberAddResponse | MemberAdd adds a member into the cluster. |
|
||||
| MemberRemove | MemberRemoveRequest | MemberRemoveResponse | MemberRemove removes an existing member from the cluster. |
|
||||
| MemberUpdate | MemberUpdateRequest | MemberUpdateResponse | MemberUpdate updates the member configuration. |
|
||||
| MemberList | MemberListRequest | MemberListResponse | MemberList lists all the members in the cluster. |
|
||||
|
||||
|
||||
|
||||
##### service `KV` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
for grpc-gateway
|
||||
|
||||
| Method | Request Type | Response Type | Description |
|
||||
| ------ | ------------ | ------------- | ----------- |
|
||||
| Range | RangeRequest | RangeResponse | Range gets the keys in the range from the key-value store. |
|
||||
| Put | PutRequest | PutResponse | Put puts the given key into the key-value store. A put request increments the revision of the key-value store and generates one event in the event history. |
|
||||
| DeleteRange | DeleteRangeRequest | DeleteRangeResponse | DeleteRange deletes the given range from the key-value store. A delete request increments the revision of the key-value store and generates a delete event in the event history for every deleted key. |
|
||||
| Txn | TxnRequest | TxnResponse | Txn processes multiple requests in a single transaction. A txn request increments the revision of the key-value store and generates events with the same revision for every completed request. It is not allowed to modify the same key several times within one txn. |
|
||||
| Compact | CompactionRequest | CompactionResponse | Compact compacts the event history in the etcd key-value store. The key-value store should be periodically compacted or the event history will continue to grow indefinitely. |
|
||||
|
||||
|
||||
|
||||
##### service `Lease` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Method | Request Type | Response Type | Description |
|
||||
| ------ | ------------ | ------------- | ----------- |
|
||||
| LeaseGrant | LeaseGrantRequest | LeaseGrantResponse | LeaseGrant creates a lease which expires if the server does not receive a keepAlive within a given time to live period. All keys attached to the lease will be expired and deleted if the lease expires. Each expired key generates a delete event in the event history. |
|
||||
| LeaseRevoke | LeaseRevokeRequest | LeaseRevokeResponse | LeaseRevoke revokes a lease. All keys attached to the lease will expire and be deleted. |
|
||||
| LeaseKeepAlive | LeaseKeepAliveRequest | LeaseKeepAliveResponse | LeaseKeepAlive keeps the lease alive by streaming keep alive requests from the client to the server and streaming keep alive responses from the server to the client. |
|
||||
|
||||
|
||||
|
||||
##### service `Maintenance` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Method | Request Type | Response Type | Description |
|
||||
| ------ | ------------ | ------------- | ----------- |
|
||||
| Alarm | AlarmRequest | AlarmResponse | Alarm activates, deactivates, and queries alarms regarding cluster health. |
|
||||
| Status | StatusRequest | StatusResponse | Status gets the status of the member. |
|
||||
| Defragment | DefragmentRequest | DefragmentResponse | Defragment defragments a member's backend database to recover storage space. |
|
||||
| Hash | HashRequest | HashResponse | Hash returns the hash of the local KV state for consistency checking purpose. This is designed for testing; do not use this in production when there are ongoing transactions. |
|
||||
| Snapshot | SnapshotRequest | SnapshotResponse | Snapshot sends a snapshot of the entire backend from a member over a stream to a client. |
|
||||
|
||||
|
||||
|
||||
##### service `Watch` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Method | Request Type | Response Type | Description |
|
||||
| ------ | ------------ | ------------- | ----------- |
|
||||
| Watch | WatchRequest | WatchResponse | Watch watches for events happening or that have happened. Both input and output are streams; the input stream is for creating and canceling watchers and the output stream sends events. One watch RPC can watch on multiple key ranges, streaming events for several watches at once. The entire event history can be watched starting from the last compaction revision. |
|
||||
|
||||
|
||||
|
||||
##### message `AlarmMember` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| memberID | memberID is the ID of the member associated with the raised alarm. | uint64 |
|
||||
| alarm | alarm is the type of alarm which has been raised. | AlarmType |
|
||||
|
||||
|
||||
|
||||
##### message `AlarmRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
default, used to query if any alarm is active space quota is exhausted
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| action | action is the kind of alarm request to issue. The action may GET alarm statuses, ACTIVATE an alarm, or DEACTIVATE a raised alarm. | AlarmAction |
|
||||
| memberID | memberID is the ID of the member associated with the alarm. If memberID is 0, the alarm request covers all members. | uint64 |
|
||||
| alarm | alarm is the type of alarm to consider for this request. | AlarmType |
|
||||
|
||||
|
||||
|
||||
##### message `AlarmResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| alarms | alarms is a list of alarms associated with the alarm request. | (slice of) AlarmMember |
|
||||
|
||||
|
||||
|
||||
##### message `AuthDisableRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `AuthDisableResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthEnableRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `AuthEnableResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleAddRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | name is the name of the role to add to the authentication system. | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleAddResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleDeleteRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| role | | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleDeleteResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleGetRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| role | | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleGetResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| perm | | (slice of) authpb.Permission |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleGrantPermissionRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | name is the name of the role which will be granted the permission. | string |
|
||||
| perm | perm is the permission to grant to the role. | authpb.Permission |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleGrantPermissionResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleListRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleListResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| roles | | (slice of) string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleRevokePermissionRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| role | | string |
|
||||
| key | | string |
|
||||
| range_end | | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthRoleRevokePermissionResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserAddRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | | string |
|
||||
| password | | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserAddResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserChangePasswordRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | name is the name of the user whose password is being changed. | string |
|
||||
| password | password is the new password for the user. | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserChangePasswordResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserDeleteRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | name is the name of the user to delete. | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserDeleteResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserGetRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserGetResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| roles | | (slice of) string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserGrantRoleRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| user | user is the name of the user which should be granted a given role. | string |
|
||||
| role | role is the name of the role to grant to the user. | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserGrantRoleResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserListRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserListResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| users | | (slice of) string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserRevokeRoleRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | | string |
|
||||
| role | | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthUserRevokeRoleResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `AuthenticateRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | | string |
|
||||
| password | | string |
|
||||
|
||||
|
||||
|
||||
##### message `AuthenticateResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| token | token is an authorized token that can be used in succeeding RPCs | string |
|
||||
|
||||
|
||||
|
||||
##### message `CompactionRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
CompactionRequest compacts the key-value store up to a given revision. All superseded keys with a revision less than the compaction revision will be removed.
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| revision | revision is the key-value store revision for the compaction operation. | int64 |
|
||||
| physical | physical is set so the RPC will wait until the compaction is physically applied to the local database such that compacted entries are totally removed from the backend database. | bool |
|
||||
|
||||
|
||||
|
||||
##### message `CompactionResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `Compare` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| result | result is logical comparison operation for this comparison. | CompareResult |
|
||||
| target | target is the key-value field to inspect for the comparison. | CompareTarget |
|
||||
| key | key is the subject key for the comparison operation. | bytes |
|
||||
| target_union | | oneof |
|
||||
| version | version is the version of the given key | int64 |
|
||||
| create_revision | create_revision is the creation revision of the given key | int64 |
|
||||
| mod_revision | mod_revision is the last modified revision of the given key. | int64 |
|
||||
| value | value is the value of the given key, in bytes. | bytes |
|
||||
|
||||
|
||||
|
||||
##### message `DefragmentRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `DefragmentResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `DeleteRangeRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| key | key is the first key to delete in the range. | bytes |
|
||||
| range_end | range_end is the key following the last key to delete for the range [key, range_end). If range_end is not given, the range is defined to contain only the key argument. If range_end is '\0', the range is all keys greater than or equal to the key argument. | bytes |
|
||||
|
||||
|
||||
|
||||
##### message `DeleteRangeResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| deleted | deleted is the number of keys deleted by the delete range request. | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `HashRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `HashResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| hash | hash is the hash value computed from the responding member's key-value store. | uint32 |
|
||||
|
||||
|
||||
|
||||
##### message `LeaseGrantRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| TTL | TTL is the advisory time-to-live in seconds. | int64 |
|
||||
| ID | ID is the requested ID for the lease. If ID is set to 0, the lessor chooses an ID. | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `LeaseGrantResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| ID | ID is the lease ID for the granted lease. | int64 |
|
||||
| TTL | TTL is the server chosen lease time-to-live in seconds. | int64 |
|
||||
| error | | string |
|
||||
|
||||
|
||||
|
||||
##### message `LeaseKeepAliveRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| ID | ID is the lease ID for the lease to keep alive. | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `LeaseKeepAliveResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| ID | ID is the lease ID from the keep alive request. | int64 |
|
||||
| TTL | TTL is the new time-to-live for the lease. | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `LeaseRevokeRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| ID | ID is the lease ID to revoke. When the ID is revoked, all associated keys will be deleted. | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `LeaseRevokeResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `Member` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| ID | ID is the member ID for this member. | uint64 |
|
||||
| name | name is the human-readable name of the member. If the member is not started, the name will be an empty string. | string |
|
||||
| peerURLs | peerURLs is the list of URLs the member exposes to the cluster for communication. | (slice of) string |
|
||||
| clientURLs | clientURLs is the list of URLs the member exposes to clients for communication. If the member is not started, clientURLs will be empty. | (slice of) string |
|
||||
|
||||
|
||||
|
||||
##### message `MemberAddRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| peerURLs | peerURLs is the list of URLs the added member will use to communicate with the cluster. | (slice of) string |
|
||||
|
||||
|
||||
|
||||
##### message `MemberAddResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| member | member is the member information for the added member. | Member |
|
||||
|
||||
|
||||
|
||||
##### message `MemberListRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `MemberListResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| members | members is a list of all members associated with the cluster. | (slice of) Member |
|
||||
|
||||
|
||||
|
||||
##### message `MemberRemoveRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| ID | ID is the member ID of the member to remove. | uint64 |
|
||||
|
||||
|
||||
|
||||
##### message `MemberRemoveResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `MemberUpdateRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| ID | ID is the member ID of the member to update. | uint64 |
|
||||
| peerURLs | peerURLs is the new list of URLs the member will use to communicate with the cluster. | (slice of) string |
|
||||
|
||||
|
||||
|
||||
##### message `MemberUpdateResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `PutRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| key | key is the key, in bytes, to put into the key-value store. | bytes |
|
||||
| value | value is the value, in bytes, to associate with the key in the key-value store. | bytes |
|
||||
| lease | lease is the lease ID to associate with the key in the key-value store. A lease value of 0 indicates no lease. | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `PutResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
|
||||
|
||||
|
||||
##### message `RangeRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| key | default, no sorting lowest target value first highest target value first key is the first key for the range. If range_end is not given, the request only looks up key. | bytes |
|
||||
| range_end | range_end is the upper bound on the requested range [key, range_end). If range_end is '\0', the range is all keys >= key. If the range_end is one bit larger than the given key, then the range requests get the all keys with the prefix (the given key). If both key and range_end are '\0', then range requests returns all keys. | bytes |
|
||||
| limit | limit is a limit on the number of keys returned for the request. | int64 |
|
||||
| revision | revision is the point-in-time of the key-value store to use for the range. If revision is less or equal to zero, the range is over the newest key-value store. If the revision has been compacted, ErrCompacted is returned as a response. | int64 |
|
||||
| sort_order | sort_order is the order for returned sorted results. | SortOrder |
|
||||
| sort_target | sort_target is the key-value field to use for sorting. | SortTarget |
|
||||
| serializable | serializable sets the range request to use serializable member-local reads. Range requests are linearizable by default; linearizable requests have higher latency and lower throughput than serializable requests but reflect the current consensus of the cluster. For better performance, in exchange for possible stale reads, a serializable range request is served locally without needing to reach consensus with other nodes in the cluster. | bool |
|
||||
|
||||
|
||||
|
||||
##### message `RangeResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| kvs | kvs is the list of key-value pairs matched by the range request. | (slice of) mvccpb.KeyValue |
|
||||
| more | more indicates if there are more keys to return in the requested range. | bool |
|
||||
|
||||
|
||||
|
||||
##### message `RequestOp` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| request | request is a union of request types accepted by a transaction. | oneof |
|
||||
| request_range | | RangeRequest |
|
||||
| request_put | | PutRequest |
|
||||
| request_delete_range | | DeleteRangeRequest |
|
||||
|
||||
|
||||
|
||||
##### message `ResponseHeader` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| cluster_id | cluster_id is the ID of the cluster which sent the response. | uint64 |
|
||||
| member_id | member_id is the ID of the member which sent the response. | uint64 |
|
||||
| revision | revision is the key-value store revision when the request was applied. | int64 |
|
||||
| raft_term | raft_term is the raft term when the request was applied. | uint64 |
|
||||
|
||||
|
||||
|
||||
##### message `ResponseOp` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| response | response is a union of response types returned by a transaction. | oneof |
|
||||
| response_range | | RangeResponse |
|
||||
| response_put | | PutResponse |
|
||||
| response_delete_range | | DeleteRangeResponse |
|
||||
|
||||
|
||||
|
||||
##### message `SnapshotRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `SnapshotResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | header has the current key-value store information. The first header in the snapshot stream indicates the point in time of the snapshot. | ResponseHeader |
|
||||
| remaining_bytes | remaining_bytes is the number of blob bytes to be sent after this message | uint64 |
|
||||
| blob | blob contains the next chunk of the snapshot in the snapshot stream. | bytes |
|
||||
|
||||
|
||||
|
||||
##### message `StatusRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
Empty field.
|
||||
|
||||
|
||||
|
||||
##### message `StatusResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| version | version is the cluster protocol version used by the responding member. | string |
|
||||
| dbSize | dbSize is the size of the backend database, in bytes, of the responding member. | int64 |
|
||||
| leader | leader is the member ID which the responding member believes is the current leader. | uint64 |
|
||||
| raftIndex | raftIndex is the current raft index of the responding member. | uint64 |
|
||||
| raftTerm | raftTerm is the current raft term of the responding member. | uint64 |
|
||||
|
||||
|
||||
|
||||
##### message `TxnRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
From google paxosdb paper: Our implementation hinges around a powerful primitive which we call MultiOp. All other database operations except for iteration are implemented as a single call to MultiOp. A MultiOp is applied atomically and consists of three components: 1. A list of tests called guard. Each test in guard checks a single entry in the database. It may check for the absence or presence of a value, or compare with a given value. Two different tests in the guard may apply to the same or different entries in the database. All tests in the guard are applied and MultiOp returns the results. If all tests are true, MultiOp executes t op (see item 2 below), otherwise it executes f op (see item 3 below). 2. A list of database operations called t op. Each operation in the list is either an insert, delete, or lookup operation, and applies to a single database entry. Two different operations in the list may apply to the same or different entries in the database. These operations are executed if guard evaluates to true. 3. A list of database operations called f op. Like t op, but executed if guard evaluates to false.
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| compare | compare is a list of predicates representing a conjunction of terms. If the comparisons succeed, then the success requests will be processed in order, and the response will contain their respective responses in order. If the comparisons fail, then the failure requests will be processed in order, and the response will contain their respective responses in order. | (slice of) Compare |
|
||||
| success | success is a list of requests which will be applied when compare evaluates to true. | (slice of) RequestOp |
|
||||
| failure | failure is a list of requests which will be applied when compare evaluates to false. | (slice of) RequestOp |
|
||||
|
||||
|
||||
|
||||
##### message `TxnResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| succeeded | succeeded is set to true if the compare evaluated to true or false otherwise. | bool |
|
||||
| responses | responses is a list of responses corresponding to the results from applying success if succeeded is true or failure if succeeded is false. | (slice of) ResponseOp |
|
||||
|
||||
|
||||
|
||||
##### message `WatchCancelRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| watch_id | watch_id is the watcher id to cancel so that no more events are transmitted. | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `WatchCreateRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| key | key is the key to register for watching. | bytes |
|
||||
| range_end | range_end is the end of the range [key, range_end) to watch. If range_end is not given, only the key argument is watched. If range_end is equal to '\0', all keys greater than or equal to the key argument are watched. | bytes |
|
||||
| start_revision | start_revision is an optional revision to watch from (inclusive). No start_revision is "now". | int64 |
|
||||
| progress_notify | progress_notify is set so that the etcd server will periodically send a WatchResponse with no events to the new watcher if there are no recent events. It is useful when clients wish to recover a disconnected watcher starting from a recent known revision. The etcd server may decide how often it will send notifications based on current load. | bool |
|
||||
|
||||
|
||||
|
||||
##### message `WatchRequest` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| request_union | request_union is a request to either create a new watcher or cancel an existing watcher. | oneof |
|
||||
| create_request | | WatchCreateRequest |
|
||||
| cancel_request | | WatchCancelRequest |
|
||||
|
||||
|
||||
|
||||
##### message `WatchResponse` (etcdserver/etcdserverpb/rpc.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| header | | ResponseHeader |
|
||||
| watch_id | watch_id is the ID of the watcher that corresponds to the response. | int64 |
|
||||
| created | created is set to true if the response is for a create watch request. The client should record the watch_id and expect to receive events for the created watcher from the same stream. All events sent to the created watcher will attach with the same watch_id. | bool |
|
||||
| canceled | canceled is set to true if the response is for a cancel watch request. No further events will be sent to the canceled watcher. | bool |
|
||||
| compact_revision | compact_revision is set to the minimum index if a watcher tries to watch at a compacted index. This happens when creating a watcher at a compacted revision or the watcher cannot catch up with the progress of the key-value store. The client should treat the watcher as canceled and should not try to create any watcher with the same start_revision again. | int64 |
|
||||
| events | | (slice of) mvccpb.Event |
|
||||
|
||||
|
||||
|
||||
##### message `Event` (mvcc/mvccpb/kv.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| type | type is the kind of event. If type is a PUT, it indicates new data has been stored to the key. If type is a DELETE, it indicates the key was deleted. | EventType |
|
||||
| kv | kv holds the KeyValue for the event. A PUT event contains current kv pair. A PUT event with kv.Version=1 indicates the creation of a key. A DELETE/EXPIRE event contains the deleted key with its modification revision set to the revision of deletion. | KeyValue |
|
||||
|
||||
|
||||
|
||||
##### message `KeyValue` (mvcc/mvccpb/kv.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| key | key is the key in bytes. An empty key is not allowed. | bytes |
|
||||
| create_revision | create_revision is the revision of last creation on this key. | int64 |
|
||||
| mod_revision | mod_revision is the revision of last modification on this key. | int64 |
|
||||
| version | version is the version of the key. A deletion resets the version to zero and any modification of the key increases its version. | int64 |
|
||||
| value | value is the value held by the key, in bytes. | bytes |
|
||||
| lease | lease is the ID of the lease that attached to key. When the attached lease expires, the key will be deleted. If lease is 0, then no lease is attached to the key. | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `Lease` (lease/leasepb/lease.proto)
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| ID | | int64 |
|
||||
| TTL | | int64 |
|
||||
|
||||
|
||||
|
||||
##### message `Permission` (auth/authpb/auth.proto)
|
||||
|
||||
Permission is a single entity
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| permType | | Type |
|
||||
| key | | bytes |
|
||||
| range_end | | bytes |
|
||||
|
||||
|
||||
|
||||
##### message `Role` (auth/authpb/auth.proto)
|
||||
|
||||
Role is a single entry in the bucket authRoles
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | | bytes |
|
||||
| keyPermission | | (slice of) Permission |
|
||||
|
||||
|
||||
|
||||
##### message `User` (auth/authpb/auth.proto)
|
||||
|
||||
User is a single entry in the bucket authUsers
|
||||
|
||||
| Field | Description | Type |
|
||||
| ----- | ----------- | ---- |
|
||||
| name | | bytes |
|
||||
| password | | bytes |
|
||||
| roles | | (slice of) string |
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
||||
# Experimental APIs and features
|
||||
|
||||
For the most part, the etcd project is stable, but we are still moving fast! We believe in the release fast philosophy. We want to get early feedback on features still in development and stabilizing. Thus, there are, and will be more, experimental features and APIs. We plan to improve these features based on the early feedback from the community, or abandon them if there is little interest, in the next few releases. If you are running a production system, please do not rely on any experimental features or APIs.
|
||||
|
||||
## The current experimental API/features are:
|
||||
|
||||
- v3 auth API: expect to be stable in 3.1 release
|
||||
- etcd gateway: expect to be stable in 3.1 release
|
@ -1,243 +0,0 @@
|
||||
# Interacting with etcd
|
||||
|
||||
Users mostly interact with etcd by putting or getting the value of a key. This section describes how to do that by using etcdctl, a command line tool for interacting with etcd server. The concepts described here should apply to the gRPC APIs or client library APIs.
|
||||
|
||||
By default, etcdctl talks to the etcd server with the v2 API for backward compatibility. For etcdctl to speak to etcd using the v3 API, the API version must be set to version 3 via the `ETCDCTL_API` environment variable.
|
||||
|
||||
``` bash
|
||||
export ETCDCTL_API=3
|
||||
```
|
||||
|
||||
## Write a key
|
||||
|
||||
Applications store keys into the etcd cluster by writing to keys. Every stored key is replicated to all etcd cluster members through the Raft protocol to achieve consistency and reliability.
|
||||
|
||||
Here is the command to set the value of key `foo` to `bar`:
|
||||
|
||||
``` bash
|
||||
$ etcdctl put foo bar
|
||||
OK
|
||||
```
|
||||
|
||||
## Read keys
|
||||
|
||||
Applications can read values of keys from an etcd cluster. Queries may read a single key, or a range of keys.
|
||||
|
||||
Suppose the etcd cluster has stored the following keys:
|
||||
|
||||
```
|
||||
foo = bar
|
||||
foo1 = bar1
|
||||
foo3 = bar3
|
||||
```
|
||||
|
||||
Here is the command to read the value of key `foo`:
|
||||
|
||||
```bash
|
||||
$ etcdctl get foo
|
||||
foo
|
||||
bar
|
||||
```
|
||||
|
||||
Here is the command to range over the keys from `foo` to `foo9`:
|
||||
|
||||
```bash
|
||||
$ etcdctl get foo foo9
|
||||
foo
|
||||
bar
|
||||
foo1
|
||||
bar1
|
||||
foo3
|
||||
bar3
|
||||
```
|
||||
|
||||
## Read past version of keys
|
||||
|
||||
Applications may want to read superseded versions of a key. For example, an application may wish to roll back to an old configuration by accessing an earlier version of a key. Alternatively, an application may want a consistent view over multiple keys through multiple requests by accessing key history.
|
||||
Since every modification to the etcd cluster key-value store increments the global revision of an etcd cluster, an application can read superseded keys by providing an older etcd revision.
|
||||
|
||||
Suppose an etcd cluster already has the following keys:
|
||||
|
||||
``` bash
|
||||
$ etcdctl put foo bar # revision = 2
|
||||
$ etcdctl put foo1 bar1 # revision = 3
|
||||
$ etcdctl put foo bar_new # revision = 4
|
||||
$ etcdctl put foo1 bar1_new # revision = 5
|
||||
```
|
||||
|
||||
Here are an example to access the past versions of keys:
|
||||
|
||||
```bash
|
||||
$ etcdctl get foo foo9 # access the most recent versions of keys
|
||||
foo
|
||||
bar_new
|
||||
foo1
|
||||
bar1_new
|
||||
|
||||
$ etcdctl get --rev=4 foo foo9 # access the versions of keys at revision 4
|
||||
foo
|
||||
bar_new
|
||||
foo1
|
||||
bar1
|
||||
|
||||
$ etcdctl get --rev=3 foo foo9 # access the versions of keys at revision 3
|
||||
foo
|
||||
bar
|
||||
foo1
|
||||
bar1
|
||||
|
||||
$ etcdctl get --rev=2 foo foo9 # access the versions of keys at revision 2
|
||||
foo
|
||||
bar
|
||||
|
||||
$ etcdctl get --rev=1 foo foo9 # access the versions of keys at revision 1
|
||||
```
|
||||
|
||||
## Delete keys
|
||||
|
||||
Applications can delete a key or a range of keys from an etcd cluster.
|
||||
|
||||
Here is the command to delete key `foo`:
|
||||
|
||||
```bash
|
||||
$ etcdctl del foo
|
||||
1 # one key is deleted
|
||||
```
|
||||
|
||||
Here is the command to delete keys ranging from `foo` to `foo9`:
|
||||
|
||||
```bash
|
||||
$ etcdctl del foo foo9
|
||||
2 # two keys are deleted
|
||||
```
|
||||
|
||||
## Watch key changes
|
||||
|
||||
Applications can watch on a key or a range of keys to monitor for any updates.
|
||||
|
||||
Here is the command to watch on key `foo`:
|
||||
|
||||
```bash
|
||||
$ etcdctl watch foo
|
||||
# in another terminal: etcdctl put foo bar
|
||||
foo
|
||||
bar
|
||||
```
|
||||
|
||||
Here is the command to watch on a range key from `foo` to `foo9`:
|
||||
|
||||
```bash
|
||||
$ etcdctl watch foo foo9
|
||||
# in another terminal: etcdctl put foo bar
|
||||
foo
|
||||
bar
|
||||
# in another terminal: etcdctl put foo1 bar1
|
||||
foo1
|
||||
bar1
|
||||
```
|
||||
|
||||
## Watch historical changes of keys
|
||||
|
||||
Applications may want to watch for historical changes of keys in etcd. For example, an application may wish to receive all the modifications of a key; if the application stays connected to etcd, then `watch` is good enough. However, if the application or etcd fails, a change may happen during the failure, and the application will not receive the update in real time. To guarantee the update is delivered, the application must be able to watch for historical changes to keys. To do this, an application can specify a historical revision on a watch, just like reading past version of keys.
|
||||
|
||||
Suppose we finished the following sequence of operations:
|
||||
|
||||
``` bash
|
||||
etcdctl put foo bar # revision = 2
|
||||
etcdctl put foo1 bar1 # revision = 3
|
||||
etcdctl put foo bar_new # revision = 4
|
||||
etcdctl put foo1 bar1_new # revision = 5
|
||||
```
|
||||
|
||||
Here is an example to watch the historical changes:
|
||||
```bash
|
||||
# watch for changes on key `foo` since revision 2
|
||||
$ etcdctl watch --rev=2 foo
|
||||
PUT
|
||||
foo
|
||||
bar
|
||||
PUT
|
||||
foo
|
||||
bar_new
|
||||
|
||||
# watch for changes on key `foo` since revision 3
|
||||
$ etcdctl watch --rev=3 foo
|
||||
PUT
|
||||
foo
|
||||
bar_new
|
||||
```
|
||||
|
||||
## Compacted revisions
|
||||
|
||||
As we mentioned, etcd keeps revisions so that applications can read past versions of keys. However, to avoid accumulating an unbounded amount of history, it is important to compact past revisions. After compacting, etcd removes historical revisions, releasing resources for future use. All superseded data with revisions before the compacted revision will be unavailable.
|
||||
|
||||
Here is the command to compact the revisions:
|
||||
|
||||
```bash
|
||||
$ etcdctl compact 5
|
||||
compacted revision 5
|
||||
|
||||
# any revisions before the compacted one are not accessible
|
||||
$ etcdctl get --rev=4 foo
|
||||
Error: rpc error: code = 11 desc = etcdserver: mvcc: required revision has been compacted
|
||||
```
|
||||
|
||||
## Grant leases
|
||||
|
||||
Applications can grant leases for keys from an etcd cluster. When a key is attached to a lease, its lifetime is bound to the lease's lifetime which in turn is governed by a time-to-live (TTL). Each lease has a minimum time-to-live (TTL) value specified by the application at grant time. The lease's actual TTL value is at least the minimum TTL and is chosen by the etcd cluster. Once a lease's TTL elapses, the lease expires and all attached keys are deleted.
|
||||
|
||||
Here is the command to grant a lease:
|
||||
|
||||
```
|
||||
# grant a lease with 10 second TTL
|
||||
$ etcdctl lease grant 10
|
||||
lease 32695410dcc0ca06 granted with TTL(10s)
|
||||
|
||||
# attach key foo to lease 32695410dcc0ca06
|
||||
$ etcdctl put --lease=32695410dcc0ca06 foo bar
|
||||
OK
|
||||
```
|
||||
|
||||
## Revoke leases
|
||||
|
||||
Applications revoke leases by lease ID. Revoking a lease deletes all of its attached keys.
|
||||
|
||||
Suppose we finished the following sequence of operations:
|
||||
|
||||
```
|
||||
$ etcdctl lease grant 10
|
||||
lease 32695410dcc0ca06 granted with TTL(10s)
|
||||
$ etcdctl put --lease=32695410dcc0ca06 foo bar
|
||||
OK
|
||||
```
|
||||
|
||||
Here is the command to revoke the same lease:
|
||||
|
||||
```
|
||||
$ etcdctl lease revoke 32695410dcc0ca06
|
||||
lease 32695410dcc0ca06 revoked
|
||||
|
||||
$ etcdctl get foo
|
||||
# empty response since foo is deleted due to lease revocation
|
||||
```
|
||||
|
||||
## Keep leases alive
|
||||
|
||||
Applications can keep a lease alive by refreshing its TTL so it does not expire.
|
||||
|
||||
Suppose we finished the following sequence of operations:
|
||||
|
||||
```
|
||||
$ etcdctl lease grant 10
|
||||
lease 32695410dcc0ca06 granted with TTL(10s)
|
||||
```
|
||||
|
||||
Here is the command to keep the same lease alive:
|
||||
|
||||
```
|
||||
$ etcdctl lease keep-alive 32695410dcc0ca0
|
||||
lease 32695410dcc0ca0 keepalived with TTL(100)
|
||||
lease 32695410dcc0ca0 keepalived with TTL(100)
|
||||
lease 32695410dcc0ca0 keepalived with TTL(100)
|
||||
...
|
||||
```
|
@ -1,90 +0,0 @@
|
||||
# Setup a local cluster
|
||||
|
||||
For testing and development deployments, the quickest and easiest way is to set up a local cluster. For a production deployment, refer to the [clustering][clustering] section.
|
||||
|
||||
## Local standalone cluster
|
||||
|
||||
Deploying an etcd cluster as a standalone cluster is straightforward. Start it with just one command:
|
||||
|
||||
```
|
||||
$ ./etcd
|
||||
...
|
||||
```
|
||||
|
||||
The started etcd member listens on `localhost:2379` for client requests.
|
||||
|
||||
To interact with the started cluster by using etcdctl:
|
||||
|
||||
```
|
||||
# use API version 3
|
||||
$ export ETCDCTL_API=3
|
||||
|
||||
$ ./etcdctl put foo bar
|
||||
OK
|
||||
|
||||
$ ./etcdctl get foo
|
||||
bar
|
||||
```
|
||||
|
||||
## Local multi-member cluster
|
||||
|
||||
A Procfile is provided to easily set up a local multi-member cluster. Start a multi-member cluster with a few commands:
|
||||
|
||||
```
|
||||
# install goreman program to control Profile-based applications.
|
||||
$ go get github.com/mattn/goreman
|
||||
$ goreman -f Procfile start
|
||||
...
|
||||
```
|
||||
|
||||
The started members listen on `localhost:12379`, `localhost:22379`, and `localhost:32379` for client requests respectively.
|
||||
|
||||
To interact with the started cluster by using etcdctl:
|
||||
|
||||
```
|
||||
# use API version 3
|
||||
$ export ETCDCTL_API=3
|
||||
|
||||
$ etcdctl --write-out=table --endpoints=localhost:12379 member list
|
||||
+------------------+---------+--------+------------------------+------------------------+
|
||||
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
|
||||
+------------------+---------+--------+------------------------+------------------------+
|
||||
| 8211f1d0f64f3269 | started | infra1 | http://127.0.0.1:12380 | http://127.0.0.1:12379 |
|
||||
| 91bc3c398fb3c146 | started | infra2 | http://127.0.0.1:22380 | http://127.0.0.1:22379 |
|
||||
| fd422379fda50e48 | started | infra3 | http://127.0.0.1:32380 | http://127.0.0.1:32379 |
|
||||
+------------------+---------+--------+------------------------+------------------------+
|
||||
|
||||
$ etcdctl --endpoints=localhost:12379 put foo bar
|
||||
OK
|
||||
```
|
||||
|
||||
To exercise etcd's fault tolerance, kill a member:
|
||||
|
||||
```
|
||||
# kill etcd2
|
||||
$ goreman run stop etcd2
|
||||
|
||||
$ etcdctl --endpoints=localhost:12379 put key hello
|
||||
OK
|
||||
|
||||
$ etcdctl --endpoints=localhost:12379 get key
|
||||
hello
|
||||
|
||||
# try to get key from the killed member
|
||||
$ etcdctl --endpoints=localhost:22379 get key
|
||||
2016/04/18 23:07:35 grpc: Conn.resetTransport failed to create client transport: connection error: desc = "transport: dial tcp 127.0.0.1:22379: getsockopt: connection refused"; Reconnecting to "localhost:22379"
|
||||
Error: grpc: timed out trying to connect
|
||||
|
||||
# restart the killed member
|
||||
$ goreman run restart etcd2
|
||||
|
||||
# get the key from restarted member
|
||||
$ etcdctl --endpoints=localhost:22379 get key
|
||||
hello
|
||||
```
|
||||
|
||||
To learn more about interacting with etcd, read [interacting with etcd section][interacting].
|
||||
|
||||
[interacting]: ./interacting_v3.md
|
||||
[clustering]: ../op-guide/clustering.md
|
||||
|
@ -1,113 +0,0 @@
|
||||
# Discovery service protocol
|
||||
|
||||
Discovery service protocol helps new etcd member to discover all other members in cluster bootstrap phase using a shared discovery URL.
|
||||
|
||||
Discovery service protocol is _only_ used in cluster bootstrap phase, and cannot be used for runtime reconfiguration or cluster monitoring.
|
||||
|
||||
The protocol uses a new discovery token to bootstrap one _unique_ etcd cluster. Remember that one discovery token can represent only one etcd cluster. As long as discovery protocol on this token starts, even if it fails halfway, it must not be used to bootstrap another etcd cluster.
|
||||
|
||||
The rest of this article will walk through the discovery process with examples that correspond to a self-hosted discovery cluster. The public discovery service, discovery.etcd.io, functions the same way, but with a layer of polish to abstract away ugly URLs, generate UUIDs automatically, and provide some protections against excessive requests. At its core, the public discovery service still uses an etcd cluster as the data store as described in this document.
|
||||
|
||||
## Protocol workflow
|
||||
|
||||
The idea of discovery protocol is to use an internal etcd cluster to coordinate bootstrap of a new cluster. First, all new members interact with discovery service and help to generate the expected member list. Then each new member bootstraps its server using this list, which performs the same functionality as -initial-cluster flag.
|
||||
|
||||
In the following example workflow, we will list each step of protocol in curl format for ease of understanding.
|
||||
|
||||
By convention the etcd discovery protocol uses the key prefix `_etcd/registry`. If `http://example.com` hosts an etcd cluster for discovery service, a full URL to discovery keyspace will be `http://example.com/v2/keys/_etcd/registry`. We will use this as the URL prefix in the example.
|
||||
|
||||
### Creating a new discovery token
|
||||
|
||||
Generate a unique token that will identify the new cluster. This will be used as a unique prefix in discovery keyspace in the following steps. An easy way to do this is to use `uuidgen`:
|
||||
|
||||
```
|
||||
UUID=$(uuidgen)
|
||||
```
|
||||
|
||||
### Specifying the expected cluster size
|
||||
|
||||
The discovery token expects a cluster size that must be specified. The size is used by the discovery service to know when it has found all members that will initially form the cluster.
|
||||
|
||||
```
|
||||
curl -X PUT http://example.com/v2/keys/_etcd/registry/${UUID}/_config/size -d value=${cluster_size}
|
||||
```
|
||||
|
||||
Usually the cluster size is 3, 5 or 7. Check [optimal cluster size][cluster-size] for more details.
|
||||
|
||||
### Bringing up etcd processes
|
||||
|
||||
Given the discovery URL, use it as `-discovery` flag and bring up etcd processes. Every etcd process will follow this next few steps internally if given a `-discovery` flag.
|
||||
|
||||
### Registering itself
|
||||
|
||||
The first thing for etcd process is to register itself into the discovery URL as a member. This is done by creating member ID as a key in the discovery URL.
|
||||
|
||||
```
|
||||
curl -X PUT http://example.com/v2/keys/_etcd/registry/${UUID}/${member_id}?prevExist=false -d value="${member_name}=${member_peer_url_1}&${member_name}=${member_peer_url_2}"
|
||||
```
|
||||
|
||||
### Checking the status
|
||||
|
||||
It checks the expected cluster size and registration status in discovery URL, and decides what the next action is.
|
||||
|
||||
```
|
||||
curl -X GET http://example.com/v2/keys/_etcd/registry/${UUID}/_config/size
|
||||
curl -X GET http://example.com/v2/keys/_etcd/registry/${UUID}
|
||||
```
|
||||
|
||||
If registered members are still not enough, it will wait for left members to appear.
|
||||
|
||||
If the number of registered members is bigger than the expected size N, it treats the first N registered members as the member list for the cluster. If the member itself is in the member list, the discovery procedure succeeds and it fetches all peers through the member list. If it is not in the member list, the discovery procedure finishes with the failure that the cluster has been full.
|
||||
|
||||
In etcd implementation, the member may check the cluster status even before registering itself. So it could fail quickly if the cluster has been full.
|
||||
|
||||
### Waiting for all members
|
||||
|
||||
The wait process is described in detail in the [etcd API documentation][api].
|
||||
|
||||
```
|
||||
curl -X GET http://example.com/v2/keys/_etcd/registry/${UUID}?wait=true&waitIndex=${current_etcd_index}
|
||||
```
|
||||
|
||||
It keeps waiting until finding all members.
|
||||
|
||||
## Public discovery service
|
||||
|
||||
CoreOS Inc. hosts a public discovery service at https://discovery.etcd.io/ , which provides some nice features for ease of use.
|
||||
|
||||
### Mask key prefix
|
||||
|
||||
Public discovery service will redirect `https://discovery.etcd.io/${UUID}` to etcd cluster behind for the key at `/v2/keys/_etcd/registry`. It masks register key prefix for short and readable discovery url.
|
||||
|
||||
### Get new token
|
||||
|
||||
```
|
||||
GET /new
|
||||
|
||||
Sent query:
|
||||
size=${cluster_size}
|
||||
Possible status codes:
|
||||
200 OK
|
||||
400 Bad Request
|
||||
200 Body:
|
||||
generated discovery url
|
||||
```
|
||||
|
||||
The generation process in the service follows the steps from [Creating a New Discovery Token][new-discovery-token] to [Specifying the Expected Cluster Size][expected-cluster-size].
|
||||
|
||||
### Check discovery status
|
||||
|
||||
```
|
||||
GET /${UUID}
|
||||
```
|
||||
|
||||
The status for this discovery token, including the machines that have been registered, can be checked by requesting the value of the UUID.
|
||||
|
||||
### Open-source repository
|
||||
|
||||
The repository is located at https://github.com/coreos/discovery.etcd.io. It could be used to build a custom discovery service.
|
||||
|
||||
[api]: ../v2/api.md#waiting-for-a-change
|
||||
[cluster-size]: ../v2/admin_guide.md#optimal-cluster-size
|
||||
[expected-cluster-size]: #specifying-the-expected-cluster-size
|
||||
[new-discovery-token]: #creating-a-new-discovery-token
|
@ -1,29 +0,0 @@
|
||||
# Logging conventions
|
||||
|
||||
etcd uses the [capnslog][capnslog] library for logging application output categorized into *levels*. A log message's level is determined according to these conventions:
|
||||
|
||||
* Error: Data has been lost, a request has failed for a bad reason, or a required resource has been lost
|
||||
* Examples:
|
||||
* A failure to allocate disk space for WAL
|
||||
|
||||
* Warning: (Hopefully) Temporary conditions that may cause errors, but may work fine. A replica disappearing (that may reconnect) is a warning.
|
||||
* Examples:
|
||||
* Failure to send raft message to a remote peer
|
||||
* Failure to receive heartbeat message within the configured election timeout
|
||||
|
||||
* Notice: Normal, but important (uncommon) log information.
|
||||
* Examples:
|
||||
* Add a new node into the cluster
|
||||
* Add a new user into auth subsystem
|
||||
|
||||
* Info: Normal, working log information, everything is fine, but helpful notices for auditing or common operations.
|
||||
* Examples:
|
||||
* Startup configuration
|
||||
* Start to do snapshot
|
||||
|
||||
* Debug: Everything is still fine, but even common operations may be logged, and less helpful but more quantity of notices.
|
||||
* Examples:
|
||||
* Send a normal message to a remote peer
|
||||
* Write a log entry to disk
|
||||
|
||||
[capnslog]: [https://github.com/coreos/pkg/tree/master/capnslog]
|
@ -1,109 +0,0 @@
|
||||
# etcd release guide
|
||||
|
||||
The guide talks about how to release a new version of etcd.
|
||||
|
||||
The procedure includes some manual steps for sanity checking but it can probably be further scripted. Please keep this document up-to-date if making changes to the release process.
|
||||
|
||||
## Prepare release
|
||||
|
||||
Set desired version as environment variable for following steps. Here is an example to release 2.3.0:
|
||||
|
||||
```
|
||||
export VERSION=v2.3.0
|
||||
export PREV_VERSION=v2.2.5
|
||||
```
|
||||
|
||||
All releases version numbers follow the format of [semantic versioning 2.0.0](http://semver.org/).
|
||||
|
||||
### Major, minor version release, or its pre-release
|
||||
|
||||
- Ensure the relevant milestone on GitHub is complete. All referenced issues should be closed, or moved elsewhere.
|
||||
- Remove this release from [roadmap](https://github.com/coreos/etcd/blob/master/ROADMAP.md), if necessary.
|
||||
- Ensure the latest upgrade documentation is available.
|
||||
- Bump [hardcoded MinClusterVerion in the repository](https://github.com/coreos/etcd/blob/master/version/version.go#L29), if necessary.
|
||||
- Add feature capability maps for the new version, if necessary.
|
||||
|
||||
### Patch version release
|
||||
|
||||
- Discuss about commits that are backported to the patch release. The commits should not include merge commits.
|
||||
- Cherry-pick these commits starting from the oldest one into stable branch.
|
||||
|
||||
## Write release note
|
||||
|
||||
- Write introduction for the new release. For example, what major bug we fix, what new features we introduce or what performance improvement we make.
|
||||
- Write changelog for the last release. ChangeLog should be straightforward and easy to understand for the end-user.
|
||||
- Put `[GH XXXX]` at the head of change line to reference Pull Request that introduces the change. Moreover, add a link on it to jump to the Pull Request.
|
||||
|
||||
## Tag version
|
||||
|
||||
- Bump [hardcoded Version in the repository](https://github.com/coreos/etcd/blob/master/version/version.go#L30) to the latest version `${VERSION}`.
|
||||
- Ensure all tests on CI system are passed.
|
||||
- Manually check etcd is buildable in Linux, Darwin and Windows.
|
||||
- Manually check upgrade etcd cluster of previous minor version works well.
|
||||
- Manually check new features work well.
|
||||
- Add a signed tag through `git tag -s ${VERSION}`.
|
||||
- Sanity check tag correctness through `git show tags/$VERSION`.
|
||||
- Push the tag to GitHub through `git push origin tags/$VERSION`. This assumes `origin` corresponds to "https://github.com/coreos/etcd".
|
||||
|
||||
## Build release binaries and images
|
||||
|
||||
- Ensure `actool` is available, or installing it through `go get github.com/appc/spec/actool`.
|
||||
- Ensure `docker` is available.
|
||||
|
||||
Run release script in root directory:
|
||||
|
||||
```
|
||||
./scripts/release.sh ${VERSION}
|
||||
```
|
||||
|
||||
It generates all release binaries and images under directory ./release.
|
||||
|
||||
## Sign binaries and images
|
||||
|
||||
etcd project key must be used to sign the generated binaries and images.`$SUBKEYID` is the key ID of etcd project Yubikey. Connect the key and run `gpg2 --card-status` to get the ID.
|
||||
|
||||
The following commands are used for public release sign:
|
||||
|
||||
```
|
||||
cd release
|
||||
for i in etcd-*{.zip,.tar.gz}; do gpg2 --default-key $SUBKEYID --armor --output ${i}.asc --detach-sign ${i}; done
|
||||
for i in etcd-*{.zip,.tar.gz}; do gpg2 --verify ${i}.asc ${i}; done
|
||||
```
|
||||
|
||||
The public key for GPG signing can be found at [CoreOS Application Signing Key](https://coreos.com/security/app-signing-key)
|
||||
|
||||
|
||||
## Publish release page in GitHub
|
||||
|
||||
- Set release title as the version name.
|
||||
- Follow the format of previous release pages.
|
||||
- Attach the generated binaries, aci image and signatures.
|
||||
- Select whether it is a pre-release.
|
||||
- Publish the release!
|
||||
|
||||
## Publish docker image in Quay.io
|
||||
|
||||
- Push docker image:
|
||||
|
||||
```
|
||||
docker login quay.io
|
||||
docker push quay.io/coreos/etcd:${VERSION}
|
||||
```
|
||||
|
||||
- Add `latest` tag to the new image on [quay.io](https://quay.io/repository/coreos/etcd?tag=latest&tab=tags) if this is a stable release.
|
||||
|
||||
## Announce to the etcd-dev Googlegroup
|
||||
|
||||
- Follow the format of [previous release emails](https://groups.google.com/forum/#!forum/etcd-dev).
|
||||
- Make sure to include a list of authors that contributed since the previous release - something like the following might be handy:
|
||||
|
||||
```
|
||||
git log ...${PREV_VERSION} --pretty=format:"%an" | sort | uniq | tr '\n' ',' | sed -e 's#,#, #g' -e 's#, $##'
|
||||
```
|
||||
|
||||
- Send email to etcd-dev@googlegroups.com
|
||||
|
||||
## Post release
|
||||
|
||||
- Create new stable branch through `git push origin ${VERSION_MAJOR}.${VERSION_MINOR}` if this is a major stable release. This assumes `origin` corresponds to "https://github.com/coreos/etcd".
|
||||
- Bump [hardcoded Version in the repository](https://github.com/coreos/etcd/blob/master/version/version.go#L30) to the version `${VERSION}+git`.
|
@ -1,56 +0,0 @@
|
||||
# Download and build
|
||||
|
||||
## System requirements
|
||||
|
||||
The etcd performance benchmarks run etcd on 8 vCPU, 16GB RAM, 50GB SSD GCE instances, but any relatively modern machine with low latency storage and a few gigabytes of memory should suffice for most use cases. Applications with large v2 data stores will require more memory than a large v3 data store since data is kept in anonymous memory instead of memory mapped from a file. than For running etcd on a cloud provider, we suggest at least a medium instance on AWS or a standard-1 instance on GCE.
|
||||
|
||||
## Download the pre-built binary
|
||||
|
||||
The easiest way to get etcd is to use one of the pre-built release binaries which are available for OSX, Linux, Windows, appc, and Docker. Instructions for using these binaries are on the [GitHub releases page][github-release].
|
||||
|
||||
## Build the latest version
|
||||
|
||||
For those wanting to try the very latest version, build etcd from the `master` branch.
|
||||
[Go](https://golang.org/) version 1.6+ (with HTTP2 support) is required to build the latest version of etcd.
|
||||
|
||||
Here are the commands to build an etcd binary from the `master` branch:
|
||||
|
||||
```
|
||||
# go is required
|
||||
$ go version
|
||||
go version go1.6 darwin/amd64
|
||||
|
||||
# GOPATH should be set correctly
|
||||
$ echo $GOPATH
|
||||
/Users/example/go
|
||||
|
||||
$ mkdir -p $GOPATH/src/github.com/coreos
|
||||
$ cd $GOPATH/src/github.com/coreos
|
||||
$ git clone github.com:coreos/etcd.git
|
||||
$ cd etcd
|
||||
$ ./build
|
||||
$ ./bin/etcd
|
||||
...
|
||||
```
|
||||
|
||||
## Test the installation
|
||||
|
||||
Check the etcd binary is built correctly by starting etcd and setting a key.
|
||||
|
||||
Start etcd:
|
||||
|
||||
```
|
||||
$ ./bin/etcd
|
||||
```
|
||||
|
||||
Set a key:
|
||||
|
||||
```
|
||||
$ ETCDCTL_API=3 ./bin/etcdctl put foo bar
|
||||
OK
|
||||
```
|
||||
|
||||
If OK is printed, then etcd is working!
|
||||
|
||||
[github-release]: https://github.com/coreos/etcd/releases/
|
||||
[go]: https://golang.org/doc/install
|
@ -12,11 +12,8 @@ export HostIP="192.168.12.50"
|
||||
|
||||
The following `docker run` command will expose the etcd client API over ports 4001 and 2379, and expose the peer port over 2380.
|
||||
|
||||
This will run the latest release version of etcd. You can specify version if needed (e.g. `quay.io/coreos/etcd:v2.2.0`).
|
||||
|
||||
```
|
||||
docker run -d -v /usr/share/ca-certificates/:/etc/ssl/certs -p 4001:4001 -p 2380:2380 -p 2379:2379 \
|
||||
--name etcd quay.io/coreos/etcd \
|
||||
docker run -d -p 4001:4001 -p 2380:2380 -p 2379:2379 --name etcd quay.io/coreos/etcd:v2.0.3 \
|
||||
-name etcd0 \
|
||||
-advertise-client-urls http://${HostIP}:2379,http://${HostIP}:4001 \
|
||||
-listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 \
|
||||
@ -45,8 +42,7 @@ The main difference being the value used for the `-initial-cluster` flag, which
|
||||
### etcd0
|
||||
|
||||
```
|
||||
docker run -d -v /usr/share/ca-certificates/:/etc/ssl/certs -p 4001:4001 -p 2380:2380 -p 2379:2379 \
|
||||
--name etcd quay.io/coreos/etcd \
|
||||
docker run -d -p 4001:4001 -p 2380:2380 -p 2379:2379 --name etcd quay.io/coreos/etcd:v2.0.3 \
|
||||
-name etcd0 \
|
||||
-advertise-client-urls http://192.168.12.50:2379,http://192.168.12.50:4001 \
|
||||
-listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 \
|
||||
@ -60,8 +56,7 @@ docker run -d -v /usr/share/ca-certificates/:/etc/ssl/certs -p 4001:4001 -p 2380
|
||||
### etcd1
|
||||
|
||||
```
|
||||
docker run -d -v /usr/share/ca-certificates/:/etc/ssl/certs -p 4001:4001 -p 2380:2380 -p 2379:2379 \
|
||||
--name etcd quay.io/coreos/etcd \
|
||||
docker run -d -p 4001:4001 -p 2380:2380 -p 2379:2379 --name etcd quay.io/coreos/etcd:v2.0.3 \
|
||||
-name etcd1 \
|
||||
-advertise-client-urls http://192.168.12.51:2379,http://192.168.12.51:4001 \
|
||||
-listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 \
|
||||
@ -75,8 +70,7 @@ docker run -d -v /usr/share/ca-certificates/:/etc/ssl/certs -p 4001:4001 -p 2380
|
||||
### etcd2
|
||||
|
||||
```
|
||||
docker run -d -v /usr/share/ca-certificates/:/etc/ssl/certs -p 4001:4001 -p 2380:2380 -p 2379:2379 \
|
||||
--name etcd quay.io/coreos/etcd \
|
||||
docker run -d -p 4001:4001 -p 2380:2380 -p 2379:2379 --name etcd quay.io/coreos/etcd:v2.0.3 \
|
||||
-name etcd2 \
|
||||
-advertise-client-urls http://192.168.12.52:2379,http://192.168.12.52:4001 \
|
||||
-listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 \
|
@ -1,73 +0,0 @@
|
||||
# Documentation
|
||||
|
||||
etcd is a distributed key-value store designed to reliably and quickly preserve and provide access to critical data. It enables reliable distributed coordination through distributed locking, leader elections, and write barriers. An etcd cluster is intended for high availability and permanent data storage and retrieval.
|
||||
|
||||
## Getting started
|
||||
|
||||
New etcd users and developers should get started by [downloading and building][download_build] etcd. After getting etcd, follow this [quick demo][demo] to see the basics of creating and working with an etcd cluster.
|
||||
|
||||
## Developing with etcd
|
||||
|
||||
The easiest way to get started using etcd as a distributed key-value store is to [set up a local cluster][local_cluster].
|
||||
|
||||
- [Setting up local clusters][local_cluster]
|
||||
- [Interacting with etcd][interacting]
|
||||
- [API references][api_ref]
|
||||
- [gRPC gateway][api_grpc_gateway]
|
||||
- [Experimental features and APIs][experimental]
|
||||
|
||||
## Operating etcd clusters
|
||||
|
||||
Administrators who need to create reliable and scalable key-value stores for the developers they support should begin with a [cluster on multiple machines][clustering].
|
||||
|
||||
- [Setting up clusters][clustering]
|
||||
- [Run etcd clusters inside containers][container]
|
||||
- [Configuration][conf]
|
||||
- [Security][security]
|
||||
- Monitoring
|
||||
- [Maintenance][maintenance]
|
||||
- [Understand failures][failures]
|
||||
- [Disaster recovery][recovery]
|
||||
- [Performance][performance]
|
||||
- [Versioning][versioning]
|
||||
- [Supported platform][supported_platform]
|
||||
|
||||
## Learning
|
||||
|
||||
To learn more about the concepts and internals behind etcd, read the following pages:
|
||||
|
||||
- Why etcd (TODO)
|
||||
- [Understand data model][data_model]
|
||||
- [Understand APIs][understand_apis]
|
||||
- [Glossary][glossary]
|
||||
- Internals (TODO)
|
||||
|
||||
## Upgrading and compatibility
|
||||
|
||||
- [Migrate applications from using API v2 to API v3][v2_migration]
|
||||
- [Updating v2.3 to v3.0][v3_upgrade]
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
[api_ref]: dev-guide/api_reference_v3.md
|
||||
[api_grpc_gateway]: dev-guide/api_grpc_gateway.md
|
||||
[clustering]: op-guide/clustering.md
|
||||
[conf]: op-guide/configuration.md
|
||||
[data_model]: learning/data_model.md
|
||||
[demo]: demo.md
|
||||
[download_build]: dl_build.md
|
||||
[failures]: op-guide/failures.md
|
||||
[glossary]: learning/glossary.md
|
||||
[interacting]: dev-guide/interacting_v3.md
|
||||
[local_cluster]: dev-guide/local_cluster.md
|
||||
[performance]: op-guide/performance.md
|
||||
[recovery]: op-guide/recovery.md
|
||||
[maintenance]: op-guide/maintenance.md
|
||||
[security]: op-guide/security.md
|
||||
[v2_migration]: op-guide/v2-migration.md
|
||||
[container]: op-guide/container.md
|
||||
[understand_apis]: learning/api.md
|
||||
[versioning]: op-guide/versioning.md
|
||||
[supported_platform]: op-guide/supported-platform.md
|
||||
[experimental]: dev-guide/experimental_apis.md
|
||||
[v3_upgrade]: upgrades/upgrade_3_0.md
|
@ -1,4 +1,4 @@
|
||||
# Error Code
|
||||
Error Code
|
||||
======
|
||||
|
||||
This document describes the error code used in key space '/v2/keys'. Feel free to import 'github.com/coreos/etcd/error' to use.
|
@ -1,35 +1,31 @@
|
||||
# Glossary
|
||||
## Glossary
|
||||
|
||||
This document defines the various terms used in etcd documentation, command line and source code.
|
||||
|
||||
## Node
|
||||
### Node
|
||||
|
||||
Node is an instance of raft state machine.
|
||||
|
||||
It has a unique identification, and records other nodes' progress internally when it is the leader.
|
||||
|
||||
## Member
|
||||
### Member
|
||||
|
||||
Member is an instance of etcd. It hosts a node, and provides service to clients.
|
||||
|
||||
## Cluster
|
||||
### Cluster
|
||||
|
||||
Cluster consists of several members.
|
||||
|
||||
The node in each member follows raft consensus protocol to replicate logs. Cluster receives proposals from members, commits them and apply to local store.
|
||||
|
||||
## Peer
|
||||
### Peer
|
||||
|
||||
Peer is another member of the same cluster.
|
||||
|
||||
## Proposal
|
||||
|
||||
A proposal is a request (for example a write request, a configuration change request) that needs to go through raft protocol.
|
||||
|
||||
## Client
|
||||
### Client
|
||||
|
||||
Client is a caller of the cluster's HTTP API.
|
||||
|
||||
## Machine (deprecated)
|
||||
### Machine (deprecated)
|
||||
|
||||
The alternative of Member in etcd before 2.0
|
@ -1,57 +0,0 @@
|
||||
# etcd3 API
|
||||
|
||||
NOTE: this doc is not finished!
|
||||
|
||||
## Response header
|
||||
|
||||
All Responses from etcd API have a [response header][response_header] attached. The response header includes the metadata of the response.
|
||||
|
||||
```proto
|
||||
message ResponseHeader {
|
||||
uint64 cluster_id = 1;
|
||||
uint64 member_id = 2;
|
||||
int64 revision = 3;
|
||||
uint64 raft_term = 4;
|
||||
}
|
||||
```
|
||||
|
||||
* Cluster_ID - the ID of the cluster that generates the response
|
||||
* Member_ID - the ID of the member that generates the response
|
||||
* Revision - the revision of the key-value store when the response is generated
|
||||
* Raft_Term - the Raft term of the member when the response is generated
|
||||
|
||||
An application may read the Cluster_ID (Member_ID) field to ensure it is communicating with the intended cluster (member).
|
||||
|
||||
Applications can use the `Revision` to know the latest revision of the key-value store. This is especially useful when applications specify a historical revision to make time `travel query` and wishes to know the latest revision at the time of the request.
|
||||
|
||||
Applications can use `Raft_Term` to detect when the cluster completes a new leader election.
|
||||
|
||||
## Key-Value API
|
||||
|
||||
Key-Value API is used to manipulate key-value pairs stored inside etcd. The key-value API is defined as a [gRPC service][kv-service]. The Key-Value pair is defined as structured data in [protobuf format][kv-proto].
|
||||
|
||||
### Key-Value pair
|
||||
|
||||
A key-value pair is the smallest unit that the key-value API can manipulate. Each key-value pair has a number of fields:
|
||||
|
||||
```protobuf
|
||||
message KeyValue {
|
||||
bytes key = 1;
|
||||
int64 create_revision = 2;
|
||||
int64 mod_revision = 3;
|
||||
int64 version = 4;
|
||||
bytes value = 5;
|
||||
int64 lease = 6;
|
||||
}
|
||||
```
|
||||
|
||||
* Key - key in bytes. An empty key is not allowed.
|
||||
* Value - value in bytes.
|
||||
* Version - version is the version of the key. A deletion resets the version to zero and any modification of the key increases its version.
|
||||
* Create_Revision - revision of the last creation on the key.
|
||||
* Mod_Revision - revision of the last modification on the key.
|
||||
* Lease - the ID of the lease attached to the key. If lease is 0, then no lease is attached to the key.
|
||||
|
||||
[kv-proto]: https://github.com/coreos/etcd/blob/master/mvcc/mvccpb/kv.proto
|
||||
[kv-service]: https://github.com/coreos/etcd/blob/master/etcdserver/etcdserverpb/rpc.proto
|
||||
[response_header]: https://github.com/coreos/etcd/blob/master/etcdserver/etcdserverpb/rpc.proto
|
@ -1,63 +0,0 @@
|
||||
# KV API guarantees
|
||||
|
||||
etcd is a consistent and durable key value store with mini-transaction(TODO: link to txn doc when we have it) support. The key value store is exposed through the KV APIs. etcd tries to ensure the strongest consistency and durability guarantees for a distributed system. This specification enumerates the KV API guarantees made by etcd.
|
||||
|
||||
### APIs to consider
|
||||
|
||||
* Read APIs
|
||||
* range
|
||||
* watch
|
||||
* Write APIs
|
||||
* put
|
||||
* delete
|
||||
* Combination (read-modify-write) APIs
|
||||
* txn
|
||||
|
||||
### etcd specific definitions
|
||||
|
||||
#### Operation completed
|
||||
|
||||
An etcd operation is considered complete when it is committed through consensus, and therefore “executed” -- permanently stored -- by the etcd storage engine. The client knows an operation is completed when it receives a response from the etcd server. Note that the client may be uncertain about the status of an operation if it times out, or there is a network disruption between the client and the etcd member. etcd may also abort operations when there is a leader election. etcd does not send `abort` responses to clients’ outstanding requests in this event.
|
||||
|
||||
#### Revision
|
||||
|
||||
An etcd operation that modifies the key value store is assigned with a single increasing revision. A transaction operation might modifies the key value store multiple times, but only one revision is assigned. The revision attribute of a key value pair that modified by the operation has the same value as the revision of the operation. The revision can be used as a logical clock for key value store. A key value pair that has a larger revision is modified after a key value pair with a smaller revision. Two key value pairs that have the same revision are modified by an operation "concurrently".
|
||||
|
||||
### Guarantees provided
|
||||
|
||||
#### Atomicity
|
||||
|
||||
All API requests are atomic; an operation either completes entirely or not at all. For watch requests, all events generated by one operation will be in one watch response. Watch never observes partial events for a single operation.
|
||||
|
||||
#### Consistency
|
||||
|
||||
All API calls ensure [sequential consistency][seq_consistency], the strongest consistency guarantee available from distributed systems. No matter which etcd member server a client makes requests to, a client reads the same events in the same order. If two members complete the same number of operations, the state of the two members is consistent.
|
||||
|
||||
For watch operations, etcd guarantees to return the same value for the same key across all members for the same revision. For range operations, etcd has a similar guarantee for [linearized][Linearizability] access; serialized access may be behind the quorum state, so that the later revision is not yet available.
|
||||
|
||||
As with all distributed systems, it is impossible for etcd to ensure [strict consistency][strict_consistency]. etcd does not guarantee that it will return to a read the “most recent” value (as measured by a wall clock when a request is completed) available on any cluster member.
|
||||
|
||||
#### Isolation
|
||||
|
||||
etcd ensures [serializable isolation][serializable_isolation], which is the highest isolation level available in distributed systems. Read operations will never observe any intermediate data.
|
||||
|
||||
#### Durability
|
||||
|
||||
Any completed operations are durable. All accessible data is also durable data. A read will never return data that has not been made durable.
|
||||
|
||||
#### Linearizability
|
||||
|
||||
Linearizability (also known as Atomic Consistency or External Consistency) is a consistency level between strict consistency and sequential consistency.
|
||||
|
||||
For linearizability, suppose each operation receives a timestamp from a loosely synchronized global clock. Operations are linearized if and only if they always complete as though they were executed in a sequential order and each operation appears to complete in the order specified by the program. Likewise, if an operation’s timestamp precedes another, that operation must also precede the other operation in the sequence.
|
||||
|
||||
For example, consider a client completing a write at time point 1 (*t1*). A client issuing a read at *t2* (for *t2* > *t1*) should receive a value at least as recent as the previous write, completed at *t1*. However, the read might actually complete only by *t3*, and the returned value, current at *t2* when the read began, might be "stale" by *t3*.
|
||||
|
||||
etcd does not ensure linearizability for watch operations. Users are expected to verify the revision of watch responses to ensure correct ordering.
|
||||
|
||||
etcd ensures linearizability for all other operations by default. Linearizability comes with a cost, however, because linearized requests must go through the Raft consensus process. To obtain lower latencies and higher throughput for read requests, clients can configure a request’s consistency mode to `serializable`, which may access stale data with respect to quorum, but removes the performance penalty of linearized accesses' reliance on live consensus.
|
||||
|
||||
[seq_consistency]: https://en.wikipedia.org/wiki/Consistency_model#Sequential_consistency
|
||||
[strict_consistency]: https://en.wikipedia.org/wiki/Consistency_model#Strict_consistency
|
||||
[serializable_isolation]: https://en.wikipedia.org/wiki/Isolation_(database_systems)#Serializable
|
||||
[Linearizability]: #Linearizability
|
@ -1,25 +0,0 @@
|
||||
# Data model
|
||||
|
||||
etcd is designed to reliably store infrequently updated data and provide reliable watch queries. etcd exposes previous versions of key-value pairs to support inexpensive snapshots and watch history events (“time travel queries”). A persistent, multi-version, concurrency-control data model is a good fit for these use cases.
|
||||
|
||||
etcd stores data in a multiversion [persistent][persistent-ds] key-value store. The persistent key-value store preserves the previous version of a key-value pair when its value is superseded with new data. The key-value store is effectively immutable; its operations do not update the structure in-place, but instead always generates a new updated structure. All past versions of keys are still accessible and watchable after modification. To prevent the data store from growing indefinitely over time from maintaining old versions, the store may be compacted to shed the oldest versions of superseded data.
|
||||
|
||||
### Logical view
|
||||
|
||||
The store’s logical view is a flat binary key space. The key space has a lexically sorted index on byte string keys so range queries are inexpensive.
|
||||
|
||||
The key space maintains multiple revisions. Each atomic mutative operation (e.g., a transaction operation may contain multiple operations) creates a new revision on the key space. All data held by previous revisions remains unchanged. Old versions of key can still be accessed through previous revisions. Likewise, revisions are indexed as well; ranging over revisions with watchers is efficient. If the store is compacted to recover space, revisions before the compact revision will be removed.
|
||||
|
||||
A key’s lifetime spans a generation. Each key may have one or multiple generations. Creating a key increments the generation of that key, starting at 1 if the key never existed. Deleting a key generates a key tombstone, concluding the key’s current generation. Each modification of a key creates a new version of the key. Once a compaction happens, any generation ended before the given revision will be removed and values set before the compaction revision except the latest one will be removed.
|
||||
|
||||
### Physical view
|
||||
|
||||
etcd stores the physical data as key-value pairs in a persistent [b+tree][b+tree]. Each revision of the store’s state only contains the delta from its previous revision to be efficient. A single revision may correspond to multiple keys in the tree.
|
||||
|
||||
The key of key-value pair is a 3-tuple (major, sub, type). Major is the store revision holding the key. Sub differentiates among keys within the same revision. Type is an optional suffix for special value (e.g., `t` if the value contains a tombstone). The value of the key-value pair contains the modification from previous revision, thus one delta from previous revision. The b+tree is ordered by key in lexical byte-order. Ranged lookups over revision deltas are fast; this enables quickly finding modifications from one specific revision to another. Compaction removes out-of-date keys-value pairs.
|
||||
|
||||
etcd also keeps a secondary in-memory [btree][btree] index to speed up range queries over keys. The keys in the btree index are the keys of the store exposed to user. The value is a pointer to the modification of the persistent b+tree. Compaction removes dead pointers.
|
||||
|
||||
[persistent-ds]: https://en.wikipedia.org/wiki/Persistent_data_structure
|
||||
[btree]: https://en.wikipedia.org/wiki/B-tree
|
||||
[b+tree]: https://en.wikipedia.org/wiki/B%2B_tree
|
@ -1,35 +0,0 @@
|
||||
# Glossary
|
||||
|
||||
This document defines the various terms used in etcd documentation, command line and source code.
|
||||
|
||||
## Node
|
||||
|
||||
Node is an instance of raft state machine.
|
||||
|
||||
It has a unique identification, and records other nodes' progress internally when it is the leader.
|
||||
|
||||
## Member
|
||||
|
||||
Member is an instance of etcd. It hosts a node, and provides service to clients.
|
||||
|
||||
## Cluster
|
||||
|
||||
Cluster consists of several members.
|
||||
|
||||
The node in each member follows raft consensus protocol to replicate logs. Cluster receives proposals from members, commits them and apply to local store.
|
||||
|
||||
## Peer
|
||||
|
||||
Peer is another member of the same cluster.
|
||||
|
||||
## Proposal
|
||||
|
||||
A proposal is a request (for example a write request, a configuration change request) that needs to go through raft protocol.
|
||||
|
||||
## Client
|
||||
|
||||
Client is a caller of the cluster's HTTP API.
|
||||
|
||||
## Machine (deprecated)
|
||||
|
||||
The alternative of Member in etcd before 2.0
|
@ -1,25 +1,18 @@
|
||||
# Libraries and tools
|
||||
## Libraries and Tools
|
||||
|
||||
**Tools**
|
||||
|
||||
- [etcdctl](https://github.com/coreos/etcd/tree/master/etcdctl) - A command line client for etcd
|
||||
- [etcdctl](https://github.com/coreos/etcdctl) - A command line client for etcd
|
||||
- [etcd-backup](https://github.com/fanhattan/etcd-backup) - A powerful command line utility for dumping/restoring etcd - Supports v2
|
||||
- [etcd-dump](https://npmjs.org/package/etcd-dump) - Command line utility for dumping/restoring etcd.
|
||||
- [etcd-fs](https://github.com/xetorthio/etcd-fs) - FUSE filesystem for etcd
|
||||
- [etcddir](https://github.com/rekby/etcddir) - Realtime sync etcd and local directory. Work with windows and linux.
|
||||
- [etcd-browser](https://github.com/henszey/etcd-browser) - A web-based key/value editor for etcd using AngularJS
|
||||
- [etcd-lock](https://github.com/datawisesystems/etcd-lock) - Master election & distributed r/w lock implementation using etcd - Supports v2
|
||||
- [etcd-lock](https://github.com/datawisesystems/etcd-lock) - A lock implementation for etcd
|
||||
- [etcd-console](https://github.com/matishsiao/etcd-console) - A web-base key/value editor for etcd using PHP
|
||||
- [etcd-viewer](https://github.com/nikfoundas/etcd-viewer) - An etcd key-value store editor/viewer written in Java
|
||||
- [etcdtool](https://github.com/mickep76/etcdtool) - Export/Import/Edit etcd directory as JSON/YAML/TOML and Validate directory using JSON schema
|
||||
- [etcd-rest](https://github.com/mickep76/etcd-rest) - Create generic REST API in Go using etcd as a backend with validation using JSON schema
|
||||
- [etcdsh](https://github.com/kamilhark/etcdsh) - A command line client with support of command history and tab completion. Supports v2
|
||||
|
||||
**Go libraries**
|
||||
|
||||
- [etcd/clientv3](https://github.com/coreos/etcd/blob/master/clientv3) - the officially maintained Go client for v3
|
||||
- [etcd/client](https://github.com/coreos/etcd/blob/master/client) - the officially maintained Go client for v2
|
||||
- [go-etcd](https://github.com/coreos/go-etcd) - the deprecated official client. May be useful for older (<2.0.0) versions of etcd.
|
||||
- [go-etcd](https://github.com/coreos/go-etcd) - Supports v2
|
||||
|
||||
**Java libraries**
|
||||
|
||||
@ -28,11 +21,6 @@
|
||||
- [diwakergupta/jetcd](https://github.com/diwakergupta/jetcd) - Supports v2
|
||||
- [jurmous/etcd4j](https://github.com/jurmous/etcd4j) - Supports v2, Async/Sync, waits and SSL
|
||||
- [AdoHe/etcd4j](http://github.com/AdoHe/etcd4j) - Supports v2 (enhance for real production cluster)
|
||||
- [cdancy/etcd-rest](https://github.com/cdancy/etcd-rest) - Uses jclouds to provide a complete implementation of v2 API.
|
||||
|
||||
**Scala libraries**
|
||||
|
||||
- [maciej/etcd-client](https://github.com/maciej/etcd-client) - Supports v2. Akka HTTP-based fully async client
|
||||
|
||||
**Python libraries**
|
||||
|
||||
@ -45,7 +33,6 @@
|
||||
|
||||
- [stianeikeland/node-etcd](https://github.com/stianeikeland/node-etcd) - Supports v2 (w Coffeescript)
|
||||
- [lavagetto/nodejs-etcd](https://github.com/lavagetto/nodejs-etcd) - Supports v2
|
||||
- [deedubs/node-etcd-config](https://github.com/deedubs/node-etcd-config) - Supports v2
|
||||
|
||||
**Ruby libraries**
|
||||
|
||||
@ -56,11 +43,9 @@
|
||||
**C libraries**
|
||||
|
||||
- [jdarcy/etcd-api](https://github.com/jdarcy/etcd-api) - Supports v2
|
||||
- [shafreeck/cetcd](https://github.com/shafreeck/cetcd) - Supports v2
|
||||
|
||||
**C++ libraries**
|
||||
- [edwardcapriolo/etcdcpp](https://github.com/edwardcapriolo/etcdcpp) - Supports v2
|
||||
- [suryanathan/etcdcpp](https://github.com/suryanathan/etcdcpp) - Supports v2 (with waits)
|
||||
|
||||
**Clojure libraries**
|
||||
|
||||
@ -74,7 +59,6 @@
|
||||
|
||||
**.Net Libraries**
|
||||
|
||||
- [wangjia184/etcdnet](https://github.com/wangjia184/etcdnet) - Supports v2
|
||||
- [drusellers/etcetera](https://github.com/drusellers/etcetera)
|
||||
|
||||
**PHP Libraries**
|
||||
@ -84,18 +68,14 @@
|
||||
**Haskell libraries**
|
||||
|
||||
- [wereHamster/etcd-hs](https://github.com/wereHamster/etcd-hs)
|
||||
|
||||
**R libraries**
|
||||
|
||||
- [ropensci/etseed](https://github.com/ropensci/etseed)
|
||||
|
||||
|
||||
**Tcl libraries**
|
||||
|
||||
- [efrecon/etcd-tcl](https://github.com/efrecon/etcd-tcl) - Supports v2, except wait.
|
||||
|
||||
**Gradle Plugins**
|
||||
A detailed recap of client functionalities can be found in the [clients compatibility matrix][clients-matrix.md].
|
||||
|
||||
- [gradle-etcd-rest-plugin](https://github.com/cdancy/gradle-etcd-rest-plugin) - Supports v2
|
||||
[clients-matrix.md]: https://github.com/coreos/etcd/blob/master/Documentation/clients-matrix.md
|
||||
|
||||
**Chef Integration**
|
||||
|
||||
@ -124,12 +104,9 @@
|
||||
- [configdb](https://git.autistici.org/ai/configdb/tree/master) - A REST relational abstraction on top of arbitrary database backends, aimed at storing configs and inventories.
|
||||
- [scrz](https://github.com/scrz/scrz) - Container manager, stores configuration in etcd.
|
||||
- [fleet](https://github.com/coreos/fleet) - Distributed init system
|
||||
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes) - Container cluster manager introduced by Google.
|
||||
- [GoogleCloudPlatform/kubernetes](https://github.com/GoogleCloudPlatform/kubernetes) - Container cluster manager.
|
||||
- [mailgun/vulcand](https://github.com/mailgun/vulcand) - HTTP proxy that uses etcd as a configuration backend.
|
||||
- [duedil-ltd/discodns](https://github.com/duedil-ltd/discodns) - Simple DNS nameserver using etcd as a database for names and records.
|
||||
- [skynetservices/skydns](https://github.com/skynetservices/skydns) - RFC compliant DNS server
|
||||
- [xordataexchange/crypt](https://github.com/xordataexchange/crypt) - Securely store values in etcd using GPG encryption
|
||||
- [spf13/viper](https://github.com/spf13/viper) - Go configuration library, reads values from ENV, pflags, files, and etcd with optional encryption
|
||||
- [lytics/metafora](https://github.com/lytics/metafora) - Go distributed task library
|
||||
- [ryandoyle/nss-etcd](https://github.com/ryandoyle/nss-etcd) - A GNU libc NSS module for resolving names from etcd.
|
||||
- [Gru](https://github.com/dnaeon/gru) - Orchestration made easy with Go
|
||||
|
@ -1,136 +0,0 @@
|
||||
# Metrics
|
||||
|
||||
etcd uses [Prometheus][prometheus] for metrics reporting. The metrics can be used for real-time monitoring and debugging. etcd does not persist its metrics; if a member restarts, the metrics will be reset.
|
||||
|
||||
The simplest way to see the available metrics is to cURL the metrics endpoint `/metrics`. The format is described [here](http://prometheus.io/docs/instrumenting/exposition_formats/).
|
||||
|
||||
Follow the [Prometheus getting started doc][prometheus-getting-started] to spin up a Prometheus server to collect etcd metrics.
|
||||
|
||||
The naming of metrics follows the suggested [Prometheus best practices][prometheus-naming]. A metric name has an `etcd` or `etcd_debugging` prefix as its namespace and a subsystem prefix (for example `wal` and `etcdserver`).
|
||||
|
||||
## etcd namespace metrics
|
||||
|
||||
The metrics under the `etcd` prefix are for monitoring and alerting. They are stable high level metrics. If there is any change of these metrics, it will be included in release notes.
|
||||
|
||||
Metrics that are etcd2 related are documented [v2 metrics guide][v2-http-metrics].
|
||||
|
||||
### Server
|
||||
|
||||
These metrics describe the status of the etcd server. In order to detect outages or problems for troubleshooting, the server metrics of every production etcd cluster should be closely monitored.
|
||||
|
||||
All these metrics are prefixed with `etcd_server_`
|
||||
|
||||
| Name | Description | Type |
|
||||
|---------------------------|----------------------------------------------------------|---------|
|
||||
| has_leader | Whether or not a leader exists. 1 is existence, 0 is not.| Gauge |
|
||||
| leader_changes_seen_total | The number of leader changes seen. | Counter |
|
||||
| proposals_committed_total | The total number of consensus proposals committed. | Gauge |
|
||||
| proposals_applied_total | The total number of consensus proposals applied. | Gauge |
|
||||
| proposals_pending | The current number of pending proposals. | Gauge |
|
||||
| proposals_failed_total | The total number of failed proposals seen. | Counter |
|
||||
|
||||
`has_leader` indicates whether the member has a leader. If a member does not have a leader, it is
|
||||
totally unavailable. If all the members in the cluster do not have any leader, the entire cluster
|
||||
is totally unavailable.
|
||||
|
||||
`leader_changes_seen_total` counts the number of leader changes the member has seen since its start. Rapid leadership changes impact the performance of etcd significantly. It also signals that the leader is unstable, perhaps due to network connectivity issues or excessive load hitting the etcd cluster.
|
||||
|
||||
`proposals_committed_total` records the total number of consensus proposals committed. This gauge should increase over time if the cluster is healthy. Several healthy members of an etcd cluster may have different total committed proposals at once. This discrepancy may be due to recovering from peers after starting, lagging behind the leader, or being the leader and therefore having the most commits. It is important to monitor this metric across all the members in the cluster; a consistently large lag between a single member and its leader indicates that member is slow or unhealthy.
|
||||
|
||||
`proposals_applied_total` records the total number of consensus proposals applied. The etcd server applies every committed proposal asynchronously. The difference between `proposals_committed_total` and `proposals_applied_total` should usually be small (within a few thousands even under high load). If the difference between them continues to rise, it indicates that the etcd server is overloaded. This might happen when applying expensive queries like heavy range queries or large txn operations.
|
||||
|
||||
`proposals_pending` indicates how many proposals are queued to commit. Rising pending proposals suggests there is a high client load or the member cannot commit proposals.
|
||||
|
||||
`proposals_failed_total` are normally related to two issues: temporary failures related to a leader election or longer downtime caused by a loss of quorum in the cluster.
|
||||
|
||||
### Disk
|
||||
|
||||
These metrics describe the status of the disk operations.
|
||||
|
||||
All these metrics are prefixed with `etcd_disk_`.
|
||||
|
||||
| Name | Description | Type |
|
||||
|------------------------------------|-------------------------------------------------------|-----------|
|
||||
| wal_fsync_duration_seconds | The latency distributions of fsync called by wal | Histogram |
|
||||
| backend_commit_duration_seconds | The latency distributions of commit called by backend.| Histogram |
|
||||
|
||||
A `wal_fsync` is called when etcd persists its log entries to disk before applying them.
|
||||
|
||||
A `backend_commit` is called when etcd commits an incremental snapshot of its most recent changes to disk.
|
||||
|
||||
High disk operation latencies (`wal_fsync_duration_seconds` or `backend_commit_duration_seconds`) often indicate disk issues. It may cause high request latency or make the cluster unstable.
|
||||
|
||||
### Network
|
||||
|
||||
These metrics describe the status of the network.
|
||||
|
||||
All these metrics are prefixed with `etcd_network_`
|
||||
|
||||
| Name | Description | Type |
|
||||
|---------------------------|--------------------------------------------------------------------|---------------|
|
||||
| peer_sent_bytes_total | The total number of bytes sent to the peer with ID `To`. | Counter(To) |
|
||||
| peer_received_bytes_total | The total number of bytes received from the peer with ID `From`. | Counter(From) |
|
||||
| peer_round_trip_time_seconds | Round-Trip-Time histogram between peers. | Histogram(To) |
|
||||
| client_grpc_sent_bytes_total | The total number of bytes sent to grpc clients. | Counter |
|
||||
| client_grpc_received_bytes_total| The total number of bytes received to grpc clients. | Counter |
|
||||
|
||||
`peer_sent_bytes_total` counts the total number of bytes sent to a specific peer. Usually the leader member sends more data than other members since it is responsible for transmitting replicated data.
|
||||
|
||||
`peer_received_bytes_total` counts the total number of bytes received from a specific peer. Usually follower members receive data only from the leader member.
|
||||
|
||||
### gRPC requests
|
||||
|
||||
These metrics describe the requests served by a specific etcd member: total received requests, total failed requests, and processing latency. They are useful for tracking user-generated traffic hitting the etcd cluster.
|
||||
|
||||
All these metrics are prefixed with `etcd_grpc_`
|
||||
|
||||
| Name | Description | Type |
|
||||
|--------------------------------|-------------------------------------------------------------------------------------|------------------------|
|
||||
| requests_total | Total number of received requests | Counter(method) |
|
||||
| requests_failed_total | Total number of failed requests. | Counter(method,error) |
|
||||
| unary_requests_duration_seconds | Bucketed handling duration of the requests. | Histogram(method) |
|
||||
|
||||
|
||||
Example Prometheus queries that may be useful from these metrics (across all etcd members):
|
||||
|
||||
* `sum(rate(etcd_grpc_requests_failed_total{job="etcd"}[1m]) by (grpc_method) / sum(rate(etcd_grpc_total{job="etcd"})[1m]) by (grpc_method)`
|
||||
|
||||
Shows the fraction of events that failed by gRPC method across all members, across a time window of `1m`.
|
||||
|
||||
* `sum(rate(etcd_grpc_requests_total{job="etcd",grpc_method="PUT"})[1m]) by (grpc_method)`
|
||||
|
||||
Shows the rate of PUT requests across all members, across a time window of `1m`.
|
||||
|
||||
* `histogram_quantile(0.9, sum(rate(etcd_grpc_unary_requests_duration_seconds{job="etcd",grpc_method="PUT"}[5m]) ) by (le))`
|
||||
|
||||
Show the 0.90-tile latency (in seconds) of PUT request handling across all members, with a window of `5m`.
|
||||
|
||||
## etcd_debugging namespace metrics
|
||||
|
||||
The metrics under the `etcd_debugging` prefix are for debugging. They are very implementation dependent and volatile. They might be changed or removed without any warning in new etcd releases. Some of the metrics might be moved to the `etcd` prefix when they become more stable.
|
||||
|
||||
|
||||
### Snapshot
|
||||
|
||||
| Name | Description | Type |
|
||||
|--------------------------------------------|------------------------------------------------------------|-----------|
|
||||
| snapshot_save_total_duration_seconds | The total latency distributions of save called by snapshot | Histogram |
|
||||
|
||||
Abnormally high snapshot duration (`snapshot_save_total_duration_seconds`) indicates disk issues and might cause the cluster to be unstable.
|
||||
|
||||
## Prometheus supplied metrics
|
||||
|
||||
The Prometheus client library provides a number of metrics under the `go` and `process` namespaces. There are a few that are particlarly interesting.
|
||||
|
||||
| Name | Description | Type |
|
||||
|-----------------------------------|--------------------------------------------|--------------|
|
||||
| process_open_fds | Number of open file descriptors. | Gauge |
|
||||
| process_max_fds | Maximum number of open file descriptors. | Gauge |
|
||||
|
||||
Heavy file descriptor (`process_open_fds`) usage (i.e., near the process's file descriptor limit, `process_max_fds`) indicates a potential file descriptor exhaustion issue. If the file descriptors are exhausted, etcd may panic because it cannot create new WAL files.
|
||||
|
||||
[glossary-proposal]: learning/glossary.md#proposal
|
||||
[prometheus]: http://prometheus.io/
|
||||
[prometheus-getting-started]: http://prometheus.io/docs/introduction/getting_started/
|
||||
[prometheus-naming]: http://prometheus.io/docs/practices/naming/
|
||||
[v2-http-metrics]: v2/metrics.md#http-requests
|
@ -1,472 +0,0 @@
|
||||
# Clustering Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Starting an etcd cluster statically requires that each member knows another in the cluster. In a number of cases, the IPs of the cluster members may be unknown ahead of time. In these cases, the etcd cluster can be bootstrapped with the help of a discovery service.
|
||||
|
||||
Once an etcd cluster is up and running, adding or removing members is done via [runtime reconfiguration][runtime-conf]. To better understand the design behind runtime reconfiguration, we suggest reading [the runtime configuration design document][runtime-reconf-design].
|
||||
|
||||
This guide will cover the following mechanisms for bootstrapping an etcd cluster:
|
||||
|
||||
* [Static](#static)
|
||||
* [etcd Discovery](#etcd-discovery)
|
||||
* [DNS Discovery](#dns-discovery)
|
||||
|
||||
Each of the bootstrapping mechanisms will be used to create a three machine etcd cluster with the following details:
|
||||
|
||||
|Name|Address|Hostname|
|
||||
|------|---------|------------------|
|
||||
|infra0|10.0.1.10|infra0.example.com|
|
||||
|infra1|10.0.1.11|infra1.example.com|
|
||||
|infra2|10.0.1.12|infra2.example.com|
|
||||
|
||||
## Static
|
||||
|
||||
As we know the cluster members, their addresses and the size of the cluster before starting, we can use an offline bootstrap configuration by setting the `initial-cluster` flag. Each machine will get either the following environment variables or command line:
|
||||
|
||||
```
|
||||
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380"
|
||||
ETCD_INITIAL_CLUSTER_STATE=new
|
||||
```
|
||||
|
||||
```
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state new
|
||||
```
|
||||
|
||||
Note that the URLs specified in `initial-cluster` are the _advertised peer URLs_, i.e. they should match the value of `initial-advertise-peer-urls` on the respective nodes.
|
||||
|
||||
If spinning up multiple clusters (or creating and destroying a single cluster) with same configuration for testing purpose, it is highly recommended that each cluster is given a unique `initial-cluster-token`. By doing this, etcd can generate unique cluster IDs and member IDs for the clusters even if they otherwise have the exact same configuration. This can protect etcd from cross-cluster-interaction, which might corrupt the clusters.
|
||||
|
||||
etcd listens on [`listen-client-urls`][conf-listen-client] to accept client traffic. etcd member advertises the URLs specified in [`advertise-client-urls`][conf-adv-client] to other members, proxies, clients. Please make sure the `advertise-client-urls` are reachable from intended clients. A common mistake is setting `advertise-client-urls` to localhost or leave it as default if the remote clients should reach etcd.
|
||||
|
||||
On each machine, start etcd with these flags:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state new
|
||||
```
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state new
|
||||
```
|
||||
```
|
||||
$ etcd --name infra2 --initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.12:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state new
|
||||
```
|
||||
|
||||
The command line parameters starting with `--initial-cluster` will be ignored on subsequent runs of etcd. Feel free to remove the environment variables or command line flags after the initial bootstrap process. If the configuration needs changes later (for example, adding or removing members to/from the cluster), see the [runtime configuration][runtime-conf] guide.
|
||||
|
||||
### TLS
|
||||
|
||||
etcd supports encrypted communication through the TLS protocol. TLS channels can be used for encrypted internal cluster communication between peers as well as encrypted client traffic. This section provides examples for setting up a cluster with peer and client TLS. Additional information detailing etcd's TLS support can be found in the [security guide][security-guide].
|
||||
|
||||
#### Self-signed certificates
|
||||
|
||||
A cluster using self-signed certificates both encrypts traffic and authenticates its connections. To start a cluster with self-signed certificates, each cluster member should have a unique key pair (`member.crt`, `member.key`) signed by a shared cluster CA certificate (`ca.crt`) for both peer connections and client connections. Certificates may be generated by following the etcd [TLS setup][tls-setup] example.
|
||||
|
||||
On each machine, etcd would be started with these flags:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls https://10.0.1.10:2380 \
|
||||
--listen-client-urls https://10.0.1.10:2379,https://127.0.0.1:2379 \
|
||||
--advertise-client-urls https://10.0.1.10:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=https://10.0.1.10:2380,infra1=https://10.0.1.11:2380,infra2=https://10.0.1.12:2380 \
|
||||
--initial-cluster-state new \
|
||||
--client-cert-auth --trusted-ca-file=/path/to/ca-client.crt \
|
||||
--cert-file=/path/to/infra0-client.crt --key-file=/path/to/infra0-client.key \
|
||||
--peer-client-cert-auth --peer-trusted-ca-file=ca-peer.crt \
|
||||
--peer-cert-file=/path/to/infra0-peer.crt --peer-key-file=/path/to/infra0-peer.key
|
||||
```
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls https://10.0.1.11:2380 \
|
||||
--listen-peer-urls https://10.0.1.11:2380 \
|
||||
--listen-client-urls https://10.0.1.11:2379,https://127.0.0.1:2379 \
|
||||
--advertise-client-urls https://10.0.1.11:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=https://10.0.1.10:2380,infra1=https://10.0.1.11:2380,infra2=https://10.0.1.12:2380 \
|
||||
--initial-cluster-state new \
|
||||
--client-cert-auth --trusted-ca-file=/path/to/ca-client.crt \
|
||||
--cert-file=/path/to/infra1-client.crt --key-file=/path/to/infra1-client.key \
|
||||
--peer-client-cert-auth --peer-trusted-ca-file=ca-peer.crt \
|
||||
--peer-cert-file=/path/to/infra1-peer.crt --peer-key-file=/path/to/infra1-peer.key
|
||||
```
|
||||
```
|
||||
$ etcd --name infra2 --initial-advertise-peer-urls https://10.0.1.12:2380 \
|
||||
--listen-peer-urls https://10.0.1.12:2380 \
|
||||
--listen-client-urls https://10.0.1.12:2379,https://127.0.0.1:2379 \
|
||||
--advertise-client-urls https://10.0.1.12:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=https://10.0.1.10:2380,infra1=https://10.0.1.11:2380,infra2=https://10.0.1.12:2380 \
|
||||
--initial-cluster-state new \
|
||||
--client-cert-auth --trusted-ca-file=/path/to/ca-client.crt \
|
||||
--cert-file=/path/to/infra2-client.crt --key-file=/path/to/infra2-client.key \
|
||||
--peer-client-cert-auth --peer-trusted-ca-file=ca-peer.crt \
|
||||
--peer-cert-file=/path/to/infra2-peer.crt --peer-key-file=/path/to/infra2-peer.key
|
||||
```
|
||||
|
||||
#### Automatic certificates
|
||||
|
||||
If the cluster needs encrypted communication but does not require authenticated connections, etcd can be configured to automatically generate its keys. On initialization, each member creates its own set of keys based on its advertised IP addresses and hosts.
|
||||
|
||||
On each machine, etcd would be started with these flag:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls https://10.0.1.10:2380 \
|
||||
--listen-peer-urls https://10.0.1.10:2380 \
|
||||
--listen-client-urls https://10.0.1.10:2379,https://127.0.0.1:2379 \
|
||||
--advertise-client-urls https://10.0.1.10:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=https://10.0.1.10:2380,infra1=https://10.0.1.11:2380,infra2=https://10.0.1.12:2380 \
|
||||
--initial-cluster-state new \
|
||||
--auto-tls \
|
||||
--peer-auto-tls
|
||||
```
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls https://10.0.1.11:2380 \
|
||||
--listen-peer-urls https://10.0.1.11:2380 \
|
||||
--listen-client-urls https://10.0.1.11:2379,https://127.0.0.1:2379 \
|
||||
--advertise-client-urls https://10.0.1.11:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=https://10.0.1.10:2380,infra1=https://10.0.1.11:2380,infra2=https://10.0.1.12:2380 \
|
||||
--initial-cluster-state new \
|
||||
--auto-tls \
|
||||
--peer-auto-tls
|
||||
```
|
||||
```
|
||||
$ etcd --name infra2 --initial-advertise-peer-urls https://10.0.1.12:2380 \
|
||||
--listen-peer-urls https://10.0.1.12:2380 \
|
||||
--listen-client-urls https://10.0.1.12:2379,https://127.0.0.1:2379 \
|
||||
--advertise-client-urls https://10.0.1.12:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=https://10.0.1.10:2380,infra1=https://10.0.1.11:2380,infra2=https://10.0.1.12:2380 \
|
||||
--initial-cluster-state new \
|
||||
--auto-tls \
|
||||
--peer-auto-tls
|
||||
```
|
||||
|
||||
### Error cases
|
||||
|
||||
In the following example, we have not included our new host in the list of enumerated nodes. If this is a new cluster, the node _must_ be added to the list of initial cluster members.
|
||||
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-peer-urls https://10.0.1.11:2380 \
|
||||
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380 \
|
||||
--initial-cluster-state new
|
||||
etcd: infra1 not listed in the initial cluster config
|
||||
exit 1
|
||||
```
|
||||
|
||||
In this example, we are attempting to map a node (infra0) on a different address (127.0.0.1:2380) than its enumerated address in the cluster list (10.0.1.10:2380). If this node is to listen on multiple addresses, all addresses _must_ be reflected in the "initial-cluster" configuration directive.
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://127.0.0.1:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state=new
|
||||
etcd: error setting up initial cluster: infra0 has different advertised URLs in the cluster and advertised peer URLs list
|
||||
exit 1
|
||||
```
|
||||
|
||||
If a peer is configured with a different set of configuration arguments and attempts to join this cluster, etcd will report a cluster ID mismatch will exit.
|
||||
|
||||
```
|
||||
$ etcd --name infra3 --initial-advertise-peer-urls http://10.0.1.13:2380 \
|
||||
--listen-peer-urls http://10.0.1.13:2380 \
|
||||
--listen-client-urls http://10.0.1.13:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.13:2379 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra3=http://10.0.1.13:2380 \
|
||||
--initial-cluster-state=new
|
||||
etcd: conflicting cluster ID to the target cluster (c6ab534d07e8fcc4 != bc25ea2a74fb18b0). Exiting.
|
||||
exit 1
|
||||
```
|
||||
|
||||
## Discovery
|
||||
|
||||
In a number of cases, the IPs of the cluster peers may not be known ahead of time. This is common when utilizing cloud providers or when the network uses DHCP. In these cases, rather than specifying a static configuration, use an existing etcd cluster to bootstrap a new one. We call this process "discovery".
|
||||
|
||||
There two methods that can be used for discovery:
|
||||
|
||||
* etcd discovery service
|
||||
* DNS SRV records
|
||||
|
||||
### etcd discovery
|
||||
|
||||
To better understand the design about discovery service protocol, we suggest reading the discovery service protocol [documentation][discovery-proto].
|
||||
|
||||
#### Lifetime of a discovery URL
|
||||
|
||||
A discovery URL identifies a unique etcd cluster. Instead of reusing a discovery URL, always create discovery URLs for new clusters.
|
||||
|
||||
Moreover, discovery URLs should ONLY be used for the initial bootstrapping of a cluster. To change cluster membership after the cluster is already running, see the [runtime reconfiguration][runtime-conf] guide.
|
||||
|
||||
#### Custom etcd discovery service
|
||||
|
||||
Discovery uses an existing cluster to bootstrap itself. If using a private etcd cluster, can create a URL like so:
|
||||
|
||||
```
|
||||
$ curl -X PUT https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/_config/size -d value=3
|
||||
```
|
||||
|
||||
By setting the size key to the URL, a discovery URL is created with an expected cluster size of 3.
|
||||
|
||||
The URL to use in this case will be `https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83` and the etcd members will use the `https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83` directory for registration as they start.
|
||||
|
||||
**Each member must have a different name flag specified. `Hostname` or `machine-id` can be a good choice. Or discovery will fail due to duplicated name.**
|
||||
|
||||
Now we start etcd with those relevant flags for each member:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
```
|
||||
$ etcd --name infra2 --initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.12:2379 \
|
||||
--discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
|
||||
This will cause each member to register itself with the custom etcd discovery service and begin the cluster once all machines have been registered.
|
||||
|
||||
#### Public etcd discovery service
|
||||
|
||||
If no exiting cluster is available, use the public discovery service hosted at `discovery.etcd.io`. To create a private discovery URL using the "new" endpoint, use the command:
|
||||
|
||||
```
|
||||
$ curl https://discovery.etcd.io/new?size=3
|
||||
https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
This will create the cluster with an initial expected size of 3 members. If no size is specified, a default of 3 is used.
|
||||
|
||||
```
|
||||
ETCD_DISCOVERY=https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
```
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
**Each member must have a different name flag specified. `Hostname` or `machine-id` can be a good choice. Or discovery will fail due to duplicated name.**
|
||||
|
||||
Now we start etcd with those relevant flags for each member:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
```
|
||||
$ etcd --name infra2 --initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.12:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
This will cause each member to register itself with the discovery service and begin the cluster once all members have been registered.
|
||||
|
||||
Use the environment variable `ETCD_DISCOVERY_PROXY` to cause etcd to use an HTTP proxy to connect to the discovery service.
|
||||
|
||||
#### Error and warning cases
|
||||
|
||||
##### Discovery server errors
|
||||
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
etcd: error: the cluster doesn’t have a size configuration value in https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de/_config
|
||||
exit 1
|
||||
```
|
||||
|
||||
##### Warnings
|
||||
|
||||
This is a harmless warning indicating the discovery URL will be ignored on this machine.
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
etcdserver: discovery token ignored since a cluster has already been initialized. Valid log found at /var/lib/etcd
|
||||
```
|
||||
|
||||
### DNS discovery
|
||||
|
||||
DNS [SRV records][rfc-srv] can be used as a discovery mechanism.
|
||||
The `-discovery-srv` flag can be used to set the DNS domain name where the discovery SRV records can be found.
|
||||
The following DNS SRV records are looked up in the listed order:
|
||||
|
||||
* _etcd-server-ssl._tcp.example.com
|
||||
* _etcd-server._tcp.example.com
|
||||
|
||||
If `_etcd-server-ssl._tcp.example.com` is found then etcd will attempt the bootstrapping process over TLS.
|
||||
|
||||
To help clients discover the etcd cluster, the following DNS SRV records are looked up in the listed order:
|
||||
|
||||
* _etcd-client._tcp.example.com
|
||||
* _etcd-client-ssl._tcp.example.com
|
||||
|
||||
If `_etcd-client-ssl._tcp.example.com` is found, clients will attempt to communicate with the etcd cluster over SSL/TLS.
|
||||
|
||||
#### Create DNS SRV records
|
||||
|
||||
```
|
||||
$ dig +noall +answer SRV _etcd-server._tcp.example.com
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra0.example.com.
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra1.example.com.
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra2.example.com.
|
||||
```
|
||||
|
||||
```
|
||||
$ dig +noall +answer SRV _etcd-client._tcp.example.com
|
||||
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra0.example.com.
|
||||
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra1.example.com.
|
||||
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra2.example.com.
|
||||
```
|
||||
|
||||
```
|
||||
$ dig +noall +answer infra0.example.com infra1.example.com infra2.example.com
|
||||
infra0.example.com. 300 IN A 10.0.1.10
|
||||
infra1.example.com. 300 IN A 10.0.1.11
|
||||
infra2.example.com. 300 IN A 10.0.1.12
|
||||
```
|
||||
|
||||
#### Bootstrap the etcd cluster using DNS
|
||||
|
||||
etcd cluster members can listen on domain names or IP address, the bootstrap process will resolve DNS A records.
|
||||
|
||||
The resolved address in `--initial-advertise-peer-urls` *must match* one of the resolved addresses in the SRV targets. The etcd member reads the resolved address to find out if it belongs to the cluster defined in the SRV records.
|
||||
|
||||
```
|
||||
$ etcd --name infra0 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://infra0.example.com:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://infra0.example.com:2379 \
|
||||
--listen-client-urls http://infra0.example.com:2379 \
|
||||
--listen-peer-urls http://infra0.example.com:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd --name infra1 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://infra1.example.com:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://infra1.example.com:2379 \
|
||||
--listen-client-urls http://infra1.example.com:2379 \
|
||||
--listen-peer-urls http://infra1.example.com:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd --name infra2 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://infra2.example.com:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://infra2.example.com:2379 \
|
||||
--listen-client-urls http://infra2.example.com:2379 \
|
||||
--listen-peer-urls http://infra2.example.com:2380
|
||||
```
|
||||
|
||||
The cluster can also bootstrap using IP addresses instead of domain names:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--listen-client-urls http://10.0.1.10:2379 \
|
||||
--listen-peer-urls http://10.0.1.10:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd --name infra1 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--listen-client-urls http://10.0.1.11:2379 \
|
||||
--listen-peer-urls http://10.0.1.11:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd --name infra2 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://10.0.1.12:2379 \
|
||||
--listen-client-urls http://10.0.1.12:2379 \
|
||||
--listen-peer-urls http://10.0.1.12:2380
|
||||
```
|
||||
|
||||
### Proxy
|
||||
|
||||
When the `--proxy` flag is set, etcd runs in [proxy mode][proxy]. This proxy mode only supports the etcd v2 API; there are no plans to support the v3 API. Instead, for v3 API support, there will be a new proxy with enhanced features following the etcd 3.0 release.
|
||||
|
||||
To setup an etcd cluster with proxies of v2 API, please read the the [clustering doc in etcd 2.3 release][clustering_etcd2].
|
||||
|
||||
[conf-adv-client]: configuration.md#--advertise-client-urls
|
||||
[conf-listen-client]: configuration.md#--listen-client-urls
|
||||
[discovery-proto]: ../dev-internal/discovery_protocol.md
|
||||
[rfc-srv]: http://www.ietf.org/rfc/rfc2052.txt
|
||||
[runtime-conf]: runtime-configuration.md
|
||||
[runtime-reconf-design]: runtime-reconf-design.md
|
||||
[proxy]: https://github.com/coreos/etcd/blob/release-2.3/Documentation/proxy.md
|
||||
[clustering_etcd2]: https://github.com/coreos/etcd/blob/release-2.3/Documentation/clustering.md
|
||||
[security-guide]: security.md
|
||||
[tls-setup]: /hack/tls-setup
|
@ -1,290 +0,0 @@
|
||||
# Configuration flags
|
||||
|
||||
etcd is configurable through command-line flags and environment variables. Options set on the command line take precedence over those from the environment.
|
||||
|
||||
The format of environment variable for flag `--my-flag` is `ETCD_MY_FLAG`. It applies to all flags.
|
||||
|
||||
The [official etcd ports][iana-ports] are 2379 for client requests and 2380 for peer communication. The etcd ports can be set to accept TLS traffic, non-TLS traffic, or both TLS and non-TLS traffic.
|
||||
|
||||
To start etcd automatically using custom settings at startup in Linux, using a [systemd][systemd-intro] unit is highly recommended.
|
||||
|
||||
## Member flags
|
||||
|
||||
### --name
|
||||
+ Human-readable name for this member.
|
||||
+ default: "default"
|
||||
+ env variable: ETCD_NAME
|
||||
+ This value is referenced as this node's own entries listed in the `--initial-cluster` flag (e.g., `default=http://localhost:2380`). This needs to match the key used in the flag if using [static bootstrapping][build-cluster]. When using discovery, each member must have a unique name. `Hostname` or `machine-id` can be a good choice.
|
||||
|
||||
### --data-dir
|
||||
+ Path to the data directory.
|
||||
+ default: "${name}.etcd"
|
||||
+ env variable: ETCD_DATA_DIR
|
||||
|
||||
### --wal-dir
|
||||
+ Path to the dedicated wal directory. If this flag is set, etcd will write the WAL files to the walDir rather than the dataDir. This allows a dedicated disk to be used, and helps avoid io competition between logging and other IO operations.
|
||||
+ default: ""
|
||||
+ env variable: ETCD_WAL_DIR
|
||||
|
||||
### --snapshot-count
|
||||
+ Number of committed transactions to trigger a snapshot to disk.
|
||||
+ default: "10000"
|
||||
+ env variable: ETCD_SNAPSHOT_COUNT
|
||||
|
||||
### --heartbeat-interval
|
||||
+ Time (in milliseconds) of a heartbeat interval.
|
||||
+ default: "100"
|
||||
+ env variable: ETCD_HEARTBEAT_INTERVAL
|
||||
|
||||
### --election-timeout
|
||||
+ Time (in milliseconds) for an election to timeout. See [Documentation/tuning.md][tuning] for details.
|
||||
+ default: "1000"
|
||||
+ env variable: ETCD_ELECTION_TIMEOUT
|
||||
|
||||
### --listen-peer-urls
|
||||
+ List of URLs to listen on for peer traffic. This flag tells the etcd to accept incoming requests from its peers on the specified scheme://IP:port combinations. Scheme can be either http or https.If 0.0.0.0 is specified as the IP, etcd listens to the given port on all interfaces. If an IP address is given as well as a port, etcd will listen on the given port and interface. Multiple URLs may be used to specify a number of addresses and ports to listen on. The etcd will respond to requests from any of the listed addresses and ports.
|
||||
+ default: "http://localhost:2380"
|
||||
+ env variable: ETCD_LISTEN_PEER_URLS
|
||||
+ example: "http://10.0.0.1:2380"
|
||||
+ invalid example: "http://example.com:2380" (domain name is invalid for binding)
|
||||
|
||||
### --listen-client-urls
|
||||
+ List of URLs to listen on for client traffic. This flag tells the etcd to accept incoming requests from the clients on the specified scheme://IP:port combinations. Scheme can be either http or https. If 0.0.0.0 is specified as the IP, etcd listens to the given port on all interfaces. If an IP address is given as well as a port, etcd will listen on the given port and interface. Multiple URLs may be used to specify a number of addresses and ports to listen on. The etcd will respond to requests from any of the listed addresses and ports.
|
||||
+ default: "http://localhost:2379"
|
||||
+ env variable: ETCD_LISTEN_CLIENT_URLS
|
||||
+ example: "http://10.0.0.1:2379"
|
||||
+ invalid example: "http://example.com:2379" (domain name is invalid for binding)
|
||||
|
||||
### --max-snapshots
|
||||
+ Maximum number of snapshot files to retain (0 is unlimited)
|
||||
+ default: 5
|
||||
+ env variable: ETCD_MAX_SNAPSHOTS
|
||||
+ The default for users on Windows is unlimited, and manual purging down to 5 (or some preference for safety) is recommended.
|
||||
|
||||
### --max-wals
|
||||
+ Maximum number of wal files to retain (0 is unlimited)
|
||||
+ default: 5
|
||||
+ env variable: ETCD_MAX_WALS
|
||||
+ The default for users on Windows is unlimited, and manual purging down to 5 (or some preference for safety) is recommended.
|
||||
|
||||
### --cors
|
||||
+ Comma-separated white list of origins for CORS (cross-origin resource sharing).
|
||||
+ default: none
|
||||
+ env variable: ETCD_CORS
|
||||
|
||||
## Clustering flags
|
||||
|
||||
`--initial` prefix flags are used in bootstrapping ([static bootstrap][build-cluster], [discovery-service bootstrap][discovery] or [runtime reconfiguration][reconfig]) a new member, and ignored when restarting an existing member.
|
||||
|
||||
`--discovery` prefix flags need to be set when using [discovery service][discovery].
|
||||
|
||||
### --initial-advertise-peer-urls
|
||||
|
||||
+ List of this member's peer URLs to advertise to the rest of the cluster. These addresses are used for communicating etcd data around the cluster. At least one must be routable to all cluster members. These URLs can contain domain names.
|
||||
+ default: "http://localhost:2380"
|
||||
+ env variable: ETCD_INITIAL_ADVERTISE_PEER_URLS
|
||||
+ example: "http://example.com:2380, http://10.0.0.1:2380"
|
||||
|
||||
### --initial-cluster
|
||||
+ Initial cluster configuration for bootstrapping.
|
||||
+ default: "default=http://localhost:2380"
|
||||
+ env variable: ETCD_INITIAL_CLUSTER
|
||||
+ The key is the value of the `--name` flag for each node provided. The default uses `default` for the key because this is the default for the `--name` flag.
|
||||
|
||||
### --initial-cluster-state
|
||||
+ Initial cluster state ("new" or "existing"). Set to `new` for all members present during initial static or DNS bootstrapping. If this option is set to `existing`, etcd will attempt to join the existing cluster. If the wrong value is set, etcd will attempt to start but fail safely.
|
||||
+ default: "new"
|
||||
+ env variable: ETCD_INITIAL_CLUSTER_STATE
|
||||
|
||||
[static bootstrap]: clustering.md#static
|
||||
|
||||
### --initial-cluster-token
|
||||
+ Initial cluster token for the etcd cluster during bootstrap.
|
||||
+ default: "etcd-cluster"
|
||||
+ env variable: ETCD_INITIAL_CLUSTER_TOKEN
|
||||
|
||||
### --advertise-client-urls
|
||||
+ List of this member's client URLs to advertise to the rest of the cluster. These URLs can contain domain names.
|
||||
+ default: "http://localhost:2379"
|
||||
+ env variable: ETCD_ADVERTISE_CLIENT_URLS
|
||||
+ example: "http://example.com:2379, http://10.0.0.1:2379"
|
||||
+ Be careful if advertising URLs such as http://localhost:2379 from a cluster member and are using the proxy feature of etcd. This will cause loops, because the proxy will be forwarding requests to itself until its resources (memory, file descriptors) are eventually depleted.
|
||||
|
||||
### --discovery
|
||||
+ Discovery URL used to bootstrap the cluster.
|
||||
+ default: none
|
||||
+ env variable: ETCD_DISCOVERY
|
||||
|
||||
### --discovery-srv
|
||||
+ DNS srv domain used to bootstrap the cluster.
|
||||
+ default: none
|
||||
+ env variable: ETCD_DISCOVERY_SRV
|
||||
|
||||
### --discovery-fallback
|
||||
+ Expected behavior ("exit" or "proxy") when discovery services fails. "proxy" supports v2 API only.
|
||||
+ default: "proxy"
|
||||
+ env variable: ETCD_DISCOVERY_FALLBACK
|
||||
|
||||
### --discovery-proxy
|
||||
+ HTTP proxy to use for traffic to discovery service.
|
||||
+ default: none
|
||||
+ env variable: ETCD_DISCOVERY_PROXY
|
||||
|
||||
### --strict-reconfig-check
|
||||
+ Reject reconfiguration requests that would cause quorum loss.
|
||||
+ default: false
|
||||
+ env variable: ETCD_STRICT_RECONFIG_CHECK
|
||||
|
||||
### --auto-compaction-retention
|
||||
+ Auto compaction retention for mvcc key value store in hour. 0 means disable auto compaction.
|
||||
+ default: 0
|
||||
+ env variable: ETCD_AUTO_COMPACTION_RETENTION
|
||||
|
||||
## Proxy flags
|
||||
|
||||
`--proxy` prefix flags configures etcd to run in [proxy mode][proxy]. "proxy" supports v2 API only.
|
||||
|
||||
### --proxy
|
||||
+ Proxy mode setting ("off", "readonly" or "on").
|
||||
+ default: "off"
|
||||
+ env variable: ETCD_PROXY
|
||||
|
||||
### --proxy-failure-wait
|
||||
+ Time (in milliseconds) an endpoint will be held in a failed state before being reconsidered for proxied requests.
|
||||
+ default: 5000
|
||||
+ env variable: ETCD_PROXY_FAILURE_WAIT
|
||||
|
||||
### --proxy-refresh-interval
|
||||
+ Time (in milliseconds) of the endpoints refresh interval.
|
||||
+ default: 30000
|
||||
+ env variable: ETCD_PROXY_REFRESH_INTERVAL
|
||||
|
||||
### --proxy-dial-timeout
|
||||
+ Time (in milliseconds) for a dial to timeout or 0 to disable the timeout
|
||||
+ default: 1000
|
||||
+ env variable: ETCD_PROXY_DIAL_TIMEOUT
|
||||
|
||||
### --proxy-write-timeout
|
||||
+ Time (in milliseconds) for a write to timeout or 0 to disable the timeout.
|
||||
+ default: 5000
|
||||
+ env variable: ETCD_PROXY_WRITE_TIMEOUT
|
||||
|
||||
### --proxy-read-timeout
|
||||
+ Time (in milliseconds) for a read to timeout or 0 to disable the timeout.
|
||||
+ Don't change this value if using watches because use long polling requests.
|
||||
+ default: 0
|
||||
+ env variable: ETCD_PROXY_READ_TIMEOUT
|
||||
|
||||
## Security flags
|
||||
|
||||
The security flags help to [build a secure etcd cluster][security].
|
||||
|
||||
### --ca-file [DEPRECATED]
|
||||
+ Path to the client server TLS CA file. `--ca-file ca.crt` could be replaced by `--trusted-ca-file ca.crt --client-cert-auth` and etcd will perform the same.
|
||||
+ default: none
|
||||
+ env variable: ETCD_CA_FILE
|
||||
|
||||
### --cert-file
|
||||
+ Path to the client server TLS cert file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_CERT_FILE
|
||||
|
||||
### --key-file
|
||||
+ Path to the client server TLS key file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_KEY_FILE
|
||||
|
||||
### --client-cert-auth
|
||||
+ Enable client cert authentication.
|
||||
+ default: false
|
||||
+ env variable: ETCD_CLIENT_CERT_AUTH
|
||||
|
||||
### --trusted-ca-file
|
||||
+ Path to the client server TLS trusted CA key file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_TRUSTED_CA_FILE
|
||||
|
||||
### --auto-tls
|
||||
+ Client TLS using generated certificates
|
||||
+ default: false
|
||||
+ env variable: ETCD_AUTO_TLS
|
||||
|
||||
### --peer-ca-file [DEPRECATED]
|
||||
+ Path to the peer server TLS CA file. `--peer-ca-file ca.crt` could be replaced by `--peer-trusted-ca-file ca.crt --peer-client-cert-auth` and etcd will perform the same.
|
||||
+ default: none
|
||||
+ env variable: ETCD_PEER_CA_FILE
|
||||
|
||||
### --peer-cert-file
|
||||
+ Path to the peer server TLS cert file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_PEER_CERT_FILE
|
||||
|
||||
### --peer-key-file
|
||||
+ Path to the peer server TLS key file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_PEER_KEY_FILE
|
||||
|
||||
### --peer-client-cert-auth
|
||||
+ Enable peer client cert authentication.
|
||||
+ default: false
|
||||
+ env variable: ETCD_PEER_CLIENT_CERT_AUTH
|
||||
|
||||
### --peer-trusted-ca-file
|
||||
+ Path to the peer server TLS trusted CA file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_PEER_TRUSTED_CA_FILE
|
||||
|
||||
### --peer-auto-tls
|
||||
+ Peer TLS using generated certificates
|
||||
+ default: false
|
||||
+ env variable: ETCD_PEER_AUTO_TLS
|
||||
|
||||
## Logging flags
|
||||
|
||||
### --debug
|
||||
+ Drop the default log level to DEBUG for all subpackages.
|
||||
+ default: false (INFO for all packages)
|
||||
+ env variable: ETCD_DEBUG
|
||||
|
||||
### --log-package-levels
|
||||
+ Set individual etcd subpackages to specific log levels. An example being `etcdserver=WARNING,security=DEBUG`
|
||||
+ default: none (INFO for all packages)
|
||||
+ env variable: ETCD_LOG_PACKAGE_LEVELS
|
||||
|
||||
|
||||
## Unsafe flags
|
||||
|
||||
Please be CAUTIOUS when using unsafe flags because it will break the guarantees given by the consensus protocol.
|
||||
For example, it may panic if other members in the cluster are still alive.
|
||||
Follow the instructions when using these flags.
|
||||
|
||||
### --force-new-cluster
|
||||
+ Force to create a new one-member cluster. It commits configuration changes forcing to remove all existing members in the cluster and add itself. It needs to be set to [restore a backup][restore].
|
||||
+ default: false
|
||||
+ env variable: ETCD_FORCE_NEW_CLUSTER
|
||||
|
||||
## Miscellaneous flags
|
||||
|
||||
### --version
|
||||
+ Print the version and exit.
|
||||
+ default: false
|
||||
|
||||
### --config-file
|
||||
+ Load server configuration from a file.
|
||||
+ default: none
|
||||
|
||||
## Profiling flags
|
||||
|
||||
### --enable-pprof
|
||||
+ Enable runtime profiling data via HTTP server. Address is at client URL + "/debug/pprof"
|
||||
+ default: false
|
||||
|
||||
[build-cluster]: clustering.md#static
|
||||
[reconfig]: runtime-configuration.md
|
||||
[discovery]: clustering.md#discovery
|
||||
[iana-ports]: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=etcd
|
||||
[proxy]: ../v2/proxy.md
|
||||
[restore]: ../v2/admin_guide.md#restoring-a-backup
|
||||
[security]: security.md
|
||||
[systemd-intro]: http://freedesktop.org/wiki/Software/systemd/
|
||||
[tuning]: ../tuning.md#time-parameters
|
@ -1,61 +0,0 @@
|
||||
# Run etcd clusters inside containers
|
||||
|
||||
The following guide shows how to run etcd with rkt and Docker using the [static bootstrap process](clustering.md#static).
|
||||
|
||||
## Docker
|
||||
|
||||
In order to expose the etcd API to clients outside of Docker host, use the host IP address of the container. Please see [`docker inspect`](https://docs.docker.com/engine/reference/commandline/inspect) for more detail on how to get the IP address. Alternatively, specify `--net=host` flag to `docker run` command to skip placing the container inside of a separate network stack.
|
||||
|
||||
```
|
||||
# For each machine
|
||||
ETCD_VERSION=v3.0.0
|
||||
TOKEN=my-etcd-token
|
||||
CLUSTER_STATE=new
|
||||
NAME_1=etcd-node-0
|
||||
NAME_2=etcd-node-1
|
||||
NAME_3=etcd-node-2
|
||||
HOST_1=10.20.30.1
|
||||
HOST_2=10.20.30.2
|
||||
HOST_3=10.20.30.3
|
||||
CLUSTER=${NAME_1}=http://${HOST_1}:2380,${NAME_2}=http://${HOST_2}:2380,${NAME_3}=http://${HOST_3}:2380
|
||||
|
||||
# For node 1
|
||||
THIS_NAME=${NAME_1}
|
||||
THIS_IP=${HOST_1}
|
||||
sudo docker run --net=host --name etcd quay.io/coreos/etcd:${ETCD_VERSION} \
|
||||
/usr/local/bin/etcd \
|
||||
--data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
|
||||
# For node 2
|
||||
THIS_NAME=${NAME_2}
|
||||
THIS_IP=${HOST_2}
|
||||
sudo docker run --net=host --name etcd quay.io/coreos/etcd:${ETCD_VERSION} \
|
||||
/usr/local/bin/etcd \
|
||||
--data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
|
||||
# For node 3
|
||||
THIS_NAME=${NAME_3}
|
||||
THIS_IP=${HOST_3}
|
||||
sudo docker run --net=host --name etcd quay.io/coreos/etcd:${ETCD_VERSION} \
|
||||
/usr/local/bin/etcd \
|
||||
--data-dir=data.etcd --name ${THIS_NAME} \
|
||||
--initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 \
|
||||
--advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 \
|
||||
--initial-cluster ${CLUSTER} \
|
||||
--initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}
|
||||
```
|
||||
|
||||
To run `etcdctl` using API version 3:
|
||||
|
||||
```
|
||||
docker exec etcd /bin/sh -c "export ETCDCTL_API=3 && /usr/local/bin/etcdctl put foo bar"
|
||||
```
|
||||
|
@ -1,44 +0,0 @@
|
||||
# Understand failures
|
||||
|
||||
Failures are common in a large deployment of machines. A machine fails when its hardware or software malfunctions. Multiple machines fail together when there are power failures or network issues. Multiple kinds of failures can also happen at once; it is almost impossible to enumerate all possible failure cases.
|
||||
|
||||
In this section, we catalog kinds of failures and discuss how etcd is designed to tolerate these failures. Most users, if not all, can map a particular failure into one kind of failure. To prepare for rare or [unrecoverable failures][unrecoverable], always [back up][backup] the etcd cluster.
|
||||
|
||||
## Minor followers failure
|
||||
|
||||
When fewer than half of the followers fail, the etcd cluster can still accept requests and make progress without any major disruption. For example, two follower failures will not affect a five member etcd cluster’s operation. However, clients will lose connectivity to the failed members. Client libraries should hide these interruptions from users for read requests by automatically reconnecting to other members. Operators should expect the system load on the other members to increase due to the reconnections.
|
||||
|
||||
## Leader failure
|
||||
|
||||
When a leader fails, the etcd cluster automatically elects a new leader. The election does not happen instantly once the leader fails. It takes about an election timeout to elect a new leader since the failure detection model is timeout based.
|
||||
|
||||
During the leader election the cluster cannot process any writes. Write requests sent during the election are queued for processing until a new leader is elected.
|
||||
|
||||
Writes already sent to the old leader but not yet committed may be lost. The new leader has the power to rewrite any uncommitted entries from the previous leader. From the user perspective, some write requests might time out after a new leader election. However, no committed writes are ever lost.
|
||||
|
||||
The new leader extends timeouts automatically for all leases. This mechanism ensures a lease will not expire before the granted TTL even if it was granted by the old leader.
|
||||
|
||||
## Majority failure
|
||||
|
||||
When the majority members of the cluster fail, the etcd cluster fails and cannot accept more writes.
|
||||
|
||||
The etcd cluster can only recover from a majority failure once the majority of members become available. If a majority of members cannot come back online, then the operator must start [disaster recovery][unrecoverable] to recover the cluster.
|
||||
|
||||
Once a majority of members works, the etcd cluster elects a new leader automatically and returns to a healthy state. The new leader extends timeouts automatically for all leases. This mechanism ensures no lease expires due to server side unavailability.
|
||||
|
||||
## Network partition
|
||||
|
||||
A network partition is similar to a minor followers failure or a leader failure. A network partition divides the etcd cluster into two parts; one with a member majority and the other with a member minority. The majority side becomes the available cluster and the minority side is unavailable; there is no “split-brain” in etcd.
|
||||
|
||||
If the leader is on the majority side, then from the majority point of view the failure is a minority follower failure. If the leader is on the minority side, then it is a leader failure. The leader on the minority side steps down and the majority side elects a new leader.
|
||||
|
||||
Once the network partition clears, the minority side automatically recognizes the leader from the majority side and recovers its state.
|
||||
|
||||
## Failure during bootstrapping
|
||||
|
||||
A cluster bootstrap is only successful if all required members successfully start. If any failure happens during bootstrapping, remove the data directories on all members and re-bootstrap the cluster with a new cluster-token or new discovery token.
|
||||
|
||||
Of course, it is possible to recover a failed bootstrapped cluster like recovering a running cluster. However, it almost always takes more time and resources to recover that cluster than bootstrapping a new one, since there is no data to recover.
|
||||
|
||||
[backup]: maintenance.md#snapshot-backup
|
||||
[unrecoverable]: recovery.md#disaster-recovery
|
@ -1,115 +0,0 @@
|
||||
# Maintenance
|
||||
|
||||
## Overview
|
||||
|
||||
An etcd cluster needs periodic maintenance to remain reliable. Depending on an etcd application's needs, this maintenance can usually be automated and performed without downtime or significantly degraded performance.
|
||||
|
||||
All etcd maintenance manages storage resources consumed by the etcd keyspace. Failure to adequately control the keyspace size is guarded by storage space quotas; if an etcd member runs low on space, a quota will trigger cluster-wide alarms which will put the system into a limited-operation maintenance mode. To avoid running out of space for writes to the keyspace, the etcd keyspace history must be compacted. Storage space itself may be reclaimed by defragmenting etcd members. Finally, periodic snapshot backups of etcd member state makes it possible to recover any unintended logical data loss or corruption caused by operational error.
|
||||
|
||||
## History compaction
|
||||
|
||||
Since etcd keeps an exact history of its keyspace, this history should be periodically compacted to avoid performance degradation and eventual storage space exhaustion. Compacting the keyspace history drops all information about keys superseded prior to a given keyspace revision. The space used by these keys then becomes available for additional writes to the keyspace.
|
||||
|
||||
The keyspace can be compacted automatically with `etcd`'s time windowed history retention policy, or manually with `etcdctl`. The `etcdctl` method provides fine-grained control over the compacting process whereas automatic compacting fits applications that only need key history for some length of time.
|
||||
|
||||
`etcd` can be set to automatically compact the keyspace with the `--auto-compaction` option with a period of hours:
|
||||
|
||||
```sh
|
||||
# keep one hour of history
|
||||
$ etcd --auto-compaction-retention=1
|
||||
```
|
||||
|
||||
An `etcdctl` initiated compaction works as follows:
|
||||
|
||||
```sh
|
||||
# compact up to revision 3
|
||||
$ etcdctl compact 3
|
||||
|
||||
```
|
||||
|
||||
Revisions prior to the compaction revision become inaccessible:
|
||||
|
||||
```sh
|
||||
$ etcdctl get --rev=2 somekey
|
||||
Error: rpc error: code = 11 desc = etcdserver: mvcc: required revision has been compacted
|
||||
```
|
||||
|
||||
## Defragmentation
|
||||
|
||||
After compacting the keyspace, the backend database may exhibit internal fragmentation. Any internal fragmentation is space that is free to use by the backend but still consumes storage space. The process of defragmentation releases this storage space back to the file system. Defragmentation is issued on a per-member so that cluster-wide latency spikes may be avoided.
|
||||
|
||||
Compacting old revisions internally fragments `etcd` by leaving gaps in backend database. Fragmented space is available for use by `etcd` but unavailable to the host filesystem.
|
||||
|
||||
To defragment an etcd member, use the `etcdctl defrag` command:
|
||||
|
||||
```sh
|
||||
$ etcdctl defrag
|
||||
Finished defragmenting etcd member[127.0.0.1:2379]
|
||||
```
|
||||
|
||||
## Space quota
|
||||
|
||||
The space quota in `etcd` ensures the cluster operates in a reliable fashion. Without a space quota, `etcd` may suffer from poor performance if the keyspace grows excessively large, or it may simply run out of storage space, leading to unpredictable cluster behavior. If the keyspace's backend database for any member exceeds the space quota, `etcd` raises a cluster-wide alarm that puts the cluster into a maintenance mode which only accepts key reads and deletes. After freeing enough space in the keyspace, the alarm can be disarmed and the cluster will resume normal operation.
|
||||
|
||||
By default, `etcd` sets a conservative space quota suitable for most applications, but it may be configured on the command line, in bytes:
|
||||
|
||||
```sh
|
||||
# set a very small 16MB quota
|
||||
$ etcd --quota-backend-bytes=16777216
|
||||
```
|
||||
|
||||
The space quota can be triggered with a loop:
|
||||
|
||||
```sh
|
||||
# fill keyspace
|
||||
$ while [ 1 ]; do dd if=/dev/urandom bs=1024 count=1024 | etcdctl put key || break; done
|
||||
...
|
||||
Error: rpc error: code = 8 desc = etcdserver: mvcc: database space exceeded
|
||||
# confirm quota space is exceeded
|
||||
$ etcdctl --write-out=table endpoint status
|
||||
+----------------+------------------+-----------+---------+-----------+-----------+------------+
|
||||
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
|
||||
+----------------+------------------+-----------+---------+-----------+-----------+------------+
|
||||
| 127.0.0.1:2379 | bf9071f4639c75cc | 2.3.0+git | 18 MB | true | 2 | 3332 |
|
||||
+----------------+------------------+-----------+---------+-----------+-----------+------------+
|
||||
# confirm alarm is raised
|
||||
$ etcdctl alarm list
|
||||
memberID:13803658152347727308 alarm:NOSPACE
|
||||
```
|
||||
|
||||
Removing excessive keyspace data will put the cluster back within the quota limits so the alarm can be disarmed:
|
||||
|
||||
```sh
|
||||
# get current revision
|
||||
$ etcdctl --endpoints=:2379 endpoint status
|
||||
[{"Endpoint":"127.0.0.1:2379","Status":{"header":{"cluster_id":8925027824743593106,"member_id":13803658152347727308,"revision":1516,"raft_term":2},"version":"2.3.0+git","dbSize":17973248,"leader":13803658152347727308,"raftIndex":6359,"raftTerm":2}}]
|
||||
# compact away all old revisions
|
||||
$ etdctl compact 1516
|
||||
compacted revision 1516
|
||||
# defragment away excessive space
|
||||
$ etcdctl defrag
|
||||
Finished defragmenting etcd member[127.0.0.1:2379]
|
||||
# disarm alarm
|
||||
$ etcdctl alarm disarm
|
||||
memberID:13803658152347727308 alarm:NOSPACE
|
||||
# test puts are allowed again
|
||||
$ etdctl put newkey 123
|
||||
OK
|
||||
```
|
||||
|
||||
## Snapshot backup
|
||||
|
||||
Snapshotting the `etcd` cluster on a regular basis serves as a durable backup for an etcd keyspace. By taking periodic snapshots of an etcd member's backend database, an `etcd` cluster can be recovered to a point in time with a known good state.
|
||||
|
||||
A snapshot is taken with `etcdctl`:
|
||||
|
||||
```sh
|
||||
$ etcdctl snapshot save backup.db
|
||||
$ etcdctl --write-out=table snapshot status backup.db
|
||||
+----------+----------+------------+------------+
|
||||
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
|
||||
+----------+----------+------------+------------+
|
||||
| fe01cf57 | 10 | 7 | 2.1 MB |
|
||||
+----------+----------+------------+------------+
|
||||
|
||||
```
|
@ -1,74 +0,0 @@
|
||||
# Performance
|
||||
|
||||
## Understanding performance
|
||||
|
||||
etcd provides stable, sustained high performance. Two factors define performance: latency and throughput. Latency is the time taken to complete an operation. Throughput is the total operations completed within some time period. Usually average latency increases as the overall throughput increases when etcd accepts concurrent client requests. In common cloud environments, like a standard `n-4` on Google Compute Engine (GCE) or a comparable machine type on AWS, a three member etcd cluster finishes a request in less than one millisecond under light load, and can complete more than 30,000 requests per second under heavy load.
|
||||
|
||||
etcd uses the Raft consensus algorithm to replicate requests among members and reach agreement. Consensus performance, especially commit latency, is limited by two physical constraints: network IO latency and disk IO latency. The minimum time to finish an etcd request is the network Round Trip Time (RTT) between members, plus the time `fdatasync` requires to commit the data to permanant storage. The RTT within a datacenter may be as long as several hundred microseconds. A typical RTT within the United States is around 50ms, and can be as slow as 400ms between continents. The typical fdatasync latency for a spinning disk is about 10ms. For SSDs, the latency is often lower than 1ms. To increase throughput, etcd batches multiple requests together and submits them to Raft. This batching policy lets etcd attain high throughput despite heavy load.
|
||||
|
||||
There are other sub-systems which impact the overall performance of etcd. Each serialized etcd request must run through etcd’s boltdb-backed MVCC storage engine, which usually takes tens of microseconds to finish. Periodically etcd incrementally snapshots its recently applied requests, merging them back with the previous on-disk snapshot. This process may lead to a latency spike. Although this is usually not a problem on SSDs, it may double the observed latency on HDD. Likewise, inflight compactions can impact etcd’s performance. Fortunately, the impact is often insignificant since the compaction is staggered so it does not compete for resources with regular requests. The RPC system, gRPC, gives etcd a well-defined, extensible API, but it also introduces additional latency, especially for local reads.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Benchmarking etcd performance can be done with the [benchmark](https://github.com/coreos/etcd/tree/master/tools/benchmark) CLI tool included with etcd.
|
||||
|
||||
For some baseline performance numbers, we consider a three member etcd cluster with the following hardware configuration:
|
||||
|
||||
- Google Cloud Compute Engine
|
||||
- 3 machines of 8 vCPUs + 16GB Memory + 50GB SSD
|
||||
- 1 machine(client) of 16 vCPUs + 30GB Memory + 50GB SSD
|
||||
- Ubuntu 15.10
|
||||
- etcd v3 master branch (commit SHA d8f325d), Go 1.6.2
|
||||
|
||||
With this configuration, etcd can approximately write:
|
||||
|
||||
| Number of keys | Key size in bytes | Value size in bytes | Number of connections | Number of clients | Target etcd server | Average write QPS | Average latency per request | Memory |
|
||||
|----------------|-------------------|---------------------|-----------------------|-------------------|--------------------|-------------------|-----------------------------|--------|
|
||||
| 10,000 | 8 | 256 | 1 | 1 | leader only | 525 | 2ms | 35 MB |
|
||||
| 100,000 | 8 | 256 | 100 | 1000 | leader only | 25,000 | 30ms | 35 MB |
|
||||
| 100,000 | 8 | 256 | 100 | 1000 | all members | 33,000 | 25ms | 35 MB |
|
||||
|
||||
Sample commands are:
|
||||
|
||||
```
|
||||
# assuming IP_1 is leader, write requests to the leader
|
||||
benchmark --endpoints={IP_1} --conns=1 --clients=1 \
|
||||
put --key-size=8 --sequential-keys --total=10000 --val-size=256
|
||||
benchmark --endpoints={IP_1} --conns=100 --clients=1000 \
|
||||
put --key-size=8 --sequential-keys --total=100000 --val-size=256
|
||||
|
||||
# write to all members
|
||||
benchmark --endpoints={IP_1},{IP_2},{IP_3} --conns=100 --clients=1000 \
|
||||
put --key-size=8 --sequential-keys --total=100000 --val-size=256
|
||||
```
|
||||
|
||||
Linearizable read requests go through a quorum of cluster members for consensus to fetch the most recent data. Serializable read requests are cheaper than linearizable reads since they are served by any single etcd member, instead of a quorum of members, in exchange for possibly serving stale data. etcd can read:
|
||||
|
||||
| Number of requests | Key size in bytes | Value size in bytes | Number of connections | Number of clients | Consistency | Average latency per request | Average read QPS |
|
||||
|--------------------|-------------------|---------------------|-----------------------|-------------------|-------------|-----------------------------|------------------|
|
||||
| 10,000 | 8 | 256 | 1 | 1 | Linearizable | 2ms | 560 |
|
||||
| 10,000 | 8 | 256 | 1 | 1 | Serializable | 0.4ms | 7,500 |
|
||||
| 100,000 | 8 | 256 | 100 | 1000 | Linearizable | 15ms | 43,000 |
|
||||
| 100,000 | 8 | 256 | 100 | 1000 | Serializable | 9ms | 93,000 |
|
||||
|
||||
Sample commands are:
|
||||
|
||||
```
|
||||
# Linearizable read requests
|
||||
benchmark --endpoints={IP_1},{IP_2},{IP_3} --conns=1 --clients=1 \
|
||||
range YOUR_KEY --consistency=l --total=10000
|
||||
benchmark --endpoints={IP_1},{IP_2},{IP_3} --conns=100 --clients=1000 \
|
||||
range YOUR_KEY --consistency=l --total=100000
|
||||
|
||||
# Serializable read requests for each member and sum up the numbers
|
||||
for endpoint in {IP_1} {IP_2} {IP_3}; do
|
||||
benchmark --endpoints=$endpoint --conns=1 --clients=1 \
|
||||
range YOUR_KEY --consistency=s --total=10000
|
||||
done
|
||||
for endpoint in {IP_1} {IP_2} {IP_3}; do
|
||||
benchmark --endpoints=$endpoint --conns=100 --clients=1000 \
|
||||
range YOUR_KEY --consistency=s --total=100000
|
||||
done
|
||||
```
|
||||
|
||||
We encourage running the benchmark test when setting up an etcd cluster for the first time in a new environment to ensure the cluster achieves adequate performance; cluster latency and throughput can be sensitive to minor environment differences.
|
@ -1,63 +0,0 @@
|
||||
## Disaster recovery
|
||||
|
||||
etcd is designed to withstand machine failures. An etcd cluster automatically recovers from temporary failures (e.g., machine reboots) and tolerates up to *(N-1)/2* permanent failures for a cluster of N members. When a member permanently fails, whether due to hardware failure or disk corruption, it loses access to the cluster. If the cluster permanently loses more than *(N-1)/2* members then it disastrously fails, irrevocably losing quorum. Once quorum is lost, the cluster cannot reach consensus and therefore cannot continue accepting updates.
|
||||
|
||||
To recover from disastrous failure, etcd v3 provides snapshot and restore facilities to recreate the cluster without v3 key data loss. To recover v2 keys, refer to the [v2 admin guide][v2_recover].
|
||||
|
||||
[v2_recover]: ../v2/admin_guide.md#disaster-recovery
|
||||
|
||||
### Snapshotting the keyspace
|
||||
|
||||
Recovering a cluster first needs a snapshot of the keyspace from an etcd member. A snapshot may either be taken from a live member with the `etcdctl snapshot save` command or by copying the `member/snap/db` file from an etcd data directory. For example, the following command snapshots the keyspace served by `$ENDPOINT` to the file `snapshot.db`:
|
||||
|
||||
```sh
|
||||
$ etcdctl --endpoints $ENDPOINT snapshot save snapshot.db
|
||||
```
|
||||
|
||||
### Restoring a cluster
|
||||
|
||||
To restore a cluster, all that is needed is a single snapshot "db" file. A cluster restore with `etcdctl snapshot restore` creates new etcd data directories; all members should restore using the same snapshot. Restoring overwrites some snapshot metadata (specifically, the member ID and cluster ID); the member loses its former identity. This metadata overwrite prevents the new member from inadvertently joining an existing cluster. Therefore in order to start a cluster from a snapshot, the restore must start a new logical cluster.
|
||||
|
||||
Snapshot integrity may be optionally verified at restore time. If the snapshot is taken with `etcdctl snapshot save`, it will have an integrity hash that is checked by `etcdctl snapshot restore`. If the snapshot is copied from the data directory, there is no integrity hash and it will only restore by using `--skip-hash-check`.
|
||||
|
||||
A restore initializes a new member of a new cluster, with a fresh cluster configuration using `etcd`'s cluster configuration flags, but preserves the contents of the etcd keyspace. Continuing from the previous example, the following creates new etcd data directories (`m1.etcd`, `m2.etcd`, `m3.etcd`) for a three member cluster:
|
||||
|
||||
```sh
|
||||
$ etcdctl snapshot restore snapshot.db \
|
||||
--name m1 \
|
||||
--initial-cluster m1=http:/host1:2380,m2=http://host2:2380,m3=http://host3:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-advertise-peer-urls http://host1:2380
|
||||
$ etcdctl snapshot restore snapshot.db \
|
||||
--name m2 \
|
||||
--initial-cluster m1=http:/host1:2380,m2=http://host2:2380,m3=http://host3:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-advertise-peer-urls http://host2:2380
|
||||
$ etcdctl snapshot restore snapshot.db \
|
||||
--name m3 \
|
||||
--initial-cluster m1=http:/host1:2380,m2=http://host2:2380,m3=http://host3:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-advertise-peer-urls http://host3:2380
|
||||
```
|
||||
|
||||
Next, start `etcd` with the new data directories:
|
||||
|
||||
```sh
|
||||
$ etcd \
|
||||
--name m1 \
|
||||
--listen-client-urls http://host1:2379 \
|
||||
--advertise-client-urls http://host1:2379 \
|
||||
--listen-peer-urls http://host1:2380 &
|
||||
$ etcd \
|
||||
--name m2 \
|
||||
--listen-client-urls http://host2:2379 \
|
||||
--advertise-client-urls http://host2:2379 \
|
||||
--listen-peer-urls http://host2:2380 &
|
||||
$ etcd \
|
||||
--name m3 \
|
||||
--listen-client-urls http://host3:2379 \
|
||||
--advertise-client-urls http://host3:2379 \
|
||||
--listen-peer-urls http://host3:2380 &
|
||||
```
|
||||
|
||||
Now the restored etcd cluster should be available and serving the keyspace given by the snapshot.
|
@ -1,185 +0,0 @@
|
||||
# Runtime reconfiguration
|
||||
|
||||
etcd comes with support for incremental runtime reconfiguration, which allows users to update the membership of the cluster at run time.
|
||||
|
||||
Reconfiguration requests can only be processed when the majority of the cluster members are functioning. It is **highly recommended** to always have a cluster size greater than two in production. It is unsafe to remove a member from a two member cluster. The majority of a two member cluster is also two. If there is a failure during the removal process, the cluster might not able to make progress and need to [restart from majority failure][majority failure].
|
||||
|
||||
To better understand the design behind runtime reconfiguration, we suggest reading [the runtime reconfiguration document][runtime-reconf].
|
||||
|
||||
## Reconfiguration use cases
|
||||
|
||||
Let's walk through some common reasons for reconfiguring a cluster. Most of these just involve combinations of adding or removing a member, which are explained below under [Cluster Reconfiguration Operations][cluster-reconf].
|
||||
|
||||
### Cycle or upgrade multiple machines
|
||||
|
||||
If multiple cluster members need to move due to planned maintenance (hardware upgrades, network downtime, etc.), it is recommended to modify members one at a time.
|
||||
|
||||
It is safe to remove the leader, however there is a brief period of downtime while the election process takes place. If the cluster holds more than 50MB, it is recommended to [migrate the member's data directory][member migration].
|
||||
|
||||
### Change the cluster size
|
||||
|
||||
Increasing the cluster size can enhance [failure tolerance][fault tolerance table] and provide better read performance. Since clients can read from any member, increasing the number of members increases the overall read throughput.
|
||||
|
||||
Decreasing the cluster size can improve the write performance of a cluster, with a trade-off of decreased resilience. Writes into the cluster are replicated to a majority of members of the cluster before considered committed. Decreasing the cluster size lowers the majority, and each write is committed more quickly.
|
||||
|
||||
### Replace a failed machine
|
||||
|
||||
If a machine fails due to hardware failure, data directory corruption, or some other fatal situation, it should be replaced as soon as possible. Machines that have failed but haven't been removed adversely affect the quorum and reduce the tolerance for an additional failure.
|
||||
|
||||
To replace the machine, follow the instructions for [removing the member][remove member] from the cluster, and then [add a new member][add member] in its place. If the cluster holds more than 50MB, it is recommended to [migrate the failed member's data directory][member migration] if it is still accessible.
|
||||
|
||||
### Restart cluster from majority failure
|
||||
|
||||
If the majority of the cluster is lost or all of the nodes have changed IP addresses, then manual action is necessary to recover safely.
|
||||
The basic steps in the recovery process include [creating a new cluster using the old data][disaster recovery], forcing a single member to act as the leader, and finally using runtime configuration to [add new members][add member] to this new cluster one at a time.
|
||||
|
||||
## Cluster reconfiguration operations
|
||||
|
||||
Now that we have the use cases in mind, let us lay out the operations involved in each.
|
||||
|
||||
Before making any change, the simple majority (quorum) of etcd members must be available.
|
||||
This is essentially the same requirement as for any other write to etcd.
|
||||
|
||||
All changes to the cluster are done one at a time:
|
||||
|
||||
* To update a single member peerURLs, make an update operation
|
||||
* To replace a single member, make an add then a remove operation
|
||||
* To increase from 3 to 5 members, make two add operations
|
||||
* To decrease from 5 to 3, make two remove operations
|
||||
|
||||
All of these examples will use the `etcdctl` command line tool that ships with etcd.
|
||||
To change membership without `etcdctl`, use the [v2 HTTP members API][member-api] or the [v3 gRPC members API][member-api-grpc].
|
||||
|
||||
### Update a member
|
||||
|
||||
#### Update advertise client URLs
|
||||
|
||||
To update the advertise client URLs of a member, simply restart
|
||||
that member with updated client urls flag (`--advertise-client-urls`) or environment variable
|
||||
(`ETCD_ADVERTISE_CLIENT_URLS`). The restarted member will self publish the updated URLs.
|
||||
A wrongly updated client URL will not affect the health of the etcd cluster.
|
||||
|
||||
#### Update advertise peer URLs
|
||||
|
||||
To update the advertise peer URLs of a member, first update
|
||||
it explicitly via member command and then restart the member. The additional action is required
|
||||
since updating peer URLs changes the cluster wide configuration and can affect the health of the etcd cluster.
|
||||
|
||||
To update the peer URLs, first, we need to find the target member's ID. To list all members with `etcdctl`:
|
||||
|
||||
```sh
|
||||
$ etcdctl member list
|
||||
6e3bd23ae5f1eae0: name=node2 peerURLs=http://localhost:23802 clientURLs=http://127.0.0.1:23792
|
||||
924e2e83e93f2560: name=node3 peerURLs=http://localhost:23803 clientURLs=http://127.0.0.1:23793
|
||||
a8266ecf031671f3: name=node1 peerURLs=http://localhost:23801 clientURLs=http://127.0.0.1:23791
|
||||
```
|
||||
|
||||
In this example let's `update` a8266ecf031671f3 member ID and change its peerURLs value to http://10.0.1.10:2380
|
||||
|
||||
```sh
|
||||
$ etcdctl member update a8266ecf031671f3 http://10.0.1.10:2380
|
||||
Updated member with ID a8266ecf031671f3 in cluster
|
||||
```
|
||||
|
||||
### Remove a member
|
||||
|
||||
Let us say the member ID we want to remove is a8266ecf031671f3.
|
||||
We then use the `remove` command to perform the removal:
|
||||
|
||||
```sh
|
||||
$ etcdctl member remove a8266ecf031671f3
|
||||
Removed member a8266ecf031671f3 from cluster
|
||||
```
|
||||
|
||||
The target member will stop itself at this point and print out the removal in the log:
|
||||
|
||||
```
|
||||
etcd: this member has been permanently removed from the cluster. Exiting.
|
||||
```
|
||||
|
||||
It is safe to remove the leader, however the cluster will be inactive while a new leader is elected. This duration is normally the period of election timeout plus the voting process.
|
||||
|
||||
### Add a new member
|
||||
|
||||
Adding a member is a two step process:
|
||||
|
||||
* Add the new member to the cluster via the [HTTP members API][member-api], the [gRPC members API][member-api-grpc], or the `etcdctl member add` command.
|
||||
* Start the new member with the new cluster configuration, including a list of the updated members (existing members + the new member).
|
||||
|
||||
Using `etcdctl` let's add the new member to the cluster by specifying its [name][conf-name] and [advertised peer URLs][conf-adv-peer]:
|
||||
|
||||
```sh
|
||||
$ etcdctl member add infra3 http://10.0.1.13:2380
|
||||
added member 9bf1b35fc7761a23 to cluster
|
||||
|
||||
ETCD_NAME="infra3"
|
||||
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
|
||||
ETCD_INITIAL_CLUSTER_STATE=existing
|
||||
```
|
||||
|
||||
`etcdctl` has informed the cluster about the new member and printed out the environment variables needed to successfully start it.
|
||||
Now start the new etcd process with the relevant flags for the new member:
|
||||
|
||||
```sh
|
||||
$ export ETCD_NAME="infra3"
|
||||
$ export ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
|
||||
$ export ETCD_INITIAL_CLUSTER_STATE=existing
|
||||
$ etcd --listen-client-urls http://10.0.1.13:2379 --advertise-client-urls http://10.0.1.13:2379 --listen-peer-urls http://10.0.1.13:2380 --initial-advertise-peer-urls http://10.0.1.13:2380 --data-dir %data_dir%
|
||||
```
|
||||
|
||||
The new member will run as a part of the cluster and immediately begin catching up with the rest of the cluster.
|
||||
|
||||
If adding multiple members the best practice is to configure a single member at a time and verify it starts correctly before adding more new members.
|
||||
If adding a new member to a 1-node cluster, the cluster cannot make progress before the new member starts because it needs two members as majority to agree on the consensus. This behavior only happens between the time `etcdctl member add` informs the cluster about the new member and the new member successfully establishing a connection to the existing one.
|
||||
|
||||
#### Error cases when adding members
|
||||
|
||||
In the following case we have not included our new host in the list of enumerated nodes.
|
||||
If this is a new cluster, the node must be added to the list of initial cluster members.
|
||||
|
||||
```sh
|
||||
$ etcd --name infra3 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state existing
|
||||
etcdserver: assign ids error: the member count is unequal
|
||||
exit 1
|
||||
```
|
||||
|
||||
In this case we give a different address (10.0.1.14:2380) to the one that we used to join the cluster (10.0.1.13:2380).
|
||||
|
||||
```sh
|
||||
$ etcd --name infra4 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra4=http://10.0.1.14:2380 \
|
||||
--initial-cluster-state existing
|
||||
etcdserver: assign ids error: unmatched member while checking PeerURLs
|
||||
exit 1
|
||||
```
|
||||
|
||||
When we start etcd using the data directory of a removed member, etcd will exit automatically if it connects to any active member in the cluster:
|
||||
|
||||
```sh
|
||||
$ etcd
|
||||
etcd: this member has been permanently removed from the cluster. Exiting.
|
||||
exit 1
|
||||
```
|
||||
|
||||
### Strict reconfiguration check mode (`-strict-reconfig-check`)
|
||||
|
||||
As described in the above, the best practice of adding new members is to configure a single member at a time and verify it starts correctly before adding more new members. This step by step approach is very important because if newly added members is not configured correctly (for example the peer URLs are incorrect), the cluster can lose quorum. The quorum loss happens since the newly added member are counted in the quorum even if that member is not reachable from other existing members. Also quorum loss might happen if there is a connectivity issue or there are operational issues.
|
||||
|
||||
For avoiding this problem, etcd provides an option `-strict-reconfig-check`. If this option is passed to etcd, etcd rejects reconfiguration requests if the number of started members will be less than a quorum of the reconfigured cluster.
|
||||
|
||||
It is recommended to enable this option. However, it is disabled by default because of keeping compatibility.
|
||||
|
||||
[add member]: #add-a-new-member
|
||||
[cluster-reconf]: #cluster-reconfiguration-operations
|
||||
[conf-adv-peer]: configuration.md#-initial-advertise-peer-urls
|
||||
[conf-name]: configuration.md#-name
|
||||
[disaster recovery]: recovery.md
|
||||
[fault tolerance table]: ../v2/admin_guide.md#fault-tolerance-table
|
||||
[majority failure]: #restart-cluster-from-majority-failure
|
||||
[member-api]: ../v2/members_api.md
|
||||
[member-api-grpc]: ../dev-guide/api_reference_v3.md#service-cluster-etcdserveretcdserverpbrpcproto
|
||||
[member migration]: ../v2/admin_guide.md#member-migration
|
||||
[remove member]: #remove-a-member
|
||||
[runtime-reconf]: runtime-reconf-design.md
|
@ -1,50 +0,0 @@
|
||||
# Design of runtime reconfiguration
|
||||
|
||||
Runtime reconfiguration is one of the hardest and most error prone features in a distributed system, especially in a consensus based system like etcd.
|
||||
|
||||
Read on to learn about the design of etcd's runtime reconfiguration commands and how we tackled these problems.
|
||||
|
||||
## Two phase config changes keep the cluster safe
|
||||
|
||||
In etcd, every runtime reconfiguration has to go through [two phases][add-member] for safety reasons. For example, to add a member, first inform cluster of new configuration and then start the new member.
|
||||
|
||||
Phase 1 - Inform cluster of new configuration
|
||||
|
||||
To add a member into etcd cluster, make an API call to request a new member to be added to the cluster. This is only way to add a new member into an existing cluster. The API call returns when the cluster agrees on the configuration change.
|
||||
|
||||
Phase 2 - Start new member
|
||||
|
||||
To join the etcd member into the existing cluster, specify the correct `initial-cluster` and set `initial-cluster-state` to `existing`. When the member starts, it will contact the existing cluster first and verify the current cluster configuration matches the expected one specified in `initial-cluster`. When the new member successfully starts, the cluster has reached the expected configuration.
|
||||
|
||||
By splitting the process into two discrete phases users are forced to be explicit regarding cluster membership changes. This actually gives users more flexibility and makes things easier to reason about. For example, if there is an attempt to add a new member with the same ID as an existing member in an etcd cluster, the action will fail immediately during phase one without impacting the running cluster. Similar protection is provided to prevent adding new members by mistake. If a new etcd member attempts to join the cluster before the cluster has accepted the configuration change,, it will not be accepted by the cluster.
|
||||
|
||||
Without the explicit workflow around cluster membership etcd would be vulnerable to unexpected cluster membership changes. For example, if etcd is running under an init system such as systemd, etcd would be restarted after being removed via the membership API, and attempt to rejoin the cluster on startup. This cycle would continue every time a member is removed via the API and systemd is set to restart etcd after failing, which is unexpected.
|
||||
|
||||
We expect runtime reconfiguration to be an infrequent operation. We decided to keep it explicit and user-driven to ensure configuration safety and keep the cluster always running smoothly under explicit control.
|
||||
|
||||
## Permanent loss of quorum requires new cluster
|
||||
|
||||
If a cluster permanently loses a majority of its members, a new cluster will need to be started from an old data directory to recover the previous state.
|
||||
|
||||
It is entirely possible to force removing the failed members from the existing cluster to recover. However, we decided not to support this method since it bypasses the normal consensus committing phase, which is unsafe. If the member to remove is not actually dead or force removed through different members in the same cluster, etcd will end up with a diverged cluster with same clusterID. This is very dangerous and hard to debug/fix afterwards.
|
||||
|
||||
With a correct deployment, the possibility of permanent majority lose is very low. But it is a severe enough problem that worth special care. We strongly suggest reading the [disaster recovery documentation][disaster-recovery] and prepare for permanent majority lose before putting etcd into production.
|
||||
|
||||
## Do not use public discovery service for runtime reconfiguration
|
||||
|
||||
The public discovery service should only be used for bootstrapping a cluster. To join member into an existing cluster, use runtime reconfiguration API.
|
||||
|
||||
Discovery service is designed for bootstrapping an etcd cluster in the cloud environment, when the IP addresses of all the members are not known beforehand. After successfully bootstrapping a cluster, the IP addresses of all the members are known. Technically, the discovery service should no longer be needed.
|
||||
|
||||
It seems that using public discovery service is a convenient way to do runtime reconfiguration, after all discovery service already has all the cluster configuration information. However relying on public discovery service brings troubles:
|
||||
|
||||
1. it introduces external dependencies for the entire life-cycle of the cluster, not just bootstrap time. If there is a network issue between the cluster and public discovery service, the cluster will suffer from it.
|
||||
|
||||
2. public discovery service must reflect correct runtime configuration of the cluster during it life-cycle. It has to provide security mechanism to avoid bad actions, and it is hard.
|
||||
|
||||
3. public discovery service has to keep tens of thousands of cluster configurations. Our public discovery service backend is not ready for that workload.
|
||||
|
||||
To have a discovery service that supports runtime reconfiguration, the best choice is to build a private one.
|
||||
|
||||
[add-member]: runtime-configuration.md#add-a-new-member
|
||||
[disaster-recovery]: recovery.md
|
@ -1,224 +0,0 @@
|
||||
# Security model
|
||||
|
||||
etcd supports automatic TLS as well as authentication through client certificates for both clients to server as well as peer (server to server / cluster) communication.
|
||||
|
||||
To get up and running, first have a CA certificate and a signed key pair for one member. It is recommended to create and sign a new key pair for every member in a cluster.
|
||||
|
||||
For convenience, the [cfssl] tool provides an easy interface to certificate generation, and we provide an example using the tool [here][tls-setup]. Alternatively, try this [guide to generating self-signed key pairs][tls-guide].
|
||||
|
||||
## Basic setup
|
||||
|
||||
etcd takes several certificate related configuration options, either through command-line flags or environment variables:
|
||||
|
||||
**Client-to-server communication:**
|
||||
|
||||
`--cert-file=<path>`: Certificate used for SSL/TLS connections **to** etcd. When this option is set, advertise-client-urls can use the HTTPS schema.
|
||||
|
||||
`--key-file=<path>`: Key for the certificate. Must be unencrypted.
|
||||
|
||||
`--client-cert-auth`: When this is set etcd will check all incoming HTTPS requests for a client certificate signed by the trusted CA, requests that don't supply a valid client certificate will fail.
|
||||
|
||||
`--trusted-ca-file=<path>`: Trusted certificate authority.
|
||||
|
||||
`--auto-tls`: Use automatically generated self-signed certificates for TLS connections with clients.
|
||||
|
||||
**Peer (server-to-server / cluster) communication:**
|
||||
|
||||
The peer options work the same way as the client-to-server options:
|
||||
|
||||
`--peer-cert-file=<path>`: Certificate used for SSL/TLS connections between peers. This will be used both for listening on the peer address as well as sending requests to other peers.
|
||||
|
||||
`--peer-key-file=<path>`: Key for the certificate. Must be unencrypted.
|
||||
|
||||
`--peer-client-cert-auth`: When set, etcd will check all incoming peer requests from the cluster for valid client certificates signed by the supplied CA.
|
||||
|
||||
`--peer-trusted-ca-file=<path>`: Trusted certificate authority.
|
||||
|
||||
`--peer-auto-tls`: Use automatically generated self-signed certificates for TLS connections between peers.
|
||||
|
||||
If either a client-to-server or peer certificate is supplied the key must also be set. All of these configuration options are also available through the environment variables, `ETCD_CA_FILE`, `ETCD_PEER_CA_FILE` and so on.
|
||||
|
||||
## Example 1: Client-to-server transport security with HTTPS
|
||||
|
||||
For this, have a CA certificate (`ca.crt`) and signed key pair (`server.crt`, `server.key`) ready.
|
||||
|
||||
Let us configure etcd to provide simple HTTPS transport security step by step:
|
||||
|
||||
```sh
|
||||
$ etcd --name infra0 --data-dir infra0 \
|
||||
--cert-file=/path/to/server.crt --key-file=/path/to/server.key \
|
||||
--advertise-client-urls=https://127.0.0.1:2379 --listen-client-urls=https://127.0.0.1:2379
|
||||
```
|
||||
|
||||
This should start up fine and it will be possible to test the configuration by speaking HTTPS to etcd:
|
||||
|
||||
```sh
|
||||
$ curl --cacert /path/to/ca.crt https://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -v
|
||||
```
|
||||
|
||||
The command should show that the handshake succeed. Since we use self-signed certificates with our own certificate authority, the CA must be passed to curl using the `--cacert` option. Another possibility would be to add the CA certificate to the system's trusted certificates directory (usually in `/etc/pki/tls/certs` or `/etc/ssl/certs`).
|
||||
|
||||
**OSX 10.9+ Users**: curl 7.30.0 on OSX 10.9+ doesn't understand certificates passed in on the command line.
|
||||
Instead, import the dummy ca.crt directly into the keychain or add the `-k` flag to curl to ignore errors.
|
||||
To test without the `-k` flag, run `open ./fixtures/ca/ca.crt` and follow the prompts.
|
||||
Please remove this certificate after testing!
|
||||
If there is a workaround, let us know.
|
||||
|
||||
## Example 2: Client-to-server authentication with HTTPS client certificates
|
||||
|
||||
For now we've given the etcd client the ability to verify the server identity and provide transport security. We can however also use client certificates to prevent unauthorized access to etcd.
|
||||
|
||||
The clients will provide their certificates to the server and the server will check whether the cert is signed by the supplied CA and decide whether to serve the request.
|
||||
|
||||
The same files mentioned in the first example are needed for this, as well as a key pair for the client (`client.crt`, `client.key`) signed by the same certificate authority.
|
||||
|
||||
```sh
|
||||
$ etcd --name infra0 --data-dir infra0 \
|
||||
--client-cert-auth --trusted-ca-file=/path/to/ca.crt --cert-file=/path/to/server.crt --key-file=/path/to/server.key \
|
||||
--advertise-client-urls https://127.0.0.1:2379 --listen-client-urls https://127.0.0.1:2379
|
||||
```
|
||||
|
||||
Now try the same request as above to this server:
|
||||
|
||||
```sh
|
||||
$ curl --cacert /path/to/ca.crt https://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -v
|
||||
```
|
||||
|
||||
The request should be rejected by the server:
|
||||
|
||||
```
|
||||
...
|
||||
routines:SSL3_READ_BYTES:sslv3 alert bad certificate
|
||||
...
|
||||
```
|
||||
|
||||
To make it succeed, we need to give the CA signed client certificate to the server:
|
||||
|
||||
```sh
|
||||
$ curl --cacert /path/to/ca.crt --cert /path/to/client.crt --key /path/to/client.key \
|
||||
-L https://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -v
|
||||
```
|
||||
|
||||
The output should include:
|
||||
|
||||
```
|
||||
...
|
||||
SSLv3, TLS handshake, CERT verify (15):
|
||||
...
|
||||
TLS handshake, Finished (20)
|
||||
```
|
||||
|
||||
And also the response from the server:
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "set",
|
||||
"node": {
|
||||
"createdIndex": 12,
|
||||
"key": "/foo",
|
||||
"modifiedIndex": 12,
|
||||
"value": "bar"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Example 3: Transport security & client certificates in a cluster
|
||||
|
||||
etcd supports the same model as above for **peer communication**, that means the communication between etcd members in a cluster.
|
||||
|
||||
Assuming we have our `ca.crt` and two members with their own keypairs (`member1.crt` & `member1.key`, `member2.crt` & `member2.key`) signed by this CA, we launch etcd as follows:
|
||||
|
||||
|
||||
```sh
|
||||
DISCOVERY_URL=... # from https://discovery.etcd.io/new
|
||||
|
||||
# member1
|
||||
$ etcd --name infra1 --data-dir infra1 \
|
||||
--peer-client-cert-auth --peer-trusted-ca-file=/path/to/ca.crt --peer-cert-file=/path/to/member1.crt --peer-key-file=/path/to/member1.key \
|
||||
--initial-advertise-peer-urls=https://10.0.1.10:2380 --listen-peer-urls=https://10.0.1.10:2380 \
|
||||
--discovery ${DISCOVERY_URL}
|
||||
|
||||
# member2
|
||||
$ etcd --name infra2 --data-dir infra2 \
|
||||
--peer-client-cert-auth --peer-trusted-ca-file=/path/to/ca.crt --peer-cert-file=/path/to/member2.crt --peer-key-file=/path/to/member2.key \
|
||||
--initial-advertise-peer-urls=https://10.0.1.11:2380 --listen-peer-urls=https://10.0.1.11:2380 \
|
||||
--discovery ${DISCOVERY_URL}
|
||||
```
|
||||
|
||||
The etcd members will form a cluster and all communication between members in the cluster will be encrypted and authenticated using the client certificates. The output of etcd will show that the addresses it connects to use HTTPS.
|
||||
|
||||
## Example 4: Automatic self-signed transport security
|
||||
|
||||
For cases where communication encryption, but not authentication, is needed, etcd supports encrypting its messages with automatically generated self-signed certificates. This simplifies deployment because there is no need for managing certificates and keys outside of etcd.
|
||||
|
||||
Configure etcd to use self-signed certificates for client and peer connections with the flags `--auto-tls` and `--peer-auto-tls`:
|
||||
|
||||
```sh
|
||||
DISCOVERY_URL=... # from https://discovery.etcd.io/new
|
||||
|
||||
# member1
|
||||
$ etcd --name infra1 --data-dir infra1 \
|
||||
--auto-tls --peer-auto-tls \
|
||||
--initial-advertise-peer-urls=https://10.0.1.10:2380 --listen-peer-urls=https://10.0.1.10:2380 \
|
||||
--discovery ${DISCOVERY_URL}
|
||||
|
||||
# member2
|
||||
$ etcd --name infra2 --data-dir infra2 \
|
||||
--auto-tls --peer-auto-tls \
|
||||
--initial-advertise-peer-urls=https://10.0.1.11:2380 --listen-peer-urls=https://10.0.1.11:2380 \
|
||||
--discovery ${DISCOVERY_URL}
|
||||
```
|
||||
|
||||
Self-signed certificates do not authenticate identity so curl will return an error:
|
||||
|
||||
```sh
|
||||
curl: (60) SSL certificate problem: Invalid certificate chain
|
||||
```
|
||||
|
||||
To disable certificate chain checking, invoke curl with the `-k` flag:
|
||||
|
||||
```sh
|
||||
$ curl -k https://127.0.0.1:2379/v2/keys/foo -Xput -d value=bar -v
|
||||
```
|
||||
|
||||
## Notes for etcd proxy
|
||||
|
||||
etcd proxy terminates the TLS from its client if the connection is secure, and uses proxy's own key/cert specified in `--peer-key-file` and `--peer-cert-file` to communicate with etcd members.
|
||||
|
||||
The proxy communicates with etcd members through both the `--advertise-client-urls` and `--advertise-peer-urls` of a given member. It forwards client requests to etcd members’ advertised client urls, and it syncs the initial cluster configuration through etcd members’ advertised peer urls.
|
||||
|
||||
When client authentication is enabled for an etcd member, the administrator must ensure that the peer certificate specified in the proxy's `--peer-cert-file` option is valid for that authentication. The proxy's peer certificate must also be valid for peer authentication if peer authentication is enabled.
|
||||
|
||||
## Frequently asked questions
|
||||
|
||||
### I'm seeing a SSLv3 alert handshake failure when using TLS client authentication?
|
||||
|
||||
The `crypto/tls` package of `golang` checks the key usage of the certificate public key before using it.
|
||||
To use the certificate public key to do client auth, we need to add `clientAuth` to `Extended Key Usage` when creating the certificate public key.
|
||||
|
||||
Here is how to do it:
|
||||
|
||||
Add the following section to openssl.cnf:
|
||||
|
||||
```
|
||||
[ ssl_client ]
|
||||
...
|
||||
extendedKeyUsage = clientAuth
|
||||
...
|
||||
```
|
||||
|
||||
When creating the cert be sure to reference it in the `-extensions` flag:
|
||||
|
||||
```
|
||||
$ openssl ca -config openssl.cnf -policy policy_anything -extensions ssl_client -out certs/machine.crt -infiles machine.csr
|
||||
```
|
||||
|
||||
### With peer certificate authentication I receive "certificate is valid for 127.0.0.1, not $MY_IP"
|
||||
Make sure to sign the certificates with a Subject Name the member's public IP address. The `etcd-ca` tool for example provides an `--ip=` option for its `new-cert` command.
|
||||
|
||||
The certificate needs to be signed for the member's FQDN in its Subject Name, use Subject Alternative Names (short IP SANs) to add the IP address. The `etcd-ca` tool provides `--domain=` option for its `new-cert` command, and openssl can make [it][alt-name] too.
|
||||
|
||||
[cfssl]: https://github.com/cloudflare/cfssl
|
||||
[tls-setup]: /hack/tls-setup
|
||||
[tls-guide]: https://github.com/coreos/docs/blob/master/os/generate-self-signed-certificates.md
|
||||
[alt-name]: http://wiki.cacert.org/FAQ/subjectAltName
|
@ -1,14 +0,0 @@
|
||||
## Supported platform
|
||||
|
||||
### 32-bit and other unsupported systems
|
||||
|
||||
etcd has known issues on 32-bit systems due to a bug in the Go runtime. See #[358][358] for more information.
|
||||
|
||||
To avoid inadvertently running a possibly unstable etcd server, `etcd` on unsupported architectures will print
|
||||
a warning message and immediately exit if the environment variable `ETCD_UNSUPPORTED_ARCH` is not set to
|
||||
the target architecture.
|
||||
|
||||
Currently only the amd64 architecture is officially supported by `etcd`.
|
||||
|
||||
[358]: https://github.com/coreos/etcd/issues/358
|
||||
|
@ -1,47 +0,0 @@
|
||||
# Migrate applications from using API v2 to API v3
|
||||
|
||||
The data store v2 is still accessible from the API v2 after upgrading to etcd3. Thus, it will work as before and require no application changes. With etcd 3, applications use the new grpc API v3 to access the mvcc store, which provides more features and improved performance. The mvcc store and the old store v2 are separate and isolated; writes to the store v2 will not affect the mvcc store and, similarly, writes to the mvcc store will not affect the store v2.
|
||||
|
||||
Migrating an application from the API v2 to the API v3 involves two steps: 1) migrate the client library and, 2) migrate the data. If the application can rebuild the data, then migrating the data is unnecessary.
|
||||
|
||||
## Migrate client library
|
||||
|
||||
API v3 is different from API v2, thus application developers need to use a new client library to send requests to etcd API v3. The documentation of the client v3 is available at https://godoc.org/github.com/coreos/etcd/clientv3.
|
||||
|
||||
There are some notable differences between API v2 and API v3:
|
||||
|
||||
- Transaction: In v3, etcd provides multi-key conditional transactions. Applications should use transactions in place of `Compare-And-Swap` operations.
|
||||
|
||||
- Flat key space: There are no directories in API v3, only keys. For example, "/a/b/c/" is a key. Range queries support getting all keys matching a given prefix.
|
||||
|
||||
- Compacted responses: Operations like `Delete` no longer return previous values. To get the deleted value, a transaction can be used to atomically get the key and then delete its value.
|
||||
|
||||
- Leases: A replacement for v2 TTLs; the TTL is bound to a lease and keys attach to the lease. When the TTL expires, the lease is revoked and all attached keys are removed.
|
||||
|
||||
## Migrate data
|
||||
|
||||
Application data can be migrated either offline or online. Offline migration is much simpler than online migration and is recommended.
|
||||
|
||||
### Offline migration
|
||||
|
||||
Offline migration is very simple but requires etcd downtime. If an etcd downtime window spanning from seconds to minutes is acceptable, offline migration is a good choice and is easy to automate.
|
||||
|
||||
First, all members in the etcd cluster must converge to the same state. This can be achieved by stopping all applications that write keys to etcd. Alternatively, if the applications must remain running, configure etcd to listen on a different client URL and restart all etcd members. To check if the states converged, within a few seconds, use the `ETCDCTL_API=3 etcdctl endpoint status` command to confirm that the `raft index` of all members match (or differ by at most 1 due to an internal sync raft command).
|
||||
|
||||
Second, migrate the v2 keys into v3 with the [migrate][migrate_command] (`ETCDCTL_API=3 etcdctl migrate`) command. The migrate command writes keys in the v2 store to a user-provided transformer program and reads back transformed keys. It then writes transformed keys into the mvcc store. This usually takes at most tens of seconds.
|
||||
|
||||
Restart the etcd members and everything should just work.
|
||||
|
||||
### Online migration
|
||||
|
||||
If the application cannot tolerate any downtime, then it must migrate online. The implementation of online migration will vary from application to application but the overall idea is the same.
|
||||
|
||||
First, write application code using the v3 API. The application must support two modes: a migration mode and a normal mode. The application starts in migration mode. When running in migration mode, the application reads keys using the v3 API first, and, if it cannot find the key, it retries with the API v2. In normal mode, the application only reads keys using the v3 API. The application writes keys over the API v3 in both modes. To acknowledge a switch from migration mode to normal mode, the application watches on a switch mode key. When switch key’s value turns to `true`, the application switches over from migration mode to normal mode.
|
||||
|
||||
Second, start a background job to migrate data from the store v2 to the mvcc store by reading keys from the API v2 and writing keys to the API v3.
|
||||
|
||||
After finishing data migration, the background job writes `true` into the switch mode key to notify the application that it may switch modes.
|
||||
|
||||
Online migration can be difficult when the application logic depends on store v2 indexes. Applications will need additional logic to convert mvcc store revisions to store v2 indexes.
|
||||
|
||||
[migrate_command]: ../../etcdctl/README.md#migrate-options
|
@ -1,17 +0,0 @@
|
||||
## Versioning
|
||||
|
||||
### Service versioning
|
||||
|
||||
etcd uses [semantic versioning](http://semver.org)
|
||||
New minor versions may add additional features to the API.
|
||||
|
||||
Get the running etcd cluster version with `etcdctl`:
|
||||
|
||||
```sh
|
||||
ETCDCTL_API=3 etcdctl --endpoints=127.0.0.1:2379 endpoint status
|
||||
```
|
||||
|
||||
### API versioning
|
||||
|
||||
The `v3` API responses should not change after the 3.0.0 release but new features will be added over time.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Members API
|
||||
## Members API
|
||||
|
||||
* [List members](#list-members)
|
||||
* [Add a member](#add-a-member)
|
||||
@ -50,7 +50,7 @@ curl http://10.0.0.10:2379/v2/members
|
||||
|
||||
## Add a member
|
||||
|
||||
Returns an HTTP 201 response code and the representation of added member with a newly generated a memberID when successful. Returns a string describing the failure condition when unsuccessful.
|
||||
Returns an HTTP 201 response code and the representation of added member with a newly generated a memberID when successful. Returns a string describing the failure condition when unsuccessful.
|
||||
|
||||
If the POST body is malformed an HTTP 400 will be returned. If the member exists in the cluster or existed in the cluster at some point in the past an HTTP 409 will be returned. If any of the given peerURLs exists in the cluster an HTTP 409 will be returned. If the cluster fails to process the request within timeout an HTTP 500 will be returned, though the request may be processed later.
|
||||
|
||||
@ -81,7 +81,7 @@ curl http://10.0.0.10:2379/v2/members -XPOST \
|
||||
## Delete a member
|
||||
|
||||
Remove a member from the cluster. The member ID must be a hex-encoded uint64.
|
||||
Returns 204 with empty content when successful. Returns a string describing the failure condition when unsuccessful.
|
||||
Returns 204 with empty content when successful. Returns a string describing the failure condition when unsuccessful.
|
||||
|
||||
If the member does not exist in the cluster an HTTP 500(TODO: fix this) will be returned. If the cluster fails to process the request within timeout an HTTP 500 will be returned, though the request may be processed later.
|
||||
|
||||
@ -103,7 +103,7 @@ Change the peer urls of a given member. The member ID must be a hex-encoded uint
|
||||
|
||||
If the POST body is malformed an HTTP 400 will be returned. If the member does not exist in the cluster an HTTP 404 will be returned. If any of the given peerURLs exists in the cluster an HTTP 409 will be returned. If the cluster fails to process the request within timeout an HTTP 500 will be returned, though the request may be processed later.
|
||||
|
||||
### Request
|
||||
#### Request
|
||||
|
||||
```
|
||||
PUT /v2/members/<id> HTTP/1.1
|
||||
@ -111,10 +111,9 @@ PUT /v2/members/<id> HTTP/1.1
|
||||
{"peerURLs": ["http://10.0.0.10:2380"]}
|
||||
```
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
```sh
|
||||
curl http://10.0.0.10:2379/v2/members/272e204152 -XPUT \
|
||||
-H "Content-Type: application/json" -d '{"peerURLs":["http://10.0.0.10:2380"]}'
|
||||
```
|
||||
|
@ -15,7 +15,7 @@ when asked
|
||||
|
||||
2. Update your repository data with `pkg update`
|
||||
|
||||
3. Install etcd with `pkg install coreos-etcd coreos-etcdctl`
|
||||
3. Install etcd with `pkg install coreosetcd coreosetcdctl`
|
||||
|
||||
4. Verify successful installation with `pkg info | grep etcd` and you should get:
|
||||
|
||||
|
4
Documentation/production-ready.md
Normal file
4
Documentation/production-ready.md
Normal file
@ -0,0 +1,4 @@
|
||||
etcd is being used successfully by many companies in production. It is,
|
||||
however, under active development and systems like etcd are difficult to get
|
||||
correct. If you are comfortable with bleeding-edge software please use etcd and
|
||||
provide us with the feedback and testing young software needs.
|
@ -1,62 +0,0 @@
|
||||
# Production users
|
||||
|
||||
This document tracks people and use cases for etcd in production. By creating a list of production use cases we hope to build a community of advisors that we can reach out to with experience using various etcd applications, operation environments, and cluster sizes. The etcd development team may reach out periodically to check-in on how etcd is working in the field and update this list.
|
||||
|
||||
## discovery.etcd.io
|
||||
|
||||
- *Application*: https://github.com/coreos/discovery.etcd.io
|
||||
- *Launched*: Feb. 2014
|
||||
- *Cluster Size*: 5 members, 5 discovery proxies
|
||||
- *Order of Data Size*: 100s of Megabytes
|
||||
- *Operator*: CoreOS, brandon.philips@coreos.com
|
||||
- *Environment*: AWS
|
||||
- *Backups*: Periodic async to S3
|
||||
|
||||
discovery.etcd.io is the longest continuously running etcd backed service that we know about. It is the basis of automatic cluster bootstrap and was launched in Feb. 2014: https://coreos.com/blog/etcd-0.3.0-released/.
|
||||
|
||||
## OpenTable
|
||||
|
||||
- *Application*: OpenTable internal service discovery and cluster configuration management
|
||||
- *Launched*: May 2014
|
||||
- *Cluster Size*: 3 members each in 6 independent clusters; approximately 50 nodes reading / writing
|
||||
- *Order of Data Size*: 10s of MB
|
||||
- *Operator*: OpenTable, Inc; sschlansker@opentable.com
|
||||
- *Environment*: AWS, VMWare
|
||||
- *Backups*: None, all data can be re-created if necessary.
|
||||
|
||||
## cycoresys.com
|
||||
|
||||
- *Application*: multiple
|
||||
- *Launched*: Jul. 2014
|
||||
- *Cluster Size*: 3 members, _n_ proxies
|
||||
- *Order of Data Size*: 100s of kilobytes
|
||||
- *Operator*: CyCore Systems, Inc, sys@cycoresys.com
|
||||
- *Environment*: Baremetal
|
||||
- *Backups*: Periodic sync to Ceph RadosGW and DigitalOcean VM
|
||||
|
||||
CyCore Systems provides architecture and engineering for computing systems. This cluster provides microservices, virtual machines, databases, storage clusters to a number of clients. It is built on CoreOS machines, with each machine in the cluster running etcd as a peer or proxy.
|
||||
|
||||
## Radius Intelligence
|
||||
|
||||
- *Application*: multiple internal tools, Kubernetes clusters, bootstrappable system configs
|
||||
- *Launched*: June 2015
|
||||
- *Cluster Size*: 2 clusters of 5 and 3 members; approximately a dozen nodes read/write
|
||||
- *Order of Data Size*: 100s of kilobytes
|
||||
- *Operator*: Radius Intelligence; jcderr@radius.com
|
||||
- *Environment*: AWS, CoreOS, Kubernetes
|
||||
- *Backups*: None, all data can be recreated if necessary.
|
||||
|
||||
Radius Intelligence uses Kubernetes running CoreOS to containerize and scale internal toolsets. Examples include running [JetBrains TeamCity][teamcity] and internal AWS security and cost reporting tools. etcd clusters back these clusters as well as provide some basic environment bootstrapping configuration keys.
|
||||
|
||||
## Vonage
|
||||
|
||||
- *Application*: system configuration for microservices, scheduling, locks (future - service discovery)
|
||||
- *Launched*: August 2015
|
||||
- *Cluster Size*: 2 clusters of 5 members in 2 DCs, n local proxies 1-to-1 with microservice, (ssl and SRV look up)
|
||||
- *Order of Data Size*: kilobytes
|
||||
- *Operator*: Vonage [devAdmin][raoofm]
|
||||
- *Environment*: VMWare, AWS
|
||||
- *Backups*: Daily snapshots on VMs. Backups done for upgrades.
|
||||
|
||||
[teamcity]: https://www.jetbrains.com/teamcity/
|
||||
[raoofm]:https://github.com/raoofm
|
36
Documentation/proxy.md
Normal file
36
Documentation/proxy.md
Normal file
@ -0,0 +1,36 @@
|
||||
## Proxy
|
||||
|
||||
etcd can now run as a transparent proxy. Running etcd as a proxy allows for easily discovery of etcd within your infrastructure, since it can run on each machine as a local service. In this mode, etcd acts as a reverse proxy and forwards client requests to an active etcd cluster. The etcd proxy does not participant in the consensus replication of the etcd cluster, thus it neither increases the resilience nor decreases the write performance of the etcd cluster.
|
||||
|
||||
etcd currently supports two proxy modes: `readwrite` and `readonly`. The default mode is `readwrite`, which forwards both read and write requests to the etcd cluster. A `readonly` etcd proxy only forwards read requests to the etcd cluster, and returns `HTTP 501` to all write requests.
|
||||
|
||||
The proxy will shuffle the list of cluster members periodically to avoid sending all connections to a single member.
|
||||
|
||||
The member list used by proxy consists of all client URLs advertised within the cluster, as specified in each members' `-advertise-client-urls` flag. If this flag is set incorrectly, requests sent to the proxy are forwarded to wrong addresses and then fail. The fix for this problem is to restart etcd member with correct `-advertise-client-urls` flag. After client URLs list in proxy is recalculated, which happens every 30 seconds, requests will be forwarded correctly.
|
||||
|
||||
### Using an etcd proxy
|
||||
To start etcd in proxy mode, you need to provide three flags: `proxy`, `listen-client-urls`, and `initial-cluster` (or `discovery`).
|
||||
|
||||
To start a readwrite proxy, set `-proxy on`; To start a readonly proxy, set `-proxy readonly`.
|
||||
|
||||
The proxy will be listening on `listen-client-urls` and forward requests to the etcd cluster discovered from in `initial-cluster` or `discovery` url.
|
||||
|
||||
#### Start an etcd proxy with a static configuration
|
||||
To start a proxy that will connect to a statically defined etcd cluster, specify the `initial-cluster` flag:
|
||||
```
|
||||
etcd -proxy on -listen-client-urls 127.0.0.1:8080 -initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380
|
||||
```
|
||||
|
||||
#### Start an etcd proxy with the discovery service
|
||||
If you bootstrap an etcd cluster using the [discovery service][discovery-service], you can also start the proxy with the same `discovery`.
|
||||
|
||||
To start a proxy using the discovery service, specify the `discovery` flag. The proxy will wait until the etcd cluster defined at the `discovery` url finishes bootstrapping, and then start to forward the requests.
|
||||
|
||||
```
|
||||
etcd -proxy on -listen-client-urls 127.0.0.1:8080 -discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
#### Fallback to proxy mode with discovery service
|
||||
If you bootstrap a etcd cluster using [discovery service][discovery-service] with more than the expected number of etcd members, the extra etcd processes will fall back to being `readwrite` proxies by default. They will forward the requests to the cluster as described above. For example, if you create a discovery url with `size=5`, and start ten etcd processes using that same discovery url, the result will be a cluster with five etcd members and five proxies. Note that this behaviour can be disabled with the `proxy-fallback` flag.
|
||||
|
||||
[discovery-service]: https://github.com/coreos/etcd/blob/master/Documentation/clustering.md#discovery
|
@ -1,45 +0,0 @@
|
||||
# Reporting bugs
|
||||
|
||||
If any part of the etcd project has bugs or documentation mistakes, please let us know by [opening an issue][issue]. We treat bugs and mistakes very seriously and believe no issue is too small. Before creating a bug report, please check that an issue reporting the same problem does not already exist.
|
||||
|
||||
To make the bug report accurate and easy to understand, please try to create bug reports that are:
|
||||
|
||||
- Specific. Include as much details as possible: which version, what environment, what configuration, etc. If the bug is related to running the etcd server, please attach the etcd log (the starting log with etcd configuration is especially important).
|
||||
|
||||
- Reproducible. Include the steps to reproduce the problem. We understand some issues might be hard to reproduce, please includes the steps that might lead to the problem. If possible, please attach the affected etcd data dir and stack strace to the bug report.
|
||||
|
||||
- Isolated. Please try to isolate and reproduce the bug with minimum dependencies. It would significantly slow down the speed to fix a bug if too many dependencies are involved in a bug report. Debugging external systems that rely on etcd is out of scope, but we are happy to provide guidance in the right direction or help with using etcd itself.
|
||||
|
||||
- Unique. Do not duplicate existing bug report.
|
||||
|
||||
- Scoped. One bug per report. Do not follow up with another bug inside one report.
|
||||
|
||||
It may be worthwhile to read [Elika Etemad’s article on filing good bug reports][filing-good-bugs] before creating a bug report.
|
||||
|
||||
We might ask for further information to locate a bug. A duplicated bug report will be closed.
|
||||
|
||||
## Frequently asked questions
|
||||
|
||||
### How to get a stack trace
|
||||
|
||||
``` bash
|
||||
$ kill -QUIT $PID
|
||||
```
|
||||
|
||||
### How to get etcd version
|
||||
|
||||
``` bash
|
||||
$ etcd --version
|
||||
```
|
||||
|
||||
### How to get etcd configuration and log when it runs as systemd service ‘etcd2.service’
|
||||
|
||||
``` bash
|
||||
$ sudo systemctl cat etcd2
|
||||
$ sudo journalctl -u etcd2
|
||||
```
|
||||
|
||||
Due to an upstream systemd bug, journald may miss the last few log lines when its processes exit. If journalctl says etcd stopped without fatal or panic message, try `sudo journalctl -f -t etcd2` to get full log.
|
||||
|
||||
[etcd-issue]: https://github.com/coreos/etcd/issues/new
|
||||
[filing-good-bugs]: http://fantasai.inkedblade.net/style/talks/filing-good-bugs/
|
470
Documentation/rfc/api_security.md
Normal file
470
Documentation/rfc/api_security.md
Normal file
@ -0,0 +1,470 @@
|
||||
# v2 Auth and Security
|
||||
|
||||
## etcd Resources
|
||||
There are three types of resources in etcd
|
||||
|
||||
1. user resources: users and roles in the user store
|
||||
2. key-value resources: key-value pairs in the key-value store
|
||||
3. settings resources: security settings, auth settings, and dynamic etcd cluster settings (election/heartbeat)
|
||||
|
||||
### User Resources
|
||||
|
||||
#### Users
|
||||
A user is an identity to be authenticated. Each user can have multiple roles. The user has a capability on the resource if one of the roles has that capability.
|
||||
|
||||
The special static `root` user has a ROOT role. (Caps for visual aid throughout)
|
||||
|
||||
#### Role
|
||||
Each role has exact one associated Permission List. An permission list exists for each permission on key-value resources. A role with `manage` permission of a key-value resource can grant/revoke capability of that key-value to other roles.
|
||||
|
||||
The special static ROOT role has a full permissions on all key-value resources, the permission to manage user resources and settings resources. Only the ROOT role has the permission to manage user resources and modify settings resources.
|
||||
|
||||
#### Permissions
|
||||
|
||||
There are two types of permissions, `read` and `write`. All management stems from the ROOT user.
|
||||
|
||||
A Permission List is a list of allowed patterns for that particular permission (read or write). Only ALLOW prefixes (incidentally, this is what Amazon S3 does). DENY becomes more complicated and is TBD.
|
||||
|
||||
### Key-Value Resources
|
||||
A key-value resource is a key-value pairs in the store. Given a list of matching patterns, permission for any given key in a request is granted if any of the patterns in the list match.
|
||||
|
||||
The glob match rules are as follows:
|
||||
|
||||
* `*` and `\` are special characters, representing "greedy match" and "escape" respectively.
|
||||
* As a corrolary, `\*` and `\\` are the corresponding literal matches.
|
||||
* All other bytes match exactly their bytes, starting always from the *first byte*. (For regex fans, `re.match` in Python)
|
||||
* Examples:
|
||||
* `/foo` matches only the single key/directory of `/foo`
|
||||
* `/foo*` matches the prefix `/foo`, and all subdirectories/keys
|
||||
* `/foo/*/bar` matches the keys bar in any (recursive) subdirectory of `/foo`.
|
||||
|
||||
### Settings Resources
|
||||
|
||||
Specific settings for the cluster as a whole. This can include adding and removing cluster members, enabling or disabling security, replacing certificates, and any other dynamic configuration by the administrator.
|
||||
|
||||
## v2 Auth
|
||||
|
||||
### Basic Auth
|
||||
We only support [Basic Auth](http://en.wikipedia.org/wiki/Basic_access_authentication) for the first version. Client needs to attach the basic auth to the HTTP Authorization Header.
|
||||
|
||||
### Authorization field for operations
|
||||
Added to requests to /v2/keys, /v2/security
|
||||
Add code 403 Forbidden to the set of responses from the v2 API
|
||||
Authorization: Basic {encoded string}
|
||||
|
||||
### Future Work
|
||||
Other types of auth can be considered for the future (eg, signed certs, public keys) but the `Authorization:` header allows for other such types
|
||||
|
||||
### Things out of Scope for etcd Permissions
|
||||
|
||||
* Pluggable AUTH backends like LDAP (other Authorization tokens generated by LDAP et al may be a possiblity)
|
||||
* Very fine-grained access controls (eg: users modifying keys outside work hours)
|
||||
|
||||
|
||||
|
||||
## API endpoints
|
||||
|
||||
An Error JSON corresponds to:
|
||||
{
|
||||
"name": "ErrErrorName",
|
||||
"description" : "The longer helpful description of the error."
|
||||
}
|
||||
|
||||
#### Users
|
||||
|
||||
The User JSON object is formed as follows:
|
||||
|
||||
```
|
||||
{
|
||||
"user": "userName"
|
||||
"password": "password"
|
||||
"roles": [
|
||||
"role1",
|
||||
"role2"
|
||||
],
|
||||
"grant": [],
|
||||
"revoke": [],
|
||||
"lastModified": "2006-01-02Z04:05:07"
|
||||
}
|
||||
```
|
||||
|
||||
Password is only passed when necessary. Last Modified is set by the server and ignored in all client posts.
|
||||
|
||||
**Get a list of users**
|
||||
|
||||
GET/HEAD /v2/security/user
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
200 Headers:
|
||||
ETag: "<hash of list of users>"
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"users": ["alice", "bob", "eve"]
|
||||
}
|
||||
|
||||
**Get User Details**
|
||||
|
||||
GET/HEAD /v2/security/users/alice
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
ETag: "users/alice:<lastModified>"
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"user" : "alice"
|
||||
"roles" : ["fleet", "etcd"]
|
||||
"lastModified": "2015-02-05Z18:00:00"
|
||||
}
|
||||
|
||||
**Create A User**
|
||||
|
||||
A user can be created with initial roles, if filled in. However, no roles are required; only the username and password fields
|
||||
|
||||
PUT /v2/security/users/charlie
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Put Body:
|
||||
JSON struct, above, matching the appropriate name and with starting roles.
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
409 Conflict (if exists)
|
||||
200 Headers:
|
||||
ETag: "users/charlie:<tzNow>"
|
||||
200 Body: (empty)
|
||||
|
||||
**Remove A User**
|
||||
|
||||
DELETE /v2/security/users/charlie
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
200 Body: (empty)
|
||||
|
||||
**Grant a Role(s) to a User**
|
||||
|
||||
PUT /v2/security/users/charlie/grant
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Put Body:
|
||||
{ "grantRoles" : ["fleet", "etcd"], (extra JSON data for checking OK) }
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
409 Conflict
|
||||
200 Headers:
|
||||
ETag: "users/charlie:<tzNow>"
|
||||
200 Body:
|
||||
JSON user struct, updated. "roles" now contains the grants, and "grantRoles" is empty. If there is an error in the set of roles to be added, for example, a non-existent role, then 409 is returned, with an error JSON stating why.
|
||||
|
||||
**Revoke a Role(s) from a User**
|
||||
|
||||
PUT /v2/security/users/charlie/revoke
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Put Body:
|
||||
{ "revokeRoles" : ["fleet"], (extra JSON data for checking OK) }
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
409 Conflict
|
||||
200 Headers:
|
||||
ETag: "users/charlie:<tzNow>"
|
||||
200 Body:
|
||||
JSON user struct, updated. "roles" now doesn't contain the roles, and "revokeRoles" is empty. If there is an error in the set of roles to be removed, for example, a non-existent role, then 409 is returned, with an error JSON stating why.
|
||||
|
||||
**Change password**
|
||||
|
||||
PUT /v2/security/users/charlie/password
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Put Body:
|
||||
{"user": "charlie", "password": "newCharliePassword"}
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
ETag: "users/charlie:<tzNow>"
|
||||
200 Body:
|
||||
JSON user struct, updated
|
||||
|
||||
#### Roles
|
||||
|
||||
A full role structure may look like this. A Permission List structure is used for the "permissions", "grant", and "revoke" keys.
|
||||
```
|
||||
{
|
||||
"role" : "fleet",
|
||||
"permissions" : {
|
||||
"kv" {
|
||||
"read" : [ "/fleet/" ],
|
||||
"write": [ "/fleet/" ],
|
||||
}
|
||||
}
|
||||
"grant" : {"kv": {...}},
|
||||
"revoke": {"kv": {...}},
|
||||
"members" : ["alice", "bob"],
|
||||
"lastModified": "2015-02-05Z18:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
**Get a list of Roles**
|
||||
|
||||
GET/HEAD /v2/security/roles
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
200 Headers:
|
||||
ETag: "<hash of list of roles>"
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"roles": ["fleet", "etcd", "quay"]
|
||||
}
|
||||
|
||||
**Get Role Details**
|
||||
|
||||
GET/HEAD /v2/security/roles/fleet
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
ETag: "roles/fleet:<lastModified>"
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"role" : "fleet",
|
||||
"read": {
|
||||
"prefixesAllowed": ["/fleet/"],
|
||||
},
|
||||
"write": {
|
||||
"prefixesAllowed": ["/fleet/"],
|
||||
},
|
||||
"members" : ["alice", "bob"] // Reverse map optional?
|
||||
"lastModified": "2015-02-05Z18:00:00"
|
||||
}
|
||||
|
||||
**Create A Role**
|
||||
|
||||
PUT /v2/security/roles/rocket
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Put Body:
|
||||
Initial desired JSON state, complete with prefixes and
|
||||
Possible Status Codes:
|
||||
201 Created
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
409 Conflict (if exists)
|
||||
200 Headers:
|
||||
ETag: "roles/rocket:<tzNow>"
|
||||
200 Body:
|
||||
JSON state of the role
|
||||
|
||||
**Remove A Role**
|
||||
|
||||
DELETE /v2/security/roles/rocket
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
200 Body: (empty)
|
||||
|
||||
**Update a Role’s Permission List for {read,write}ing**
|
||||
|
||||
PUT /v2/security/roles/rocket/update
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Put Body:
|
||||
{
|
||||
"role" : "rocket",
|
||||
"grant": {
|
||||
"kv": {
|
||||
"read" : [ "/rocket/"]
|
||||
}
|
||||
},
|
||||
"revoke": {
|
||||
"kv": {
|
||||
"read" : [ "/fleet/"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
403 Forbidden
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
ETag: "roles/rocket:<tzNow>"
|
||||
200 Body:
|
||||
JSON state of the role, with change containing empty lists and the deltas applied appropriately.
|
||||
|
||||
|
||||
#### TBD Management modification
|
||||
|
||||
|
||||
## Example Workflow
|
||||
|
||||
Let's walk through an example to show two tenants (applications, in our case) using etcd permissions.
|
||||
|
||||
### Enable security
|
||||
|
||||
//TODO(barakmich): Maybe this is dynamic? I don't like the idea of rebooting when we don't have to.
|
||||
|
||||
#### Default ROOT
|
||||
|
||||
etcd always has a ROOT when started with security enabled. The default username is `root`, and the password is `root`.
|
||||
|
||||
// TODO(barakmich): if the enabling is dynamic, perhaps that'd be a good time to set a password? Thus obviating the next section.
|
||||
|
||||
|
||||
### Change root's password
|
||||
|
||||
```
|
||||
PUT /v2/security/users/root/password
|
||||
Headers:
|
||||
Authorization: Basic <root:root>
|
||||
Put Body:
|
||||
{"user" : "root", "password": "betterRootPW!"}
|
||||
```
|
||||
|
||||
//TODO(barakmich): How do you recover the root password? *This* may require a flag and a restart. `--disable-permissions`
|
||||
|
||||
### Create Roles for the Applications
|
||||
|
||||
Create the rocket role fully specified:
|
||||
|
||||
```
|
||||
PUT /v2/security/roles/rocket
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{
|
||||
"role" : "rocket",
|
||||
"permissions" : {
|
||||
"kv": {
|
||||
"read": [
|
||||
"/rocket/"
|
||||
],
|
||||
"write": [
|
||||
"/rocket/"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
But let's make fleet just a basic role for now:
|
||||
|
||||
```
|
||||
PUT /v2/security/roles/fleet
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{
|
||||
"role" : "fleet",
|
||||
}
|
||||
```
|
||||
|
||||
### Optional: Add some permissions to the roles
|
||||
|
||||
Well, we finally figured out where we want fleet to live. Let's fix it.
|
||||
(Note that we avoided this in the rocket case. So this step is optional.)
|
||||
|
||||
|
||||
```
|
||||
PUT /v2/security/roles/fleet/update
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Put Body:
|
||||
{
|
||||
"role" : "fleet",
|
||||
"grant" : {
|
||||
"kv" : {
|
||||
"read": [
|
||||
"/fleet/"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Create Users
|
||||
|
||||
Same as before, let's use rocket all at once and fleet separately
|
||||
|
||||
```
|
||||
PUT /v2/security/users/rocketuser
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{"user" : "rocketuser", "password" : "rocketpw", "roles" : ["rocket"]}
|
||||
```
|
||||
|
||||
```
|
||||
PUT /v2/security/users/fleetuser
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{"user" : "fleetuser", "password" : "fleetpw"}
|
||||
```
|
||||
|
||||
### Optional: Grant Roles to Users
|
||||
|
||||
Likewise, let's explicitly grant fleetuser access.
|
||||
|
||||
```
|
||||
PUT /v2/security/users/fleetuser/grant
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{"user": "fleetuser", "grant": ["fleet"]}
|
||||
```
|
||||
|
||||
#### Start to use fleetuser and rocketuser
|
||||
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
PUT /v2/keys/rocket/RocketData
|
||||
Headers:
|
||||
Authorization: Basic <rocketuser:rocketpw>
|
||||
```
|
||||
|
||||
Reads and writes outside the prefixes granted will fail with a 403 Forbidden.
|
||||
|
@ -1,211 +0,0 @@
|
||||
# Overview
|
||||
|
||||
The etcd v3 API is designed to give users a more efficient and cleaner abstraction compared to etcd v2. There are a number of semantic and protocol changes in this new API. For an overview [see Xiang Li's video](https://youtu.be/J5AioGtEPeQ?t=211).
|
||||
|
||||
To prove out the design of the v3 API the team has also built [a number of example recipes](https://github.com/coreos/etcd/tree/master/contrib/recipes), there is a [video discussing these recipes too](https://www.youtube.com/watch?v=fj-2RY-3yVU&feature=youtu.be&t=590).
|
||||
|
||||
# Design
|
||||
|
||||
1. Flatten binary key-value space
|
||||
|
||||
2. Keep the event history until compaction
|
||||
- access to old version of keys
|
||||
- user controlled history compaction
|
||||
|
||||
3. Support range query
|
||||
- Pagination support with limit argument
|
||||
- Support consistency guarantee across multiple range queries
|
||||
|
||||
4. Replace TTL key with Lease
|
||||
- more efficient/ low cost keep alive
|
||||
- a logical group of TTL keys
|
||||
|
||||
5. Replace CAS/CAD with multi-object Txn
|
||||
- MUCH MORE powerful and flexible
|
||||
|
||||
6. Support efficient watching with multiple ranges
|
||||
|
||||
7. RPC API supports the completed set of APIs.
|
||||
- more efficient than JSON/HTTP
|
||||
- additional txn/lease support
|
||||
|
||||
8. HTTP API supports a subset of APIs.
|
||||
- easy for people to try out etcd
|
||||
- easy for people to write simple etcd application
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
### Request Size Limitation
|
||||
|
||||
The max request size is around 1MB. Since etcd replicates requests in a streaming fashion, a very large
|
||||
request might block other requests for a long time. The use case for etcd is to store small configuration
|
||||
values, so we prevent user from submitting large requests. This also applies to Txn requests. We might loosen
|
||||
the size in the future a little bit or make it configurable.
|
||||
|
||||
## Protobuf Defined API
|
||||
|
||||
[api protobuf][api-protobuf]
|
||||
|
||||
[kv protobuf][kv-protobuf]
|
||||
|
||||
## Examples
|
||||
|
||||
### Put a key (foo=bar)
|
||||
```
|
||||
// A put is always successful
|
||||
Put( PutRequest { key = foo, value = bar } )
|
||||
|
||||
PutResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 1,
|
||||
raft_term = 0x1,
|
||||
}
|
||||
```
|
||||
|
||||
### Get a key (assume we have foo=bar)
|
||||
```
|
||||
Get ( RangeRequest { key = foo } )
|
||||
|
||||
RangeResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 1,
|
||||
raft_term = 0x1,
|
||||
kvs = {
|
||||
{
|
||||
key = foo,
|
||||
value = bar,
|
||||
create_revision = 1,
|
||||
mod_revision = 1,
|
||||
version = 1;
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Range over a key space (assume we have foo0=bar0… foo100=bar100)
|
||||
```
|
||||
Range ( RangeRequest { key = foo, end_key = foo80, limit = 30 } )
|
||||
|
||||
RangeResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 100,
|
||||
raft_term = 0x1,
|
||||
kvs = {
|
||||
{
|
||||
key = foo0,
|
||||
value = bar0,
|
||||
create_revision = 1,
|
||||
mod_revision = 1,
|
||||
version = 1;
|
||||
},
|
||||
...,
|
||||
{
|
||||
key = foo30,
|
||||
value = bar30,
|
||||
create_revision = 30,
|
||||
mod_revision = 30,
|
||||
version = 1;
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Finish a txn (assume we have foo0=bar0, foo1=bar1)
|
||||
```
|
||||
Txn(TxnRequest {
|
||||
// mod_revision of foo0 is equal to 1, mod_revision of foo1 is greater than 1
|
||||
compare = {
|
||||
{compareType = equal, key = foo0, mod_revision = 1},
|
||||
{compareType = greater, key = foo1, mod_revision = 1}}
|
||||
},
|
||||
// if the comparison succeeds, put foo2 = bar2
|
||||
success = {PutRequest { key = foo2, value = success }},
|
||||
// if the comparison fails, put foo2=fail
|
||||
failure = {PutRequest { key = foo2, value = failure }},
|
||||
)
|
||||
|
||||
TxnResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 3,
|
||||
raft_term = 0x1,
|
||||
succeeded = true,
|
||||
responses = {
|
||||
// response of PUT foo2=success
|
||||
{
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 3,
|
||||
raft_term = 0x1,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Watch on a key/range
|
||||
|
||||
```
|
||||
Watch( WatchRequest{
|
||||
key = foo,
|
||||
end_key = fop, // prefix foo
|
||||
start_revision = 20,
|
||||
end_revision = 10000,
|
||||
// server decided notification frequency
|
||||
progress_notification = true,
|
||||
}
|
||||
… // this can be a watch request stream
|
||||
)
|
||||
|
||||
// put (foo0=bar0) event at 3
|
||||
WatchResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 3,
|
||||
raft_term = 0x1,
|
||||
event_type = put,
|
||||
kv = {
|
||||
key = foo0,
|
||||
value = bar0,
|
||||
create_revision = 1,
|
||||
mod_revision = 1,
|
||||
version = 1;
|
||||
},
|
||||
}
|
||||
…
|
||||
|
||||
// a notification at 2000
|
||||
WatchResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 2000,
|
||||
raft_term = 0x1,
|
||||
// nil event as notification
|
||||
}
|
||||
|
||||
…
|
||||
|
||||
// put (foo0=bar3000) event at 3000
|
||||
WatchResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 3000,
|
||||
raft_term = 0x1,
|
||||
event_type = put,
|
||||
kv = {
|
||||
key = foo0,
|
||||
value = bar3000,
|
||||
create_revision = 1,
|
||||
mod_revision = 3000,
|
||||
version = 2;
|
||||
},
|
||||
}
|
||||
…
|
||||
|
||||
```
|
||||
|
||||
[api-protobuf]: https://github.com/coreos/etcd/blob/master/etcdserver/etcdserverpb/rpc.proto
|
||||
[kv-protobuf]: https://github.com/coreos/etcd/blob/master/mvcc/mvccpb/kv.proto
|
@ -1,14 +1,14 @@
|
||||
# Runtime Reconfiguration
|
||||
## Runtime Reconfiguration
|
||||
|
||||
etcd comes with support for incremental runtime reconfiguration, which allows users to update the membership of the cluster at run time.
|
||||
|
||||
Reconfiguration requests can only be processed when the majority of the cluster members are functioning. It is **highly recommended** to always have a cluster size greater than two in production. It is unsafe to remove a member from a two member cluster. The majority of a two member cluster is also two. If there is a failure during the removal process, the cluster might not able to make progress and need to [restart from majority failure][majority failure].
|
||||
Reconfiguration requests can only be processed when the the majority of the cluster members are functioning. It is **highly recommended** to always have a cluster size greater than two in production. It is unsafe to remove a member from a two member cluster. The majority of a two member cluster is also two. If there is a failure during the removal process, the cluster might not able to make progress and need to [restart from majority failure][majority failure].
|
||||
|
||||
To better understand the design behind runtime reconfiguration, we suggest you read [the runtime reconfiguration document][runtime-reconf].
|
||||
[majority failure]: #restart-cluster-from-majority-failure
|
||||
|
||||
## Reconfiguration Use Cases
|
||||
|
||||
Let's walk through some common reasons for reconfiguring a cluster. Most of these just involve combinations of adding or removing a member, which are explained below under [Cluster Reconfiguration Operations][cluster-reconf].
|
||||
Let us walk through some common reasons for reconfiguring a cluster. Most of these just involve combinations of adding or removing a member, which are explained below under [Cluster Reconfiguration Operations](#cluster-reconfiguration-operations).
|
||||
|
||||
### Cycle or Upgrade Multiple Machines
|
||||
|
||||
@ -16,23 +16,33 @@ If you need to move multiple members of your cluster due to planned maintenance
|
||||
|
||||
It is safe to remove the leader, however there is a brief period of downtime while the election process takes place. If your cluster holds more than 50MB, it is recommended to [migrate the member's data directory][member migration].
|
||||
|
||||
[member migration]: admin_guide.md#member-migration
|
||||
|
||||
### Change the Cluster Size
|
||||
|
||||
Increasing the cluster size can enhance [failure tolerance][fault tolerance table] and provide better read performance. Since clients can read from any member, increasing the number of members increases the overall read throughput.
|
||||
|
||||
Decreasing the cluster size can improve the write performance of a cluster, with a trade-off of decreased resilience. Writes into the cluster are replicated to a majority of members of the cluster before considered committed. Decreasing the cluster size lowers the majority, and each write is committed more quickly.
|
||||
|
||||
[fault tolerance table]: admin_guide.md#fault-tolerance-table
|
||||
|
||||
### Replace A Failed Machine
|
||||
|
||||
If a machine fails due to hardware failure, data directory corruption, or some other fatal situation, it should be replaced as soon as possible. Machines that have failed but haven't been removed adversely affect your quorum and reduce the tolerance for an additional failure.
|
||||
|
||||
To replace the machine, follow the instructions for [removing the member][remove member] from the cluster, and then [add a new member][add member] in its place. If your cluster holds more than 50MB, it is recommended to [migrate the failed member's data directory][member migration] if you can still access it.
|
||||
|
||||
[remove member]: #remove-a-member
|
||||
[add member]: #add-a-new-member
|
||||
|
||||
### Restart Cluster from Majority Failure
|
||||
|
||||
If the majority of your cluster is lost or all of your nodes have changed IP addresses, then you need to take manual action in order to recover safely.
|
||||
If the majority of your cluster is lost, then you need to take manual action in order to recover safely.
|
||||
The basic steps in the recovery process include [creating a new cluster using the old data][disaster recovery], forcing a single member to act as the leader, and finally using runtime configuration to [add new members][add member] to this new cluster one at a time.
|
||||
|
||||
[add member]: #add-a-new-member
|
||||
[disaster recovery]: admin_guide.md#disaster-recovery
|
||||
|
||||
## Cluster Reconfiguration Operations
|
||||
|
||||
Now that we have the use cases in mind, let us lay out the operations involved in each.
|
||||
@ -42,51 +52,28 @@ This is essentially the same requirement as for any other write to etcd.
|
||||
|
||||
All changes to the cluster are done one at a time:
|
||||
|
||||
* To update a single member peerURLs you will make an update operation
|
||||
* To replace a single member you will make an add then a remove operation
|
||||
* To increase from 3 to 5 members you will make two add operations
|
||||
* To decrease from 5 to 3 you will make two remove operations
|
||||
To replace a single member you will make an add then a remove operation
|
||||
To increase from 3 to 5 members you will make two add operations
|
||||
To decrease from 5 to 3 you will make two remove operations
|
||||
|
||||
All of these examples will use the `etcdctl` command line tool that ships with etcd.
|
||||
If you want to use the members API directly you can find the documentation [here][member-api].
|
||||
|
||||
### Update a Member
|
||||
|
||||
#### Update advertise client URLs
|
||||
|
||||
If you would like to update the advertise client URLs of a member, you can simply restart
|
||||
that member with updated client urls flag (`--advertise-client-urls`) or environment variable
|
||||
(`ETCD_ADVERTISE_CLIENT_URLS`). The restarted member will self publish the updated URLs.
|
||||
A wrongly updated client URL will not affect the health of the etcd cluster.
|
||||
|
||||
#### Update advertise peer URLs
|
||||
|
||||
If you would like to update the advertise peer URLs of a member, you have to first update
|
||||
it explicitly via member command and then restart the member. The additional action is required
|
||||
since updating peer URLs changes the cluster wide configuration and can affect the health of the etcd cluster.
|
||||
|
||||
To update the peer URLs, first, we need to find the target member's ID. You can list all members with `etcdctl`:
|
||||
|
||||
```sh
|
||||
$ etcdctl member list
|
||||
6e3bd23ae5f1eae0: name=node2 peerURLs=http://localhost:23802 clientURLs=http://127.0.0.1:23792
|
||||
924e2e83e93f2560: name=node3 peerURLs=http://localhost:23803 clientURLs=http://127.0.0.1:23793
|
||||
a8266ecf031671f3: name=node1 peerURLs=http://localhost:23801 clientURLs=http://127.0.0.1:23791
|
||||
```
|
||||
|
||||
In this example let's `update` a8266ecf031671f3 member ID and change its peerURLs value to http://10.0.1.10:2380
|
||||
|
||||
```sh
|
||||
$ etcdctl member update a8266ecf031671f3 http://10.0.1.10:2380
|
||||
Updated member with ID a8266ecf031671f3 in cluster
|
||||
```
|
||||
If you want to use the member API directly you can find the documentation [here](https://github.com/coreos/etcd/blob/master/Documentation/other_apis.md).
|
||||
|
||||
### Remove a Member
|
||||
|
||||
First, we need to find the target member's ID. You can list all members with `etcdctl`:
|
||||
|
||||
```
|
||||
$ etcdctl member list
|
||||
6e3bd23ae5f1eae0: name=node2 peerURLs=http://localhost:7002 clientURLs=http://127.0.0.1:4002
|
||||
924e2e83e93f2560: name=node3 peerURLs=http://localhost:7003 clientURLs=http://127.0.0.1:4003
|
||||
a8266ecf031671f3: name=node1 peerURLs=http://localhost:7001 clientURLs=http://127.0.0.1:4001
|
||||
```
|
||||
|
||||
Let us say the member ID we want to remove is a8266ecf031671f3.
|
||||
We then use the `remove` command to perform the removal:
|
||||
|
||||
```sh
|
||||
```
|
||||
$ etcdctl member remove a8266ecf031671f3
|
||||
Removed member a8266ecf031671f3 from cluster
|
||||
```
|
||||
@ -103,12 +90,12 @@ It is safe to remove the leader, however the cluster will be inactive while a ne
|
||||
|
||||
Adding a member is a two step process:
|
||||
|
||||
* Add the new member to the cluster via the [members API][member-api] or the `etcdctl member add` command.
|
||||
* Add the new member to the cluster via the [members API](https://github.com/coreos/etcd/blob/master/Documentation/other_apis.md#post-v2members) or the `etcdctl member add` command.
|
||||
* Start the new member with the new cluster configuration, including a list of the updated members (existing members + the new member).
|
||||
|
||||
Using `etcdctl` let's add the new member to the cluster by specifying its [name][conf-name] and [advertised peer URLs][conf-adv-peer]:
|
||||
Using `etcdctl` let's add the new member to the cluster by specifing its [name](configuration.md#-name) and [advertised peer URLs](configuration.md#-initial-advertise-peer-urls):
|
||||
|
||||
```sh
|
||||
```
|
||||
$ etcdctl member add infra3 http://10.0.1.13:2380
|
||||
added member 9bf1b35fc7761a23 to cluster
|
||||
|
||||
@ -120,11 +107,11 @@ ETCD_INITIAL_CLUSTER_STATE=existing
|
||||
`etcdctl` has informed the cluster about the new member and printed out the environment variables needed to successfully start it.
|
||||
Now start the new etcd process with the relevant flags for the new member:
|
||||
|
||||
```sh
|
||||
```
|
||||
$ export ETCD_NAME="infra3"
|
||||
$ export ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra3=http://10.0.1.13:2380"
|
||||
$ export ETCD_INITIAL_CLUSTER_STATE=existing
|
||||
$ etcd -listen-client-urls http://10.0.1.13:2379 -advertise-client-urls http://10.0.1.13:2379 -listen-peer-urls http://10.0.1.13:2380 -initial-advertise-peer-urls http://10.0.1.13:2380 -data-dir %data_dir%
|
||||
$ etcd -listen-client-urls http://10.0.1.13:2379 -advertise-client-urls http://10.0.1.13:2379 -listen-peer-urls http://10.0.1.13:2380 -initial-advertise-peer-urls http://10.0.1.13:2380
|
||||
```
|
||||
|
||||
The new member will run as a part of the cluster and immediately begin catching up with the rest of the cluster.
|
||||
@ -132,12 +119,12 @@ The new member will run as a part of the cluster and immediately begin catching
|
||||
If you are adding multiple members the best practice is to configure a single member at a time and verify it starts correctly before adding more new members.
|
||||
If you add a new member to a 1-node cluster, the cluster cannot make progress before the new member starts because it needs two members as majority to agree on the consensus. You will only see this behavior between the time `etcdctl member add` informs the cluster about the new member and the new member successfully establishing a connection to the existing one.
|
||||
|
||||
#### Error Cases When Adding Members
|
||||
#### Error Cases
|
||||
|
||||
In the following case we have not included our new host in the list of enumerated nodes.
|
||||
If this is a new cluster, the node must be added to the list of initial cluster members.
|
||||
|
||||
```sh
|
||||
```
|
||||
$ etcd -name infra3 \
|
||||
-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
-initial-cluster-state existing
|
||||
@ -147,7 +134,7 @@ exit 1
|
||||
|
||||
In this case we give a different address (10.0.1.14:2380) to the one that we used to join the cluster (10.0.1.13:2380).
|
||||
|
||||
```sh
|
||||
```
|
||||
$ etcd -name infra4 \
|
||||
-initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380,infra4=http://10.0.1.14:2380 \
|
||||
-initial-cluster-state existing
|
||||
@ -155,30 +142,10 @@ etcdserver: assign ids error: unmatched member while checking PeerURLs
|
||||
exit 1
|
||||
```
|
||||
|
||||
When we start etcd using the data directory of a removed member, etcd will exit automatically if it connects to any active member in the cluster:
|
||||
When we start etcd using the data directory of a removed member, etcd will exit automatically if it connects to any alive member in the cluster:
|
||||
|
||||
```sh
|
||||
```
|
||||
$ etcd
|
||||
etcd: this member has been permanently removed from the cluster. Exiting.
|
||||
exit 1
|
||||
```
|
||||
|
||||
### Strict Reconfiguration Check Mode (`-strict-reconfig-check`)
|
||||
|
||||
As described in the above, the best practice of adding new members is to configure a single member at a time and verify it starts correctly before adding more new members. This step by step approach is very important because if newly added members is not configured correctly (for example the peer URLs are incorrect), the cluster can lose quorum. The quorum loss happens since the newly added member are counted in the quorum even if that member is not reachable from other existing members. Also quorum loss might happen if there is a connectivity issue or there are operational issues.
|
||||
|
||||
For avoiding this problem, etcd provides an option `-strict-reconfig-check`. If this option is passed to etcd, etcd rejects reconfiguration requests if the number of started members will be less than a quorum of the reconfigured cluster.
|
||||
|
||||
It is recommended to enable this option. However, it is disabled by default because of keeping compatibility.
|
||||
|
||||
[add member]: #add-a-new-member
|
||||
[cluster-reconf]: #cluster-reconfiguration-operations
|
||||
[conf-adv-peer]: configuration.md#-initial-advertise-peer-urls
|
||||
[conf-name]: configuration.md#-name
|
||||
[disaster recovery]: admin_guide.md#disaster-recovery
|
||||
[fault tolerance table]: admin_guide.md#fault-tolerance-table
|
||||
[majority failure]: #restart-cluster-from-majority-failure
|
||||
[member-api]: members_api.md
|
||||
[member migration]: admin_guide.md#member-migration
|
||||
[remove member]: #remove-a-member
|
||||
[runtime-reconf]: runtime-reconf-design.md
|
@ -1,10 +1,12 @@
|
||||
# Security Model
|
||||
# security model
|
||||
|
||||
etcd supports SSL/TLS as well as authentication through client certificates, both for clients to server as well as peer (server to server / cluster) communication.
|
||||
|
||||
To get up and running you first need to have a CA certificate and a signed key pair for one member. It is recommended to create and sign a new key pair for every member in a cluster.
|
||||
|
||||
For convenience, the [cfssl] tool provides an easy interface to certificate generation, and we provide an example using the tool [here][tls-setup]. You can also examine this [alternative guide to generating self-signed key pairs][tls-guide].
|
||||
For convenience the [etcd-ca](https://github.com/coreos/etcd-ca) tool provides an easy interface to certificate generation, alternatively this site provides a good reference on how to generate self-signed key pairs:
|
||||
|
||||
http://www.g-loaded.eu/2005/11/10/be-your-own-ca/
|
||||
|
||||
## Basic setup
|
||||
|
||||
@ -16,9 +18,7 @@ etcd takes several certificate related configuration options, either through com
|
||||
|
||||
`--key-file=<path>`: Key for the certificate. Must be unencrypted.
|
||||
|
||||
`--client-cert-auth`: When this is set etcd will check all incoming HTTPS requests for a client certificate signed by the trusted CA, requests that don't supply a valid client certificate will fail.
|
||||
|
||||
`--trusted-ca-file=<path>`: Trusted certificate authority.
|
||||
`--ca-file=<path>`: When this is set etcd will check all incoming HTTPS requests for a client certificate signed by the supplied CA, requests that don't supply a valid client certificate will fail.
|
||||
|
||||
**Peer (server-to-server / cluster) communication:**
|
||||
|
||||
@ -28,9 +28,7 @@ The peer options work the same way as the client-to-server options:
|
||||
|
||||
`--peer-key-file=<path>`: Key for the certificate. Must be unencrypted.
|
||||
|
||||
`--peer-client-cert-auth`: When set, etcd will check all incoming peer requests from the cluster for valid client certificates signed by the supplied CA.
|
||||
|
||||
`--peer-trusted-ca-file=<path>`: Trusted certificate authority.
|
||||
`--peer-ca-file=<path>`: When set, etcd will check all incoming peer requests from the cluster for valid client certificates signed by the supplied CA.
|
||||
|
||||
If either a client-to-server or peer certificate is supplied the key must also be set. All of these configuration options are also available through the environment variables, `ETCD_CA_FILE`, `ETCD_PEER_CA_FILE` and so on.
|
||||
|
||||
@ -70,10 +68,12 @@ You need the same files mentioned in the first example for this, as well as a ke
|
||||
|
||||
```sh
|
||||
$ etcd -name infra0 -data-dir infra0 \
|
||||
-client-cert-auth -trusted-ca-file=/path/to/ca.crt -cert-file=/path/to/server.crt -key-file=/path/to/server.key \
|
||||
-ca-file=/path/to/ca.crt -cert-file=/path/to/server.crt -key-file=/path/to/server.key \
|
||||
-advertise-client-urls https://127.0.0.1:2379 -listen-client-urls https://127.0.0.1:2379
|
||||
```
|
||||
|
||||
Notice that the addition of the `-ca-file` option automatically enables client certificate checking.
|
||||
|
||||
Now try the same request as above to this server:
|
||||
|
||||
```sh
|
||||
@ -95,7 +95,7 @@ $ curl --cacert /path/to/ca.crt --cert /path/to/client.crt --key /path/to/client
|
||||
-L https://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -v
|
||||
```
|
||||
|
||||
You should be able to see:
|
||||
You should able to see:
|
||||
|
||||
```
|
||||
...
|
||||
@ -130,36 +130,21 @@ DISCOVERY_URL=... # from https://discovery.etcd.io/new
|
||||
|
||||
# member1
|
||||
$ etcd -name infra1 -data-dir infra1 \
|
||||
-peer-client-cert-auth -peer-trusted-ca-file=/path/to/ca.crt -peer-cert-file=/path/to/member1.crt -peer-key-file=/path/to/member1.key \
|
||||
-ca-file=/path/to/ca.crt -cert-file=/path/to/member1.crt -key-file=/path/to/member1.key \
|
||||
-initial-advertise-peer-urls=https://10.0.1.10:2380 -listen-peer-urls=https://10.0.1.10:2380 \
|
||||
-discovery ${DISCOVERY_URL}
|
||||
|
||||
# member2
|
||||
$ etcd -name infra2 -data-dir infra2 \
|
||||
-peer-client-cert-auth -peer-trusted-ca-file=/path/to/ca.crt -peer-cert-file=/path/to/member2.crt -peer-key-file=/path/to/member2.key \
|
||||
-ca-file=/path/to/ca.crt -cert-file=/path/to/member2.crt -key-file=/path/to/member2.key \
|
||||
-initial-advertise-peer-urls=https://10.0.1.11:2380 -listen-peer-urls=https://10.0.1.11:2380 \
|
||||
-discovery ${DISCOVERY_URL}
|
||||
```
|
||||
|
||||
The etcd members will form a cluster and all communication between members in the cluster will be encrypted and authenticated using the client certificates. You will see in the output of etcd that the addresses it connects to use HTTPS.
|
||||
|
||||
## Notes For etcd Proxy
|
||||
|
||||
etcd proxy terminates the TLS from its client if the connection is secure, and uses proxy's own key/cert specified in `--peer-key-file` and `--peer-cert-file` to communicate with etcd members.
|
||||
|
||||
The proxy communicates with etcd members through both the `--advertise-client-urls` and `--advertise-peer-urls` of a given member. It forwards client requests to etcd members’ advertised client urls, and it syncs the initial cluster configuration through etcd members’ advertised peer urls.
|
||||
|
||||
When client authentication is enabled for an etcd member, the administrator must ensure that the peer certificate specified in the proxy's `--peer-cert-file` option is valid for that authentication. The proxy's peer certificate must also be valid for peer authentication if peer authentication is enabled.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### My cluster is not working with peer tls configuration?
|
||||
|
||||
The internal protocol of etcd v2.0.x uses a lot of short-lived HTTP connections.
|
||||
So, when enabling TLS you may need to increase the heartbeat interval and election timeouts to reduce internal cluster connection churn.
|
||||
A reasonable place to start are these values: ` --heartbeat-interval 500 --election-timeout 2500`.
|
||||
These issues are resolved in the etcd v2.1.x series of releases which uses fewer connections.
|
||||
|
||||
### I'm seeing a SSLv3 alert handshake failure when using SSL client authentication?
|
||||
|
||||
The `crypto/tls` package of `golang` checks the key usage of the certificate public key before using it.
|
||||
@ -185,9 +170,4 @@ $ openssl ca -config openssl.cnf -policy policy_anything -extensions ssl_client
|
||||
### With peer certificate authentication I receive "certificate is valid for 127.0.0.1, not $MY_IP"
|
||||
Make sure that you sign your certificates with a Subject Name your member's public IP address. The `etcd-ca` tool for example provides an `--ip=` option for its `new-cert` command.
|
||||
|
||||
If you need your certificate to be signed for your member's FQDN in its Subject Name then you could use Subject Alternative Names (short IP SANs) to add your IP address. The `etcd-ca` tool provides `--domain=` option for its `new-cert` command, and openssl can make [it][alt-name] too.
|
||||
|
||||
[cfssl]: https://github.com/cloudflare/cfssl
|
||||
[tls-setup]: /hack/tls-setup
|
||||
[tls-guide]: https://github.com/coreos/docs/blob/master/os/generate-self-signed-certificates.md
|
||||
[alt-name]: http://wiki.cacert.org/FAQ/subjectAltName
|
||||
If you need your certificate to be signed for your member's FQDN in its Subject Name then you could use Subject Alternative Names (short IP SANs) to add your IP address. The `etcd-ca` tool provides `--domain=` option for its `new-cert` command, and openssl can make [it](http://wiki.cacert.org/FAQ/subjectAltName) too.
|
@ -1,15 +1,16 @@
|
||||
# Tuning
|
||||
## Tuning
|
||||
|
||||
The default settings in etcd should work well for installations on a local network where the average network latency is low. However, when using etcd across multiple data centers or over networks with high latency, the heartbeat interval and election timeout settings may need tuning.
|
||||
The default settings in etcd should work well for installations on a local network where the average network latency is low.
|
||||
However, when using etcd across multiple data centers or over networks with high latency you may need to tweak the heartbeat interval and election timeout settings.
|
||||
|
||||
The network isn't the only source of latency. Each request and response may be impacted by slow disks on both the leader and follower. Each of these timeouts represents the total time from request to successful response from the other machine.
|
||||
|
||||
## Time parameters
|
||||
### Time Parameters
|
||||
|
||||
The underlying distributed consensus protocol relies on two separate time parameters to ensure that nodes can handoff leadership if one stalls or goes offline.
|
||||
The first parameter is called the *Heartbeat Interval*.
|
||||
This is the frequency with which the leader will notify followers that it is still the leader.
|
||||
For best practices, the parameter should be set around round-trip time between members.
|
||||
etcd batches commands together for higher throughput so this heartbeat interval is also a delay for how long it takes for commands to be committed.
|
||||
By default, etcd uses a `100ms` heartbeat interval.
|
||||
|
||||
The second parameter is the *Election Timeout*.
|
||||
@ -17,30 +18,21 @@ This timeout is how long a follower node will go without hearing a heartbeat bef
|
||||
By default, etcd uses a `1000ms` election timeout.
|
||||
|
||||
Adjusting these values is a trade off.
|
||||
The value of heartbeat interval is recommended to be around the maximum of average round-trip time (RTT) between members, normally around 0.5-1.5x the round-trip time.
|
||||
If heartbeat interval is too low, etcd will send unnecessary messages that increase the usage of CPU and network resources.
|
||||
On the other side, a too high heartbeat interval leads to high election timeout. Higher election timeout takes longer time to detect a leader failure.
|
||||
The easiest way to measure round-trip time (RTT) is to use [PING utility][ping].
|
||||
Lowering the heartbeat interval will cause individual commands to be committed faster but it will lower the overall throughput of etcd.
|
||||
If your etcd instances have low utilization then lowering the heartbeat interval can improve your command response time.
|
||||
|
||||
The election timeout should be set based on the heartbeat interval and average round-trip time between members.
|
||||
Election timeouts must be at least 10 times the round-trip time so it can account for variance in the network.
|
||||
For example, if the round-trip time between members is 10ms then the election timeout should be at least 100ms.
|
||||
The election timeout should be set based on the heartbeat interval and your network ping time between nodes.
|
||||
Election timeouts should be at least 10 times your ping time so it can account for variance in your network.
|
||||
For example, if the ping time between your nodes is 10ms then you should have at least a 100ms election timeout.
|
||||
|
||||
The election timeout should be set to at least 5 to 10 times the heartbeat interval to account for variance in leader replication.
|
||||
For a heartbeat interval of 50ms, set the election timeout to at least 250ms - 500ms.
|
||||
You should also set your election timeout to at least 4 to 5 times your heartbeat interval to account for variance in leader replication.
|
||||
For a heartbeat interval of 50ms you should set your election timeout to at least 200ms - 250ms.
|
||||
|
||||
The upper limit of election timeout is 50000ms (50s), which should only be used when deploying a globally-distributed etcd cluster.
|
||||
A reasonable round-trip time for the continental United States is 130ms, and the time between US and Japan is around 350-400ms.
|
||||
If the network has uneven performance or regular packet delays/loss then it is possible that a couple of retries may be necessary to successfully send a packet. So 5s is a safe upper limit of global round-trip time.
|
||||
As the election timeout should be an order of magnitude bigger than broadcast time, in the case of ~5s for a globally distributed cluster, then 50 seconds becomes a reasonable maximum.
|
||||
|
||||
The heartbeat interval and election timeout value should be the same for all members in one cluster. Setting different values for etcd members may disrupt cluster stability.
|
||||
|
||||
The default values can be overridden on the command line:
|
||||
You can override the default values on the command line:
|
||||
|
||||
```sh
|
||||
# Command line arguments:
|
||||
$ etcd --heartbeat-interval=100 --election-timeout=500
|
||||
$ etcd -heartbeat-interval=100 -election-timeout=500
|
||||
|
||||
# Environment variables:
|
||||
$ ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 etcd
|
||||
@ -48,7 +40,7 @@ $ ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 etcd
|
||||
|
||||
The values are specified in milliseconds.
|
||||
|
||||
## Snapshots
|
||||
### Snapshots
|
||||
|
||||
etcd appends all key changes to a log file.
|
||||
This log grows forever and is a complete linear history of every change made to the keys.
|
||||
@ -57,18 +49,26 @@ A complete history works well for lightly used clusters but clusters that are he
|
||||
To avoid having a huge log etcd makes periodic snapshots.
|
||||
These snapshots provide a way for etcd to compact the log by saving the current state of the system and removing old logs.
|
||||
|
||||
### Snapshot tuning
|
||||
### Snapshot Tuning
|
||||
|
||||
Creating snapshots can be expensive so they're only created after a given number of changes to etcd.
|
||||
By default, snapshots will be made after every 10,000 changes.
|
||||
If etcd's memory usage and disk usage are too high, try lowering the snapshot threshold by setting the following on the command line:
|
||||
If etcd's memory usage and disk usage are too high, you can lower the snapshot threshold by setting the following on the command line:
|
||||
|
||||
```sh
|
||||
# Command line arguments:
|
||||
$ etcd --snapshot-count=5000
|
||||
$ etcd -snapshot-count=5000
|
||||
|
||||
# Environment variables:
|
||||
$ ETCD_SNAPSHOT_COUNT=5000 etcd
|
||||
```
|
||||
|
||||
[ping]: https://en.wikipedia.org/wiki/Ping_(networking_utility)
|
||||
You can also disable snapshotting by adding the following to your command line:
|
||||
|
||||
```sh
|
||||
# Command line arguments:
|
||||
$ etcd -snapshot false
|
||||
|
||||
# Environment variables:
|
||||
$ ETCD_SNAPSHOT=false etcd
|
||||
```
|
||||
|
@ -1,119 +0,0 @@
|
||||
## Upgrade etcd from 2.3 to 3.0
|
||||
|
||||
In the general case, upgrading from etcd 2.3 to 3.0 can be a zero-downtime, rolling upgrade:
|
||||
- one by one, stop the etcd v2.3 processes and replace them with etcd v3.0 processes
|
||||
- after running all v3.0 processes, new features in v3.0 are available to the cluster
|
||||
|
||||
Before [starting an upgrade](#upgrade-procedure), read through the rest of this guide to prepare.
|
||||
|
||||
### Upgrade Checklists
|
||||
|
||||
#### Upgrade Requirements
|
||||
|
||||
To upgrade an existing etcd deployment to 3.0, the running cluster must be 2.3 or greater. If it's before 2.3, please upgrade to [2.3](https://github.com/coreos/etcd/releases/tag/v2.3.0) before upgrading to 3.0.
|
||||
|
||||
Also, to ensure a smooth rolling upgrade, the running cluster must be healthy. You can check the health of the cluster by using the `etcdctl cluster-health` command.
|
||||
|
||||
#### Preparation
|
||||
|
||||
Before upgrading etcd, always test the services relying on etcd in a staging environment before deploying the upgrade to the production environment.
|
||||
|
||||
Before beginning, [backup the etcd data directory](admin_guide.md#backing-up-the-datastore). Should something go wrong with the upgrade, it is possible to use this backup to [downgrade](#downgrade) back to existing etcd version.
|
||||
|
||||
#### Mixed Versions
|
||||
|
||||
While upgrading, an etcd cluster supports mixed versions of etcd members, and operates with the protocol of the lowest common version. The cluster is only considered upgraded once all of its members are upgraded to version 3.0. Internally, etcd members negotiate with each other to determine the overall cluster version, which controls the reported version and the supported features.
|
||||
|
||||
#### Limitations
|
||||
|
||||
It might take up to 2 minutes for the newly upgraded member to catch up with the existing cluster when the total data size is larger than 50MB. Check the size of a recent snapshot to estimate the total data size. In other words, it is safest to wait for 2 minutes between upgrading each member.
|
||||
|
||||
For a much larger total data size, 100MB or more , this one-time process might take even more time. Administrators of very large etcd clusters of this magnitude can feel free to contact the [etcd team][etcd-contact] before upgrading, and we’ll be happy to provide advice on the procedure.
|
||||
|
||||
#### Downgrade
|
||||
|
||||
If all members have been upgraded to v3.0, the cluster will be upgraded to v3.0, and downgrade from this completed state is **not possible**. If any single member is still v2.3, however, the cluster and its operations remains “v2.3”, and it is possible from this mixed cluster state to return to using a v2.3 etcd binary on all members.
|
||||
|
||||
Please [backup the data directory](admin_guide.md#backing-up-the-datastore) of all etcd members to make downgrading the cluster possible even after it has been completely upgraded.
|
||||
|
||||
### Upgrade Procedure
|
||||
|
||||
This example details the upgrade of a three-member v2.3 ectd cluster running on a local machine.
|
||||
|
||||
#### 1. Check upgrade requirements.
|
||||
|
||||
Is the the cluster healthy and running v.2.3.x?
|
||||
|
||||
```
|
||||
$ etcdctl cluster-health
|
||||
member 6e3bd23ae5f1eae0 is healthy: got healthy result from http://localhost:22379
|
||||
member 924e2e83e93f2560 is healthy: got healthy result from http://localhost:32379
|
||||
member 8211f1d0f64f3269 is healthy: got healthy result from http://localhost:12379
|
||||
cluster is healthy
|
||||
|
||||
$ curl http://localhost:2379/version
|
||||
{"etcdserver":"2.3.x","etcdcluster":"2.3.0"}
|
||||
```
|
||||
|
||||
#### 2. Stop the existing etcd process
|
||||
|
||||
When each etcd process is stopped, expected errors will be logged by other cluster members. This is normal since a cluster member connection has been (temporarily) broken:
|
||||
|
||||
```
|
||||
2016-06-27 15:21:48.624124 E | rafthttp: failed to dial 8211f1d0f64f3269 on stream Message (dial tcp 127.0.0.1:12380: getsockopt: connection refused)
|
||||
2016-06-27 15:21:48.624175 I | rafthttp: the connection with 8211f1d0f64f3269 became inactive
|
||||
```
|
||||
|
||||
It’s a good idea at this point to [backup the etcd data directory](https://github.com/coreos/etcd/blob/master/Documentation/v2/admin_guide.md#backing-up-the-datastore) to provide a downgrade path should any problems occur:
|
||||
|
||||
```
|
||||
$ etcdctl backup \
|
||||
--data-dir /var/lib/etcd \
|
||||
--backup-dir /tmp/etcd_backup
|
||||
```
|
||||
|
||||
#### 3. Drop-in etcd v3.0 binary and start the new etcd process
|
||||
|
||||
The new v3.0 etcd will publish its information to the cluster:
|
||||
|
||||
```
|
||||
09:58:25.938673 I | etcdserver: published {Name:infra1 ClientURLs:[http://localhost:12379]} to cluster 524400597fb1d5f6
|
||||
```
|
||||
|
||||
Verify that each member, and then the entire cluster, becomes healthy with the new v3.0 etcd binary:
|
||||
|
||||
```
|
||||
$ etcdctl cluster-health
|
||||
member 6e3bd23ae5f1eae0 is healthy: got healthy result from http://localhost:22379
|
||||
member 924e2e83e93f2560 is healthy: got healthy result from http://localhost:32379
|
||||
member 8211f1d0f64f3269 is healthy: got healthy result from http://localhost:12379
|
||||
cluster is healthy
|
||||
```
|
||||
|
||||
|
||||
Upgraded members will log warnings like the following until the entire cluster is upgraded. This is expected and will cease after all etcd cluster members are upgraded to v3.0:
|
||||
|
||||
```
|
||||
2016-06-27 15:22:05.679644 W | etcdserver: the local etcd version 2.3.7 is not up-to-date
|
||||
2016-06-27 15:22:05.679660 W | etcdserver: member 8211f1d0f64f3269 has a higher version 3.0.0
|
||||
```
|
||||
|
||||
#### 4. Repeat step 2 to step 3 for all other members
|
||||
|
||||
#### 5. Finish
|
||||
|
||||
When all members are upgraded, the cluster will report upgrading to 3.0 successfully:
|
||||
|
||||
```
|
||||
2016-06-27 15:22:19.873751 N | membership: updated the cluster version from 2.3 to 3.0
|
||||
2016-06-27 15:22:19.914574 I | api: enabled capabilities for version 3.0.0
|
||||
```
|
||||
|
||||
```
|
||||
$ ETCDCTL_API=3 etcdctl endpoint health
|
||||
127.0.0.1:12379 is healthy: successfully committed proposal: took = 18.440155ms
|
||||
127.0.0.1:32379 is healthy: successfully committed proposal: took = 13.651368ms
|
||||
127.0.0.1:22379 is healthy: successfully committed proposal: took = 18.513301ms
|
||||
```
|
||||
|
||||
[etcd-contact]: https://groups.google.com/forum/#!forum/etcd-dev
|
@ -1,31 +0,0 @@
|
||||
# Snapshot Migration
|
||||
|
||||
You can migrate a snapshot of your data from a v0.4.9+ cluster into a new etcd 2.2 cluster using a snapshot migration. After snapshot migration, the etcd indexes of your data will change. Many etcd applications rely on these indexes to behave correctly. This operation should only be done while all etcd applications are stopped.
|
||||
|
||||
To get started get the newest data snapshot from the 0.4.9+ cluster:
|
||||
|
||||
```
|
||||
curl http://cluster.example.com:4001/v2/migration/snapshot > backup.snap
|
||||
```
|
||||
|
||||
Now, import the snapshot into your new cluster:
|
||||
|
||||
```
|
||||
etcdctl --endpoint new_cluster.example.com import --snap backup.snap
|
||||
```
|
||||
|
||||
If you have a large amount of data, you can specify more concurrent works to copy data in parallel by using `-c` flag.
|
||||
If you have hidden keys to copy, you can use `--hidden` flag to specify. For example fleet uses `/_coreos.com/fleet` so to import those keys use `--hidden /_coreos.com`.
|
||||
|
||||
And the data will quickly copy into the new cluster:
|
||||
|
||||
```
|
||||
entering dir: /
|
||||
entering dir: /foo
|
||||
entering dir: /foo/bar
|
||||
copying key: /foo/bar/1 1
|
||||
entering dir: /
|
||||
entering dir: /foo2
|
||||
entering dir: /foo2/bar2
|
||||
copying key: /foo2/bar2/2 2
|
||||
```
|
@ -1,165 +0,0 @@
|
||||
# etcd2
|
||||
|
||||
[](https://goreportcard.com/report/github.com/coreos/etcd)
|
||||
[](https://travis-ci.org/coreos/etcd)
|
||||
[](https://semaphoreci.com/coreos/etcd)
|
||||
[](https://quay.io/repository/coreos/etcd-git)
|
||||
|
||||
**Note**: The `master` branch may be in an *unstable or even broken state* during development. Please use [releases][github-release] instead of the `master` branch in order to get stable binaries.
|
||||
|
||||

|
||||
|
||||
etcd is a distributed, consistent key-value store for shared configuration and service discovery, with a focus on being:
|
||||
|
||||
* *Simple*: curl'able user-facing API (HTTP+JSON)
|
||||
* *Secure*: optional SSL client cert authentication
|
||||
* *Fast*: benchmarked 1000s of writes/s per instance
|
||||
* *Reliable*: properly distributed using Raft
|
||||
|
||||
etcd is written in Go and uses the [Raft][raft] consensus algorithm to manage a highly-available replicated log.
|
||||
|
||||
etcd is used [in production by many companies](./production-users.md), and the development team stands behind it in critical deployment scenarios, where etcd is frequently teamed with applications such as [Kubernetes][k8s], [fleet][fleet], [locksmith][locksmith], [vulcand][vulcand], and many others.
|
||||
|
||||
See [etcdctl][etcdctl] for a simple command line client.
|
||||
Or feel free to just use `curl`, as in the examples below.
|
||||
|
||||
[raft]: https://raft.github.io/
|
||||
[k8s]: http://kubernetes.io/
|
||||
[fleet]: https://github.com/coreos/fleet
|
||||
[locksmith]: https://github.com/coreos/locksmith
|
||||
[vulcand]: https://github.com/vulcand/vulcand
|
||||
[etcdctl]: https://github.com/coreos/etcd/tree/master/etcdctl
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Getting etcd
|
||||
|
||||
The easiest way to get etcd is to use one of the pre-built release binaries which are available for OSX, Linux, Windows, AppC (ACI), and Docker. Instructions for using these binaries are on the [GitHub releases page][github-release].
|
||||
|
||||
For those wanting to try the very latest version, you can build the latest version of etcd from the `master` branch.
|
||||
You will first need [*Go*](https://golang.org/) installed on your machine (version 1.5+ is required).
|
||||
All development occurs on `master`, including new features and bug fixes.
|
||||
Bug fixes are first targeted at `master` and subsequently ported to release branches, as described in the [branch management][branch-management] guide.
|
||||
|
||||
[github-release]: https://github.com/coreos/etcd/releases/
|
||||
[branch-management]: branch_management.md
|
||||
|
||||
### Running etcd
|
||||
|
||||
First start a single-member cluster of etcd:
|
||||
|
||||
```sh
|
||||
./bin/etcd
|
||||
```
|
||||
|
||||
This will bring up etcd listening on port 2379 for client communication and on port 2380 for server-to-server communication.
|
||||
|
||||
Next, let's set a single key, and then retrieve it:
|
||||
|
||||
```
|
||||
curl -L http://127.0.0.1:2379/v2/keys/mykey -XPUT -d value="this is awesome"
|
||||
curl -L http://127.0.0.1:2379/v2/keys/mykey
|
||||
```
|
||||
|
||||
You have successfully started an etcd and written a key to the store.
|
||||
|
||||
### etcd TCP ports
|
||||
|
||||
The [official etcd ports][iana-ports] are 2379 for client requests, and 2380 for peer communication. To maintain compatibility, some etcd configuration and documentation continues to refer to the legacy ports 4001 and 7001, but all new etcd use and discussion should adopt the IANA-assigned ports. The legacy ports 4001 and 7001 will be fully deprecated, and support for their use removed, in future etcd releases.
|
||||
|
||||
[iana-ports]: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=etcd
|
||||
|
||||
### Running local etcd cluster
|
||||
|
||||
First install [goreman](https://github.com/mattn/goreman), which manages Procfile-based applications.
|
||||
|
||||
Our [Procfile script](./Procfile) will set up a local example cluster. You can start it with:
|
||||
|
||||
```sh
|
||||
goreman start
|
||||
```
|
||||
|
||||
This will bring up 3 etcd members `infra1`, `infra2` and `infra3` and etcd proxy `proxy`, which runs locally and composes a cluster.
|
||||
|
||||
You can write a key to the cluster and retrieve the value back from any member or proxy.
|
||||
|
||||
### Next Steps
|
||||
|
||||
Now it's time to dig into the full etcd API and other guides.
|
||||
|
||||
- Explore the full [API][api].
|
||||
- Set up a [multi-machine cluster][clustering].
|
||||
- Learn the [config format, env variables and flags][configuration].
|
||||
- Find [language bindings and tools][libraries-and-tools].
|
||||
- Use TLS to [secure an etcd cluster][security].
|
||||
- [Tune etcd][tuning].
|
||||
- [Upgrade from 0.4.9+ to 2.2.0][upgrade].
|
||||
|
||||
[api]: ./api.md
|
||||
[clustering]: ./clustering.md
|
||||
[configuration]: ./configuration.md
|
||||
[libraries-and-tools]: ./libraries-and-tools.md
|
||||
[security]: ./security.md
|
||||
[tuning]: ./tuning.md
|
||||
[upgrade]: ./04_to_2_snapshot_migration.md
|
||||
|
||||
## Contact
|
||||
|
||||
- Mailing list: [etcd-dev](https://groups.google.com/forum/?hl=en#!forum/etcd-dev)
|
||||
- IRC: #[etcd](irc://irc.freenode.org:6667/#etcd) on freenode.org
|
||||
- Planning/Roadmap: [milestones](https://github.com/coreos/etcd/milestones), [roadmap](../../ROADMAP.md)
|
||||
- Bugs: [issues](https://github.com/coreos/etcd/issues)
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING](../../CONTRIBUTING.md) for details on submitting patches and the contribution workflow.
|
||||
|
||||
## Reporting bugs
|
||||
|
||||
See [reporting bugs](reporting_bugs.md) for details about reporting any issue you may encounter.
|
||||
|
||||
## Known bugs
|
||||
|
||||
[GH518](https://github.com/coreos/etcd/issues/518) is a known bug. Issue is that:
|
||||
|
||||
```
|
||||
curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar
|
||||
curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d dir=true -d prevExist=true
|
||||
```
|
||||
|
||||
If the previous node is a key and client tries to overwrite it with `dir=true`, it does not give warnings such as `Not a directory`. Instead, the key is set to empty value.
|
||||
|
||||
## Project Details
|
||||
|
||||
### Versioning
|
||||
|
||||
#### Service Versioning
|
||||
|
||||
etcd uses [semantic versioning](http://semver.org)
|
||||
New minor versions may add additional features to the API.
|
||||
|
||||
You can get the version of etcd by issuing a request to /version:
|
||||
|
||||
```sh
|
||||
curl -L http://127.0.0.1:2379/version
|
||||
```
|
||||
|
||||
#### API Versioning
|
||||
|
||||
The `v2` API responses should not change after the 2.0.0 release but new features will be added over time.
|
||||
|
||||
#### 32-bit and other unsupported systems
|
||||
|
||||
etcd has known issues on 32-bit systems due to a bug in the Go runtime. See #[358][358] for more information.
|
||||
|
||||
To avoid inadvertently running a possibly unstable etcd server, `etcd` on unsupported architectures will print
|
||||
a warning message and immediately exit if the environment variable `ETCD_UNSUPPORTED_ARCH` is not set to
|
||||
the target architecture.
|
||||
|
||||
Currently only the amd64 architecture is officially supported by `etcd`.
|
||||
|
||||
[358]: https://github.com/coreos/etcd/issues/358
|
||||
|
||||
### License
|
||||
|
||||
etcd is under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
|
@ -1,92 +0,0 @@
|
||||
# etcd3 API
|
||||
|
||||
TODO: API doc
|
||||
|
||||
## Data Model
|
||||
|
||||
etcd is designed to reliably store infrequently updated data and provide reliable watch queries. etcd exposes previous versions of key-value pairs to support inexpensive snapshots and watch history events (“time travel queries”). A persistent, multi-version, concurrency-control data model is a good fit for these use cases.
|
||||
|
||||
etcd stores data in a multiversion [persistent][persistent-ds] key-value store. The persistent key-value store preserves the previous version of a key-value pair when its value is superseded with new data. The key-value store is effectively immutable; its operations do not update the structure in-place, but instead always generates a new updated structure. All past versions of keys are still accessible and watchable after modification. To prevent the data store from growing indefinitely over time from maintaining old versions, the store may be compacted to shed the oldest versions of superseded data.
|
||||
|
||||
### Logical View
|
||||
|
||||
The store’s logical view is a flat binary key space. The key space has a lexically sorted index on byte string keys so range queries are inexpensive.
|
||||
|
||||
The key space maintains multiple revisions. Each atomic mutative operation (e.g., a transaction operation may contain multiple operations) creates a new revision on the key space. All data held by previous revisions remains unchanged. Old versions of key can still be accessed through previous revisions. Likewise, revisions are indexed as well; ranging over revisions with watchers is efficient. If the store is compacted to recover space, revisions before the compact revision will be removed.
|
||||
|
||||
A key’s lifetime spans a generation. Each key may have one or multiple generations. Creating a key increments the generation of that key, starting at 1 if the key never existed. Deleting a key generates a key tombstone, concluding the key’s current generation. Each modification of a key creates a new version of the key. Once a compaction happens, any generation ended before the given revision will be removed and values set before the compaction revision except the latest one will be removed.
|
||||
|
||||
### Physical View
|
||||
|
||||
etcd stores the physical data as key-value pairs in a persistent [b+tree][b+tree]. Each revision of the store’s state only contains the delta from its previous revision to be efficient. A single revision may correspond to multiple keys in the tree.
|
||||
|
||||
The key of key-value pair is a 3-tuple (major, sub, type). Major is the store revision holding the key. Sub differentiates among keys within the same revision. Type is an optional suffix for special value (e.g., `t` if the value contains a tombstone). The value of the key-value pair contains the modification from previous revision, thus one delta from previous revision. The b+tree is ordered by key in lexical byte-order. Ranged lookups over revision deltas are fast; this enables quickly finding modifications from one specific revision to another. Compaction removes out-of-date keys-value pairs.
|
||||
|
||||
etcd also keeps a secondary in-memory [btree][btree] index to speed up range queries over keys. The keys in the btree index are the keys of the store exposed to user. The value is a pointer to the modification of the persistent b+tree. Compaction removes dead pointers.
|
||||
|
||||
## KV API Guarantees
|
||||
|
||||
etcd is a consistent and durable key value store with mini-transaction(TODO: link to txn doc when we have it) support. The key value store is exposed through the KV APIs. etcd tries to ensure the strongest consistency and durability guarantees for a distributed system. This specification enumerates the KV API guarantees made by etcd.
|
||||
|
||||
### APIs to consider
|
||||
|
||||
* Read APIs
|
||||
* range
|
||||
* watch
|
||||
* Write APIs
|
||||
* put
|
||||
* delete
|
||||
* Combination (read-modify-write) APIs
|
||||
* txn
|
||||
|
||||
### etcd Specific Definitions
|
||||
|
||||
#### operation completed
|
||||
|
||||
An etcd operation is considered complete when it is committed through consensus, and therefore “executed” -- permanently stored -- by the etcd storage engine. The client knows an operation is completed when it receives a response from the etcd server. Note that the client may be uncertain about the status of an operation if it times out, or there is a network disruption between the client and the etcd member. etcd may also abort operations when there is a leader election. etcd does not send `abort` responses to clients’ outstanding requests in this event.
|
||||
|
||||
#### revision
|
||||
|
||||
An etcd operation that modifies the key value store is assigned with a single increasing revision. A transaction operation might modifies the key value store multiple times, but only one revision is assigned. The revision attribute of a key value pair that modified by the operation has the same value as the revision of the operation. The revision can be used as a logical clock for key value store. A key value pair that has a larger revision is modified after a key value pair with a smaller revision. Two key value pairs that have the same revision are modified by an operation "concurrently".
|
||||
|
||||
### Guarantees Provided
|
||||
|
||||
#### Atomicity
|
||||
|
||||
All API requests are atomic; an operation either completes entirely or not at all. For watch requests, all events generated by one operation will be in one watch response. Watch never observes partial events for a single operation.
|
||||
|
||||
#### Consistency
|
||||
|
||||
All API calls ensure [sequential consistency][seq_consistency], the strongest consistency guarantee available from distributed systems. No matter which etcd member server a client makes requests to, a client reads the same events in the same order. If two members complete the same number of operations, the state of the two members is consistent.
|
||||
|
||||
For watch operations, etcd guarantees to return the same value for the same key across all members for the same revision. For range operations, etcd has a similar guarantee for [linearized][Linearizability] access; serialized access may be behind the quorum state, so that the later revision is not yet available.
|
||||
|
||||
As with all distributed systems, it is impossible for etcd to ensure [strict consistency][strict_consistency]. etcd does not guarantee that it will return to a read the “most recent” value (as measured by a wall clock when a request is completed) available on any cluster member.
|
||||
|
||||
#### Isolation
|
||||
|
||||
etcd ensures [serializable isolation][serializable_isolation], which is the highest isolation level available in distributed systems. Read operations will never observe any intermediate data.
|
||||
|
||||
#### Durability
|
||||
|
||||
Any completed operations are durable. All accessible data is also durable data. A read will never return data that has not been made durable.
|
||||
|
||||
#### Linearizability
|
||||
|
||||
Linearizability (also known as Atomic Consistency or External Consistency) is a consistency level between strict consistency and sequential consistency.
|
||||
|
||||
For linearizability, suppose each operation receives a timestamp from a loosely synchronized global clock. Operations are linearized if and only if they always complete as though they were executed in a sequential order and each operation appears to complete in the order specified by the program. Likewise, if an operation’s timestamp precedes another, that operation must also precede the other operation in the sequence.
|
||||
|
||||
For example, consider a client completing a write at time point 1 (*t1*). A client issuing a read at *t2* (for *t2* > *t1*) should receive a value at least as recent as the previous write, completed at *t1*. However, the read might actually complete only by *t3*, and the returned value, current at *t2* when the read began, might be "stale" by *t3*.
|
||||
|
||||
etcd does not ensure linearizability for watch operations. Users are expected to verify the revision of watch responses to ensure correct ordering.
|
||||
|
||||
etcd ensures linearizability for all other operations by default. Linearizability comes with a cost, however, because linearized requests must go through the Raft consensus process. To obtain lower latencies and higher throughput for read requests, clients can configure a request’s consistency mode to `serializable`, which may access stale data with respect to quorum, but removes the performance penalty of linearized accesses' reliance on live consensus.
|
||||
|
||||
[persistent-ds]: [https://en.wikipedia.org/wiki/Persistent_data_structure]
|
||||
[btree]: [https://en.wikipedia.org/wiki/B-tree]
|
||||
[b+tree]: [https://en.wikipedia.org/wiki/B%2B_tree]
|
||||
[seq_consistency]: [https://en.wikipedia.org/wiki/Consistency_model#Sequential_consistency]
|
||||
[strict_consistency]: [https://en.wikipedia.org/wiki/Consistency_model#Strict_consistency]
|
||||
[serializable_isolation]: [https://en.wikipedia.org/wiki/Isolation_(database_systems)#Serializable]
|
||||
[Linearizability]: [#Linearizability]
|
@ -1,511 +0,0 @@
|
||||
# v2 Auth and Security
|
||||
|
||||
## etcd Resources
|
||||
There are three types of resources in etcd
|
||||
|
||||
1. permission resources: users and roles in the user store
|
||||
2. key-value resources: key-value pairs in the key-value store
|
||||
3. settings resources: security settings, auth settings, and dynamic etcd cluster settings (election/heartbeat)
|
||||
|
||||
### Permission Resources
|
||||
|
||||
#### Users
|
||||
A user is an identity to be authenticated. Each user can have multiple roles. The user has a capability (such as reading or writing) on the resource if one of the roles has that capability.
|
||||
|
||||
A user named `root` is required before authentication can be enabled, and it always has the ROOT role. The ROOT role can be granted to multiple users, but `root` is required for recovery purposes.
|
||||
|
||||
#### Roles
|
||||
Each role has exact one associated Permission List. An permission list exists for each permission on key-value resources.
|
||||
|
||||
The special static ROOT (named `root`) role has a full permissions on all key-value resources, the permission to manage user resources and settings resources. Only the ROOT role has the permission to manage user resources and modify settings resources. The ROOT role is built-in and does not need to be created.
|
||||
|
||||
There is also a special GUEST role, named 'guest'. These are the permissions given to unauthenticated requests to etcd. This role will be created automatically, and by default allows access to the full keyspace due to backward compatibility. (etcd did not previously authenticate any actions.). This role can be modified by a ROOT role holder at any time, to reduce the capabilities of unauthenticated users.
|
||||
|
||||
#### Permissions
|
||||
|
||||
There are two types of permissions, `read` and `write`. All management and settings require the ROOT role.
|
||||
|
||||
A Permission List is a list of allowed patterns for that particular permission (read or write). Only ALLOW prefixes are supported. DENY becomes more complicated and is TBD.
|
||||
|
||||
### Key-Value Resources
|
||||
A key-value resource is a key-value pairs in the store. Given a list of matching patterns, permission for any given key in a request is granted if any of the patterns in the list match.
|
||||
|
||||
Only prefixes or exact keys are supported. A prefix permission string ends in `*`.
|
||||
A permission on `/foo` is for that exact key or directory, not its children or recursively. `/foo*` is a prefix that matches `/foo` recursively, and all keys thereunder, and keys with that prefix (eg. `/foobar`. Contrast to the prefix `/foo/*`). `*` alone is permission on the full keyspace.
|
||||
|
||||
### Settings Resources
|
||||
|
||||
Specific settings for the cluster as a whole. This can include adding and removing cluster members, enabling or disabling authentication, replacing certificates, and any other dynamic configuration by the administrator (holder of the ROOT role).
|
||||
|
||||
## v2 Auth
|
||||
|
||||
### Basic Auth
|
||||
We only support [Basic Auth][basic-auth] for the first version. Client needs to attach the basic auth to the HTTP Authorization Header.
|
||||
|
||||
### Authorization field for operations
|
||||
Added to requests to /v2/keys, /v2/auth
|
||||
Add code 401 Unauthorized to the set of responses from the v2 API
|
||||
Authorization: Basic {encoded string}
|
||||
|
||||
### Future Work
|
||||
Other types of auth can be considered for the future (eg, signed certs, public keys) but the `Authorization:` header allows for other such types
|
||||
|
||||
### Things out of Scope for etcd Permissions
|
||||
|
||||
* Pluggable AUTH backends like LDAP (other Authorization tokens generated by LDAP et al may be a possibility)
|
||||
* Very fine-grained access controls (eg: users modifying keys outside work hours)
|
||||
|
||||
|
||||
|
||||
## API endpoints
|
||||
|
||||
An Error JSON corresponds to:
|
||||
{
|
||||
"name": "ErrErrorName",
|
||||
"description" : "The longer helpful description of the error."
|
||||
}
|
||||
|
||||
#### Enable and Disable Authentication
|
||||
|
||||
**Get auth status**
|
||||
|
||||
GET /v2/auth/enable
|
||||
|
||||
Sent Headers:
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
200 Body:
|
||||
{
|
||||
"enabled": true
|
||||
}
|
||||
|
||||
|
||||
**Enable auth**
|
||||
|
||||
PUT /v2/auth/enable
|
||||
|
||||
Sent Headers:
|
||||
Put Body: (empty)
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
400 Bad Request (if root user has not been created)
|
||||
409 Conflict (already enabled)
|
||||
200 Body: (empty)
|
||||
|
||||
**Disable auth**
|
||||
|
||||
DELETE /v2/auth/enable
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <RootAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized (if not a root user)
|
||||
409 Conflict (already disabled)
|
||||
200 Body: (empty)
|
||||
|
||||
|
||||
#### Users
|
||||
|
||||
The User JSON object is formed as follows:
|
||||
|
||||
```
|
||||
{
|
||||
"user": "userName",
|
||||
"password": "password",
|
||||
"roles": [
|
||||
"role1",
|
||||
"role2"
|
||||
],
|
||||
"grant": [],
|
||||
"revoke": []
|
||||
}
|
||||
```
|
||||
|
||||
Password is only passed when necessary.
|
||||
|
||||
**Get a List of Users**
|
||||
|
||||
GET/HEAD /v2/auth/users
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized
|
||||
200 Headers:
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"users": [
|
||||
{
|
||||
"user": "alice",
|
||||
"roles": [
|
||||
{
|
||||
"role": "root",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["/*"],
|
||||
"write": ["/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"user": "bob",
|
||||
"roles": [
|
||||
{
|
||||
"role": "guest",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["/*"],
|
||||
"write": ["/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Get User Details**
|
||||
|
||||
GET/HEAD /v2/auth/users/alice
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"user" : "alice",
|
||||
"roles" : [
|
||||
{
|
||||
"role": "fleet",
|
||||
"permissions" : {
|
||||
"kv" : {
|
||||
"read": [ "/fleet/" ],
|
||||
"write": [ "/fleet/" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "etcd",
|
||||
"permissions" : {
|
||||
"kv" : {
|
||||
"read": [ "/*" ],
|
||||
"write": [ "/*" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Create Or Update A User**
|
||||
|
||||
A user can be created with initial roles, if filled in. However, no roles are required; only the username and password fields
|
||||
|
||||
PUT /v2/auth/users/charlie
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Put Body:
|
||||
JSON struct, above, matching the appropriate name
|
||||
* Starting password and roles when creating.
|
||||
* Grant/Revoke/Password filled in when updating (to grant roles, revoke roles, or change the password).
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
201 Created
|
||||
400 Bad Request
|
||||
401 Unauthorized
|
||||
404 Not Found (update non-existent users)
|
||||
409 Conflict (when granting duplicated roles or revoking non-existent roles)
|
||||
200 Headers:
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
JSON state of the user
|
||||
|
||||
**Remove A User**
|
||||
|
||||
DELETE /v2/auth/users/charlie
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized
|
||||
403 Forbidden (remove root user when auth is enabled)
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
200 Body: (empty)
|
||||
|
||||
#### Roles
|
||||
|
||||
A full role structure may look like this. A Permission List structure is used for the "permissions", "grant", and "revoke" keys.
|
||||
```
|
||||
{
|
||||
"role" : "fleet",
|
||||
"permissions" : {
|
||||
"kv" : {
|
||||
"read" : [ "/fleet/" ],
|
||||
"write": [ "/fleet/" ]
|
||||
}
|
||||
},
|
||||
"grant" : {"kv": {...}},
|
||||
"revoke": {"kv": {...}}
|
||||
}
|
||||
```
|
||||
|
||||
**Get Role Details**
|
||||
|
||||
GET/HEAD /v2/auth/roles/fleet
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"role" : "fleet",
|
||||
"permissions" : {
|
||||
"kv" : {
|
||||
"read": [ "/fleet/" ],
|
||||
"write": [ "/fleet/" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
**Get a list of Roles**
|
||||
|
||||
GET/HEAD /v2/auth/roles
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized
|
||||
200 Headers:
|
||||
Content-type: application/json
|
||||
200 Body:
|
||||
{
|
||||
"roles": [
|
||||
{
|
||||
"role": "fleet",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["/fleet/"],
|
||||
"write": ["/fleet/"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "etcd",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["/*"],
|
||||
"write": ["/*"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"role": "quay",
|
||||
"permissions": {
|
||||
"kv": {
|
||||
"read": ["/*"],
|
||||
"write": ["/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Create Or Update A Role**
|
||||
|
||||
PUT /v2/auth/roles/rkt
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Put Body:
|
||||
Initial desired JSON state, including the role name for verification and:
|
||||
* Starting permission set if creating
|
||||
* Granted/Revoked permission set if updating
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
201 Created
|
||||
400 Bad Request
|
||||
401 Unauthorized
|
||||
404 Not Found (update non-existent roles)
|
||||
409 Conflict (when granting duplicated permission or revoking non-existent permission)
|
||||
200 Body:
|
||||
JSON state of the role
|
||||
|
||||
**Remove A Role**
|
||||
|
||||
DELETE /v2/auth/roles/rkt
|
||||
|
||||
Sent Headers:
|
||||
Authorization: Basic <BasicAuthString>
|
||||
Possible Status Codes:
|
||||
200 OK
|
||||
401 Unauthorized
|
||||
403 Forbidden (remove root)
|
||||
404 Not Found
|
||||
200 Headers:
|
||||
200 Body: (empty)
|
||||
|
||||
|
||||
## Example Workflow
|
||||
|
||||
Let's walk through an example to show two tenants (applications, in our case) using etcd permissions.
|
||||
|
||||
### Create root role
|
||||
|
||||
```
|
||||
PUT /v2/auth/users/root
|
||||
Put Body:
|
||||
{"user" : "root", "password": "betterRootPW!"}
|
||||
```
|
||||
|
||||
### Enable auth
|
||||
|
||||
```
|
||||
PUT /v2/auth/enable
|
||||
```
|
||||
|
||||
### Modify guest role (revoke write permission)
|
||||
|
||||
```
|
||||
PUT /v2/auth/roles/guest
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Put Body:
|
||||
{
|
||||
"role" : "guest",
|
||||
"revoke" : {
|
||||
"kv" : {
|
||||
"write": [
|
||||
"/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Create Roles for the Applications
|
||||
|
||||
Create the rkt role fully specified:
|
||||
|
||||
```
|
||||
PUT /v2/auth/roles/rkt
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{
|
||||
"role" : "rkt",
|
||||
"permissions" : {
|
||||
"kv": {
|
||||
"read": [
|
||||
"/rkt/*"
|
||||
],
|
||||
"write": [
|
||||
"/rkt/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
But let's make fleet just a basic role for now:
|
||||
|
||||
```
|
||||
PUT /v2/auth/roles/fleet
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{
|
||||
"role" : "fleet"
|
||||
}
|
||||
```
|
||||
|
||||
### Optional: Grant some permissions to the roles
|
||||
|
||||
Well, we finally figured out where we want fleet to live. Let's fix it.
|
||||
(Note that we avoided this in the rkt case. So this step is optional.)
|
||||
|
||||
|
||||
```
|
||||
PUT /v2/auth/roles/fleet
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Put Body:
|
||||
{
|
||||
"role" : "fleet",
|
||||
"grant" : {
|
||||
"kv" : {
|
||||
"read": [
|
||||
"/rkt/fleet",
|
||||
"/fleet/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Create Users
|
||||
|
||||
Same as before, let's use rocket all at once and fleet separately
|
||||
|
||||
```
|
||||
PUT /v2/auth/users/rktuser
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{"user" : "rktuser", "password" : "rktpw", "roles" : ["rkt"]}
|
||||
```
|
||||
|
||||
```
|
||||
PUT /v2/auth/users/fleetuser
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{"user" : "fleetuser", "password" : "fleetpw"}
|
||||
```
|
||||
|
||||
### Optional: Grant Roles to Users
|
||||
|
||||
Likewise, let's explicitly grant fleetuser access.
|
||||
|
||||
```
|
||||
PUT /v2/auth/users/fleetuser
|
||||
Headers:
|
||||
Authorization: Basic <root:betterRootPW!>
|
||||
Body:
|
||||
{"user": "fleetuser", "grant": ["fleet"]}
|
||||
```
|
||||
|
||||
#### Start to use fleetuser and rktuser
|
||||
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
PUT /v2/keys/rkt/RktData
|
||||
Headers:
|
||||
Authorization: Basic <rktuser:rktpw>
|
||||
Body:
|
||||
value=launch
|
||||
```
|
||||
|
||||
Reads and writes outside the prefixes granted will fail with a 401 Unauthorized.
|
||||
|
||||
[basic-auth]: https://en.wikipedia.org/wiki/Basic_access_authentication
|
@ -1,180 +0,0 @@
|
||||
# Authentication Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Authentication -- having users and roles in etcd -- was added in etcd 2.1. This guide will help you set up basic authentication in etcd.
|
||||
|
||||
etcd before 2.1 was a completely open system; anyone with access to the API could change keys. In order to preserve backward compatibility and upgradability, this feature is off by default.
|
||||
|
||||
For a full discussion of the RESTful API, see [the authentication API documentation][auth-api]
|
||||
|
||||
## Special Users and Roles
|
||||
|
||||
There is one special user, `root`, and there are two special roles, `root` and `guest`.
|
||||
|
||||
### User `root`
|
||||
|
||||
User `root` must be created before security can be activated. It has the `root` role and allows for the changing of anything inside etcd. The idea behind the `root` user is for recovery purposes -- a password is generated and stored somewhere -- and the root role is granted to the administrator accounts on the system. In the future, for troubleshooting and recovery, we will need to assume some access to the system, and future documentation will assume this root user (though anyone with the role will suffice).
|
||||
|
||||
### Role `root`
|
||||
|
||||
Role `root` cannot be modified, but it may be granted to any user. Having access via the root role not only allows global read-write access (as was the case before 2.1) but allows modification of the authentication policy and all administrative things, like modifying the cluster membership.
|
||||
|
||||
### Role `guest`
|
||||
|
||||
The `guest` role defines the permissions granted to any request that does not provide an authentication. This will be created on security activation (if it doesn't already exist) to have full access to all keys, as was true in etcd 2.0. It may be modified at any time, and cannot be removed.
|
||||
|
||||
## Working with users
|
||||
|
||||
The `user` subcommand for `etcdctl` handles all things having to do with user accounts.
|
||||
|
||||
A listing of users can be found with
|
||||
|
||||
```
|
||||
$ etcdctl user list
|
||||
```
|
||||
|
||||
Creating a user is as easy as
|
||||
|
||||
```
|
||||
$ etcdctl user add myusername
|
||||
```
|
||||
|
||||
And there will be prompt for a new password.
|
||||
|
||||
Roles can be granted and revoked for a user with
|
||||
|
||||
```
|
||||
$ etcdctl user grant myusername -roles foo,bar,baz
|
||||
$ etcdctl user revoke myusername -roles bar,baz
|
||||
```
|
||||
|
||||
We can look at this user with
|
||||
|
||||
```
|
||||
$ etcdctl user get myusername
|
||||
```
|
||||
|
||||
And the password for a user can be changed with
|
||||
|
||||
```
|
||||
$ etcdctl user passwd myusername
|
||||
```
|
||||
|
||||
Which will prompt again for a new password.
|
||||
|
||||
To delete an account, there's always
|
||||
```
|
||||
$ etcdctl user remove myusername
|
||||
```
|
||||
|
||||
|
||||
## Working with roles
|
||||
|
||||
The `role` subcommand for `etcdctl` handles all things having to do with access controls for particular roles, as were granted to individual users.
|
||||
|
||||
A listing of roles can be found with
|
||||
|
||||
```
|
||||
$ etcdctl role list
|
||||
```
|
||||
|
||||
A new role can be created with
|
||||
|
||||
```
|
||||
$ etcdctl role add myrolename
|
||||
```
|
||||
|
||||
A role has no password; we are merely defining a new set of access rights.
|
||||
|
||||
Roles are granted access to various parts of the keyspace, a single path at a time.
|
||||
|
||||
Reading a path is simple; if the path ends in `*`, that key **and all keys prefixed with it**, are granted to holders of this role. If it does not end in `*`, only that key and that key alone is granted.
|
||||
|
||||
Access can be granted as either read, write, or both, as in the following examples:
|
||||
|
||||
```
|
||||
# Give read access to keys under the /foo directory
|
||||
$ etcdctl role grant myrolename -path '/foo/*' -read
|
||||
|
||||
# Give write-only access to the key at /foo/bar
|
||||
$ etcdctl role grant myrolename -path '/foo/bar' -write
|
||||
|
||||
# Give full access to keys under /pub
|
||||
$ etcdctl role grant myrolename -path '/pub/*' -readwrite
|
||||
```
|
||||
|
||||
Beware that
|
||||
|
||||
```
|
||||
# Give full access to keys under /pub??
|
||||
$ etcdctl role grant myrolename -path '/pub*' -readwrite
|
||||
```
|
||||
|
||||
Without the slash may include keys under `/publishing`, for example. To do both, grant `/pub` and `/pub/*`
|
||||
|
||||
To see what's granted, we can look at the role at any time:
|
||||
|
||||
```
|
||||
$ etcdctl role get myrolename
|
||||
```
|
||||
|
||||
Revocation of permissions is done the same logical way:
|
||||
|
||||
```
|
||||
$ etcdctl role revoke myrolename -path '/foo/bar' -write
|
||||
```
|
||||
|
||||
As is removing a role entirely
|
||||
|
||||
```
|
||||
$ etcdctl role remove myrolename
|
||||
```
|
||||
|
||||
## Enabling authentication
|
||||
|
||||
The minimal steps to enabling auth are as follows. The administrator can set up users and roles before or after enabling authentication, as a matter of preference.
|
||||
|
||||
Make sure the root user is created:
|
||||
|
||||
```
|
||||
$ etcdctl user add root
|
||||
New password:
|
||||
```
|
||||
|
||||
And enable authentication
|
||||
|
||||
```
|
||||
$ etcdctl auth enable
|
||||
```
|
||||
|
||||
After this, etcd is running with authentication enabled. To disable it for any reason, use the reciprocal command:
|
||||
|
||||
```
|
||||
$ etcdctl -u root:rootpw auth disable
|
||||
```
|
||||
|
||||
It would also be good to check what guests (unauthenticated users) are allowed to do:
|
||||
```
|
||||
$ etcdctl -u root:rootpw role get guest
|
||||
```
|
||||
|
||||
And modify this role appropriately, depending on your policies.
|
||||
|
||||
## Using `etcdctl` to authenticate
|
||||
|
||||
`etcdctl` supports a similar flag as `curl` for authentication.
|
||||
|
||||
```
|
||||
$ etcdctl -u user:password get foo
|
||||
```
|
||||
|
||||
or if you prefer to be prompted:
|
||||
|
||||
```
|
||||
$ etcdctl -u user get foo
|
||||
```
|
||||
|
||||
Otherwise, all `etcdctl` commands remain the same. Users and roles can still be created and modified, but require authentication by a user with the root role.
|
||||
|
||||
[auth-api]: auth_api.md
|
@ -1,18 +0,0 @@
|
||||
# Benchmarks
|
||||
|
||||
etcd benchmarks will be published regularly and tracked for each release below:
|
||||
|
||||
- [etcd v2.1.0-alpha][2.1]
|
||||
- [etcd v2.2.0-rc][2.2]
|
||||
- [etcd v3 demo][3.0]
|
||||
|
||||
# Memory Usage Benchmarks
|
||||
|
||||
It records expected memory usage in different scenarios.
|
||||
|
||||
- [etcd v2.2.0-rc][2.2-mem]
|
||||
|
||||
[2.1]: etcd-2-1-0-alpha-benchmarks.md
|
||||
[2.2]: etcd-2-2-0-rc-benchmarks.md
|
||||
[2.2-mem]: etcd-2-2-0-rc-memory-benchmarks.md
|
||||
[3.0]: etcd-3-demo-benchmarks.md
|
@ -1,52 +0,0 @@
|
||||
## Physical machines
|
||||
|
||||
GCE n1-highcpu-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted under /var/lib/etcd
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 1.8 GB memory
|
||||
- 2x CPUs
|
||||
- etcd version 2.1.0 alpha
|
||||
|
||||
## etcd Cluster
|
||||
|
||||
3 etcd members, each runs on a single machine
|
||||
|
||||
## Testing
|
||||
|
||||
Bootstrap another machine and use the [boom HTTP benchmark tool][boom] to send requests to each etcd member. Check the [benchmark hacking guide][hack-benchmark] for detailed instructions.
|
||||
|
||||
## Performance
|
||||
|
||||
### reading one single key
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | read QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|--------------------|----------|---------------|
|
||||
| 64 | 1 | leader only | 1534 | 0.7 |
|
||||
| 64 | 64 | leader only | 10125 | 9.1 |
|
||||
| 64 | 256 | leader only | 13892 | 27.1 |
|
||||
| 256 | 1 | leader only | 1530 | 0.8 |
|
||||
| 256 | 64 | leader only | 10106 | 10.1 |
|
||||
| 256 | 256 | leader only | 14667 | 27.0 |
|
||||
| 64 | 64 | all servers | 24200 | 3.9 |
|
||||
| 64 | 256 | all servers | 33300 | 11.8 |
|
||||
| 256 | 64 | all servers | 24800 | 3.9 |
|
||||
| 256 | 256 | all servers | 33000 | 11.5 |
|
||||
|
||||
### writing one single key
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | write QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|--------------------|-----------|---------------|
|
||||
| 64 | 1 | leader only | 60 | 21.4 |
|
||||
| 64 | 64 | leader only | 1742 | 46.8 |
|
||||
| 64 | 256 | leader only | 3982 | 90.5 |
|
||||
| 256 | 1 | leader only | 58 | 20.3 |
|
||||
| 256 | 64 | leader only | 1770 | 47.8 |
|
||||
| 256 | 256 | leader only | 4157 | 105.3 |
|
||||
| 64 | 64 | all servers | 1028 | 123.4 |
|
||||
| 64 | 256 | all servers | 3260 | 123.8 |
|
||||
| 256 | 64 | all servers | 1033 | 121.5 |
|
||||
| 256 | 256 | all servers | 3061 | 119.3 |
|
||||
|
||||
[boom]: https://github.com/rakyll/boom
|
||||
[hack-benchmark]: /hack/benchmark/
|
@ -1,69 +0,0 @@
|
||||
# Benchmarking etcd v2.2.0
|
||||
|
||||
## Physical Machines
|
||||
|
||||
GCE n1-highcpu-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted as etcd data directory
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 1.8 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## etcd Cluster
|
||||
|
||||
3 etcd 2.2.0 members, each runs on a single machine.
|
||||
|
||||
Detailed versions:
|
||||
|
||||
```
|
||||
etcd Version: 2.2.0
|
||||
Git SHA: e4561dd
|
||||
Go Version: go1.5
|
||||
Go OS/Arch: linux/amd64
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Bootstrap another machine, outside of the etcd cluster, and run the [`boom` HTTP benchmark tool](https://github.com/rakyll/boom) with a connection reuse patch to send requests to each etcd cluster member. See the [benchmark instructions](../../hack/benchmark/) for the patch and the steps to reproduce our procedures.
|
||||
|
||||
The performance is calulated through results of 100 benchmark rounds.
|
||||
|
||||
## Performance
|
||||
|
||||
### Single Key Read Performance
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | average read QPS | read QPS stddev | average 90th Percentile Latency (ms) | latency stddev |
|
||||
|-------------------|-------------------|--------------------|------------------|-----------------|--------------------------------------|----------------|
|
||||
| 64 | 1 | leader only | 2303 | 200 | 0.49 | 0.06 |
|
||||
| 64 | 64 | leader only | 15048 | 685 | 7.60 | 0.46 |
|
||||
| 64 | 256 | leader only | 14508 | 434 | 29.76 | 1.05 |
|
||||
| 256 | 1 | leader only | 2162 | 214 | 0.52 | 0.06 |
|
||||
| 256 | 64 | leader only | 14789 | 792 | 7.69| 0.48 |
|
||||
| 256 | 256 | leader only | 14424 | 512 | 29.92 | 1.42 |
|
||||
| 64 | 64 | all servers | 45752 | 2048 | 2.47 | 0.14 |
|
||||
| 64 | 256 | all servers | 46592 | 1273 | 10.14 | 0.59 |
|
||||
| 256 | 64 | all servers | 45332 | 1847 | 2.48| 0.12 |
|
||||
| 256 | 256 | all servers | 46485 | 1340 | 10.18 | 0.74 |
|
||||
|
||||
### Single Key Write Performance
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | average write QPS | write QPS stddev | average 90th Percentile Latency (ms) | latency stddev |
|
||||
|-------------------|-------------------|--------------------|------------------|-----------------|--------------------------------------|----------------|
|
||||
| 64 | 1 | leader only | 55 | 4 | 24.51 | 13.26 |
|
||||
| 64 | 64 | leader only | 2139 | 125 | 35.23 | 3.40 |
|
||||
| 64 | 256 | leader only | 4581 | 581 | 70.53 | 10.22 |
|
||||
| 256 | 1 | leader only | 56 | 4 | 22.37| 4.33 |
|
||||
| 256 | 64 | leader only | 2052 | 151 | 36.83 | 4.20 |
|
||||
| 256 | 256 | leader only | 4442 | 560 | 71.59 | 10.03 |
|
||||
| 64 | 64 | all servers | 1625 | 85 | 58.51 | 5.14 |
|
||||
| 64 | 256 | all servers | 4461 | 298 | 89.47 | 36.48 |
|
||||
| 256 | 64 | all servers | 1599 | 94 | 60.11| 6.43 |
|
||||
| 256 | 256 | all servers | 4315 | 193 | 88.98 | 7.01 |
|
||||
|
||||
## Performance Changes
|
||||
|
||||
- Because etcd now records metrics for each API call, read QPS performance seems to see a minor decrease in most scenarios. This minimal performance impact was judged a reasonable investment for the breadth of monitoring and debugging information returned.
|
||||
|
||||
- Write QPS to cluster leaders seems to be increased by a small margin. This is because the main loop and entry apply loops were decoupled in the etcd raft logic, eliminating several blocks between them.
|
||||
|
||||
- Write QPS to all members seems to be increased by a significant margin, because followers now receive the latest commit index sooner, and commit proposals more quickly.
|
@ -1,72 +0,0 @@
|
||||
## Physical machines
|
||||
|
||||
GCE n1-highcpu-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted under /var/lib/etcd
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 1.8 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## etcd Cluster
|
||||
|
||||
3 etcd 2.2.0-rc members, each runs on a single machine.
|
||||
|
||||
Detailed versions:
|
||||
|
||||
```
|
||||
etcd Version: 2.2.0-alpha.1+git
|
||||
Git SHA: 59a5a7e
|
||||
Go Version: go1.4.2
|
||||
Go OS/Arch: linux/amd64
|
||||
```
|
||||
|
||||
Also, we use 3 etcd 2.1.0 alpha-stage members to form cluster to get base performance. etcd's commit head is at [c7146bd5][c7146bd5], which is the same as the one that we use in [etcd 2.1 benchmark][etcd-2.1-benchmark].
|
||||
|
||||
## Testing
|
||||
|
||||
Bootstrap another machine and use the [boom HTTP benchmark tool][boom] to send requests to each etcd member. Check the [benchmark hacking guide][hack-benchmark] for detailed instructions.
|
||||
|
||||
## Performance
|
||||
|
||||
### reading one single key
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | read QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|--------------------|----------|---------------|
|
||||
| 64 | 1 | leader only | 2804 (-5%) | 0.4 (+0%) |
|
||||
| 64 | 64 | leader only | 17816 (+0%) | 5.7 (-6%) |
|
||||
| 64 | 256 | leader only | 18667 (-6%) | 20.4 (+2%) |
|
||||
| 256 | 1 | leader only | 2181 (-15%) | 0.5 (+25%) |
|
||||
| 256 | 64 | leader only | 17435 (-7%) | 6.0 (+9%) |
|
||||
| 256 | 256 | leader only | 18180 (-8%) | 21.3 (+3%) |
|
||||
| 64 | 64 | all servers | 46965 (-4%) | 2.1 (+0%) |
|
||||
| 64 | 256 | all servers | 55286 (-6%) | 7.4 (+6%) |
|
||||
| 256 | 64 | all servers | 46603 (-6%) | 2.1 (+5%) |
|
||||
| 256 | 256 | all servers | 55291 (-6%) | 7.3 (+4%) |
|
||||
|
||||
### writing one single key
|
||||
|
||||
| key size in bytes | number of clients | target etcd server | write QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|--------------------|-----------|---------------|
|
||||
| 64 | 1 | leader only | 76 (+22%) | 19.4 (-15%) |
|
||||
| 64 | 64 | leader only | 2461 (+45%) | 31.8 (-32%) |
|
||||
| 64 | 256 | leader only | 4275 (+1%) | 69.6 (-10%) |
|
||||
| 256 | 1 | leader only | 64 (+20%) | 16.7 (-30%) |
|
||||
| 256 | 64 | leader only | 2385 (+30%) | 31.5 (-19%) |
|
||||
| 256 | 256 | leader only | 4353 (-3%) | 74.0 (+9%) |
|
||||
| 64 | 64 | all servers | 2005 (+81%) | 49.8 (-55%) |
|
||||
| 64 | 256 | all servers | 4868 (+35%) | 81.5 (-40%) |
|
||||
| 256 | 64 | all servers | 1925 (+72%) | 47.7 (-59%) |
|
||||
| 256 | 256 | all servers | 4975 (+36%) | 70.3 (-36%) |
|
||||
|
||||
### performance changes explanation
|
||||
|
||||
- read QPS in most scenarios is decreased by 5~8%. The reason is that etcd records store metrics for each store operation. The metrics is important for monitoring and debugging, so this is acceptable.
|
||||
|
||||
- write QPS to leader is increased by 20~30%. This is because we decouple raft main loop and entry apply loop, which avoids them blocking each other.
|
||||
|
||||
- write QPS to all servers is increased by 30~80% because follower could receive latest commit index earlier and commit proposals faster.
|
||||
|
||||
[boom]: https://github.com/rakyll/boom
|
||||
[c7146bd5]: https://github.com/coreos/etcd/commits/c7146bd5f2c73716091262edc638401bb8229144
|
||||
[etcd-2.1-benchmark]: etcd-2-1-0-alpha-benchmarks.md
|
||||
[hack-benchmark]: /hack/benchmark/
|
@ -1,47 +0,0 @@
|
||||
## Physical machine
|
||||
|
||||
GCE n1-standard-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted under /var/lib/etcd
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 7.5 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## etcd
|
||||
|
||||
```
|
||||
etcd Version: 2.2.0-rc.0+git
|
||||
Git SHA: 103cb5c
|
||||
Go Version: go1.5
|
||||
Go OS/Arch: linux/amd64
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Start 3-member etcd cluster, each of which uses 2 cores.
|
||||
|
||||
The length of key name is always 64 bytes, which is a reasonable length of average key bytes.
|
||||
|
||||
## Memory Maximal Usage
|
||||
|
||||
- etcd may use maximal memory if one follower is dead and the leader keeps sending snapshots.
|
||||
- `max RSS` is the maximal memory usage recorded in 3 runs.
|
||||
|
||||
| value bytes | key number | data size(MB) | max RSS(MB) | max RSS/data rate on leader |
|
||||
|-------------|-------------|---------------|-------------|-----------------------------|
|
||||
| 128 | 50000 | 6 | 433 | 72x |
|
||||
| 128 | 100000 | 12 | 659 | 54x |
|
||||
| 128 | 200000 | 24 | 1466 | 61x |
|
||||
| 1024 | 50000 | 48 | 1253 | 26x |
|
||||
| 1024 | 100000 | 96 | 2344 | 24x |
|
||||
| 1024 | 200000 | 192 | 4361 | 22x |
|
||||
|
||||
## Data Size Threshold
|
||||
|
||||
- When etcd reaches data size threshold, it may trigger leader election easily and drop part of proposals.
|
||||
- At most cases, etcd cluster should work smoothly if it doesn't hit the threshold. If it doesn't work well due to insufficient resources, you need to decrease its data size.
|
||||
|
||||
| value bytes | key number limitation | suggested data size threshold(MB) | consumed RSS(MB) |
|
||||
|-------------|-----------------------|-----------------------------------|------------------|
|
||||
| 128 | 400K | 48 | 2400 |
|
||||
| 1024 | 300K | 292 | 6500 |
|
@ -1,42 +0,0 @@
|
||||
## Physical machines
|
||||
|
||||
GCE n1-highcpu-2 machine type
|
||||
|
||||
- 1x dedicated local SSD mounted under /var/lib/etcd
|
||||
- 1x dedicated slow disk for the OS
|
||||
- 1.8 GB memory
|
||||
- 2x CPUs
|
||||
- etcd version 2.2.0
|
||||
|
||||
## etcd Cluster
|
||||
|
||||
1 etcd member running in v3 demo mode
|
||||
|
||||
## Testing
|
||||
|
||||
Use [etcd v3 benchmark tool][etcd-v3-benchmark].
|
||||
|
||||
## Performance
|
||||
|
||||
### reading one single key
|
||||
|
||||
| key size in bytes | number of clients | read QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|----------|---------------|
|
||||
| 256 | 1 | 2716 | 0.4 |
|
||||
| 256 | 64 | 16623 | 6.1 |
|
||||
| 256 | 256 | 16622 | 21.7 |
|
||||
|
||||
The performance is nearly the same as the one with empty server handler.
|
||||
|
||||
### reading one single key after putting
|
||||
|
||||
| key size in bytes | number of clients | read QPS | 90th Percentile Latency (ms) |
|
||||
|-------------------|-------------------|----------|---------------|
|
||||
| 256 | 1 | 2269 | 0.5 |
|
||||
| 256 | 64 | 13582 | 8.6 |
|
||||
| 256 | 256 | 13262 | 47.5 |
|
||||
|
||||
The performance with empty server handler is not affected by one put. So the
|
||||
performance downgrade should be caused by storage package.
|
||||
|
||||
[etcd-v3-benchmark]: /tools/benchmark/
|
@ -1,77 +0,0 @@
|
||||
# Watch Memory Usage Benchmark
|
||||
|
||||
*NOTE*: The watch features are under active development, and their memory usage may change as that development progresses. We do not expect it to significantly increase beyond the figures stated below.
|
||||
|
||||
A primary goal of etcd is supporting a very large number of watchers doing a massively large amount of watching. etcd aims to support O(10k) clients, O(100K) watch streams (O(10) streams per client) and O(10M) total watchings (O(100) watching per stream). The memory consumed by each individual watching accounts for the largest portion of etcd's overall usage, and is therefore the focus of current and future optimizations.
|
||||
|
||||
|
||||
Three related components of etcd watch consume physical memory: each `grpc.Conn`, each watch stream, and each instance of the watching activity. `grpc.Conn` maintains the actual TCP connection and other gRPC connection state. Each `grpc.Conn` consumes O(10kb) of memory, and might have multiple watch streams attached.
|
||||
|
||||
Each watch stream is an independent HTTP2 connection which consumes another O(10kb) of memory.
|
||||
Multiple watchings might share one watch stream.
|
||||
|
||||
Watching is the actual struct that tracks the changes on the key-value store. Each watching should only consume < O(1kb).
|
||||
|
||||
```
|
||||
+-------+
|
||||
| watch |
|
||||
+---------> | foo |
|
||||
| +-------+
|
||||
+------+-----+
|
||||
| stream |
|
||||
+--------------> | |
|
||||
| +------+-----+ +-------+
|
||||
| | | watch |
|
||||
| +---------> | bar |
|
||||
+-----+------+ +-------+
|
||||
| | +------------+
|
||||
| conn +-------> | stream |
|
||||
| | | |
|
||||
+-----+------+ +------------+
|
||||
|
|
||||
|
|
||||
|
|
||||
| +------------+
|
||||
+--------------> | stream |
|
||||
| |
|
||||
+------------+
|
||||
```
|
||||
|
||||
The theoretical memory consumption of watch can be approximated with the formula:
|
||||
`memory = c1 * number_of_conn + c2 * avg_number_of_stream_per_conn + c3 * avg_number_of_watch_stream`
|
||||
|
||||
## Testing Environment
|
||||
|
||||
etcd version
|
||||
- git head https://github.com/coreos/etcd/commit/185097ffaa627b909007e772c175e8fefac17af3
|
||||
|
||||
GCE n1-standard-2 machine type
|
||||
- 7.5 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## Overall memory usage
|
||||
|
||||
The overall memory usage captures how much [RSS][rss] etcd consumes with the client watchers. While the result may vary by as much as 10%, it is still meaningful, since the goal is to learn about the rough memory usage and the pattern of allocations.
|
||||
|
||||
With the benchmark result, we can calculate roughly that `c1 = 17kb`, `c2 = 18kb` and `c3 = 350bytes`. So each additional client connection consumes 17kb of memory and each additional stream consumes 18kb of memory, and each additional watching only cause 350bytes. A single etcd server can maintain millions of watchings with a few GB of memory in normal case.
|
||||
|
||||
|
||||
| clients | streams per client | watchings per stream | total watching | memory usage |
|
||||
|---------|---------|-----------|----------------|--------------|
|
||||
| 1k | 1 | 1 | 1k | 50MB |
|
||||
| 2k | 1 | 1 | 2k | 90MB |
|
||||
| 5k | 1 | 1 | 5k | 200MB |
|
||||
| 1k | 10 | 1 | 10k | 217MB |
|
||||
| 2k | 10 | 1 | 20k | 417MB |
|
||||
| 5k | 10 | 1 | 50k | 980MB |
|
||||
| 1k | 50 | 1 | 50k | 1001MB |
|
||||
| 2k | 50 | 1 | 100k | 1960MB |
|
||||
| 5k | 50 | 1 | 250k | 4700MB |
|
||||
| 1k | 50 | 10 | 500k | 1171MB |
|
||||
| 2k | 50 | 10 | 1M | 2371MB |
|
||||
| 5k | 50 | 10 | 2.5M | 5710MB |
|
||||
| 1k | 50 | 100 | 5M | 2380MB |
|
||||
| 2k | 50 | 100 | 10M | 4672MB |
|
||||
| 5k | 50 | 100 | 50M | *OOM* |
|
||||
|
||||
[rss]: https://en.wikipedia.org/wiki/Resident_set_size
|
@ -1,98 +0,0 @@
|
||||
# Storage Memory Usage Benchmark
|
||||
|
||||
<!---todo: link storage to storage design doc-->
|
||||
Two components of etcd storage consume physical memory. The etcd process allocates an *in-memory index* to speed key lookup. The process's *page cache*, managed by the operating system, stores recently-accessed data from disk for quick re-use.
|
||||
|
||||
The in-memory index holds all the keys in a [B-tree][btree] data structure, along with pointers to the on-disk data (the values). Each key in the B-tree may contain multiple pointers, pointing to different versions of its values. The theoretical memory consumption of the in-memory index can hence be approximated with the formula:
|
||||
|
||||
`N * (c1 + avg_key_size) + N * (avg_versions_of_key) * (c2 + size_of_pointer)`
|
||||
|
||||
where `c1` is the key metadata overhead and `c2` is the version metadata overhead.
|
||||
|
||||
The graph shows the detailed structure of the in-memory index B-tree.
|
||||
|
||||
```
|
||||
|
||||
|
||||
In mem index
|
||||
|
||||
+------------+
|
||||
| key || ... |
|
||||
+--------------+ | || |
|
||||
| | +------------+
|
||||
| | | v1 || ... |
|
||||
| disk <----------------| || | Tree Node
|
||||
| | +------------+
|
||||
| | | v2 || ... |
|
||||
| <----------------+ || |
|
||||
| | +------------+
|
||||
+--------------+ +-----+ | | |
|
||||
| | | | |
|
||||
| +------------+
|
||||
|
|
||||
|
|
||||
^
|
||||
------+
|
||||
| ... |
|
||||
| |
|
||||
+-----+
|
||||
| ... | Tree Node
|
||||
| |
|
||||
+-----+
|
||||
| ... |
|
||||
| |
|
||||
------+
|
||||
```
|
||||
|
||||
[Page cache memory][pagecache] is managed by the operating system and is not covered in detail in this document.
|
||||
|
||||
## Testing Environment
|
||||
|
||||
etcd version
|
||||
- git head https://github.com/coreos/etcd/commit/776e9fb7be7eee5e6b58ab977c8887b4fe4d48db
|
||||
|
||||
GCE n1-standard-2 machine type
|
||||
|
||||
- 7.5 GB memory
|
||||
- 2x CPUs
|
||||
|
||||
## In-memory index memory usage
|
||||
|
||||
In this test, we only benchmark the memory usage of the in-memory index. The goal is to find `c1` and `c2` mentioned above and to understand the hard limit of memory consumption of the storage.
|
||||
|
||||
We calculate the memory usage consumption via the Go runtime.ReadMemStats. We calculate the total allocated bytes difference before creating the index and after creating the index. It cannot perfectly reflect the memory usage of the in-memory index itself but can show the rough consumption pattern.
|
||||
|
||||
| N | versions | key size | memory usage |
|
||||
|------|----------|----------|--------------|
|
||||
| 100K | 1 | 64bytes | 22MB |
|
||||
| 100K | 5 | 64bytes | 39MB |
|
||||
| 1M | 1 | 64bytes | 218MB |
|
||||
| 1M | 5 | 64bytes | 432MB |
|
||||
| 100K | 1 | 256bytes | 41MB |
|
||||
| 100K | 5 | 256bytes | 65MB |
|
||||
| 1M | 1 | 256bytes | 409MB |
|
||||
| 1M | 5 | 256bytes | 506MB |
|
||||
|
||||
|
||||
Based on the result, we can calculate `c1=120bytes`, `c2=30bytes`. We only need two sets of data to calculate `c1` and `c2`, since they are the only unknown variable in the formula. The `c1=120bytes` and `c2=30bytes` are the average value of the 4 sets of `c1` and `c2` we calculated. The key metadata overhead is still relatively nontrivial (50%) for small key-value pairs. However, this is a significant improvement over the old store, which had at least 1000% overhead.
|
||||
|
||||
## Overall memory usage
|
||||
|
||||
The overall memory usage captures how much RSS etcd consumes with the storage. The value size should have very little impact on the overall memory usage of etcd, since we keep values on disk and only retain hot values in memory, managed by the OS page cache.
|
||||
|
||||
| N | versions | key size | value size | memory usage |
|
||||
|------|----------|----------|------------|--------------|
|
||||
| 100K | 1 | 64bytes | 256bytes | 40MB |
|
||||
| 100K | 5 | 64bytes | 256bytes | 89MB |
|
||||
| 1M | 1 | 64bytes | 256bytes | 470MB |
|
||||
| 1M | 5 | 64bytes | 256bytes | 880MB |
|
||||
| 100K | 1 | 64bytes | 1KB | 102MB |
|
||||
| 100K | 5 | 64bytes | 1KB | 164MB |
|
||||
| 1M | 1 | 64bytes | 1KB | 587MB |
|
||||
| 1M | 5 | 64bytes | 1KB | 836MB |
|
||||
|
||||
Based on the result, we know the value size does not significantly impact the memory consumption. There is some minor increase due to more data held in the OS page cache.
|
||||
|
||||
[btree]: https://en.wikipedia.org/wiki/B-tree
|
||||
[pagecache]: https://en.wikipedia.org/wiki/Page_cache
|
||||
|
@ -1,26 +0,0 @@
|
||||
# Branch Management
|
||||
|
||||
## Guide
|
||||
|
||||
* New development occurs on the [master branch][master].
|
||||
* Master branch should always have a green build!
|
||||
* Backwards-compatible bug fixes should target the master branch and subsequently be ported to stable branches.
|
||||
* Once the master branch is ready for release, it will be tagged and become the new stable branch.
|
||||
|
||||
The etcd team has adopted a *rolling release model* and supports one stable version of etcd.
|
||||
|
||||
### Master branch
|
||||
|
||||
The `master` branch is our development branch. All new features land here first.
|
||||
|
||||
If you want to try new features, pull `master` and play with it. Note that `master` may not be stable because new features may introduce bugs.
|
||||
|
||||
Before the release of the next stable version, feature PRs will be frozen. We will focus on the testing, bug-fix and documentation for one to two weeks.
|
||||
|
||||
### Stable branches
|
||||
|
||||
All branches with prefix `release-` are considered _stable_ branches.
|
||||
|
||||
After every minor release (http://semver.org/), we will have a new stable branch for that release. We will keep fixing the backwards-compatible bugs for the latest stable release, but not previous releases. The _patch_ release, incorporating any bug fixes, will be once every two weeks, given any patches.
|
||||
|
||||
[master]: https://github.com/coreos/etcd/tree/master
|
@ -1,435 +0,0 @@
|
||||
# Clustering Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Starting an etcd cluster statically requires that each member knows another in the cluster. In a number of cases, you might not know the IPs of your cluster members ahead of time. In these cases, you can bootstrap an etcd cluster with the help of a discovery service.
|
||||
|
||||
Once an etcd cluster is up and running, adding or removing members is done via [runtime reconfiguration][runtime-conf]. To better understand the design behind runtime reconfiguration, we suggest you read [the runtime configuration design document][runtime-reconf-design].
|
||||
|
||||
This guide will cover the following mechanisms for bootstrapping an etcd cluster:
|
||||
|
||||
* [Static](#static)
|
||||
* [etcd Discovery](#etcd-discovery)
|
||||
* [DNS Discovery](#dns-discovery)
|
||||
|
||||
Each of the bootstrapping mechanisms will be used to create a three machine etcd cluster with the following details:
|
||||
|
||||
|Name|Address|Hostname|
|
||||
|------|---------|------------------|
|
||||
|infra0|10.0.1.10|infra0.example.com|
|
||||
|infra1|10.0.1.11|infra1.example.com|
|
||||
|infra2|10.0.1.12|infra2.example.com|
|
||||
|
||||
## Static
|
||||
|
||||
As we know the cluster members, their addresses and the size of the cluster before starting, we can use an offline bootstrap configuration by setting the `initial-cluster` flag. Each machine will get either the following command line or environment variables:
|
||||
|
||||
```
|
||||
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380"
|
||||
ETCD_INITIAL_CLUSTER_STATE=new
|
||||
```
|
||||
|
||||
```
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state new
|
||||
```
|
||||
|
||||
Note that the URLs specified in `initial-cluster` are the _advertised peer URLs_, i.e. they should match the value of `initial-advertise-peer-urls` on the respective nodes.
|
||||
|
||||
If you are spinning up multiple clusters (or creating and destroying a single cluster) with same configuration for testing purpose, it is highly recommended that you specify a unique `initial-cluster-token` for the different clusters. By doing this, etcd can generate unique cluster IDs and member IDs for the clusters even if they otherwise have the exact same configuration. This can protect you from cross-cluster-interaction, which might corrupt your clusters.
|
||||
|
||||
etcd listens on [`listen-client-urls`][conf-listen-client] to accept client traffic. etcd member advertises the URLs specified in [`advertise-client-urls`][conf-adv-client] to other members, proxies, clients. Please make sure the `advertise-client-urls` are reachable from intended clients. A common mistake is setting `advertise-client-urls` to localhost or leave it as default when you want the remote clients to reach etcd.
|
||||
|
||||
On each machine you would start etcd with these flags:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state new
|
||||
```
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state new
|
||||
```
|
||||
```
|
||||
$ etcd --name infra2 --initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.12:2379 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state new
|
||||
```
|
||||
|
||||
The command line parameters starting with `--initial-cluster` will be ignored on subsequent runs of etcd. You are free to remove the environment variables or command line flags after the initial bootstrap process. If you need to make changes to the configuration later (for example, adding or removing members to/from the cluster), see the [runtime configuration][runtime-conf] guide.
|
||||
|
||||
### Error Cases
|
||||
|
||||
In the following example, we have not included our new host in the list of enumerated nodes. If this is a new cluster, the node _must_ be added to the list of initial cluster members.
|
||||
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-peer-urls https://10.0.1.11:2380 \
|
||||
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380 \
|
||||
--initial-cluster-state new
|
||||
etcd: infra1 not listed in the initial cluster config
|
||||
exit 1
|
||||
```
|
||||
|
||||
In this example, we are attempting to map a node (infra0) on a different address (127.0.0.1:2380) than its enumerated address in the cluster list (10.0.1.10:2380). If this node is to listen on multiple addresses, all addresses _must_ be reflected in the "initial-cluster" configuration directive.
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://127.0.0.1:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380 \
|
||||
--initial-cluster-state=new
|
||||
etcd: error setting up initial cluster: infra0 has different advertised URLs in the cluster and advertised peer URLs list
|
||||
exit 1
|
||||
```
|
||||
|
||||
If you configure a peer with a different set of configuration and attempt to join this cluster you will get a cluster ID mismatch and etcd will exit.
|
||||
|
||||
```
|
||||
$ etcd --name infra3 --initial-advertise-peer-urls http://10.0.1.13:2380 \
|
||||
--listen-peer-urls http://10.0.1.13:2380 \
|
||||
--listen-client-urls http://10.0.1.13:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.13:2379 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra3=http://10.0.1.13:2380 \
|
||||
--initial-cluster-state=new
|
||||
etcd: conflicting cluster ID to the target cluster (c6ab534d07e8fcc4 != bc25ea2a74fb18b0). Exiting.
|
||||
exit 1
|
||||
```
|
||||
|
||||
## Discovery
|
||||
|
||||
In a number of cases, you might not know the IPs of your cluster peers ahead of time. This is common when utilizing cloud providers or when your network uses DHCP. In these cases, rather than specifying a static configuration, you can use an existing etcd cluster to bootstrap a new one. We call this process "discovery".
|
||||
|
||||
There two methods that can be used for discovery:
|
||||
|
||||
* etcd discovery service
|
||||
* DNS SRV records
|
||||
|
||||
### etcd Discovery
|
||||
|
||||
To better understand the design about discovery service protocol, we suggest you read [this][discovery-proto].
|
||||
|
||||
#### Lifetime of a Discovery URL
|
||||
|
||||
A discovery URL identifies a unique etcd cluster. Instead of reusing a discovery URL, you should always create discovery URLs for new clusters.
|
||||
|
||||
Moreover, discovery URLs should ONLY be used for the initial bootstrapping of a cluster. To change cluster membership after the cluster is already running, see the [runtime reconfiguration][runtime-conf] guide.
|
||||
|
||||
#### Custom etcd Discovery Service
|
||||
|
||||
Discovery uses an existing cluster to bootstrap itself. If you are using your own etcd cluster you can create a URL like so:
|
||||
|
||||
```
|
||||
$ curl -X PUT https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83/_config/size -d value=3
|
||||
```
|
||||
|
||||
By setting the size key to the URL, you create a discovery URL with an expected cluster size of 3.
|
||||
|
||||
If you bootstrap an etcd cluster using discovery service with more than the expected number of etcd members, the extra etcd processes will [fall back][fall-back] to being [proxies][proxy] by default.
|
||||
|
||||
The URL you will use in this case will be `https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83` and the etcd members will use the `https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83` directory for registration as they start.
|
||||
|
||||
**Each member must have a different name flag specified. `Hostname` or `machine-id` can be a good choice. Or discovery will fail due to duplicated name.**
|
||||
|
||||
Now we start etcd with those relevant flags for each member:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
```
|
||||
$ etcd --name infra2 --initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.12:2379 \
|
||||
--discovery https://myetcd.local/v2/keys/discovery/6c007a14875d53d9bf0ef5a6fc0257c817f0fb83
|
||||
```
|
||||
|
||||
This will cause each member to register itself with the custom etcd discovery service and begin the cluster once all machines have been registered.
|
||||
|
||||
#### Public etcd Discovery Service
|
||||
|
||||
If you do not have access to an existing cluster, you can use the public discovery service hosted at `discovery.etcd.io`. You can create a private discovery URL using the "new" endpoint like so:
|
||||
|
||||
```
|
||||
$ curl https://discovery.etcd.io/new?size=3
|
||||
https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
This will create the cluster with an initial expected size of 3 members. If you do not specify a size, a default of 3 will be used.
|
||||
|
||||
If you bootstrap an etcd cluster using discovery service with more than the expected number of etcd members, the extra etcd processes will [fall back][fall-back] to being [proxies][proxy] by default.
|
||||
|
||||
```
|
||||
ETCD_DISCOVERY=https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
```
|
||||
-discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
**Each member must have a different name flag specified. `Hostname` or `machine-id` can be a good choice. Or discovery will fail due to duplicated name.**
|
||||
|
||||
Now we start etcd with those relevant flags for each member:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
```
|
||||
$ etcd --name infra1 --initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-peer-urls http://10.0.1.11:2380 \
|
||||
--listen-client-urls http://10.0.1.11:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
```
|
||||
$ etcd --name infra2 --initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-peer-urls http://10.0.1.12:2380 \
|
||||
--listen-client-urls http://10.0.1.12:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.12:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
```
|
||||
|
||||
This will cause each member to register itself with the discovery service and begin the cluster once all members have been registered.
|
||||
|
||||
You can use the environment variable `ETCD_DISCOVERY_PROXY` to cause etcd to use an HTTP proxy to connect to the discovery service.
|
||||
|
||||
#### Error and Warning Cases
|
||||
|
||||
##### Discovery Server Errors
|
||||
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
etcd: error: the cluster doesn’t have a size configuration value in https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de/_config
|
||||
exit 1
|
||||
```
|
||||
|
||||
##### User Errors
|
||||
|
||||
This error will occur if the discovery cluster already has the configured number of members, and `discovery-fallback` is explicitly disabled
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de \
|
||||
--discovery-fallback exit
|
||||
etcd: discovery: cluster is full
|
||||
exit 1
|
||||
```
|
||||
|
||||
##### Warnings
|
||||
|
||||
This is a harmless warning notifying you that the discovery URL will be
|
||||
ignored on this machine.
|
||||
|
||||
```
|
||||
$ etcd --name infra0 --initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-peer-urls http://10.0.1.10:2380 \
|
||||
--listen-client-urls http://10.0.1.10:2379,http://127.0.0.1:2379 \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de
|
||||
etcdserver: discovery token ignored since a cluster has already been initialized. Valid log found at /var/lib/etcd
|
||||
```
|
||||
|
||||
### DNS Discovery
|
||||
|
||||
DNS [SRV records][rfc-srv] can be used as a discovery mechanism.
|
||||
The `-discovery-srv` flag can be used to set the DNS domain name where the discovery SRV records can be found.
|
||||
The following DNS SRV records are looked up in the listed order:
|
||||
|
||||
* _etcd-server-ssl._tcp.example.com
|
||||
* _etcd-server._tcp.example.com
|
||||
|
||||
If `_etcd-server-ssl._tcp.example.com` is found then etcd will attempt the bootstrapping process over SSL.
|
||||
|
||||
To help clients discover the etcd cluster, the following DNS SRV records are looked up in the listed order:
|
||||
|
||||
* _etcd-client._tcp.example.com
|
||||
* _etcd-client-ssl._tcp.example.com
|
||||
|
||||
If `_etcd-client-ssl._tcp.example.com` is found, clients will attempt to communicate with the etcd cluster over SSL.
|
||||
|
||||
#### Create DNS SRV records
|
||||
|
||||
```
|
||||
$ dig +noall +answer SRV _etcd-server._tcp.example.com
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra0.example.com.
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra1.example.com.
|
||||
_etcd-server._tcp.example.com. 300 IN SRV 0 0 2380 infra2.example.com.
|
||||
```
|
||||
|
||||
```
|
||||
$ dig +noall +answer SRV _etcd-client._tcp.example.com
|
||||
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra0.example.com.
|
||||
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra1.example.com.
|
||||
_etcd-client._tcp.example.com. 300 IN SRV 0 0 2379 infra2.example.com.
|
||||
```
|
||||
|
||||
```
|
||||
$ dig +noall +answer infra0.example.com infra1.example.com infra2.example.com
|
||||
infra0.example.com. 300 IN A 10.0.1.10
|
||||
infra1.example.com. 300 IN A 10.0.1.11
|
||||
infra2.example.com. 300 IN A 10.0.1.12
|
||||
```
|
||||
|
||||
#### Bootstrap the etcd cluster using DNS
|
||||
|
||||
etcd cluster members can listen on domain names or IP address, the bootstrap process will resolve DNS A records.
|
||||
|
||||
The resolved address in `--initial-advertise-peer-urls` *must match* one of the resolved addresses in the SRV targets. The etcd member reads the resolved address to find out if it belongs to the cluster defined in the SRV records.
|
||||
|
||||
```
|
||||
$ etcd --name infra0 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://infra0.example.com:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://infra0.example.com:2379 \
|
||||
--listen-client-urls http://infra0.example.com:2379 \
|
||||
--listen-peer-urls http://infra0.example.com:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd --name infra1 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://infra1.example.com:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://infra1.example.com:2379 \
|
||||
--listen-client-urls http://infra1.example.com:2379 \
|
||||
--listen-peer-urls http://infra1.example.com:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd --name infra2 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://infra2.example.com:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://infra2.example.com:2379 \
|
||||
--listen-client-urls http://infra2.example.com:2379 \
|
||||
--listen-peer-urls http://infra2.example.com:2380
|
||||
```
|
||||
|
||||
You can also bootstrap the cluster using IP addresses instead of domain names:
|
||||
|
||||
```
|
||||
$ etcd --name infra0 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://10.0.1.10:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://10.0.1.10:2379 \
|
||||
--listen-client-urls http://10.0.1.10:2379 \
|
||||
--listen-peer-urls http://10.0.1.10:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd --name infra1 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--listen-client-urls http://10.0.1.11:2379 \
|
||||
--listen-peer-urls http://10.0.1.11:2380
|
||||
```
|
||||
|
||||
```
|
||||
$ etcd --name infra2 \
|
||||
--discovery-srv example.com \
|
||||
--initial-advertise-peer-urls http://10.0.1.12:2380 \
|
||||
--initial-cluster-token etcd-cluster-1 \
|
||||
--initial-cluster-state new \
|
||||
--advertise-client-urls http://10.0.1.12:2379 \
|
||||
--listen-client-urls http://10.0.1.12:2379 \
|
||||
--listen-peer-urls http://10.0.1.12:2380
|
||||
```
|
||||
|
||||
#### etcd proxy configuration
|
||||
|
||||
DNS SRV records can also be used to configure the list of peers for an etcd server running in proxy mode:
|
||||
|
||||
```
|
||||
$ etcd --proxy on --discovery-srv example.com
|
||||
```
|
||||
|
||||
#### etcd client configuration
|
||||
|
||||
DNS SRV records can also be used to help clients discover the etcd cluster.
|
||||
|
||||
The official [etcd/client][client] supports [DNS Discovery][client-discoverer].
|
||||
|
||||
`etcdctl` also supports DNS Discovery by specifying the `--discovery-srv` option.
|
||||
|
||||
```
|
||||
$ etcdctl --discovery-srv example.com set foo bar
|
||||
```
|
||||
|
||||
#### Error Cases
|
||||
|
||||
You might see an error like `cannot find local etcd $name from SRV records.`. That means the etcd member fails to find itself from the cluster defined in SRV records. The resolved address in `--initial-advertise-peer-urls` *must match* one of the resolved addresses in the SRV targets.
|
||||
|
||||
# 0.4 to 2.0+ Migration Guide
|
||||
|
||||
In etcd 2.0 we introduced the ability to listen on more than one address and to advertise multiple addresses. This makes using etcd easier when you have complex networking, such as private and public networks on various cloud providers.
|
||||
|
||||
To make understanding this feature easier, we changed the naming of some flags, but we support the old flags to make the migration from the old to new version easier.
|
||||
|
||||
|Old Flag |New Flag |Migration Behavior |
|
||||
|-----------------------|-----------------------|---------------------------------------------------------------------------------------|
|
||||
|-peer-addr |--initial-advertise-peer-urls |If specified, peer-addr will be used as the only peer URL. Error if both flags specified.|
|
||||
|-addr |--advertise-client-urls |If specified, addr will be used as the only client URL. Error if both flags specified.|
|
||||
|-peer-bind-addr |--listen-peer-urls |If specified, peer-bind-addr will be used as the only peer bind URL. Error if both flags specified.|
|
||||
|-bind-addr |--listen-client-urls |If specified, bind-addr will be used as the only client bind URL. Error if both flags specified.|
|
||||
|-peers |none |Deprecated. The --initial-cluster flag provides a similar concept with different semantics. Please read this guide on cluster startup.|
|
||||
|-peers-file |none |Deprecated. The --initial-cluster flag provides a similar concept with different semantics. Please read this guide on cluster startup.|
|
||||
|
||||
[client]: /client
|
||||
[client-discoverer]: https://godoc.org/github.com/coreos/etcd/client#Discoverer
|
||||
[conf-adv-client]: configuration.md#-advertise-client-urls
|
||||
[conf-listen-client]: configuration.md#-listen-client-urls
|
||||
[discovery-proto]: discovery_protocol.md
|
||||
[fall-back]: proxy.md#fallback-to-proxy-mode-with-discovery-service
|
||||
[proxy]: proxy.md
|
||||
[rfc-srv]: http://www.ietf.org/rfc/rfc2052.txt
|
||||
[runtime-conf]: runtime-configuration.md
|
||||
[runtime-reconf-design]: runtime-reconf-design.md
|
@ -1,282 +0,0 @@
|
||||
# Configuration Flags
|
||||
|
||||
etcd is configurable through command-line flags and environment variables. Options set on the command line take precedence over those from the environment.
|
||||
|
||||
The format of environment variable for flag `--my-flag` is `ETCD_MY_FLAG`. It applies to all flags.
|
||||
|
||||
The [official etcd ports][iana-ports] are 2379 for client requests, and 2380 for peer communication. Some legacy code and documentation still references ports 4001 and 7001, but all new etcd use and discussion should adopt the assigned ports.
|
||||
|
||||
To start etcd automatically using custom settings at startup in Linux, using a [systemd][systemd-intro] unit is highly recommended.
|
||||
|
||||
[systemd-intro]: http://freedesktop.org/wiki/Software/systemd/
|
||||
|
||||
## Member Flags
|
||||
|
||||
### --name
|
||||
+ Human-readable name for this member.
|
||||
+ default: "default"
|
||||
+ env variable: ETCD_NAME
|
||||
+ This value is referenced as this node's own entries listed in the `--initial-cluster` flag (Ex: `default=http://localhost:2380` or `default=http://localhost:2380,default=http://localhost:7001`). This needs to match the key used in the flag if you're using [static bootstrapping][build-cluster]. When using discovery, each member must have a unique name. `Hostname` or `machine-id` can be a good choice.
|
||||
|
||||
### --data-dir
|
||||
+ Path to the data directory.
|
||||
+ default: "${name}.etcd"
|
||||
+ env variable: ETCD_DATA_DIR
|
||||
|
||||
### --wal-dir
|
||||
+ Path to the dedicated wal directory. If this flag is set, etcd will write the WAL files to the walDir rather than the dataDir. This allows a dedicated disk to be used, and helps avoid io competition between logging and other IO operations.
|
||||
+ default: ""
|
||||
+ env variable: ETCD_WAL_DIR
|
||||
|
||||
### --snapshot-count
|
||||
+ Number of committed transactions to trigger a snapshot to disk.
|
||||
+ default: "10000"
|
||||
+ env variable: ETCD_SNAPSHOT_COUNT
|
||||
|
||||
### --heartbeat-interval
|
||||
+ Time (in milliseconds) of a heartbeat interval.
|
||||
+ default: "100"
|
||||
+ env variable: ETCD_HEARTBEAT_INTERVAL
|
||||
|
||||
### --election-timeout
|
||||
+ Time (in milliseconds) for an election to timeout. See [tuning.md](tuning.md#time-parameters) for details.
|
||||
+ default: "1000"
|
||||
+ env variable: ETCD_ELECTION_TIMEOUT
|
||||
|
||||
### --listen-peer-urls
|
||||
+ List of URLs to listen on for peer traffic. This flag tells the etcd to accept incoming requests from its peers on the specified scheme://IP:port combinations. Scheme can be either http or https.If 0.0.0.0 is specified as the IP, etcd listens to the given port on all interfaces. If an IP address is given as well as a port, etcd will listen on the given port and interface. Multiple URLs may be used to specify a number of addresses and ports to listen on. The etcd will respond to requests from any of the listed addresses and ports.
|
||||
+ default: "http://localhost:2380,http://localhost:7001"
|
||||
+ env variable: ETCD_LISTEN_PEER_URLS
|
||||
+ example: "http://10.0.0.1:2380"
|
||||
+ invalid example: "http://example.com:2380" (domain name is invalid for binding)
|
||||
|
||||
### --listen-client-urls
|
||||
+ List of URLs to listen on for client traffic. This flag tells the etcd to accept incoming requests from the clients on the specified scheme://IP:port combinations. Scheme can be either http or https. If 0.0.0.0 is specified as the IP, etcd listens to the given port on all interfaces. If an IP address is given as well as a port, etcd will listen on the given port and interface. Multiple URLs may be used to specify a number of addresses and ports to listen on. The etcd will respond to requests from any of the listed addresses and ports.
|
||||
+ default: "http://localhost:2379,http://localhost:4001"
|
||||
+ env variable: ETCD_LISTEN_CLIENT_URLS
|
||||
+ example: "http://10.0.0.1:2379"
|
||||
+ invalid example: "http://example.com:2379" (domain name is invalid for binding)
|
||||
|
||||
### --max-snapshots
|
||||
+ Maximum number of snapshot files to retain (0 is unlimited)
|
||||
+ default: 5
|
||||
+ env variable: ETCD_MAX_SNAPSHOTS
|
||||
+ The default for users on Windows is unlimited, and manual purging down to 5 (or your preference for safety) is recommended.
|
||||
|
||||
### --max-wals
|
||||
+ Maximum number of wal files to retain (0 is unlimited)
|
||||
+ default: 5
|
||||
+ env variable: ETCD_MAX_WALS
|
||||
+ The default for users on Windows is unlimited, and manual purging down to 5 (or your preference for safety) is recommended.
|
||||
|
||||
### --cors
|
||||
+ Comma-separated white list of origins for CORS (cross-origin resource sharing).
|
||||
+ default: none
|
||||
+ env variable: ETCD_CORS
|
||||
|
||||
## Clustering Flags
|
||||
|
||||
`--initial` prefix flags are used in bootstrapping ([static bootstrap][build-cluster], [discovery-service bootstrap][discovery] or [runtime reconfiguration][reconfig]) a new member, and ignored when restarting an existing member.
|
||||
|
||||
`--discovery` prefix flags need to be set when using [discovery service][discovery].
|
||||
|
||||
### --initial-advertise-peer-urls
|
||||
|
||||
+ List of this member's peer URLs to advertise to the rest of the cluster. These addresses are used for communicating etcd data around the cluster. At least one must be routable to all cluster members. These URLs can contain domain names.
|
||||
+ default: "http://localhost:2380,http://localhost:7001"
|
||||
+ env variable: ETCD_INITIAL_ADVERTISE_PEER_URLS
|
||||
+ example: "http://example.com:2380, http://10.0.0.1:2380"
|
||||
|
||||
### --initial-cluster
|
||||
+ Initial cluster configuration for bootstrapping.
|
||||
+ default: "default=http://localhost:2380,default=http://localhost:7001"
|
||||
+ env variable: ETCD_INITIAL_CLUSTER
|
||||
+ The key is the value of the `--name` flag for each node provided. The default uses `default` for the key because this is the default for the `--name` flag.
|
||||
|
||||
### --initial-cluster-state
|
||||
+ Initial cluster state ("new" or "existing"). Set to `new` for all members present during initial static or DNS bootstrapping. If this option is set to `existing`, etcd will attempt to join the existing cluster. If the wrong value is set, etcd will attempt to start but fail safely.
|
||||
+ default: "new"
|
||||
+ env variable: ETCD_INITIAL_CLUSTER_STATE
|
||||
|
||||
[static bootstrap]: clustering.md#static
|
||||
|
||||
### --initial-cluster-token
|
||||
+ Initial cluster token for the etcd cluster during bootstrap.
|
||||
+ default: "etcd-cluster"
|
||||
+ env variable: ETCD_INITIAL_CLUSTER_TOKEN
|
||||
|
||||
### --advertise-client-urls
|
||||
+ List of this member's client URLs to advertise to the rest of the cluster. These URLs can contain domain names.
|
||||
+ default: "http://localhost:2379,http://localhost:4001"
|
||||
+ env variable: ETCD_ADVERTISE_CLIENT_URLS
|
||||
+ example: "http://example.com:2379, http://10.0.0.1:2379"
|
||||
+ Be careful if you are advertising URLs such as http://localhost:2379 from a cluster member and are using the proxy feature of etcd. This will cause loops, because the proxy will be forwarding requests to itself until its resources (memory, file descriptors) are eventually depleted.
|
||||
|
||||
### --discovery
|
||||
+ Discovery URL used to bootstrap the cluster.
|
||||
+ default: none
|
||||
+ env variable: ETCD_DISCOVERY
|
||||
|
||||
### --discovery-srv
|
||||
+ DNS srv domain used to bootstrap the cluster.
|
||||
+ default: none
|
||||
+ env variable: ETCD_DISCOVERY_SRV
|
||||
|
||||
### --discovery-fallback
|
||||
+ Expected behavior ("exit" or "proxy") when discovery services fails.
|
||||
+ default: "proxy"
|
||||
+ env variable: ETCD_DISCOVERY_FALLBACK
|
||||
|
||||
### --discovery-proxy
|
||||
+ HTTP proxy to use for traffic to discovery service.
|
||||
+ default: none
|
||||
+ env variable: ETCD_DISCOVERY_PROXY
|
||||
|
||||
### --strict-reconfig-check
|
||||
+ Reject reconfiguration requests that would cause quorum loss.
|
||||
+ default: false
|
||||
+ env variable: ETCD_STRICT_RECONFIG_CHECK
|
||||
|
||||
## Proxy Flags
|
||||
|
||||
`--proxy` prefix flags configures etcd to run in [proxy mode][proxy].
|
||||
|
||||
### --proxy
|
||||
+ Proxy mode setting ("off", "readonly" or "on").
|
||||
+ default: "off"
|
||||
+ env variable: ETCD_PROXY
|
||||
|
||||
### --proxy-failure-wait
|
||||
+ Time (in milliseconds) an endpoint will be held in a failed state before being reconsidered for proxied requests.
|
||||
+ default: 5000
|
||||
+ env variable: ETCD_PROXY_FAILURE_WAIT
|
||||
|
||||
### --proxy-refresh-interval
|
||||
+ Time (in milliseconds) of the endpoints refresh interval.
|
||||
+ default: 30000
|
||||
+ env variable: ETCD_PROXY_REFRESH_INTERVAL
|
||||
|
||||
### --proxy-dial-timeout
|
||||
+ Time (in milliseconds) for a dial to timeout or 0 to disable the timeout
|
||||
+ default: 1000
|
||||
+ env variable: ETCD_PROXY_DIAL_TIMEOUT
|
||||
|
||||
### --proxy-write-timeout
|
||||
+ Time (in milliseconds) for a write to timeout or 0 to disable the timeout.
|
||||
+ default: 5000
|
||||
+ env variable: ETCD_PROXY_WRITE_TIMEOUT
|
||||
|
||||
### --proxy-read-timeout
|
||||
+ Time (in milliseconds) for a read to timeout or 0 to disable the timeout.
|
||||
+ Don't change this value if you use watches because they are using long polling requests.
|
||||
+ default: 0
|
||||
+ env variable: ETCD_PROXY_READ_TIMEOUT
|
||||
|
||||
## Security Flags
|
||||
|
||||
The security flags help to [build a secure etcd cluster][security].
|
||||
|
||||
### --ca-file [DEPRECATED]
|
||||
+ Path to the client server TLS CA file. `--ca-file ca.crt` could be replaced by `--trusted-ca-file ca.crt --client-cert-auth` and etcd will perform the same.
|
||||
+ default: none
|
||||
+ env variable: ETCD_CA_FILE
|
||||
|
||||
### --cert-file
|
||||
+ Path to the client server TLS cert file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_CERT_FILE
|
||||
|
||||
### --key-file
|
||||
+ Path to the client server TLS key file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_KEY_FILE
|
||||
|
||||
### --client-cert-auth
|
||||
+ Enable client cert authentication.
|
||||
+ default: false
|
||||
+ env variable: ETCD_CLIENT_CERT_AUTH
|
||||
|
||||
### --trusted-ca-file
|
||||
+ Path to the client server TLS trusted CA key file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_TRUSTED_CA_FILE
|
||||
|
||||
### --peer-ca-file [DEPRECATED]
|
||||
+ Path to the peer server TLS CA file. `--peer-ca-file ca.crt` could be replaced by `--peer-trusted-ca-file ca.crt --peer-client-cert-auth` and etcd will perform the same.
|
||||
+ default: none
|
||||
+ env variable: ETCD_PEER_CA_FILE
|
||||
|
||||
### --peer-cert-file
|
||||
+ Path to the peer server TLS cert file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_PEER_CERT_FILE
|
||||
|
||||
### --peer-key-file
|
||||
+ Path to the peer server TLS key file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_PEER_KEY_FILE
|
||||
|
||||
### --peer-client-cert-auth
|
||||
+ Enable peer client cert authentication.
|
||||
+ default: false
|
||||
+ env variable: ETCD_PEER_CLIENT_CERT_AUTH
|
||||
|
||||
### --peer-trusted-ca-file
|
||||
+ Path to the peer server TLS trusted CA file.
|
||||
+ default: none
|
||||
+ env variable: ETCD_PEER_TRUSTED_CA_FILE
|
||||
|
||||
## Logging Flags
|
||||
|
||||
### --debug
|
||||
+ Drop the default log level to DEBUG for all subpackages.
|
||||
+ default: false (INFO for all packages)
|
||||
+ env variable: ETCD_DEBUG
|
||||
|
||||
### --log-package-levels
|
||||
+ Set individual etcd subpackages to specific log levels. An example being `etcdserver=WARNING,security=DEBUG`
|
||||
+ default: none (INFO for all packages)
|
||||
+ env variable: ETCD_LOG_PACKAGE_LEVELS
|
||||
|
||||
|
||||
## Unsafe Flags
|
||||
|
||||
Please be CAUTIOUS when using unsafe flags because it will break the guarantees given by the consensus protocol.
|
||||
For example, it may panic if other members in the cluster are still alive.
|
||||
Follow the instructions when using these flags.
|
||||
|
||||
### --force-new-cluster
|
||||
+ Force to create a new one-member cluster. It commits configuration changes forcing to remove all existing members in the cluster and add itself. It needs to be set to [restore a backup][restore].
|
||||
+ default: false
|
||||
+ env variable: ETCD_FORCE_NEW_CLUSTER
|
||||
|
||||
## Experimental Flags
|
||||
|
||||
### --experimental-v3demo
|
||||
+ Enable experimental [v3 demo API][rfc-v3].
|
||||
+ default: false
|
||||
+ env variable: ETCD_EXPERIMENTAL_V3DEMO
|
||||
|
||||
## Miscellaneous Flags
|
||||
|
||||
### --version
|
||||
+ Print the version and exit.
|
||||
+ default: false
|
||||
|
||||
## Profiling flags
|
||||
|
||||
### --enable-pprof
|
||||
+ Enable runtime profiling data via HTTP server. Address is at client URL + "/debug/pprof"
|
||||
+ default: false
|
||||
|
||||
[build-cluster]: clustering.md#static
|
||||
[reconfig]: runtime-configuration.md
|
||||
[discovery]: clustering.md#discovery
|
||||
[iana-ports]: https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=etcd
|
||||
[proxy]: proxy.md
|
||||
[reconfig]: runtime-configuration.md
|
||||
[restore]: admin_guide.md#restoring-a-backup
|
||||
[rfc-v3]: rfc/v3api.md
|
||||
[security]: security.md
|
||||
[systemd-intro]: http://freedesktop.org/wiki/Software/systemd/
|
||||
[tuning]: tuning.md#time-parameters
|
@ -1,109 +0,0 @@
|
||||
# etcd release guide
|
||||
|
||||
The guide talks about how to release a new version of etcd.
|
||||
|
||||
The procedure includes some manual steps for sanity checking but it can probably be further scripted. Please keep this document up-to-date if you want to make changes to the release process.
|
||||
|
||||
## Prepare Release
|
||||
|
||||
Set desired version as environment variable for following steps. Here is an example to release 2.1.3:
|
||||
|
||||
```
|
||||
export VERSION=v2.1.3
|
||||
export PREV_VERSION=v2.1.2
|
||||
```
|
||||
|
||||
All releases version numbers follow the format of [semantic versioning 2.0.0](http://semver.org/).
|
||||
|
||||
### Major, Minor Version Release, or its Pre-release
|
||||
|
||||
- Ensure the relevant milestone on GitHub is complete. All referenced issues should be closed, or moved elsewhere.
|
||||
- Remove this release from [roadmap](https://github.com/coreos/etcd/blob/master/ROADMAP.md), if necessary.
|
||||
- Ensure the latest upgrade documentation is available.
|
||||
- Bump [hardcoded MinClusterVerion in the repository](https://github.com/coreos/etcd/blob/master/version/version.go#L29), if necessary.
|
||||
- Add feature capability maps for the new version, if necessary.
|
||||
|
||||
### Patch Version Release
|
||||
|
||||
- Discuss about commits that are backported to the patch release. The commits should not include merge commits.
|
||||
- Cherry-pick these commits starting from the oldest one into stable branch.
|
||||
|
||||
## Write Release Note
|
||||
|
||||
|
||||
- Write introduction for the new release. For example, what major bug we fix, what new features we introduce or what performance improvement we make.
|
||||
- Write changelog for the last release. ChangeLog should be straightforward and easy to understand for the end-user.
|
||||
- Put `[GH XXXX]` at the head of change line to reference Pull Request that introduces the change. Moreover, add a link on it to jump to the Pull Request.
|
||||
|
||||
## Tag Version
|
||||
|
||||
- Bump [hardcoded Version in the repository](https://github.com/coreos/etcd/blob/master/version/version.go#L30) to the latest version `${VERSION}`.
|
||||
- Ensure all tests on CI system are passed.
|
||||
- Manually check etcd is buildable in Linux, Darwin and Windows.
|
||||
- Manually check upgrade etcd cluster of previous minor version works well.
|
||||
- Manually check new features work well.
|
||||
- Add a signed tag through `git tag -s ${VERSION}`.
|
||||
- Sanity check tag correctness through `git show tags/$VERSION`.
|
||||
- Push the tag to GitHub through `git push origin tags/$VERSION`. This assumes `origin` corresponds to "https://github.com/coreos/etcd".
|
||||
|
||||
## Build Release Binaries and Images
|
||||
|
||||
- Ensure `actool` is available, or installing it through `go get github.com/appc/spec/actool`.
|
||||
- Ensure `docker` is available.
|
||||
|
||||
Run release script in root directory:
|
||||
|
||||
```
|
||||
./scripts/release.sh ${VERSION}
|
||||
```
|
||||
|
||||
It generates all release binaries and images under directory ./release.
|
||||
|
||||
## Sign Binaries and Images
|
||||
|
||||
Choose appropriate private key to sign the generated binaries and images.
|
||||
|
||||
The following commands are used for public release sign:
|
||||
|
||||
```
|
||||
cd release
|
||||
# personal GPG is okay for now
|
||||
for i in etcd-*{.zip,.tar.gz}; do gpg --sign ${i}; done
|
||||
# use `CoreOS ACI Builder <release@coreos.com>` secret key
|
||||
gpg -u 88182190 -a --output etcd-${VERSION}-linux-amd64.aci.asc --detach-sig etcd-${VERSION}-linux-amd64.aci
|
||||
```
|
||||
|
||||
## Publish Release Page in GitHub
|
||||
|
||||
- Set release title as the version name.
|
||||
- Follow the format of previous release pages.
|
||||
- Attach the generated binaries, aci image and signatures.
|
||||
- Select whether it is a pre-release.
|
||||
- Publish the release!
|
||||
|
||||
## Publish Docker Image in Quay.io
|
||||
|
||||
- Push docker image:
|
||||
|
||||
```
|
||||
docker login quay.io
|
||||
docker push quay.io/coreos/etcd:${VERSION}
|
||||
```
|
||||
|
||||
- Add `latest` tag to the new image on [quay.io](https://quay.io/repository/coreos/etcd?tag=latest&tab=tags) if this is a stable release.
|
||||
|
||||
## Announce to etcd-dev Googlegroup
|
||||
|
||||
- Follow the format of [previous release emails](https://groups.google.com/forum/#!forum/etcd-dev).
|
||||
- Make sure to include a list of authors that contributed since the previous release - something like the following might be handy:
|
||||
|
||||
```
|
||||
git log ...${PREV_VERSION} --pretty=format:"%an" | sort | uniq | tr '\n' ',' | sed -e 's#,#, #g' -e 's#, $##'
|
||||
```
|
||||
|
||||
- Send email to etcd-dev@googlegroups.com
|
||||
|
||||
## Post Release
|
||||
|
||||
- Create new stable branch through `git push origin ${VERSION_MAJOR}.${VERSION_MINOR}` if this is a major stable release. This assumes `origin` corresponds to "https://github.com/coreos/etcd".
|
||||
- Bump [hardcoded Version in the repository](https://github.com/coreos/etcd/blob/master/version/version.go#L30) to the version `${VERSION}+git`.
|
@ -1,114 +0,0 @@
|
||||
# Discovery Service Protocol
|
||||
|
||||
Discovery service protocol helps new etcd member to discover all other members in cluster bootstrap phase using a shared discovery URL.
|
||||
|
||||
Discovery service protocol is _only_ used in cluster bootstrap phase, and cannot be used for runtime reconfiguration or cluster monitoring.
|
||||
|
||||
The protocol uses a new discovery token to bootstrap one _unique_ etcd cluster. Remember that one discovery token can represent only one etcd cluster. As long as discovery protocol on this token starts, even if it fails halfway, it must not be used to bootstrap another etcd cluster.
|
||||
|
||||
The rest of this article will walk through the discovery process with examples that correspond to a self-hosted discovery cluster. The public discovery service, discovery.etcd.io, functions the same way, but with a layer of polish to abstract away ugly URLs, generate UUIDs automatically, and provide some protections against excessive requests. At its core, the public discovery service still uses an etcd cluster as the data store as described in this document.
|
||||
|
||||
## The Protocol Workflow
|
||||
|
||||
The idea of discovery protocol is to use an internal etcd cluster to coordinate bootstrap of a new cluster. First, all new members interact with discovery service and help to generate the expected member list. Then each new member bootstraps its server using this list, which performs the same functionality as -initial-cluster flag.
|
||||
|
||||
In the following example workflow, we will list each step of protocol in curl format for ease of understanding.
|
||||
|
||||
By convention the etcd discovery protocol uses the key prefix `_etcd/registry`. If `http://example.com` hosts an etcd cluster for discovery service, a full URL to discovery keyspace will be `http://example.com/v2/keys/_etcd/registry`. We will use this as the URL prefix in the example.
|
||||
|
||||
### Creating a New Discovery Token
|
||||
|
||||
Generate a unique token that will identify the new cluster. This will be used as a unique prefix in discovery keyspace in the following steps. An easy way to do this is to use `uuidgen`:
|
||||
|
||||
```
|
||||
UUID=$(uuidgen)
|
||||
```
|
||||
|
||||
### Specifying the Expected Cluster Size
|
||||
|
||||
You need to specify the expected cluster size for this discovery token. The size is used by the discovery service to know when it has found all members that will initially form the cluster.
|
||||
|
||||
```
|
||||
curl -X PUT http://example.com/v2/keys/_etcd/registry/${UUID}/_config/size -d value=${cluster_size}
|
||||
```
|
||||
|
||||
Usually the cluster size is 3, 5 or 7. Check [optimal cluster size][cluster-size] for more details.
|
||||
|
||||
### Bringing up etcd Processes
|
||||
|
||||
Now that you have your discovery URL, you can use it as `-discovery` flag and bring up etcd processes. Every etcd process will follow this next few steps internally if given a `-discovery` flag.
|
||||
|
||||
### Registering itself
|
||||
|
||||
The first thing for etcd process is to register itself into the discovery URL as a member. This is done by creating member ID as a key in the discovery URL.
|
||||
|
||||
```
|
||||
curl -X PUT http://example.com/v2/keys/_etcd/registry/${UUID}/${member_id}?prevExist=false -d value="${member_name}=${member_peer_url_1}&${member_name}=${member_peer_url_2}"
|
||||
```
|
||||
|
||||
### Checking the Status
|
||||
|
||||
It checks the expected cluster size and registration status in discovery URL, and decides what the next action is.
|
||||
|
||||
```
|
||||
curl -X GET http://example.com/v2/keys/_etcd/registry/${UUID}/_config/size
|
||||
curl -X GET http://example.com/v2/keys/_etcd/registry/${UUID}
|
||||
```
|
||||
|
||||
If registered members are still not enough, it will wait for left members to appear.
|
||||
|
||||
If the number of registered members is bigger than the expected size N, it treats the first N registered members as the member list for the cluster. If the member itself is in the member list, the discovery procedure succeeds and it fetches all peers through the member list. If it is not in the member list, the discovery procedure finishes with the failure that the cluster has been full.
|
||||
|
||||
In etcd implementation, the member may check the cluster status even before registering itself. So it could fail quickly if the cluster has been full.
|
||||
|
||||
### Waiting for All Members
|
||||
|
||||
|
||||
The wait process is described in detail in the [etcd API documentation][api].
|
||||
|
||||
```
|
||||
curl -X GET http://example.com/v2/keys/_etcd/registry/${UUID}?wait=true&waitIndex=${current_etcd_index}
|
||||
```
|
||||
|
||||
It keeps waiting until finding all members.
|
||||
|
||||
## Public Discovery Service
|
||||
|
||||
CoreOS Inc. hosts a public discovery service at https://discovery.etcd.io/ , which provides some nice features for ease of use.
|
||||
|
||||
### Mask Key Prefix
|
||||
|
||||
Public discovery service will redirect `https://discovery.etcd.io/${UUID}` to etcd cluster behind for the key at `/v2/keys/_etcd/registry`. It masks register key prefix for short and readable discovery url.
|
||||
|
||||
### Get new token
|
||||
|
||||
```
|
||||
GET /new
|
||||
|
||||
Sent query:
|
||||
size=${cluster_size}
|
||||
Possible status codes:
|
||||
200 OK
|
||||
400 Bad Request
|
||||
200 Body:
|
||||
generated discovery url
|
||||
```
|
||||
|
||||
The generation process in the service follows the steps from [Creating a New Discovery Token][new-discovery-token] to [Specifying the Expected Cluster Size][expected-cluster-size].
|
||||
|
||||
### Check Discovery Status
|
||||
|
||||
```
|
||||
GET /${UUID}
|
||||
```
|
||||
|
||||
You can check the status for this discovery token, including the machines that have been registered, by requesting the value of the UUID.
|
||||
|
||||
### Open-source repository
|
||||
|
||||
The repository is located at https://github.com/coreos/discovery.etcd.io. You could use it to build your own public discovery service.
|
||||
|
||||
[api]: api.md#waiting-for-a-change
|
||||
[cluster-size]: admin_guide.md#optimal-cluster-size
|
||||
[expected-cluster-size]: #specifying-the-expected-cluster-size
|
||||
[new-discovery-token]: #creating-a-new-discovery-token
|
@ -1,84 +0,0 @@
|
||||
# FAQ
|
||||
|
||||
## 1) Why can an etcd client read an old version of data when a majority of the etcd cluster members are down?
|
||||
|
||||
In situations where a client connects to a minority, etcd
|
||||
favors by default availability over consistency. This means that even though
|
||||
data might be “out of date”, it is still better to return something versus
|
||||
nothing.
|
||||
|
||||
In order to confirm that a read is up to date with a majority of the cluster,
|
||||
the client can use the `quorum=true` parameter on reads of keys. This means
|
||||
that a majority of the cluster is checked on reads before returning the data,
|
||||
otherwise the read will timeout and fail.
|
||||
|
||||
## 2) With quorum=false, doesn’t this mean that if my client switched the member it was connected to, that it could experience a logical ordering where the cluster goes backwards in time?
|
||||
|
||||
Yes, but this could be handled at the etcd client implementation via
|
||||
remembering the last seen index. The “index” is the cluster's single
|
||||
irrevocable sequence of the entire modification history. The client could
|
||||
remember the last seen index, and determine via comparing the index returned on
|
||||
the GET whether or not the state of the key-value pair is before or after its
|
||||
last seen state.
|
||||
|
||||
## 3) What happens if a watch is registered on a minority member?
|
||||
|
||||
The watch will stay untriggered, even as modifications are occurring in the
|
||||
majority quorum. This is an open issue, and is being addressed in v3. There are
|
||||
multiple ways to work around the watch trigger not firing.
|
||||
|
||||
1) build a signaling mechanism independent of etcd. This could be as simple as
|
||||
a “pulse” to the client to reissue a GET with quorum=true for the most recent
|
||||
version of the data.
|
||||
|
||||
2) poll on the `/v2/keys` endpoint and check that the raft-index is increasing every
|
||||
timeout.
|
||||
|
||||
## 4) What is a proxy used for?
|
||||
|
||||
A proxy is a redirection server to the etcd cluster. The proxy handles the
|
||||
redirection of a client to the current configuration of the etcd cluster. A
|
||||
typical use case is to start a proxy on a machine, and on first boot up of the
|
||||
proxy specify both the `--proxy` flag and the `--initial-cluster` flag.
|
||||
|
||||
From there, any etcdctl client that starts up automatically speaks to the local
|
||||
proxy and the proxy redirects operations to the current configuration of the
|
||||
cluster it was originally paired with.
|
||||
|
||||
In the v2 spec of etcd, proxies cannot be promoted to members of the cluster.
|
||||
They also cannot be promoted to followers or at any point become part of the
|
||||
replication of the etcd cluster itself.
|
||||
|
||||
## 5) How is cluster membership and health handled in etcd v2?
|
||||
|
||||
The design goal of etcd is that reconfiguration is simply an API, and health
|
||||
monitoring and addition/removal of members is up to the individual application
|
||||
and their integration with the reconfiguration API.
|
||||
|
||||
Thus, a member that is down, even infinitely, will never be automatically
|
||||
removed from the etcd cluster member list.
|
||||
|
||||
This makes sense because it's usually an application level / administrative
|
||||
action to determine whether a reconfiguration should happen based on health.
|
||||
|
||||
For more information, refer to the [runtime reconfiguration design document][runtime-reconf-design].
|
||||
|
||||
## 6) how does --endpoint work with etcdctl?
|
||||
|
||||
The `--endpoint` flag can specify any number of etcd cluster members in a comma
|
||||
separated list. This list might be a subset, equal to, or more than the actual
|
||||
etcd cluster member list itself.
|
||||
|
||||
If only one peer is specified via the `--endpoint` flag, the etcdctl discovers the
|
||||
rest of the cluster via the member list of that one peer, and then it randomly
|
||||
chooses a member to use. Again, the client can use the `quorum=true` flag on
|
||||
reads, which will always fail when using a member in the minority.
|
||||
|
||||
If peers from multiple clusters are specified via the `--endpoint` flag, etcdctl
|
||||
will randomly choose a peer, and the request will simply get routed to one of
|
||||
the clusters. This is probably not what you want.
|
||||
|
||||
Note: --peers flag is now deprecated and --endpoint should be used instead,
|
||||
as it might confuse users to give etcdctl a peerURL.
|
||||
|
||||
[runtime-reconf-design]: runtime-reconf-design.md
|
@ -1,65 +0,0 @@
|
||||
# FAQ
|
||||
|
||||
## Initial Bootstrapping UX
|
||||
|
||||
etcd initial bootstrapping is done via command line flags such as
|
||||
`--initial-cluster` or `--discovery`. These flags can safely be left on the
|
||||
command line after your cluster is running but they will be ignored if you have
|
||||
a non-empty data dir. So, why did we decide to have this sort of odd UX?
|
||||
|
||||
One of the design goals of etcd is easy bringup of clusters using a one-shot
|
||||
static configuration like AWS Cloud Formation, PXE booting, etc. Essentially we
|
||||
want to describe several virtual machines and bring them all up at once into an
|
||||
etcd cluster.
|
||||
|
||||
To achieve this sort of hands-free cluster bootstrap we had two other options:
|
||||
|
||||
**API to bootstrap**
|
||||
|
||||
This is problematic because it cannot be coordinated from a single service file
|
||||
and we didn't want to have the etcd socket listening but unresponsive to
|
||||
clients for an unbound period of time.
|
||||
|
||||
It would look something like this:
|
||||
|
||||
```
|
||||
ExecStart=/usr/bin/etcd
|
||||
ExecStartPost/usr/bin/etcd init localhost:2379 --cluster=
|
||||
```
|
||||
|
||||
**etcd init subcommand**
|
||||
|
||||
```
|
||||
etcd init --cluster='default=http://localhost:2380,default=http://localhost:7001'...
|
||||
etcd init --discovery https://discovery-example.etcd.io/193e4
|
||||
```
|
||||
|
||||
Then after running an init step you would execute `etcd`. This however
|
||||
introduced problems: we now have to define a hand-off protocol between the etcd
|
||||
init process and the etcd binary itself. This is hard to coordinate in a single
|
||||
service file such as:
|
||||
|
||||
```
|
||||
ExecStartPre=/usr/bin/etcd init --cluster=....
|
||||
ExecStart=/usr/bin/etcd
|
||||
```
|
||||
|
||||
There are several error cases:
|
||||
|
||||
0) Init has already run and the data directory is already configured
|
||||
1) Discovery fails because of network timeout, etc
|
||||
2) Discovery fails because the cluster is already full and etcd needs to fall back to proxy
|
||||
3) Static cluster configuration fails because of conflict, misconfiguration or timeout
|
||||
|
||||
In hindsight we could have made this work by doing:
|
||||
|
||||
```
|
||||
rc status
|
||||
0 Init already ran
|
||||
1 Discovery fails on network timeout, etc
|
||||
0 Discovery fails for cluster full, coordinate via proxy state file
|
||||
1 Static cluster configuration failed
|
||||
```
|
||||
|
||||
Perhaps we can add the init command in a future version and deprecate if the UX
|
||||
continues to confuse people.
|
@ -1,124 +0,0 @@
|
||||
# Libraries and Tools
|
||||
|
||||
**Tools**
|
||||
|
||||
- [etcdctl](https://github.com/coreos/etcd/tree/master/etcdctl) - A command line client for etcd
|
||||
- [etcd-backup](https://github.com/fanhattan/etcd-backup) - A powerful command line utility for dumping/restoring etcd - Supports v2
|
||||
- [etcd-dump](https://npmjs.org/package/etcd-dump) - Command line utility for dumping/restoring etcd.
|
||||
- [etcd-fs](https://github.com/xetorthio/etcd-fs) - FUSE filesystem for etcd
|
||||
- [etcddir](https://github.com/rekby/etcddir) - Realtime sync etcd and local directory. Work with windows and linux.
|
||||
- [etcd-browser](https://github.com/henszey/etcd-browser) - A web-based key/value editor for etcd using AngularJS
|
||||
- [etcd-lock](https://github.com/datawisesystems/etcd-lock) - Master election & distributed r/w lock implementation using etcd - Supports v2
|
||||
- [etcd-console](https://github.com/matishsiao/etcd-console) - A web-base key/value editor for etcd using PHP
|
||||
- [etcd-viewer](https://github.com/nikfoundas/etcd-viewer) - An etcd key-value store editor/viewer written in Java
|
||||
- [etcdtool](https://github.com/mickep76/etcdtool) - Export/Import/Edit etcd directory as JSON/YAML/TOML and Validate directory using JSON schema
|
||||
- [etcd-rest](https://github.com/mickep76/etcd-rest) - Create generic REST API in Go using etcd as a backend with validation using JSON schema
|
||||
- [etcdsh](https://github.com/kamilhark/etcdsh) - A command line client with support of command history and tab completion. Supports v2
|
||||
|
||||
**Go libraries**
|
||||
|
||||
- [etcd/client](https://github.com/coreos/etcd/blob/master/client) - the officially maintained Go client
|
||||
- [go-etcd](https://github.com/coreos/go-etcd) - the deprecated official client. May be useful for older (<2.0.0) versions of etcd.
|
||||
|
||||
**Java libraries**
|
||||
|
||||
- [boonproject/etcd](https://github.com/boonproject/boon/blob/master/etcd/README.md) - Supports v2, Async/Sync and waits
|
||||
- [justinsb/jetcd](https://github.com/justinsb/jetcd)
|
||||
- [diwakergupta/jetcd](https://github.com/diwakergupta/jetcd) - Supports v2
|
||||
- [jurmous/etcd4j](https://github.com/jurmous/etcd4j) - Supports v2, Async/Sync, waits and SSL
|
||||
- [AdoHe/etcd4j](http://github.com/AdoHe/etcd4j) - Supports v2 (enhance for real production cluster)
|
||||
|
||||
**Python libraries**
|
||||
|
||||
- [jplana/python-etcd](https://github.com/jplana/python-etcd) - Supports v2
|
||||
- [russellhaering/txetcd](https://github.com/russellhaering/txetcd) - a Twisted Python library
|
||||
- [cholcombe973/autodock](https://github.com/cholcombe973/autodock) - A docker deployment automation tool
|
||||
- [lisael/aioetcd](https://github.com/lisael/aioetcd) - (Python 3.4+) Asyncio coroutines client (Supports v2)
|
||||
|
||||
**Node libraries**
|
||||
|
||||
- [stianeikeland/node-etcd](https://github.com/stianeikeland/node-etcd) - Supports v2 (w Coffeescript)
|
||||
- [lavagetto/nodejs-etcd](https://github.com/lavagetto/nodejs-etcd) - Supports v2
|
||||
- [deedubs/node-etcd-config](https://github.com/deedubs/node-etcd-config) - Supports v2
|
||||
|
||||
**Ruby libraries**
|
||||
|
||||
- [iconara/etcd-rb](https://github.com/iconara/etcd-rb)
|
||||
- [jpfuentes2/etcd-ruby](https://github.com/jpfuentes2/etcd-ruby)
|
||||
- [ranjib/etcd-ruby](https://github.com/ranjib/etcd-ruby) - Supports v2
|
||||
|
||||
**C libraries**
|
||||
|
||||
- [jdarcy/etcd-api](https://github.com/jdarcy/etcd-api) - Supports v2
|
||||
- [shafreeck/cetcd](https://github.com/shafreeck/cetcd) - Supports v2
|
||||
|
||||
**C++ libraries**
|
||||
- [edwardcapriolo/etcdcpp](https://github.com/edwardcapriolo/etcdcpp) - Supports v2
|
||||
- [suryanathan/etcdcpp](https://github.com/suryanathan/etcdcpp) - Supports v2 (with waits)
|
||||
|
||||
**Clojure libraries**
|
||||
|
||||
- [aterreno/etcd-clojure](https://github.com/aterreno/etcd-clojure)
|
||||
- [dwwoelfel/cetcd](https://github.com/dwwoelfel/cetcd) - Supports v2
|
||||
- [rthomas/clj-etcd](https://github.com/rthomas/clj-etcd) - Supports v2
|
||||
|
||||
**Erlang libraries**
|
||||
|
||||
- [marshall-lee/etcd.erl](https://github.com/marshall-lee/etcd.erl)
|
||||
|
||||
**.Net Libraries**
|
||||
|
||||
- [wangjia184/etcdnet](https://github.com/wangjia184/etcdnet) - Supports v2
|
||||
- [drusellers/etcetera](https://github.com/drusellers/etcetera)
|
||||
|
||||
**PHP Libraries**
|
||||
|
||||
- [linkorb/etcd-php](https://github.com/linkorb/etcd-php)
|
||||
|
||||
**Haskell libraries**
|
||||
|
||||
- [wereHamster/etcd-hs](https://github.com/wereHamster/etcd-hs)
|
||||
|
||||
**R libraries**
|
||||
|
||||
- [ropensci/etseed](https://github.com/ropensci/etseed)
|
||||
|
||||
**Tcl libraries**
|
||||
|
||||
- [efrecon/etcd-tcl](https://github.com/efrecon/etcd-tcl) - Supports v2, except wait.
|
||||
|
||||
**Chef Integration**
|
||||
|
||||
- [coderanger/etcd-chef](https://github.com/coderanger/etcd-chef)
|
||||
|
||||
**Chef Cookbook**
|
||||
|
||||
- [spheromak/etcd-cookbook](https://github.com/spheromak/etcd-cookbook)
|
||||
|
||||
**BOSH Releases**
|
||||
|
||||
- [cloudfoundry-community/etcd-boshrelease](https://github.com/cloudfoundry-community/etcd-boshrelease)
|
||||
- [cloudfoundry/cf-release](https://github.com/cloudfoundry/cf-release/tree/master/jobs/etcd)
|
||||
|
||||
**Projects using etcd**
|
||||
|
||||
- [binocarlos/yoda](https://github.com/binocarlos/yoda) - etcd + ZeroMQ
|
||||
- [calavera/active-proxy](https://github.com/calavera/active-proxy) - HTTP Proxy configured with etcd
|
||||
- [derekchiang/etcdplus](https://github.com/derekchiang/etcdplus) - A set of distributed synchronization primitives built upon etcd
|
||||
- [go-discover](https://github.com/flynn/go-discover) - service discovery in Go
|
||||
- [gleicon/goreman](https://github.com/gleicon/goreman/tree/etcd) - Branch of the Go Foreman clone with etcd support
|
||||
- [garethr/hiera-etcd](https://github.com/garethr/hiera-etcd) - Puppet hiera backend using etcd
|
||||
- [mattn/etcd-vim](https://github.com/mattn/etcd-vim) - SET and GET keys from inside vim
|
||||
- [mattn/etcdenv](https://github.com/mattn/etcdenv) - "env" shebang with etcd integration
|
||||
- [kelseyhightower/confd](https://github.com/kelseyhightower/confd) - Manage local app config files using templates and data from etcd
|
||||
- [configdb](https://git.autistici.org/ai/configdb/tree/master) - A REST relational abstraction on top of arbitrary database backends, aimed at storing configs and inventories.
|
||||
- [scrz](https://github.com/scrz/scrz) - Container manager, stores configuration in etcd.
|
||||
- [fleet](https://github.com/coreos/fleet) - Distributed init system
|
||||
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes) - Container cluster manager introduced by Google.
|
||||
- [mailgun/vulcand](https://github.com/mailgun/vulcand) - HTTP proxy that uses etcd as a configuration backend.
|
||||
- [duedil-ltd/discodns](https://github.com/duedil-ltd/discodns) - Simple DNS nameserver using etcd as a database for names and records.
|
||||
- [skynetservices/skydns](https://github.com/skynetservices/skydns) - RFC compliant DNS server
|
||||
- [xordataexchange/crypt](https://github.com/xordataexchange/crypt) - Securely store values in etcd using GPG encryption
|
||||
- [spf13/viper](https://github.com/spf13/viper) - Go configuration library, reads values from ENV, pflags, files, and etcd with optional encryption
|
||||
- [lytics/metafora](https://github.com/lytics/metafora) - Go distributed task library
|
||||
- [ryandoyle/nss-etcd](https://github.com/ryandoyle/nss-etcd) - A GNU libc NSS module for resolving names from etcd.
|
@ -1,143 +0,0 @@
|
||||
# Metrics
|
||||
|
||||
etcd uses [Prometheus][prometheus] for metrics reporting. The metrics can be used for real-time monitoring and debugging. etcd does not persist its metrics; if a member restarts, the metrics will be reset.
|
||||
|
||||
The simplest way to see the available metrics is to cURL the metrics endpoint `/metrics`. The format is described [here](http://prometheus.io/docs/instrumenting/exposition_formats/).
|
||||
|
||||
Follow the [Prometheus getting started doc][prometheus-getting-started] to spin up a Prometheus server to collect etcd metrics.
|
||||
|
||||
The naming of metrics follows the suggested [Prometheus best practices][prometheus-naming]. A metric name has an `etcd` or `etcd_debugging` prefix as its namespace and a subsystem prefix (for example `wal` and `etcdserver`).
|
||||
|
||||
## etcd namespace metrics
|
||||
|
||||
The metrics under the `etcd` prefix are for monitoring and alerting. They are stable high level metrics. If there is any change of these metrics, it will be included in release notes.
|
||||
|
||||
### http requests
|
||||
|
||||
These metrics describe the serving of requests (non-watch events) served by etcd members in non-proxy mode: total
|
||||
incoming requests, request failures and processing latency (inc. raft rounds for storage). They are useful for tracking
|
||||
user-generated traffic hitting the etcd cluster .
|
||||
|
||||
All these metrics are prefixed with `etcd_http_`
|
||||
|
||||
| Name | Description | Type |
|
||||
|--------------------------------|-----------------------------------------------------------------------------------------|--------------------|
|
||||
| received_total | Total number of events after parsing and auth. | Counter(method) |
|
||||
| failed_total | Total number of failed events. | Counter(method,error) |
|
||||
| successful_duration_seconds | Bucketed handling times of the requests, including raft rounds for writes. | Histogram(method) |
|
||||
|
||||
|
||||
Example Prometheus queries that may be useful from these metrics (across all etcd members):
|
||||
|
||||
* `sum(rate(etcd_http_failed_total{job="etcd"}[1m]) by (method) / sum(rate(etcd_http_events_received_total{job="etcd"})[1m]) by (method)`
|
||||
|
||||
Shows the fraction of events that failed by HTTP method across all members, across a time window of `1m`.
|
||||
|
||||
* `sum(rate(etcd_http_received_total{job="etcd",method="GET})[1m]) by (method)`
|
||||
`sum(rate(etcd_http_received_total{job="etcd",method~="GET})[1m]) by (method)`
|
||||
|
||||
Shows the rate of successful readonly/write queries across all servers, across a time window of `1m`.
|
||||
|
||||
* `histogram_quantile(0.9, sum(rate(etcd_http_successful_duration_seconds{job="etcd",method="GET"}[5m]) ) by (le))`
|
||||
`histogram_quantile(0.9, sum(rate(etcd_http_successful_duration_seconds{job="etcd",method!="GET"}[5m]) ) by (le))`
|
||||
|
||||
Show the 0.90-tile latency (in seconds) of read/write (respectively) event handling across all members, with a window of `5m`.
|
||||
|
||||
### proxy
|
||||
|
||||
etcd members operating in proxy mode do not directly perform store operations. They forward all requests to cluster instances.
|
||||
|
||||
Tracking the rate of requests coming from a proxy allows one to pin down which machine is performing most reads/writes.
|
||||
|
||||
All these metrics are prefixed with `etcd_proxy_`
|
||||
|
||||
| Name | Description | Type |
|
||||
|---------------------------|-----------------------------------------------------------------------------------------|--------------------|
|
||||
| requests_total | Total number of requests by this proxy instance. | Counter(method) |
|
||||
| handled_total | Total number of fully handled requests, with responses from etcd members. | Counter(method) |
|
||||
| dropped_total | Total number of dropped requests due to forwarding errors to etcd members. | Counter(method,error) |
|
||||
| handling_duration_seconds | Bucketed handling times by HTTP method, including round trip to member instances. | Histogram(method) |
|
||||
|
||||
Example Prometheus queries that may be useful from these metrics (across all etcd servers):
|
||||
|
||||
* `sum(rate(etcd_proxy_handled_total{job="etcd"}[1m])) by (method)`
|
||||
|
||||
Rate of requests (by HTTP method) handled by all proxies, across a window of `1m`.
|
||||
|
||||
* `histogram_quantile(0.9, sum(rate(handling_duration_seconds{job="etcd",method="GET"}[5m])) by (le))`
|
||||
`histogram_quantile(0.9, sum(rate(handling_duration_seconds{job="etcd",method!="GET"}[5m])) by (le))`
|
||||
|
||||
Show the 0.90-tile latency (in seconds) of handling of user requests across all proxy machines, with a window of `5m`.
|
||||
|
||||
* `sum(rate(etcd_proxy_dropped_total{job="etcd"}[1m])) by (proxying_error)`
|
||||
|
||||
Number of failed request on the proxy. This should be 0, spikes here indicate connectivity issues to the etcd cluster.
|
||||
|
||||
## etcd_debugging namespace metrics
|
||||
|
||||
The metrics under the `etcd_debugging` prefix are for debugging. They are very implementation dependent and volatile. They might be changed or removed without any warning in new etcd releases. Some of the metrics might be moved to the `etcd` prefix when they become more stable.
|
||||
|
||||
### etcdserver
|
||||
|
||||
| Name | Description | Type |
|
||||
|-----------------------------------------|--------------------------------------------------|-----------|
|
||||
| proposal_duration_seconds | The latency distributions of committing proposal | Histogram |
|
||||
| proposals_pending | The current number of pending proposals | Gauge |
|
||||
| proposals_failed_total | The total number of failed proposals | Counter |
|
||||
|
||||
[Proposal][glossary-proposal] duration (`proposal_duration_seconds`) provides a proposal commit latency histogram. The reported latency reflects network and disk IO delays in etcd.
|
||||
|
||||
Proposals pending (`proposals_pending`) indicates how many proposals are queued for commit. Rising pending proposals suggests there is a high client load or the cluster is unstable.
|
||||
|
||||
Failed proposals (`proposals_failed_total`) are normally related to two issues: temporary failures related to a leader election or longer duration downtime caused by a loss of quorum in the cluster.
|
||||
|
||||
### wal
|
||||
|
||||
| Name | Description | Type |
|
||||
|------------------------------------|--------------------------------------------------|-----------|
|
||||
| fsync_duration_seconds | The latency distributions of fsync called by wal | Histogram |
|
||||
| last_index_saved | The index of the last entry saved by wal | Gauge |
|
||||
|
||||
Abnormally high fsync duration (`fsync_duration_seconds`) indicates disk issues and might cause the cluster to be unstable.
|
||||
|
||||
### snapshot
|
||||
|
||||
| Name | Description | Type |
|
||||
|--------------------------------------------|------------------------------------------------------------|-----------|
|
||||
| snapshot_save_total_duration_seconds | The total latency distributions of save called by snapshot | Histogram |
|
||||
|
||||
Abnormally high snapshot duration (`snapshot_save_total_duration_seconds`) indicates disk issues and might cause the cluster to be unstable.
|
||||
|
||||
### rafthttp
|
||||
|
||||
| Name | Description | Type | Labels |
|
||||
|-----------------------------------|--------------------------------------------|--------------|--------------------------------|
|
||||
| message_sent_latency_seconds | The latency distributions of messages sent | HistogramVec | sendingType, msgType, remoteID |
|
||||
| message_sent_failed_total | The total number of failed messages sent | Summary | sendingType, msgType, remoteID |
|
||||
|
||||
|
||||
Abnormally high message duration (`message_sent_latency_seconds`) indicates network issues and might cause the cluster to be unstable.
|
||||
|
||||
An increase in message failures (`message_sent_failed_total`) indicates more severe network issues and might cause the cluster to be unstable.
|
||||
|
||||
Label `sendingType` is the connection type to send messages. `message`, `msgapp` and `msgappv2` use HTTP streaming, while `pipeline` does HTTP request for each message.
|
||||
|
||||
Label `msgType` is the type of raft message. `MsgApp` is log replication messages; `MsgSnap` is snapshot install messages; `MsgProp` is proposal forward messages; the others maintain internal raft status. Given large snapshots, a lengthy msgSnap transmission latency should be expected. For other types of messages, given enough network bandwidth, latencies comparable to ping latency should be expected.
|
||||
|
||||
Label `remoteID` is the member ID of the message destination.
|
||||
|
||||
## Prometheus supplied metrics
|
||||
|
||||
The Prometheus client library provides a number of metrics under the `go` and `process` namespaces. There are a few that are particlarly interesting.
|
||||
|
||||
| Name | Description | Type |
|
||||
|-----------------------------------|--------------------------------------------|--------------|
|
||||
| process_open_fds | Number of open file descriptors. | Gauge |
|
||||
| process_max_fds | Maximum number of open file descriptors. | Gauge |
|
||||
|
||||
Heavy file descriptor (`process_open_fds`) usage (i.e., near the process's file descriptor limit, `process_max_fds`) indicates a potential file descriptor exhaustion issue. If the file descriptors are exhausted, etcd may panic because it cannot create new WAL files.
|
||||
|
||||
[glossary-proposal]: glossary.md#proposal
|
||||
[prometheus]: http://prometheus.io/
|
||||
[prometheus-getting-started]: http://prometheus.io/docs/introduction/getting_started/
|
||||
[prometheus-naming]: http://prometheus.io/docs/practices/naming/
|
@ -1,28 +0,0 @@
|
||||
# Miscellaneous APIs
|
||||
|
||||
* [Getting the etcd version](#getting-the-etcd-version)
|
||||
* [Checking health of an etcd member node](#checking-health-of-an-etcd-member-node)
|
||||
|
||||
## Getting the etcd version
|
||||
|
||||
The etcd version of a specific instance can be obtained from the `/version` endpoint.
|
||||
|
||||
```sh
|
||||
curl -L http://127.0.0.1:2379/version
|
||||
```
|
||||
|
||||
```
|
||||
etcd 2.0.12
|
||||
```
|
||||
|
||||
## Checking health of an etcd member node
|
||||
|
||||
etcd provides a `/health` endpoint to verify the health of a particular member.
|
||||
|
||||
```sh
|
||||
curl http://10.0.0.10:2379/health
|
||||
```
|
||||
|
||||
```json
|
||||
{"health": "true"}
|
||||
```
|
@ -1,62 +0,0 @@
|
||||
# FreeBSD
|
||||
|
||||
Starting with version 0.1.2 both etcd and etcdctl have been ported to FreeBSD and can
|
||||
be installed either via packages or ports system. Their versions have been recently
|
||||
updated to 0.2.0 so now you can enjoy using etcd and etcdctl on FreeBSD 10.0 (RC4 as
|
||||
of now) and 9.x where they have been tested. They might also work when installed from
|
||||
ports on earlier versions of FreeBSD, but your mileage may vary.
|
||||
|
||||
## Installation
|
||||
|
||||
### Using pkgng package system
|
||||
|
||||
1. If you do not have pkgng installed, install it with command `pkg` and answering 'Y'
|
||||
when asked
|
||||
|
||||
2. Update your repository data with `pkg update`
|
||||
|
||||
3. Install etcd with `pkg install coreos-etcd coreos-etcdctl`
|
||||
|
||||
4. Verify successful installation with `pkg info | grep etcd` and you should get:
|
||||
|
||||
```
|
||||
r@fbsd10:/ # pkg info | grep etcd
|
||||
coreosetcd0.2.0 Highlyavailable key value store and service discovery
|
||||
coreosetcdctl0.2.0 Simple commandline client for etcd
|
||||
r@fbsd10:/ #
|
||||
```
|
||||
|
||||
5. You’re ready to use etcd and etcdctl! For more information about using pkgng, please
|
||||
see: http://www.freebsd.org/doc/handbook/pkgngintro.html
|
||||
|
||||
### Using ports system
|
||||
|
||||
1. If you do not have ports installed, install with with `portsnap fetch extract` (it
|
||||
may take some time depending on your hardware and network connection)
|
||||
|
||||
2. Build etcd with `cd /usr/ports/devel/etcd && make install clean`, you
|
||||
will get an option to build and install documentation and etcdctl with it.
|
||||
|
||||
3. If you haven't installed it with etcdctl, and you would like to install it later, you can build it
|
||||
with `cd /usr/ports/devel/etcdctl && make install clean`
|
||||
|
||||
4. Verify successful installation with `pkg info | grep etcd` and you should get:
|
||||
|
||||
|
||||
```
|
||||
r@fbsd10:/ # pkg info | grep etcd
|
||||
coreosetcd0.2.0 Highlyavailable key value store and service discovery
|
||||
coreosetcdctl0.2.0 Simple commandline client for etcd
|
||||
r@fbsd10:/ #
|
||||
```
|
||||
|
||||
5. You’re ready to use etcd and etcdctl! For more information about using ports system,
|
||||
please see: https://www.freebsd.org/doc/handbook/portsusing.html
|
||||
|
||||
## Issues
|
||||
|
||||
If you find any issues with the build/install procedure or you've found a problem that
|
||||
you've verified is local to FreeBSD version only (for example, by not being able to
|
||||
reproduce it on any other platform, like OSX or Linux), please sent a
|
||||
problem report using this page for more
|
||||
information: http://www.freebsd.org/sendpr.html
|
@ -1,51 +0,0 @@
|
||||
# Production Users
|
||||
|
||||
This document tracks people and use cases for etcd in production. By creating a list of production use cases we hope to build a community of advisors that we can reach out to with experience using various etcd applications, operation environments, and cluster sizes. The etcd development team may reach out periodically to check-in on your experience and update this list.
|
||||
|
||||
## discovery.etcd.io
|
||||
|
||||
- *Application*: https://github.com/coreos/discovery.etcd.io
|
||||
- *Launched*: Feb. 2014
|
||||
- *Cluster Size*: 5 members, 5 discovery proxies
|
||||
- *Order of Data Size*: 100s of Megabytes
|
||||
- *Operator*: CoreOS, brandon.philips@coreos.com
|
||||
- *Environment*: AWS
|
||||
- *Backups*: Periodic async to S3
|
||||
|
||||
discovery.etcd.io is the longest continuously running etcd backed service that we know about. It is the basis of automatic cluster bootstrap and was launched in Feb. 2014: https://coreos.com/blog/etcd-0.3.0-released/.
|
||||
|
||||
## OpenTable
|
||||
|
||||
- *Application*: OpenTable internal service discovery and cluster configuration management
|
||||
- *Launched*: May 2014
|
||||
- *Cluster Size*: 3 members each in 6 independent clusters; approximately 50 nodes reading / writing
|
||||
- *Order of Data Size*: 10s of MB
|
||||
- *Operator*: OpenTable, Inc; sschlansker@opentable.com
|
||||
- *Environment*: AWS, VMWare
|
||||
- *Backups*: None, all data can be re-created if necessary.
|
||||
|
||||
## cycoresys.com
|
||||
|
||||
- *Application*: multiple
|
||||
- *Launched*: Jul. 2014
|
||||
- *Cluster Size*: 3 members, _n_ proxies
|
||||
- *Order of Data Size*: 100s of kilobytes
|
||||
- *Operator*: CyCore Systems, Inc, sys@cycoresys.com
|
||||
- *Environment*: Baremetal
|
||||
- *Backups*: Periodic sync to Ceph RadosGW and DigitalOcean VM
|
||||
|
||||
CyCore Systems provides architecture and engineering for computing systems. This cluster provides microservices, virtual machines, databases, storage clusters to a number of clients. It is built on CoreOS machines, with each machine in the cluster running etcd as a peer or proxy.
|
||||
|
||||
## Radius Intelligence
|
||||
|
||||
- *Application*: multiple internal tools, Kubernetes clusters, bootstrappable system configs
|
||||
- *Launched*: June 2015
|
||||
- *Cluster Size*: 2 clusters of 5 and 3 members; approximately a dozen nodes read/write
|
||||
- *Order of Data Size*: 100s of kilobytes
|
||||
- *Operator*: Radius Intelligence; jcderr@radius.com
|
||||
- *Environment*: AWS, CoreOS, Kubernetes
|
||||
- *Backups*: None, all data can be recreated if necessary.
|
||||
|
||||
Radius Intelligence uses Kubernetes running CoreOS to containerize and scale internal toolsets. Examples include running [JetBrains TeamCity][teamcity] and internal AWS security and cost reporting tools. etcd clusters back these clusters as well as provide some basic environment bootstrapping configuration keys.
|
||||
|
||||
[teamcity]: https://www.jetbrains.com/teamcity/
|
@ -1,153 +0,0 @@
|
||||
# Proxy
|
||||
|
||||
etcd can run as a transparent proxy. Doing so allows for easy discovery of etcd within your infrastructure, since it can run on each machine as a local service. In this mode, etcd acts as a reverse proxy and forwards client requests to an active etcd cluster. The etcd proxy does not participate in the consensus replication of the etcd cluster, thus it neither increases the resilience nor decreases the write performance of the etcd cluster.
|
||||
|
||||
etcd currently supports two proxy modes: `readwrite` and `readonly`. The default mode is `readwrite`, which forwards both read and write requests to the etcd cluster. A `readonly` etcd proxy only forwards read requests to the etcd cluster, and returns `HTTP 501` to all write requests.
|
||||
|
||||
The proxy will shuffle the list of cluster members periodically to avoid sending all connections to a single member.
|
||||
|
||||
The member list used by an etcd proxy consists of all client URLs advertised in the cluster. These client URLs are specified in each etcd cluster member's `advertise-client-urls` option.
|
||||
|
||||
An etcd proxy examines several command-line options to discover its peer URLs. In order of precedence, these options are `discovery`, `discovery-srv`, and `initial-cluster`. The `initial-cluster` option is set to a comma-separated list of one or more etcd peer URLs used temporarily in order to discover the permanent cluster.
|
||||
|
||||
After establishing a list of peer URLs in this manner, the proxy retrieves the list of client URLs from the first reachable peer. These client URLs are specified by the `advertise-client-urls` option to etcd peers. The proxy then continues to connect to the first reachable etcd cluster member every thirty seconds to refresh the list of client URLs.
|
||||
|
||||
While etcd proxies therefore do not need to be given the `advertise-client-urls` option, as they retrieve this configuration from the cluster, this implies that `initial-cluster` must be set correctly for every proxy, and the `advertise-client-urls` option must be set correctly for every non-proxy, first-order cluster peer. Otherwise, requests to any etcd proxy would be forwarded improperly. Take special care not to set the `advertise-client-urls` option to URLs that point to the proxy itself, as such a configuration will cause the proxy to enter a loop, forwarding requests to itself until resources are exhausted. To correct either case, stop etcd and restart it with the correct URLs.
|
||||
|
||||
[This example Procfile][procfile] illustrates the difference in the etcd peer and proxy command lines used to configure and start a cluster with one proxy under the [goreman process management utility][goreman].
|
||||
|
||||
To summarize etcd proxy startup and peer discovery:
|
||||
|
||||
1. etcd proxies execute the following steps in order until the cluster *peer-urls* are known:
|
||||
1. If `discovery` is set for the proxy, ask the given discovery service for
|
||||
the *peer-urls*. The *peer-urls* will be the combined
|
||||
`initial-advertise-peer-urls` of all first-order, non-proxy cluster
|
||||
members.
|
||||
2. If `discovery-srv` is set for the proxy, the *peer-urls* are discovered
|
||||
from DNS.
|
||||
3. If `initial-cluster` is set for the proxy, that will become the value of
|
||||
*peer-urls*.
|
||||
4. Otherwise use the default value of
|
||||
`http://localhost:2380,http://localhost:7001`.
|
||||
2. These *peer-urls* are used to contact the (non-proxy) members of the cluster
|
||||
to find their *client-urls*. The *client-urls* will thus be the combined
|
||||
`advertise-client-urls` of all cluster members (i.e. non-proxies).
|
||||
3. Request of clients of the proxy will be forwarded (proxied) to these
|
||||
*client-urls*.
|
||||
|
||||
Always start the first-order etcd cluster members first, then any proxies. A proxy must be able to reach the cluster members to retrieve its configuration, and will attempt connections somewhat aggressively in the absence of such a channel. Starting the members before any proxy ensures the proxy can discover the client URLs when it later starts.
|
||||
|
||||
## Using an etcd proxy
|
||||
To start etcd in proxy mode, you need to provide three flags: `proxy`, `listen-client-urls`, and `initial-cluster` (or `discovery`).
|
||||
|
||||
To start a readwrite proxy, set `-proxy on`; To start a readonly proxy, set `-proxy readonly`.
|
||||
|
||||
The proxy will be listening on `listen-client-urls` and forward requests to the etcd cluster discovered from in `initial-cluster` or `discovery` url.
|
||||
|
||||
### Start an etcd proxy with a static configuration
|
||||
To start a proxy that will connect to a statically defined etcd cluster, specify the `initial-cluster` flag:
|
||||
|
||||
```
|
||||
etcd --proxy on \
|
||||
--listen-client-urls http://127.0.0.1:2379 \
|
||||
--initial-cluster infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380,infra2=http://10.0.1.12:2380
|
||||
```
|
||||
|
||||
### Start an etcd proxy with the discovery service
|
||||
If you bootstrap an etcd cluster using the [discovery service][discovery-service], you can also start the proxy with the same `discovery`.
|
||||
|
||||
To start a proxy using the discovery service, specify the `discovery` flag. The proxy will wait until the etcd cluster defined at the `discovery` url finishes bootstrapping, and then start to forward the requests.
|
||||
|
||||
```
|
||||
etcd --proxy on \
|
||||
--listen-client-urls http://127.0.0.1:2379 \
|
||||
--discovery https://discovery.etcd.io/3e86b59982e49066c5d813af1c2e2579cbf573de \
|
||||
```
|
||||
|
||||
## Fallback to proxy mode with discovery service
|
||||
|
||||
If you bootstrap an etcd cluster using [discovery service][discovery-service] with more than the expected number of etcd members, the extra etcd processes will fall back to being `readwrite` proxies by default. They will forward the requests to the cluster as described above. For example, if you create a discovery url with `size=5`, and start ten etcd processes using that same discovery url, the result will be a cluster with five etcd members and five proxies. Note that this behaviour can be disabled with the `discovery-fallback='exit'` flag.
|
||||
|
||||
## Promote a proxy to a member of etcd cluster
|
||||
|
||||
A Proxy is in the part of etcd cluster that does not participate in consensus. A proxy will not promote itself to an etcd member that participates in consensus automatically in any case.
|
||||
|
||||
If you want to promote a proxy to an etcd member, there are four steps you need to follow:
|
||||
|
||||
- use etcdctl to add the proxy node as an etcd member into the existing cluster
|
||||
- stop the etcd proxy process or service
|
||||
- remove the existing proxy data directory
|
||||
- restart the etcd process with new member configuration
|
||||
|
||||
## Example
|
||||
|
||||
We assume you have a one member etcd cluster with one proxy. The cluster information is listed below:
|
||||
|
||||
|Name|Address|
|
||||
|------|---------|
|
||||
|infra0|10.0.1.10|
|
||||
|proxy0|10.0.1.11|
|
||||
|
||||
This example walks you through a case that you promote one proxy to an etcd member. The cluster will become a two member cluster after finishing the four steps.
|
||||
|
||||
### Add a new member into the existing cluster
|
||||
|
||||
First, use etcdctl to add the member to the cluster, which will output the environment variables need to correctly configure the new member:
|
||||
|
||||
``` bash
|
||||
$ etcdctl -endpoint http://10.0.1.10:2379 member add infra1 http://10.0.1.11:2380
|
||||
added member 9bf1b35fc7761a23 to cluster
|
||||
|
||||
ETCD_NAME="infra1"
|
||||
ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380"
|
||||
ETCD_INITIAL_CLUSTER_STATE=existing
|
||||
```
|
||||
|
||||
### Stop the proxy process
|
||||
|
||||
Stop the existing proxy so we can wipe it's state on disk and reload it with the new configuration:
|
||||
|
||||
``` bash
|
||||
px aux | grep etcd
|
||||
kill %etcd_proxy_pid%
|
||||
```
|
||||
|
||||
or (if you are running etcd proxy as etcd service under systemd)
|
||||
|
||||
``` bash
|
||||
sudo systemctl stop etcd
|
||||
```
|
||||
|
||||
### Remove the existing proxy data dir
|
||||
|
||||
``` bash
|
||||
rm -rf %data_dir%/proxy
|
||||
```
|
||||
|
||||
### Start etcd as a new member
|
||||
|
||||
Finally, start the reconfigured member and make sure it joins the cluster correctly:
|
||||
|
||||
``` bash
|
||||
$ export ETCD_NAME="infra1"
|
||||
$ export ETCD_INITIAL_CLUSTER="infra0=http://10.0.1.10:2380,infra1=http://10.0.1.11:2380"
|
||||
$ export ETCD_INITIAL_CLUSTER_STATE=existing
|
||||
$ etcd --listen-client-urls http://10.0.1.11:2379 \
|
||||
--advertise-client-urls http://10.0.1.11:2379 \
|
||||
--listen-peer-urls http://10.0.1.11:2380 \
|
||||
--initial-advertise-peer-urls http://10.0.1.11:2380 \
|
||||
--data-dir %data_dir%
|
||||
```
|
||||
|
||||
If you are running etcd under systemd, you should modify the service file with correct configuration and restart the service:
|
||||
|
||||
``` bash
|
||||
sudo systemd restart etcd
|
||||
```
|
||||
|
||||
If an error occurs, check the [add member troubleshooting doc][runtime-configuration].
|
||||
|
||||
[discovery-service]: clustering.md#discovery
|
||||
[goreman]: https://github.com/mattn/goreman
|
||||
[procfile]: /Procfile
|
||||
[runtime-configuration]: runtime-configuration.md#error-cases-when-adding-members
|
@ -1,45 +0,0 @@
|
||||
# Reporting Bugs
|
||||
|
||||
If you find bugs or documentation mistakes in the etcd project, please let us know by [opening an issue][issue]. We treat bugs and mistakes very seriously and believe no issue is too small. Before creating a bug report, please check that an issue reporting the same problem does not already exist.
|
||||
|
||||
To make your bug report accurate and easy to understand, please try to create bug reports that are:
|
||||
|
||||
- Specific. Include as much details as possible: which version, what environment, what configuration, etc. You can also attach etcd log (the starting log with etcd configuration is especially important).
|
||||
|
||||
- Reproducible. Include the steps to reproduce the problem. We understand some issues might be hard to reproduce, please includes the steps that might lead to the problem. You can also attach the affected etcd data dir and stack strace to the bug report.
|
||||
|
||||
- Isolated. Please try to isolate and reproduce the bug with minimum dependencies. It would significantly slow down the speed to fix a bug if too many dependencies are involved in a bug report. Debugging external systems that rely on etcd is out of scope, but we are happy to point you in the right direction or help you interact with etcd in the correct manner.
|
||||
|
||||
- Unique. Do not duplicate existing bug report.
|
||||
|
||||
- Scoped. One bug per report. Do not follow up with another bug inside one report.
|
||||
|
||||
You might also want to read [Elika Etemad’s article on filing good bug reports][filing-good-bugs] before creating a bug report.
|
||||
|
||||
We might ask you for further information to locate a bug. A duplicated bug report will be closed.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### How to get a stack trace
|
||||
|
||||
``` bash
|
||||
$ kill -QUIT $PID
|
||||
```
|
||||
|
||||
### How to get etcd version
|
||||
|
||||
``` bash
|
||||
$ etcd --version
|
||||
```
|
||||
|
||||
### How to get etcd configuration and log when it runs as systemd service ‘etcd2.service’
|
||||
|
||||
``` bash
|
||||
$ sudo systemctl cat etcd2
|
||||
$ sudo journalctl -u etcd2
|
||||
```
|
||||
|
||||
Due to an upstream systemd bug, journald may miss the last few log lines when its process exit. If journalctl tells you that etcd stops without fatal or panic message, you could try `sudo journalctl -f -t etcd2` to get full log.
|
||||
|
||||
[etcd-issue]: https://github.com/coreos/etcd/issues/new
|
||||
[filing-good-bugs]: http://fantasai.inkedblade.net/style/talks/filing-good-bugs/
|
@ -1,211 +0,0 @@
|
||||
# Overview
|
||||
|
||||
The etcd v3 API is designed to give users a more efficient and cleaner abstraction compared to etcd v2. There are a number of semantic and protocol changes in this new API. For an overview [see Xiang Li's video](https://youtu.be/J5AioGtEPeQ?t=211).
|
||||
|
||||
To prove out the design of the v3 API the team has also built [a number of example recipes](https://github.com/coreos/etcd/tree/master/contrib/recipes), there is a [video discussing these recipes too](https://www.youtube.com/watch?v=fj-2RY-3yVU&feature=youtu.be&t=590).
|
||||
|
||||
# Design
|
||||
|
||||
1. Flatten binary key-value space
|
||||
|
||||
2. Keep the event history until compaction
|
||||
- access to old version of keys
|
||||
- user controlled history compaction
|
||||
|
||||
3. Support range query
|
||||
- Pagination support with limit argument
|
||||
- Support consistency guarantee across multiple range queries
|
||||
|
||||
4. Replace TTL key with Lease
|
||||
- more efficient/ low cost keep alive
|
||||
- a logical group of TTL keys
|
||||
|
||||
5. Replace CAS/CAD with multi-object Txn
|
||||
- MUCH MORE powerful and flexible
|
||||
|
||||
6. Support efficient watching with multiple ranges
|
||||
|
||||
7. RPC API supports the completed set of APIs.
|
||||
- more efficient than JSON/HTTP
|
||||
- additional txn/lease support
|
||||
|
||||
8. HTTP API supports a subset of APIs.
|
||||
- easy for people to try out etcd
|
||||
- easy for people to write simple etcd application
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
### Request Size Limitation
|
||||
|
||||
The max request size is around 1MB. Since etcd replicates requests in a streaming fashion, a very large
|
||||
request might block other requests for a long time. The use case for etcd is to store small configuration
|
||||
values, so we prevent user from submitting large requests. This also applies to Txn requests. We might loosen
|
||||
the size in the future a little bit or make it configurable.
|
||||
|
||||
## Protobuf Defined API
|
||||
|
||||
[api protobuf][api-protobuf]
|
||||
|
||||
[kv protobuf][kv-protobuf]
|
||||
|
||||
## Examples
|
||||
|
||||
### Put a key (foo=bar)
|
||||
```
|
||||
// A put is always successful
|
||||
Put( PutRequest { key = foo, value = bar } )
|
||||
|
||||
PutResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 1,
|
||||
raft_term = 0x1,
|
||||
}
|
||||
```
|
||||
|
||||
### Get a key (assume we have foo=bar)
|
||||
```
|
||||
Get ( RangeRequest { key = foo } )
|
||||
|
||||
RangeResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 1,
|
||||
raft_term = 0x1,
|
||||
kvs = {
|
||||
{
|
||||
key = foo,
|
||||
value = bar,
|
||||
create_revision = 1,
|
||||
mod_revision = 1,
|
||||
version = 1;
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Range over a key space (assume we have foo0=bar0… foo100=bar100)
|
||||
```
|
||||
Range ( RangeRequest { key = foo, end_key = foo80, limit = 30 } )
|
||||
|
||||
RangeResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 100,
|
||||
raft_term = 0x1,
|
||||
kvs = {
|
||||
{
|
||||
key = foo0,
|
||||
value = bar0,
|
||||
create_revision = 1,
|
||||
mod_revision = 1,
|
||||
version = 1;
|
||||
},
|
||||
...,
|
||||
{
|
||||
key = foo30,
|
||||
value = bar30,
|
||||
create_revision = 30,
|
||||
mod_revision = 30,
|
||||
version = 1;
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Finish a txn (assume we have foo0=bar0, foo1=bar1)
|
||||
```
|
||||
Txn(TxnRequest {
|
||||
// mod_revision of foo0 is equal to 1, mod_revision of foo1 is greater than 1
|
||||
compare = {
|
||||
{compareType = equal, key = foo0, mod_revision = 1},
|
||||
{compareType = greater, key = foo1, mod_revision = 1}}
|
||||
},
|
||||
// if the comparison succeeds, put foo2 = bar2
|
||||
success = {PutRequest { key = foo2, value = success }},
|
||||
// if the comparison fails, put foo2=fail
|
||||
failure = {PutRequest { key = foo2, value = failure }},
|
||||
)
|
||||
|
||||
TxnResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 3,
|
||||
raft_term = 0x1,
|
||||
succeeded = true,
|
||||
responses = {
|
||||
// response of PUT foo2=success
|
||||
{
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 3,
|
||||
raft_term = 0x1,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Watch on a key/range
|
||||
|
||||
```
|
||||
Watch( WatchRequest{
|
||||
key = foo,
|
||||
end_key = fop, // prefix foo
|
||||
start_revision = 20,
|
||||
end_revision = 10000,
|
||||
// server decided notification frequency
|
||||
progress_notification = true,
|
||||
}
|
||||
… // this can be a watch request stream
|
||||
)
|
||||
|
||||
// put (foo0=bar0) event at 3
|
||||
WatchResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 3,
|
||||
raft_term = 0x1,
|
||||
event_type = put,
|
||||
kv = {
|
||||
key = foo0,
|
||||
value = bar0,
|
||||
create_revision = 1,
|
||||
mod_revision = 1,
|
||||
version = 1;
|
||||
},
|
||||
}
|
||||
…
|
||||
|
||||
// a notification at 2000
|
||||
WatchResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 2000,
|
||||
raft_term = 0x1,
|
||||
// nil event as notification
|
||||
}
|
||||
|
||||
…
|
||||
|
||||
// put (foo0=bar3000) event at 3000
|
||||
WatchResponse {
|
||||
cluster_id = 0x1000,
|
||||
member_id = 0x1,
|
||||
revision = 3000,
|
||||
raft_term = 0x1,
|
||||
event_type = put,
|
||||
kv = {
|
||||
key = foo0,
|
||||
value = bar3000,
|
||||
create_revision = 1,
|
||||
mod_revision = 3000,
|
||||
version = 2;
|
||||
},
|
||||
}
|
||||
…
|
||||
|
||||
```
|
||||
|
||||
[api-protobuf]: https://github.com/coreos/etcd/blob/master/etcdserver/etcdserverpb/rpc.proto
|
||||
[kv-protobuf]: https://github.com/coreos/etcd/blob/master/storage/storagepb/kv.proto
|
@ -1,50 +0,0 @@
|
||||
# Design of Runtime Reconfiguration
|
||||
|
||||
Runtime reconfiguration is one of the hardest and most error prone features in a distributed system, especially in a consensus based system like etcd.
|
||||
|
||||
Read on to learn about the design of etcd's runtime reconfiguration commands and how we tackled these problems.
|
||||
|
||||
## Two Phase Config Changes Keep you Safe
|
||||
|
||||
In etcd, every runtime reconfiguration has to go through [two phases][add-member] for safety reasons. For example, to add a member you need to first inform cluster of new configuration and then start the new member.
|
||||
|
||||
Phase 1 - Inform cluster of new configuration
|
||||
|
||||
To add a member into etcd cluster, you need to make an API call to request a new member to be added to the cluster. And this is only way that you can add a new member into an existing cluster. The API call returns when the cluster agrees on the configuration change.
|
||||
|
||||
Phase 2 - Start new member
|
||||
|
||||
To join the etcd member into the existing cluster, you need to specify the correct `initial-cluster` and set `initial-cluster-state` to `existing`. When the member starts, it will contact the existing cluster first and verify the current cluster configuration matches the expected one specified in `initial-cluster`. When the new member successfully starts, you know your cluster reached the expected configuration.
|
||||
|
||||
By splitting the process into two discrete phases users are forced to be explicit regarding cluster membership changes. This actually gives users more flexibility and makes things easier to reason about. For example, if there is an attempt to add a new member with the same ID as an existing member in an etcd cluster, the action will fail immediately during phase one without impacting the running cluster. Similar protection is provided to prevent adding new members by mistake. If a new etcd member attempts to join the cluster before the cluster has accepted the configuration change,, it will not be accepted by the cluster.
|
||||
|
||||
Without the explicit workflow around cluster membership etcd would be vulnerable to unexpected cluster membership changes. For example, if etcd is running under an init system such as systemd, etcd would be restarted after being removed via the membership API, and attempt to rejoin the cluster on startup. This cycle would continue every time a member is removed via the API and systemd is set to restart etcd after failing, which is unexpected.
|
||||
|
||||
We think runtime reconfiguration should be a low frequent operation. We made the decision to keep it explicit and user-driven to ensure configuration safety and keep your cluster always running smoothly under your control.
|
||||
|
||||
## Permanent Loss of Quorum Requires New Cluster
|
||||
|
||||
If a cluster permanently loses a majority of its members, a new cluster will need to be started from an old data directory to recover the previous state.
|
||||
|
||||
It is entirely possible to force removing the failed members from the existing cluster to recover. However, we decided not to support this method since it bypasses the normal consensus committing phase, which is unsafe. If the member to remove is not actually dead or you force to remove different members through different members in the same cluster, you will end up with diverged cluster with same clusterID. This is very dangerous and hard to debug/fix afterwards.
|
||||
|
||||
If you have a correct deployment, the possibility of permanent majority lose is very low. But it is a severe enough problem that worth special care. We strongly suggest you to read the [disaster recovery documentation][disaster-recovery] and prepare for permanent majority lose before you put etcd into production.
|
||||
|
||||
## Do Not Use Public Discovery Service For Runtime Reconfiguration
|
||||
|
||||
The public discovery service should only be used for bootstrapping a cluster. To join member into an existing cluster, you should use runtime reconfiguration API.
|
||||
|
||||
Discovery service is designed for bootstrapping an etcd cluster in the cloud environment, when you do not know the IP addresses of all the members beforehand. After you successfully bootstrap a cluster, the IP addresses of all the members are known. Technically, you should not need the discovery service any more.
|
||||
|
||||
It seems that using public discovery service is a convenient way to do runtime reconfiguration, after all discovery service already has all the cluster configuration information. However relying on public discovery service brings troubles:
|
||||
|
||||
1. it introduces external dependencies for the entire life-cycle of your cluster, not just bootstrap time. If there is a network issue between your cluster and public discovery service, your cluster will suffer from it.
|
||||
|
||||
2. public discovery service must reflect correct runtime configuration of your cluster during it life-cycle. It has to provide security mechanism to avoid bad actions, and it is hard.
|
||||
|
||||
3. public discovery service has to keep tens of thousands of cluster configurations. Our public discovery service backend is not ready for that workload.
|
||||
|
||||
If you want to have a discovery service that supports runtime reconfiguration, the best choice is to build your private one.
|
||||
|
||||
[add-member]: runtime-configuration.md#add-a-new-member
|
||||
[disaster-recovery]: admin_guide.md#disaster-recovery
|
@ -1,75 +0,0 @@
|
||||
# Tuning
|
||||
|
||||
The default settings in etcd should work well for installations on a local network where the average network latency is low.
|
||||
However, when using etcd across multiple data centers or over networks with high latency you may need to tweak the heartbeat interval and election timeout settings.
|
||||
|
||||
The network isn't the only source of latency. Each request and response may be impacted by slow disks on both the leader and follower. Each of these timeouts represents the total time from request to successful response from the other machine.
|
||||
|
||||
## Time Parameters
|
||||
|
||||
The underlying distributed consensus protocol relies on two separate time parameters to ensure that nodes can handoff leadership if one stalls or goes offline.
|
||||
The first parameter is called the *Heartbeat Interval*.
|
||||
This is the frequency with which the leader will notify followers that it is still the leader.
|
||||
For best practices, the parameter should be set around round-trip time between members.
|
||||
By default, etcd uses a `100ms` heartbeat interval.
|
||||
|
||||
The second parameter is the *Election Timeout*.
|
||||
This timeout is how long a follower node will go without hearing a heartbeat before attempting to become leader itself.
|
||||
By default, etcd uses a `1000ms` election timeout.
|
||||
|
||||
Adjusting these values is a trade off.
|
||||
The value of heartbeat interval is recommended to be around the maximum of average round-trip time (RTT) between members, normally around 0.5-1.5x the round-trip time.
|
||||
If heartbeat interval is too low, etcd will send unnecessary messages that increase the usage of CPU and network resources.
|
||||
On the other side, a too high heartbeat interval leads to high election timeout. Higher election timeout takes longer time to detect a leader failure.
|
||||
The easiest way to measure round-trip time (RTT) is to use [PING utility][ping].
|
||||
|
||||
The election timeout should be set based on the heartbeat interval and average round-trip time between members.
|
||||
Election timeouts must be at least 10 times the round-trip time so it can account for variance in your network.
|
||||
For example, if the round-trip time between your members is 10ms then you should have at least a 100ms election timeout.
|
||||
|
||||
You should also set your election timeout to at least 5 to 10 times your heartbeat interval to account for variance in leader replication.
|
||||
For a heartbeat interval of 50ms you should set your election timeout to at least 250ms - 500ms.
|
||||
|
||||
The upper limit of election timeout is 50000ms (50s), which should only be used when deploying a globally-distributed etcd cluster.
|
||||
A reasonable round-trip time for the continental United States is 130ms, and the time between US and Japan is around 350-400ms.
|
||||
If your network has uneven performance or regular packet delays/loss then it is possible that a couple of retries may be necessary to successfully send a packet. So 5s is a safe upper limit of global round-trip time.
|
||||
As the election timeout should be an order of magnitude bigger than broadcast time, in the case of ~5s for a globally distributed cluster, then 50 seconds becomes a reasonable maximum.
|
||||
|
||||
The heartbeat interval and election timeout value should be the same for all members in one cluster. Setting different values for etcd members may disrupt cluster stability.
|
||||
|
||||
You can override the default values on the command line:
|
||||
|
||||
```sh
|
||||
# Command line arguments:
|
||||
$ etcd -heartbeat-interval=100 -election-timeout=500
|
||||
|
||||
# Environment variables:
|
||||
$ ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 etcd
|
||||
```
|
||||
|
||||
The values are specified in milliseconds.
|
||||
|
||||
## Snapshots
|
||||
|
||||
etcd appends all key changes to a log file.
|
||||
This log grows forever and is a complete linear history of every change made to the keys.
|
||||
A complete history works well for lightly used clusters but clusters that are heavily used would carry around a large log.
|
||||
|
||||
To avoid having a huge log etcd makes periodic snapshots.
|
||||
These snapshots provide a way for etcd to compact the log by saving the current state of the system and removing old logs.
|
||||
|
||||
### Snapshot Tuning
|
||||
|
||||
Creating snapshots can be expensive so they're only created after a given number of changes to etcd.
|
||||
By default, snapshots will be made after every 10,000 changes.
|
||||
If etcd's memory usage and disk usage are too high, you can lower the snapshot threshold by setting the following on the command line:
|
||||
|
||||
```sh
|
||||
# Command line arguments:
|
||||
$ etcd -snapshot-count=5000
|
||||
|
||||
# Environment variables:
|
||||
$ ETCD_SNAPSHOT_COUNT=5000 etcd
|
||||
```
|
||||
|
||||
[ping]: https://en.wikipedia.org/wiki/Ping_(networking_utility)
|
@ -1,116 +0,0 @@
|
||||
# Upgrade etcd to 2.1
|
||||
|
||||
In the general case, upgrading from etcd 2.0 to 2.1 can be a zero-downtime, rolling upgrade:
|
||||
- one by one, stop the etcd v2.0 processes and replace them with etcd v2.1 processes
|
||||
- after you are running all v2.1 processes, new features in v2.1 are available to the cluster
|
||||
|
||||
Before [starting an upgrade](#upgrade-procedure), read through the rest of this guide to prepare.
|
||||
|
||||
## Upgrade Checklists
|
||||
|
||||
### Upgrade Requirements
|
||||
|
||||
To upgrade an existing etcd deployment to 2.1, you must be running 2.0. If you’re running a version of etcd before 2.0, you must upgrade to [2.0][v2.0] before upgrading to 2.1.
|
||||
|
||||
Also, to ensure a smooth rolling upgrade, your running cluster must be healthy. You can check the health of the cluster by using `etcdctl cluster-health` command.
|
||||
|
||||
### Preparedness
|
||||
|
||||
Before upgrading etcd, always test the services relying on etcd in a staging environment before deploying the upgrade to the production environment.
|
||||
|
||||
You might also want to [backup your data directory][backup-datastore] for a potential [downgrade](#downgrade).
|
||||
|
||||
etcd 2.1 introduces a new [authentication][auth] feature, which is disabled by default. If your deployment depends on these, you may want to test the auth features before enabling them in production.
|
||||
|
||||
### Mixed Versions
|
||||
|
||||
While upgrading, an etcd cluster supports mixed versions of etcd members. The cluster is only considered upgraded once all its members are upgraded to 2.1.
|
||||
|
||||
Internally, etcd members negotiate with each other to determine the overall etcd cluster version, which controls the reported cluster version and the supported features. For example, if you are mid-upgrade, any 2.1 features (such as the the authentication feature mentioned above) won’t be available.
|
||||
|
||||
### Limitations
|
||||
|
||||
If you encounter any issues during the upgrade, you can attempt to restart the etcd process in trouble using a newer v2.1 binary to solve the problem. One known issue is that etcd v2.0.0 and v2.0.2 may panic during rolling upgrades due to an existing bug, which has been fixed since etcd v2.0.3.
|
||||
|
||||
It might take up to 2 minutes for the newly upgraded member to catch up with the existing cluster when the total data size is larger than 50MB (You can check the size of the existing snapshot to know about the rough data size). In other words, it is safest to wait for 2 minutes before upgrading the next member.
|
||||
|
||||
If you have even more data, this might take more time. If you have a data size larger than 100MB you should contact us before upgrading, so we can make sure the upgrades work smoothly.
|
||||
|
||||
### Downgrade
|
||||
|
||||
If all members have been upgraded to v2.1, the cluster will be upgraded to v2.1, and downgrade is **not possible**. If any member is still v2.0, the cluster will remain in v2.0, and you can go back to use v2.0 binary.
|
||||
|
||||
Please [backup your data directory][backup-datastore] of all etcd members if you want to downgrade the cluster, even if it is upgraded.
|
||||
|
||||
### Upgrade Procedure
|
||||
|
||||
#### 1. Check upgrade requirements.
|
||||
|
||||
```
|
||||
$ etcdctl cluster-health
|
||||
cluster is healthy
|
||||
member 6e3bd23ae5f1eae0 is healthy
|
||||
member 924e2e83e93f2560 is healthy
|
||||
member a8266ecf031671f3 is healthy
|
||||
|
||||
$ curl http://127.0.0.1:4001/version
|
||||
etcd 2.0.x
|
||||
```
|
||||
|
||||
#### 2. Stop the existing etcd process
|
||||
|
||||
You will see similar error logging from other etcd processes in your cluster. This is normal, since you just shut down a member.
|
||||
|
||||
```
|
||||
2015/06/23 15:45:09 sender: error posting to 6e3bd23ae5f1eae0: dial tcp 127.0.0.1:7002: connection refused
|
||||
2015/06/23 15:45:09 sender: the connection with 6e3bd23ae5f1eae0 became inactive
|
||||
2015/06/23 15:45:11 rafthttp: encountered error writing to server log stream: write tcp 127.0.0.1:53783: broken pipe
|
||||
2015/06/23 15:45:11 rafthttp: server streaming to 6e3bd23ae5f1eae0 at term 2 has been stopped
|
||||
2015/06/23 15:45:11 stream: error sending message: stopped
|
||||
2015/06/23 15:45:11 stream: stopping the stream server...
|
||||
```
|
||||
|
||||
You could [backup your data directory][backup-datastore] for data safety.
|
||||
|
||||
```
|
||||
$ etcdctl backup \
|
||||
--data-dir /var/lib/etcd \
|
||||
--backup-dir /tmp/etcd_backup
|
||||
```
|
||||
|
||||
#### 3. Drop-in etcd v2.1 binary and start the new etcd process
|
||||
|
||||
You will see the etcd publish its information to the cluster.
|
||||
|
||||
```
|
||||
2015/06/23 15:45:39 etcdserver: published {Name:infra2 ClientURLs:[http://localhost:4002]} to cluster e9c7614f68f35fb2
|
||||
```
|
||||
|
||||
You could verify the cluster becomes healthy.
|
||||
|
||||
```
|
||||
$ etcdctl cluster-health
|
||||
cluster is healthy
|
||||
member 6e3bd23ae5f1eae0 is healthy
|
||||
member 924e2e83e93f2560 is healthy
|
||||
member a8266ecf031671f3 is healthy
|
||||
```
|
||||
|
||||
#### 4. Repeat step 2 to step 3 for all other members
|
||||
|
||||
#### 5. Finish
|
||||
|
||||
When all members are upgraded, you will see the cluster is upgraded to 2.1 successfully:
|
||||
|
||||
```
|
||||
2015/06/23 15:46:35 etcdserver: updated the cluster version from 2.0.0 to 2.1.0
|
||||
```
|
||||
|
||||
```
|
||||
$ curl http://127.0.0.1:4001/version
|
||||
{"etcdserver":"2.1.x","etcdcluster":"2.1.0"}
|
||||
```
|
||||
|
||||
[auth]: auth_api.md
|
||||
[backup-datastore]: admin_guide.md#backing-up-the-datastore
|
||||
[v2.0]: https://github.com/coreos/etcd/releases/tag/v2.0.13
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user