|
|
@@ -2,23 +2,22 @@
|
|
|
|
|
|
## Running a Single Machine Cluster
|
|
|
|
|
|
-These examples will use a single machine cluster to show you the basics of the etcd REST API.
|
|
|
+These examples will use a single member cluster to show you the basics of the etcd REST API.
|
|
|
Let's start etcd:
|
|
|
|
|
|
```sh
|
|
|
-./bin/etcd -data-dir machine0 -name machine0
|
|
|
+./bin/etcd
|
|
|
```
|
|
|
|
|
|
-This will bring up etcd listening on default ports (4001 for client communication and 7001 for server-to-server communication).
|
|
|
-The `-data-dir machine0` argument tells etcd to write machine configuration, logs and snapshots to the `./machine0/` directory.
|
|
|
-The `-name machine0` tells the rest of the cluster that this machine is named machine0.
|
|
|
+This will bring up etcd listening on the IANA assigned ports and listening on localhost.
|
|
|
+The IANA assigned ports for etcd are 2379 for client communication and 2380 for server-to-server communication.
|
|
|
|
|
|
## 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:4001/version
|
|
|
+curl -L http://127.0.0.1:2379/version
|
|
|
```
|
|
|
|
|
|
## Key Space Operations
|
|
|
@@ -26,14 +25,13 @@ curl -L http://127.0.0.1:4001/version
|
|
|
The primary API of etcd is a hierarchical key space.
|
|
|
The key space consists of directories and keys which are generically referred to as "nodes".
|
|
|
|
|
|
-
|
|
|
### Setting the value of a key
|
|
|
|
|
|
Let's set the first key-value pair in the datastore.
|
|
|
In this case the key is `/message` and the value is `Hello world`.
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/message -XPUT -d value="Hello world"
|
|
|
+curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="Hello world"
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -61,7 +59,7 @@ etcd uses a file-system-like structure to represent the key-value pairs, therefo
|
|
|
In this case, a successful request was made that attempted to change the node's value to `Hello world`.
|
|
|
|
|
|
4. `node.createdIndex`: an index is a unique, monotonically-incrementing integer created for each change to etcd.
|
|
|
-This specific index reflects the point in the etcd state machine at which a given key was created.
|
|
|
+This specific index reflects the point in the etcd state member at which a given key was created.
|
|
|
You may notice that in this example the index is `2` even though it is the first request you sent to the server.
|
|
|
This is because there are internal commands that also change the state behind the scenes, like adding and syncing servers.
|
|
|
|
|
|
@@ -77,7 +75,7 @@ etcd includes a few HTTP headers in responses that provide global information ab
|
|
|
```
|
|
|
X-Etcd-Index: 35
|
|
|
X-Raft-Index: 5398
|
|
|
-X-Raft-Term: 0
|
|
|
+X-Raft-Term: 1
|
|
|
```
|
|
|
|
|
|
- `X-Etcd-Index` is the current etcd index as explained above.
|
|
|
@@ -92,7 +90,7 @@ X-Raft-Term: 0
|
|
|
We can get the value that we just set in `/message` by issuing a `GET` request:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/message
|
|
|
+curl http://127.0.0.1:2379/v2/keys/message
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -113,7 +111,7 @@ curl -L http://127.0.0.1:4001/v2/keys/message
|
|
|
You can change the value of `/message` from `Hello world` to `Hello etcd` with another `PUT` request to the key:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/message -XPUT -d value="Hello etcd"
|
|
|
+curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="Hello etcd"
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -126,10 +124,10 @@ curl -L http://127.0.0.1:4001/v2/keys/message -XPUT -d value="Hello etcd"
|
|
|
"value": "Hello etcd"
|
|
|
},
|
|
|
"prevNode": {
|
|
|
- "createdIndex": 2,
|
|
|
- "key": "/message",
|
|
|
- "value": "Hello world",
|
|
|
- "modifiedIndex": 2
|
|
|
+ "createdIndex": 2,
|
|
|
+ "key": "/message",
|
|
|
+ "value": "Hello world",
|
|
|
+ "modifiedIndex": 2
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
@@ -141,7 +139,7 @@ Here we introduce a new field: `prevNode`. The `prevNode` field represents what
|
|
|
You can remove the `/message` key with a `DELETE` request:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/message -XDELETE
|
|
|
+curl http://127.0.0.1:2379/v2/keys/message -XDELETE
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -153,10 +151,10 @@ curl -L http://127.0.0.1:4001/v2/keys/message -XDELETE
|
|
|
"modifiedIndex": 4
|
|
|
},
|
|
|
"prevNode": {
|
|
|
- "key": "/message",
|
|
|
- "value": "Hello etcd",
|
|
|
- "modifiedIndex": 3,
|
|
|
- "createdIndex": 3
|
|
|
+ "key": "/message",
|
|
|
+ "value": "Hello etcd",
|
|
|
+ "modifiedIndex": 3,
|
|
|
+ "createdIndex": 3
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
@@ -168,7 +166,7 @@ Keys in etcd can be set to expire after a specified number of seconds.
|
|
|
You can do this by setting a TTL (time to live) on the key when sending a `PUT` request:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar -d ttl=5
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -d ttl=5
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -191,12 +189,12 @@ Note the two new fields in response:
|
|
|
|
|
|
2. The `ttl` is the specified time to live for the key, in seconds.
|
|
|
|
|
|
-_NOTE_: Keys can only be expired by a cluster leader, so if a machine gets disconnected from the cluster, its keys will not expire until it rejoins.
|
|
|
+_NOTE_: Keys can only be expired by a cluster leader, so if a member gets disconnected from the cluster, its keys will not expire until it rejoins.
|
|
|
|
|
|
Now you can try to get the key by sending a `GET` request:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo
|
|
|
```
|
|
|
|
|
|
If the TTL has expired, the key will have been deleted, and you will be returned a 100.
|
|
|
@@ -210,10 +208,10 @@ If the TTL has expired, the key will have been deleted, and you will be returned
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-The TTL could be unset to avoid expiration through update operation:
|
|
|
+The TTL can be unset to avoid expiration through update operation:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar -d ttl= -d prevExist=true
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar -d ttl= -d prevExist=true
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -245,7 +243,7 @@ This also works for child keys by passing `recursive=true` in curl.
|
|
|
In one terminal, we send a `GET` with `wait=true` :
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo?wait=true
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo?wait=true
|
|
|
```
|
|
|
|
|
|
Now we are waiting for any changes at path `/foo`.
|
|
|
@@ -253,7 +251,7 @@ Now we are waiting for any changes at path `/foo`.
|
|
|
In another terminal, we set a key `/foo` with value `bar`:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=bar
|
|
|
```
|
|
|
|
|
|
The first terminal should get the notification and return with the same response as the set request:
|
|
|
@@ -278,27 +276,70 @@ 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.
|
|
|
+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.
|
|
|
|
|
|
Let's try to watch for the set command of index 7 again:
|
|
|
|
|
|
```sh
|
|
|
-curl -L 'http://127.0.0.1:4001/v2/keys/foo?wait=true&waitIndex=7'
|
|
|
+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.
|
|
|
|
|
|
+**Note**: etcd only keeps the responses of the most recent 1000 events.
|
|
|
+It is recommended to send the response to another thread to process immediately
|
|
|
+instead of blocking the watch while processing the result.
|
|
|
+
|
|
|
+If we miss all the 1000 events, we need to recover the current state of the
|
|
|
+watching key space. First, We do a get and then start to watch from the (etcdIndex + 1).
|
|
|
+
|
|
|
+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=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 [1003/7]","index":2002}
|
|
|
+```
|
|
|
+
|
|
|
+To start watch, frist 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: 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":"","modifiedIndex":2002,"createdIndex":2002}}
|
|
|
+```
|
|
|
+
|
|
|
+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=2003'
|
|
|
+```
|
|
|
+
|
|
|
|
|
|
### Atomically Creating In-Order Keys
|
|
|
|
|
|
Using `POST` on a directory, you can create keys with key names that are created in-order.
|
|
|
This can be used in a variety of useful patterns, like implementing queues of keys which need to be processed in strict order.
|
|
|
-An example use case is the [locking module][lockmod] which uses it to ensure clients get fair access to a mutex.
|
|
|
+An example use case would be ensuring clients get fair access to a mutex.
|
|
|
|
|
|
Creating an in-order key is easy:
|
|
|
|
|
|
```sh
|
|
|
-curl http://127.0.0.1:4001/v2/keys/queue -XPOST -d value=Job1
|
|
|
+curl http://127.0.0.1:2379/v2/keys/queue -XPOST -d value=Job1
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -317,7 +358,7 @@ If you create another entry some time later, it is guaranteed to have a key name
|
|
|
Also note the key names use the global etcd index, so the next key can be more than `previous + 1`.
|
|
|
|
|
|
```sh
|
|
|
-curl http://127.0.0.1:4001/v2/keys/queue -XPOST -d value=Job2
|
|
|
+curl http://127.0.0.1:2379/v2/keys/queue -XPOST -d value=Job2
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -335,7 +376,7 @@ curl http://127.0.0.1:4001/v2/keys/queue -XPOST -d value=Job2
|
|
|
To enumerate the in-order keys as a sorted list, use the "sorted" parameter.
|
|
|
|
|
|
```sh
|
|
|
-curl -s 'http://127.0.0.1:4001/v2/keys/queue?recursive=true&sorted=true'
|
|
|
+curl -s 'http://127.0.0.1:2379/v2/keys/queue?recursive=true&sorted=true'
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -364,8 +405,6 @@ curl -s 'http://127.0.0.1:4001/v2/keys/queue?recursive=true&sorted=true'
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-[lockmod]: #lock
|
|
|
-
|
|
|
|
|
|
### Using a directory TTL
|
|
|
|
|
|
@@ -373,7 +412,7 @@ Like keys, directories in etcd can be set to expire after a specified number of
|
|
|
You can do this by setting a TTL (time to live) on a directory when it is created with a `PUT`:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/dir -XPUT -d ttl=30 -d dir=true
|
|
|
+curl http://127.0.0.1:2379/v2/keys/dir -XPUT -d ttl=30 -d dir=true
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -394,13 +433,13 @@ The directory's TTL can be refreshed by making an update.
|
|
|
You can do this by making a PUT with `prevExist=true` and a new TTL.
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/dir -XPUT -d ttl=30 -d dir=true -d prevExist=true
|
|
|
+curl http://127.0.0.1:2379/v2/keys/dir -XPUT -d ttl=30 -d dir=true -d prevExist=true
|
|
|
```
|
|
|
|
|
|
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:4001/v2/keys/dir/asdf?consistent=true&wait=true'
|
|
|
+curl 'http://127.0.0.1:2379/v2/keys/dir/asdf?consistent=true&wait=true'
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -440,14 +479,14 @@ Here is a simple example.
|
|
|
Let's create a key-value pair first: `foo=one`.
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=one
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=one
|
|
|
```
|
|
|
|
|
|
Now let's try some invalid `CompareAndSwap` commands.
|
|
|
|
|
|
Trying to set this existing key with `prevExist=false` fails as expected:
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo?prevExist=false -XPUT -d value=three
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo?prevExist=false -XPUT -d value=three
|
|
|
```
|
|
|
|
|
|
The error code explains the problem:
|
|
|
@@ -464,7 +503,7 @@ The error code explains the problem:
|
|
|
Now let's provide a `prevValue` parameter:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo?prevValue=two -XPUT -d value=three
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo?prevValue=two -XPUT -d value=three
|
|
|
```
|
|
|
|
|
|
This will try to compare the previous value of the key and the previous value we provided. If they are equal, the value of the key will change to three.
|
|
|
@@ -484,7 +523,7 @@ Note: the condition prevIndex=0 always passes.
|
|
|
Let's try a valid condition:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo?prevValue=one -XPUT -d value=two
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo?prevValue=one -XPUT -d value=two
|
|
|
```
|
|
|
|
|
|
The response should be:
|
|
|
@@ -499,10 +538,10 @@ The response should be:
|
|
|
"value": "two"
|
|
|
},
|
|
|
"prevNode": {
|
|
|
- "createdIndex": 8,
|
|
|
- "key": "/foo",
|
|
|
- "modifiedIndex": 8,
|
|
|
- "value": "one"
|
|
|
+ "createdIndex": 8,
|
|
|
+ "key": "/foo",
|
|
|
+ "modifiedIndex": 8,
|
|
|
+ "value": "one"
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
@@ -522,64 +561,64 @@ The current comparable conditions are:
|
|
|
Here is a simple example. Let's first create a key: `foo=one`.
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=one
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo -XPUT -d value=one
|
|
|
```
|
|
|
|
|
|
Now let's try some `CompareAndDelete` commands.
|
|
|
|
|
|
Trying to delete the key with `prevValue=two` fails as expected:
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo?prevValue=two -XDELETE
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo?prevValue=two -XDELETE
|
|
|
```
|
|
|
|
|
|
The error code explains the problem:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
- "errorCode": 101,
|
|
|
- "message": "Compare failed",
|
|
|
- "cause": "[two != one]",
|
|
|
- "index": 8
|
|
|
+ "errorCode": 101,
|
|
|
+ "message": "Compare failed",
|
|
|
+ "cause": "[two != one]",
|
|
|
+ "index": 8
|
|
|
}
|
|
|
```
|
|
|
|
|
|
As does a `CompareAndDelete` with a mismatched `prevIndex`:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo?prevIndex=1 -XDELETE
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo?prevIndex=1 -XDELETE
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
- "errorCode": 101,
|
|
|
- "message": "Compare failed",
|
|
|
- "cause": "[1 != 8]",
|
|
|
- "index": 8
|
|
|
+ "errorCode": 101,
|
|
|
+ "message": "Compare failed",
|
|
|
+ "cause": "[1 != 8]",
|
|
|
+ "index": 8
|
|
|
}
|
|
|
```
|
|
|
|
|
|
And now a valid `prevValue` condition:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo?prevValue=one -XDELETE
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo?prevValue=one -XDELETE
|
|
|
```
|
|
|
|
|
|
The successful response will look something like:
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
- "action": "compareAndDelete",
|
|
|
- "node": {
|
|
|
- "key": "/foo",
|
|
|
- "modifiedIndex": 9,
|
|
|
- "createdIndex": 8
|
|
|
- },
|
|
|
- "prevNode": {
|
|
|
- "key": "/foo",
|
|
|
- "value": "one",
|
|
|
- "modifiedIndex": 8,
|
|
|
- "createdIndex": 8
|
|
|
- }
|
|
|
+ "action": "compareAndDelete",
|
|
|
+ "node": {
|
|
|
+ "key": "/foo",
|
|
|
+ "modifiedIndex": 9,
|
|
|
+ "createdIndex": 8
|
|
|
+ },
|
|
|
+ "prevNode": {
|
|
|
+ "key": "/foo",
|
|
|
+ "value": "one",
|
|
|
+ "modifiedIndex": 8,
|
|
|
+ "createdIndex": 8
|
|
|
+ }
|
|
|
}
|
|
|
```
|
|
|
|
|
|
@@ -591,7 +630,7 @@ But there are cases where you will want to create a directory or remove one.
|
|
|
Creating a directory is just like a key except you cannot provide a value and must add the `dir=true` parameter.
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/dir -XPUT -d dir=true
|
|
|
+curl http://127.0.0.1:2379/v2/keys/dir -XPUT -d dir=true
|
|
|
```
|
|
|
```json
|
|
|
{
|
|
|
@@ -617,7 +656,7 @@ In this example, let's first create some keys:
|
|
|
We already have `/foo=two` so now we'll create another one called `/foo_dir/foo` with the value of `bar`:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo_dir/foo -XPUT -d value=bar
|
|
|
+curl http://127.0.0.1:2379/v2/keys/foo_dir/foo -XPUT -d value=bar
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -635,7 +674,7 @@ curl -L http://127.0.0.1:4001/v2/keys/foo_dir/foo -XPUT -d value=bar
|
|
|
Now we can list the keys under root `/`:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/
|
|
|
+curl http://127.0.0.1:2379/v2/keys/
|
|
|
```
|
|
|
|
|
|
We should see the response as an array of items:
|
|
|
@@ -668,7 +707,7 @@ Here we can see `/foo` is a key-value pair under `/` and `/foo_dir` is a directo
|
|
|
We can also recursively get all the contents under a directory by adding `recursive=true`.
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/?recursive=true
|
|
|
+curl http://127.0.0.1:2379/v2/keys/?recursive=true
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -706,51 +745,35 @@ curl -L http://127.0.0.1:4001/v2/keys/?recursive=true
|
|
|
|
|
|
### Deleting a Directory
|
|
|
|
|
|
-Now let's try to delete the directory `/dir`
|
|
|
+Now let's try to delete the directory `/foo_dir`.
|
|
|
|
|
|
-You can remove an empty directory using the `DELETE` verb and the `dir=true` parameter. Following will succeed because `/dir` was empty
|
|
|
+You can remove an empty directory using the `DELETE` verb and the `dir=true` parameter.
|
|
|
|
|
|
```sh
|
|
|
-curl -L 'http://127.0.0.1:4001/v2/keys/dir?dir=true' -XDELETE
|
|
|
+curl 'http://127.0.0.1:2379/v2/keys/foo_dir?dir=true' -XDELETE
|
|
|
```
|
|
|
-
|
|
|
```json
|
|
|
{
|
|
|
"action": "delete",
|
|
|
"node": {
|
|
|
"createdIndex": 30,
|
|
|
"dir": true,
|
|
|
- "key": "/dir",
|
|
|
+ "key": "/foo_dir",
|
|
|
"modifiedIndex": 31
|
|
|
},
|
|
|
"prevNode": {
|
|
|
- "createdIndex": 30,
|
|
|
- "key": "/dir",
|
|
|
- "dir": true,
|
|
|
- "modifiedIndex": 30
|
|
|
+ "createdIndex": 30,
|
|
|
+ "key": "/foo_dir",
|
|
|
+ "dir": true,
|
|
|
+ "modifiedIndex": 30
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-However, deleting `/foo_dir` will result into an error because `/foo_dir` is not empty.
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L 'http://127.0.0.1:4001/v2/keys/foo_dir?dir=true' -XDELETE
|
|
|
-```
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode":108,
|
|
|
- "message":"Directory not empty",
|
|
|
- "cause":"/foo_dir",
|
|
|
- "index":2
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
To delete a directory that holds keys, you must add `recursive=true`.
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/foo_dir?recursive=true -XDELETE
|
|
|
+curl http://127.0.0.1:2379/v2/keys/dir?recursive=true -XDELETE
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -763,10 +786,10 @@ curl -L http://127.0.0.1:4001/v2/keys/foo_dir?recursive=true -XDELETE
|
|
|
"modifiedIndex": 11
|
|
|
},
|
|
|
"prevNode": {
|
|
|
- "createdIndex": 10,
|
|
|
- "dir": true,
|
|
|
- "key": "/dir",
|
|
|
- "modifiedIndex": 10
|
|
|
+ "createdIndex": 10,
|
|
|
+ "dir": true,
|
|
|
+ "key": "/dir",
|
|
|
+ "modifiedIndex": 10
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
@@ -780,7 +803,7 @@ The hidden item will not be listed when sending a `GET` request for a directory.
|
|
|
First we'll add a hidden key named `/_message`:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/_message -XPUT -d value="Hello hidden world"
|
|
|
+curl http://127.0.0.1:2379/v2/keys/_message -XPUT -d value="Hello hidden world"
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -798,7 +821,7 @@ curl -L http://127.0.0.1:4001/v2/keys/_message -XPUT -d value="Hello hidden worl
|
|
|
Next we'll add a regular key named `/message`:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/message -XPUT -d value="Hello world"
|
|
|
+curl http://127.0.0.1:2379/v2/keys/message -XPUT -d value="Hello world"
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -816,7 +839,7 @@ curl -L http://127.0.0.1:4001/v2/keys/message -XPUT -d value="Hello world"
|
|
|
Now let's try to get a listing of keys under the root directory, `/`:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/
|
|
|
+curl http://127.0.0.1:2379/v2/keys/
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -852,7 +875,7 @@ For example you can use curl to upload a simple text file and encode it:
|
|
|
|
|
|
```
|
|
|
echo "Hello\nWorld" > afile.txt
|
|
|
-curl -L http://127.0.0.1:4001/v2/keys/afile -XPUT --data-urlencode value@afile.txt
|
|
|
+curl http://127.0.0.1:2379/v2/keys/afile -XPUT --data-urlencode value@afile.txt
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -875,7 +898,7 @@ Followers in a cluster can be behind the leader in their copy of the keyspace.
|
|
|
If your application wants or needs the most up-to-date version of a key then it should ensure it reads from the current leader.
|
|
|
By using the `consistent=true` flag in your GET requests, etcd will make sure you are talking to the current master.
|
|
|
|
|
|
-As an example of how a machine can be behind the leader let's start with a three machine cluster: L, F1, and F2.
|
|
|
+As an example of how a member can be behind the leader let's start with a three member cluster: L, F1, and F2.
|
|
|
A client makes a write to L and F1 acknowledges the request.
|
|
|
The client is told the write was successful and the keyspace is updated.
|
|
|
Meanwhile F2 has partitioned from the network and will have an out-of-date version of the keyspace until the partition resolves.
|
|
|
@@ -894,225 +917,10 @@ The read will take a very similar path to a write and will have a similar
|
|
|
speed. If you are unsure if you need this feature feel free to email etcd-dev
|
|
|
for advice.
|
|
|
|
|
|
-## Lock Module (*Deprecated and Removed*)
|
|
|
-
|
|
|
-The lock module is used to serialize access to resources used by clients.
|
|
|
-Multiple clients can attempt to acquire a lock but only one can have it at a time.
|
|
|
-Once the lock is released, the next client waiting for the lock will receive it.
|
|
|
-
|
|
|
-**Warning:** This module is deprecated and removed at v0.4. See [Modules][modules] for more details.
|
|
|
-
|
|
|
-
|
|
|
-### Acquiring a Lock
|
|
|
-
|
|
|
-To acquire a lock, simply send a `POST` request to the lock module with the lock name and TTL:
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:4001/mod/v2/lock/mylock -XPOST -d ttl=20
|
|
|
-```
|
|
|
-
|
|
|
-You will receive the lock index when you acquire the lock:
|
|
|
-
|
|
|
-```
|
|
|
-2
|
|
|
-```
|
|
|
-
|
|
|
-If the TTL is not specified or is not a number then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 202,
|
|
|
- "message": "The given TTL in POST form is not a number",
|
|
|
- "cause": "Acquire",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-If you specify a timeout that is not a number then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 205,
|
|
|
- "message": "The given timeout in POST form is not a number",
|
|
|
- "cause": "Acquire",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-
|
|
|
-### Renewing a Lock
|
|
|
-
|
|
|
-To extend the TTL of an already acquired lock, simply repeat your original request but with a `PUT` and the lock index instead:
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:4001/mod/v2/lock/mylock -XPUT -d index=5 -d ttl=20
|
|
|
-```
|
|
|
-
|
|
|
-If the index or value is not specified then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 207,
|
|
|
- "message": "Index or value is required",
|
|
|
- "cause": "Renew",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-If the index or value does not exist then you'll receive the following error with a `404 Not Found` HTTP code:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 100,
|
|
|
- "message": "Key not found",
|
|
|
- "index": 1
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-If the TTL is not specified or is not a number then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 202,
|
|
|
- "message": "The given TTL in POST form is not a number",
|
|
|
- "cause": "Renew",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-
|
|
|
-### Releasing a Lock
|
|
|
-
|
|
|
-When the client is finished with the lock, simply send a `DELETE` request to release the lock:
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:4001/mod/v2/lock/mylock?index=5 -XDELETE
|
|
|
-```
|
|
|
-
|
|
|
-If the index or value is not specified then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 207,
|
|
|
- "message": "Index or value is required",
|
|
|
- "cause": "Release",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-If the index and value are both specified then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 208,
|
|
|
- "message": "Index and value cannot both be specified",
|
|
|
- "cause": "Release",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-If the index or value does not exist then you'll receive the following error with a `404 Not Found` HTTP code:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 100,
|
|
|
- "message": "Key not found",
|
|
|
- "index": 1
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-
|
|
|
-### Retrieving a Lock
|
|
|
-
|
|
|
-To determine the current value or index of a lock, send a `GET` request to the lock.
|
|
|
-You can specify a `field` of `index` or `value`.
|
|
|
-The default is `value`.
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:4001/mod/v2/lock/mylock?field=index
|
|
|
-```
|
|
|
-
|
|
|
-Will return the current index:
|
|
|
-
|
|
|
-```sh
|
|
|
-2
|
|
|
-```
|
|
|
-
|
|
|
-If you specify a field other than `index` or `value` then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 209,
|
|
|
- "message": "Invalid field",
|
|
|
- "cause": "Get",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-
|
|
|
-## Leader Module (*Deprecated*)
|
|
|
-
|
|
|
-The leader module wraps the lock module to provide a simple interface for electing a single leader in a cluster.
|
|
|
-
|
|
|
-**Warning:** This module is deprecated at v0.4. See [Modules][modules] for more details.
|
|
|
-[modules]: https://github.com/coreos/etcd/blob/master/Documentation/modules.md
|
|
|
-
|
|
|
-
|
|
|
-### Setting the Leader
|
|
|
-
|
|
|
-A client can attempt to become leader by sending a `PUT` request to the leader module with the name of the leader to elect:
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:4001/mod/v2/leader/myclustername -XPUT -d ttl=300 -d name=foo.mydomain.com
|
|
|
-```
|
|
|
-
|
|
|
-You will receive a successful `200` HTTP response code when the leader is elected.
|
|
|
-
|
|
|
-If the name is not specified then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 206,
|
|
|
- "message": "Name is required in POST form",
|
|
|
- "cause": "Set",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-You can also receive any errors specified by the Lock module.
|
|
|
-
|
|
|
-
|
|
|
-### Retrieving the Current Leader
|
|
|
-
|
|
|
-A client can check to determine if there is a current leader by sending a `GET` request to the leader module:
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:4001/mod/v2/leader/myclustername
|
|
|
-```
|
|
|
-
|
|
|
-You will receive the name of the current leader:
|
|
|
-
|
|
|
-```sh
|
|
|
-foo.mydomain.com
|
|
|
-```
|
|
|
-
|
|
|
-
|
|
|
-### Relinquishing Leadership
|
|
|
-
|
|
|
-A client can give up leadership by sending a `DELETE` request with the leader name:
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:4001/mod/v2/leader/myclustername?name=foo.mydomain.com -XDELETE
|
|
|
-```
|
|
|
-
|
|
|
-If the name is not specified then you'll receive the following error:
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "errorCode": 206,
|
|
|
- "message": "Name is required in POST form",
|
|
|
- "cause": "Set",
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-
|
|
|
## Statistics
|
|
|
|
|
|
An etcd cluster keeps track of a number of statistics including latency, bandwidth and uptime.
|
|
|
-These statistics are used in the `/mod/dashboard` endpoint to generate tables and graphs about the cluster state.
|
|
|
-
|
|
|
+These are exposed via the statistics endpoint to understand the internal health of a cluster.
|
|
|
|
|
|
### Leader Statistics
|
|
|
|
|
|
@@ -1120,40 +928,24 @@ The leader has a view of the entire cluster and keeps track of two interesting s
|
|
|
You can grab these statistics from the `/v2/stats/leader` endpoint:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/stats/leader
|
|
|
+curl http://127.0.0.1:2379/v2/stats/leader
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
- "followers": {
|
|
|
- "etcd-node1": {
|
|
|
- "counts": {
|
|
|
- "fail": 1212,
|
|
|
- "success": 4163176
|
|
|
- },
|
|
|
- "latency": {
|
|
|
- "average": 2.7206299430775007,
|
|
|
- "current": 1.486487,
|
|
|
- "maximum": 2018.410279,
|
|
|
- "minimum": 1.011763,
|
|
|
- "standardDeviation": 6.246990702203536
|
|
|
- }
|
|
|
- },
|
|
|
- "etcd-node3": {
|
|
|
- "counts": {
|
|
|
- "fail": 1378,
|
|
|
- "success": 4164598
|
|
|
- },
|
|
|
- "latency": {
|
|
|
- "average": 2.707100125761001,
|
|
|
- "current": 1.666258,
|
|
|
- "maximum": 1409.054765,
|
|
|
- "minimum": 0.998415,
|
|
|
- "standardDeviation": 5.910089773061448
|
|
|
- }
|
|
|
- }
|
|
|
+ "id": "2c7d3e0b8627375b",
|
|
|
+ "leaderInfo": {
|
|
|
+ "leader": "8a69d5f6b7814500",
|
|
|
+ "startTime": "2014-10-24T13:15:51.184719899-07:00",
|
|
|
+ "uptime": "7m17.859616962s"
|
|
|
},
|
|
|
- "leader": "etcd-node2"
|
|
|
+ "name": "infra1",
|
|
|
+ "recvAppendRequestCnt": 3949,
|
|
|
+ "recvBandwidthRate": 561.5729321100841,
|
|
|
+ "recvPkgRate": 9.008227977383449,
|
|
|
+ "sendAppendRequestCnt": 0,
|
|
|
+ "startTime": "2014-10-24T13:15:50.070369454-07:00",
|
|
|
+ "state": "StateFollower"
|
|
|
}
|
|
|
```
|
|
|
|
|
|
@@ -1162,59 +954,64 @@ curl -L http://127.0.0.1:4001/v2/stats/leader
|
|
|
|
|
|
Each node keeps a number of internal statistics:
|
|
|
|
|
|
-- `leaderInfo.leader`: name of the current leader machine
|
|
|
+- `id`: the unique identifier for the member
|
|
|
+- `leaderInfo.leader`: id of the current leader member
|
|
|
- `leaderInfo.uptime`: amount of time the leader has been leader
|
|
|
-- `name`: this machine's name
|
|
|
+- `name`: this member's name
|
|
|
- `recvAppendRequestCnt`: number of append requests this node has processed
|
|
|
- `recvBandwidthRate`: number of bytes per second this node is receiving (follower only)
|
|
|
- `recvPkgRate`: number of requests per second this node is receiving (follower only)
|
|
|
- `sendAppendRequestCnt`: number of requests that this node has sent
|
|
|
-- `sendBandwidthRate`: number of bytes per second this node is sending (leader only). This value is undefined on single machine clusters.
|
|
|
-- `sendPkgRate`: number of requests per second this node is sending (leader only). This value is undefined on single machine clusters.
|
|
|
+- `sendBandwidthRate`: number of bytes per second this node is sending (leader only). This value is undefined on single member clusters.
|
|
|
+- `sendPkgRate`: number of requests per second this node is sending (leader only). This value is undefined on single member clusters.
|
|
|
- `state`: either leader or follower
|
|
|
- `startTime`: the time when this node was started
|
|
|
|
|
|
-This is an example response from a follower machine:
|
|
|
+This is an example response from a follower member:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/stats/self
|
|
|
+curl http://127.0.0.1:2379/v2/stats/self
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
+ "id": "eca0338f4ea31566",
|
|
|
"leaderInfo": {
|
|
|
- "leader": "machine1",
|
|
|
- "uptime": "1m18.544996775s"
|
|
|
+ "leader": "8a69d5f6b7814500",
|
|
|
+ "startTime": "2014-10-24T13:15:51.186620747-07:00",
|
|
|
+ "uptime": "10m59.322358947s"
|
|
|
},
|
|
|
- "name": "machine0",
|
|
|
- "recvAppendRequestCnt": 5871307,
|
|
|
- "recvBandwidthRate": 630.3121596542599,
|
|
|
- "recvPkgRate": 19.272654323628185,
|
|
|
- "sendAppendRequestCnt": 3175763,
|
|
|
- "startTime": "2014-01-01T15:26:24.96569404Z",
|
|
|
- "state": "follower"
|
|
|
+ "name": "node3",
|
|
|
+ "recvAppendRequestCnt": 5944,
|
|
|
+ "recvBandwidthRate": 570.6254930219969,
|
|
|
+ "recvPkgRate": 9.00892789741075,
|
|
|
+ "sendAppendRequestCnt": 0,
|
|
|
+ "startTime": "2014-10-24T13:15:50.072007085-07:00",
|
|
|
+ "state": "StateFollower"
|
|
|
}
|
|
|
```
|
|
|
|
|
|
-And this is an example response from a leader machine:
|
|
|
+And this is an example response from a leader member:
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/stats/self
|
|
|
+curl http://127.0.0.1:2379/v2/stats/self
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
{
|
|
|
+ "id": "eca0338f4ea31566",
|
|
|
"leaderInfo": {
|
|
|
- "leader": "machine0",
|
|
|
- "uptime": "24.648619798s"
|
|
|
+ "leader": "8a69d5f6b7814500",
|
|
|
+ "startTime": "2014-10-24T13:15:51.186620747-07:00",
|
|
|
+ "uptime": "10m47.012122091s"
|
|
|
},
|
|
|
- "name": "machine0",
|
|
|
- "recvAppendRequestCnt": 5901116,
|
|
|
- "sendAppendRequestCnt": 3212344,
|
|
|
- "sendBandwidthRate": 1254.3151237301615,
|
|
|
- "sendPkgRate": 38.71342974475808,
|
|
|
- "startTime": "2014-01-01T15:26:24.96569404Z",
|
|
|
- "state": "leader"
|
|
|
+ "name": "node3",
|
|
|
+ "recvAppendRequestCnt": 5835,
|
|
|
+ "recvBandwidthRate": 584.1485698657176,
|
|
|
+ "recvPkgRate": 9.17390765395709,
|
|
|
+ "sendAppendRequestCnt": 0,
|
|
|
+ "startTime": "2014-10-24T13:15:50.072007085-07:00",
|
|
|
+ "state": "StateFollower"
|
|
|
}
|
|
|
```
|
|
|
|
|
|
@@ -1227,7 +1024,7 @@ Operations that modify the store's state like create, delete, set and update are
|
|
|
Operations like get and watch are node local and will only be seen on this node.
|
|
|
|
|
|
```sh
|
|
|
-curl -L http://127.0.0.1:4001/v2/stats/store
|
|
|
+curl http://127.0.0.1:2379/v2/stats/store
|
|
|
```
|
|
|
|
|
|
```json
|
|
|
@@ -1251,92 +1048,6 @@ curl -L http://127.0.0.1:4001/v2/stats/store
|
|
|
|
|
|
## Cluster Config
|
|
|
|
|
|
-The configuration endpoint manages shared cluster wide properties.
|
|
|
-
|
|
|
-### Set Cluster Config
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:7001/v2/admin/config -XPUT -d '{"activeSize":3, "removeDelay":1800,"syncInterval":5}'
|
|
|
-```
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "activeSize": 3,
|
|
|
- "removeDelay": 1800,
|
|
|
- "syncInterval":5
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-`activeSize` is the maximum number of peers that can join the cluster and participate in the consensus protocol.
|
|
|
-
|
|
|
-The size of cluster is controlled to be around a certain number. If it is not, standby-mode instances will join or peer-mode instances will be removed to make it happen.
|
|
|
-
|
|
|
-`removeDelay` indicates the minimum time that a machine has been observed to be unresponsive before it is removed from the cluster.
|
|
|
-
|
|
|
-### Get Cluster Config
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:7001/v2/admin/config
|
|
|
-```
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "activeSize": 3,
|
|
|
- "removeDelay": 1800,
|
|
|
- "syncInterval":5
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-## Remove Machines
|
|
|
-
|
|
|
-At times you may want to manually remove a machine. Using the machines endpoint
|
|
|
-you can find and remove machines.
|
|
|
+See the [other etcd APIs][other-apis] for details on the cluster management.
|
|
|
|
|
|
-First, list all the machines in the cluster.
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:7001/v2/admin/machines
|
|
|
-```
|
|
|
-```json
|
|
|
-[
|
|
|
- {
|
|
|
- "clientURL": "http://127.0.0.1:4001",
|
|
|
- "name": "peer1",
|
|
|
- "peerURL": "http://127.0.0.1:7001",
|
|
|
- "state": "leader"
|
|
|
- },
|
|
|
- {
|
|
|
- "clientURL": "http://127.0.0.1:4002",
|
|
|
- "name": "peer2",
|
|
|
- "peerURL": "http://127.0.0.1:7002",
|
|
|
- "state": "follower"
|
|
|
- },
|
|
|
- {
|
|
|
- "clientURL": "http://127.0.0.1:4003",
|
|
|
- "name": "peer3",
|
|
|
- "peerURL": "http://127.0.0.1:7003",
|
|
|
- "state": "follower"
|
|
|
- }
|
|
|
-]
|
|
|
-```
|
|
|
-
|
|
|
-Then take a closer look at the machine you want to remove.
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L http://127.0.0.1:7001/v2/admin/machines/peer2
|
|
|
-```
|
|
|
-
|
|
|
-```json
|
|
|
-{
|
|
|
- "clientURL": "http://127.0.0.1:4002",
|
|
|
- "name": "peer2",
|
|
|
- "peerURL": "http://127.0.0.1:7002",
|
|
|
- "state": "follower"
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-And finally remove it.
|
|
|
-
|
|
|
-```sh
|
|
|
-curl -L -XDELETE http://127.0.0.1:7001/v2/admin/machines/peer2
|
|
|
-```
|
|
|
+[other-apis]: https://github.com/coreos/etcd/blob/master/Documentation/other_apis.md
|