github.com/qorio/etcd@v0.1.2-0.20131003183127-5cc585af9618/README.md (about) 1 # etcd 2 README version 0.1.0 3 4 [![Build Status](https://travis-ci.org/coreos/etcd.png)](https://travis-ci.org/coreos/etcd) 5 6 A highly-available key value store for shared configuration and service discovery. etcd is inspired by zookeeper and doozer, with a focus on: 7 8 * Simple: curl'able user facing API (HTTP+JSON) 9 * Secure: optional SSL client cert authentication 10 * Fast: benchmarked 1000s of writes/s per instance 11 * Reliable: Properly distributed using Raft 12 13 Etcd is written in Go and uses the [raft][raft] consensus algorithm to manage a highly-available replicated log. 14 15 See [etcdctl][etcdctl] for a simple command line client. Or feel free to just use curl, as in the examples below. 16 17 [raft]: https://github.com/coreos/go-raft 18 [etcdctl]: http://coreos.com/docs/etcdctl/ 19 20 ## Getting Started 21 22 ### Getting etcd 23 24 The latest release is available as a binary at [Github][github-release]. 25 26 [github-release]: https://github.com/coreos/etcd/releases/ 27 28 ### Building 29 30 You can build etcd from source: 31 32 ```sh 33 git clone https://github.com/coreos/etcd 34 cd etcd 35 ./build 36 ``` 37 38 This will generate a binary in the base directory called `./etcd`. 39 40 _NOTE_: you need go 1.1+. Please check your installation with 41 42 ``` 43 go version 44 ``` 45 46 ### Running a single node 47 48 These examples will use a single node cluster to show you the basics of the etcd REST API. Lets start etcd: 49 50 ```sh 51 ./etcd -d node0 -n node0 52 ``` 53 54 This will bring up an etcd node listening on port 4001 for client communication and on port 7001 for server-to-server communication. 55 The `-d node0` argument tells etcd to write node configuration, logs and snapshots to the `./node0/` directory. 56 The `-n node0` tells the rest of the cluster that this node is named node0. 57 58 ## Usage 59 60 ### Setting the value to a key 61 62 Let’s set the first key-value pair to the node. In this case the key is `/message` and the value is `Hello world`. 63 64 ```sh 65 curl -L http://127.0.0.1:4001/v1/keys/message -d value="Hello world" 66 ``` 67 68 ```json 69 {"action":"SET","key":"/message","value":"Hello world","newKey":true,"index":3} 70 ``` 71 72 This response contains five fields. We will introduce three more fields as we try more commands. 73 74 1. The action of the request; we set the value via a POST request, thus the action is `SET`. 75 76 2. The key of the request; we set `/message` to `Hello world!`, so the key field is `/message`. 77 Notice we use a file system like structure to represent the key-value pairs. So each key starts with `/`. 78 79 3. The current value of the key; we set the value to`Hello world`. 80 81 4. If we set a new key; `/message` did not exist before, so this is a new key. 82 83 5. Index is the unique internal log index of the set request. Requests that change the log index include `SET`, `DELETE` and `TESTANDSET`. The `GET`, `LIST` and `WATCH` commands do not change state in the store and so they do not change the index. You may notice that in this example the index is 3, although it is the first request you sent to the server. This is because there are internal commands that also change the state like adding and syncing servers. 84 85 ### Get the value of a key 86 87 Get the value that we just set in `/message` by issuing a GET: 88 89 ```sh 90 curl -L http://127.0.0.1:4001/v1/keys/message 91 ``` 92 93 ```json 94 {"action":"GET","key":"/message","value":"Hello world","index":3} 95 ``` 96 ### Change the value of a key 97 98 Change the value of `/message` from `Hello world` to `Hello etcd` with another POST to the key: 99 100 ```sh 101 curl -L http://127.0.0.1:4001/v1/keys/message -d value="Hello etcd" 102 ``` 103 104 ```json 105 {"action":"SET","key":"/message","prevValue":"Hello world","value":"Hello etcd","index":4} 106 ``` 107 108 Notice that the `prevValue` is set to `Hello world`. 109 110 ### Delete a key 111 112 Remove the `/message` key with a DELETE: 113 114 ```sh 115 curl -L http://127.0.0.1:4001/v1/keys/message -X DELETE 116 ``` 117 118 ```json 119 {"action":"DELETE","key":"/message","prevValue":"Hello etcd","index":5} 120 ``` 121 122 ### Using key TTL 123 124 Keys in etcd can be set to expire after a specified number of seconds. That is done by setting a TTL (time to live) on the key when you POST: 125 126 ```sh 127 curl -L http://127.0.0.1:4001/v1/keys/foo -d value=bar -d ttl=5 128 ``` 129 130 ```json 131 {"action":"SET","key":"/foo","value":"bar","newKey":true,"expiration":"2013-07-11T20:31:12.156146039-07:00","ttl":4,"index":6} 132 ``` 133 134 Note the last two new fields in response: 135 136 1. The expiration is the time that this key will expire and be deleted. 137 138 2. The ttl is the time to live of the key. 139 140 Now you can try to get the key by sending: 141 142 ```sh 143 curl -L http://127.0.0.1:4001/v1/keys/foo 144 ``` 145 146 If the TTL has expired, the key will be deleted, and you will be returned a 100. 147 148 ```json 149 {"errorCode":100,"message":"Key Not Found","cause":"/foo"} 150 ``` 151 152 ### Watching a prefix 153 154 We can watch a path prefix and get notifications if any key change under that prefix. 155 156 In one terminal, we send a watch request: 157 158 ```sh 159 curl -L http://127.0.0.1:4001/v1/watch/foo 160 ``` 161 162 Now, we are watching at the path prefix `/foo` and wait for any changes under this path. 163 164 In another terminal, we set a key `/foo/foo` to `barbar` to see what will happen: 165 166 ```sh 167 curl -L http://127.0.0.1:4001/v1/keys/foo/foo -d value=barbar 168 ``` 169 170 The first terminal should get the notification and return with the same response as the set request. 171 172 ```json 173 {"action":"SET","key":"/foo/foo","value":"barbar","newKey":true,"index":7} 174 ``` 175 176 However, the watch command can do more than this. Using the the index we can watch for commands that has happened in the past. This is useful for ensuring you don't miss events between watch commands. 177 178 Let's try to watch for the set command of index 6 again: 179 180 ```sh 181 curl -L http://127.0.0.1:4001/v1/watch/foo -d index=7 182 ``` 183 184 The watch command returns immediately with the same response as previous. 185 186 ### Atomic Test and Set 187 188 Etcd can be used as a centralized coordination service in a cluster and `TestAndSet` is the most basic operation to build distributed lock service. This command will set the value only if the client provided `prevValue` is equal the current key value. 189 190 Here is a simple example. Let's create a key-value pair first: `foo=one`. 191 192 ```sh 193 curl -L http://127.0.0.1:4001/v1/keys/foo -d value=one 194 ``` 195 196 Let's try an invalid `TestAndSet` command. 197 We can give another parameter prevValue to set command to make it a TestAndSet command. 198 199 ```sh 200 curl -L http://127.0.0.1:4001/v1/keys/foo -d prevValue=two -d value=three 201 ``` 202 203 This will try to test if the previous of the key is two, it is change it to three. 204 205 ```json 206 {"errorCode":101,"message":"The given PrevValue is not equal to the value of the key","cause":"TestAndSet: one!=two"} 207 ``` 208 209 which means `testAndSet` failed. 210 211 Let us try a valid one. 212 213 ```sh 214 curl -L http://127.0.0.1:4001/v1/keys/foo -d prevValue=one -d value=two 215 ``` 216 217 The response should be 218 219 ```json 220 {"action":"SET","key":"/foo","prevValue":"one","value":"two","index":10} 221 ``` 222 223 We successfully changed the value from “one” to “two”, since we give the correct previous value. 224 225 ### Listing a directory 226 227 Last we provide a simple List command to list all the keys under a prefix path. 228 229 Let us create some keys first. 230 231 We already have `/foo/foo=barbar` 232 233 We create another one `/foo/foo_dir/foo=barbarbar` 234 235 ```sh 236 curl -L http://127.0.0.1:4001/v1/keys/foo/foo_dir/bar -d value=barbarbar 237 ``` 238 239 Now list the keys under `/foo` 240 241 ```sh 242 curl -L http://127.0.0.1:4001/v1/keys/foo/ 243 ``` 244 245 We should see the response as an array of items 246 247 ```json 248 [{"action":"GET","key":"/foo/foo","value":"barbar","index":10},{"action":"GET","key":"/foo/foo_dir","dir":true,"index":10}] 249 ``` 250 251 which meas `foo=barbar` is a key-value pair under `/foo` and `foo_dir` is a directory. 252 253 ## Advanced Usage 254 255 ### Transport security with HTTPS 256 257 Etcd supports SSL/TLS and client cert authentication for clients to server, as well as server to server communication 258 259 First, you need to have a CA cert `clientCA.crt` and signed key pair `client.crt`, `client.key`. This site has a good reference for how to generate self-signed key pairs: 260 http://www.g-loaded.eu/2005/11/10/be-your-own-ca/ 261 262 For testing you can use the certificates in the `fixtures/ca` directory. 263 264 Next, lets configure etcd to use this keypair: 265 266 ```sh 267 ./etcd -n node0 -d node0 -clientCert=./fixtures/ca/server.crt -clientKey=./fixtures/ca/server.key.insecure -f 268 ``` 269 270 `-f` forces new node configuration if existing configuration is found (WARNING: data loss!) 271 `-clientCert` and `-clientKey` are the key and cert for transport layer security between client and server 272 273 You can now test the configuration using https: 274 275 ```sh 276 curl --cacert fixtures/ca/ca.crt https://127.0.0.1:4001/v1/keys/foo -d value=bar -v 277 ``` 278 279 You should be able to see the handshake succeed. 280 281 ``` 282 ... 283 SSLv3, TLS handshake, Finished (20): 284 ... 285 ``` 286 287 And also the response from the etcd server. 288 289 ```json 290 {"action":"SET","key":"/foo","value":"bar","newKey":true,"index":3} 291 ``` 292 293 ### Authentication with HTTPS client certificates 294 295 We can also do authentication using CA certs. The clients will provide their cert to the server and the server will check whether the cert is signed by the CA and decide whether to serve the request. 296 297 ```sh 298 ./etcd -n node0 -d node0 -clientCAFile=./fixtures/ca/ca.crt -clientCert=./fixtures/ca/server.crt -clientKey=./fixtures/ca/server.key.insecure -f 299 ``` 300 301 ```-clientCAFile``` is the path to the CA cert. 302 303 Try the same request to this server: 304 305 ```sh 306 curl --cacert fixtures/ca/ca.crt https://127.0.0.1:4001/v1/keys/foo -d value=bar -v 307 ``` 308 309 The request should be rejected by the server. 310 311 ``` 312 ... 313 routines:SSL3_READ_BYTES:sslv3 alert bad certificate 314 ... 315 ``` 316 317 We need to give the CA signed cert to the server. 318 319 ```sh 320 curl -L https://127.0.0.1:4001/v1/keys/foo -d value=bar -v --key myclient.key --cert myclient.crt -cacert clientCA.crt 321 ``` 322 323 You should able to see 324 ``` 325 ... 326 SSLv3, TLS handshake, CERT verify (15): 327 ... 328 TLS handshake, Finished (20) 329 ``` 330 331 And also the response from the server: 332 333 ```json 334 {"action":"SET","key":"/foo","value":"bar","newKey":true,"index":3} 335 ``` 336 337 ## Clustering 338 339 ### Example cluster of three machines 340 341 Let's explore the use of etcd clustering. We use go-raft as the underlying distributed protocol which provides consistency and persistence of the data across all of the etcd instances. 342 343 Let start by creating 3 new etcd instances. 344 345 We use -s to specify server port and -c to specify client port and -d to specify the directory to store the log and info of the node in the cluster 346 347 ```sh 348 ./etcd -s 127.0.0.1:7001 -c 127.0.0.1:4001 -d nodes/node1 -n node1 349 ``` 350 351 **Note:** If you want to run etcd on external IP address and still have access locally you need to add `-cl 0.0.0.0` so that it will listen on both external and localhost addresses. 352 A similar argument `-sl` is used to setup the listening address for the server port. 353 354 Let the join two more nodes to this cluster using the -C argument: 355 356 ```sh 357 ./etcd -c 127.0.0.1:4002 -s 127.0.0.1:7002 -C 127.0.0.1:7001 -d nodes/node2 -n node2 358 ./etcd -c 127.0.0.1:4003 -s 127.0.0.1:7003 -C 127.0.0.1:7001 -d nodes/node3 -n node3 359 ``` 360 361 Get the machines in the cluster: 362 363 ```sh 364 curl -L http://127.0.0.1:4001/v1/machines 365 ``` 366 367 We should see there are three nodes in the cluster 368 369 ``` 370 http://127.0.0.1:4001, http://127.0.0.1:4002, http://127.0.0.1:4003 371 ``` 372 373 The machine list is also available via this API: 374 375 ```sh 376 curl -L http://127.0.0.1:4001/v1/keys/_etcd/machines 377 ``` 378 379 ```json 380 [{"action":"GET","key":"/_etcd/machines/node1","value":"raft=http://127.0.0.1:7001&etcd=http://127.0.0.1:4001","index":4},{"action":"GET","key":"/_etcd/machines/node2","value":"raft=http://127.0.0.1:7002&etcd=http://127.0.0.1:4002","index":4},{"action":"GET","key":"/_etcd/machines/node3","value":"raft=http://127.0.0.1:7003&etcd=http://127.0.0.1:4003","index":4}] 381 ``` 382 383 The key of the machine is based on the ```commit index``` when it was added. The value of the machine is ```hostname```, ```raft port``` and ```client port```. 384 385 Also try to get the current leader in the cluster 386 387 ``` 388 curl -L http://127.0.0.1:4001/v1/leader 389 ``` 390 The first server we set up should be the leader, if it has not died during these commands. 391 392 ``` 393 http://127.0.0.1:7001 394 ``` 395 396 Now we can do normal SET and GET operations on keys as we explored earlier. 397 398 ```sh 399 curl -L http://127.0.0.1:4001/v1/keys/foo -d value=bar 400 ``` 401 402 ```json 403 {"action":"SET","key":"/foo","value":"bar","newKey":true,"index":5} 404 ``` 405 406 ### Killing Nodes in the Cluster 407 408 Let's kill the leader of the cluster and get the value from the other machine: 409 410 ```sh 411 curl -L http://127.0.0.1:4002/v1/keys/foo 412 ``` 413 414 A new leader should have been elected. 415 416 ``` 417 curl -L http://127.0.0.1:4001/v1/leader 418 ``` 419 420 ``` 421 http://127.0.0.1:7002 422 ``` 423 424 or 425 426 ``` 427 http://127.0.0.1:7003 428 ``` 429 430 You should be able to see this: 431 432 ```json 433 {"action":"GET","key":"/foo","value":"bar","index":5} 434 ``` 435 436 It succeeded! 437 438 ### Testing Persistence 439 440 OK. Next let us kill all the nodes to test persistence. And restart all the nodes use the same command as before. 441 442 Your request for the `foo` key will return the correct value: 443 444 ```sh 445 curl -L http://127.0.0.1:4002/v1/keys/foo 446 ``` 447 448 ```json 449 {"action":"GET","key":"/foo","value":"bar","index":5} 450 ``` 451 452 ### Using HTTPS between servers 453 454 In the previous example we showed how to use SSL client certs for client to server communication. Etcd can also do internal server to server communication using SSL client certs. To do this just change the ```-client*``` flags to ```-server*```. 455 456 If you are using SSL for server to server communication, you must use it on all instances of etcd. 457 458 ## Contributing 459 460 See [CONTRIBUTING](https://github.com/coreos/etcd/blob/master/CONTRIBUTING.md) for details on submitting patches and contacting developers via IRC and mailing lists. 461 462 ## Libraries and Tools 463 464 **Tools** 465 466 - [etcdctl](https://github.com/coreos/etcdctl) - A command line client for etcd 467 468 **Go libraries** 469 470 - [go-etcd](https://github.com/coreos/go-etcd) 471 472 **Java libraries** 473 474 - [justinsb/jetcd](https://github.com/justinsb/jetcd) 475 - [diwakergupta/jetcd](https://github.com/diwakergupta/jetcd) 476 477 478 **Python libraries** 479 480 - [transitorykris/etcd-py](https://github.com/transitorykris/etcd-py) 481 - [jplana/python-etcd](https://github.com/jplana/python-etcd) 482 - [russellhaering/txetcd](https://github.com/russellhaering/txetcd) - a Twisted Python library 483 484 **Node libraries** 485 486 - [stianeikeland/node-etcd](https://github.com/stianeikeland/node-etcd) 487 488 **Ruby libraries** 489 490 - [iconara/etcd-rb](https://github.com/iconara/etcd-rb) 491 - [jpfuentes2/etcd-ruby](https://github.com/jpfuentes2/etcd-ruby) 492 - [ranjib/etcd-ruby](https://github.com/ranjib/etcd-ruby) 493 494 **C libraries** 495 496 - [jdarcy/etcd-api](https://github.com/jdarcy/etcd-api) 497 498 **Chef Integration** 499 500 - [coderanger/etcd-chef](https://github.com/coderanger/etcd-chef) 501 502 **Chef Cookbook** 503 504 - [spheromak/etcd-cookbook](https://github.com/spheromak/etcd-cookbook) 505 506 **Projects using etcd** 507 508 - [binocarlos/yoda](https://github.com/binocarlos/yoda) - etcd + ZeroMQ 509 - [calavera/active-proxy](https://github.com/calavera/active-proxy) - HTTP Proxy configured with etcd 510 - [derekchiang/etcdplus](https://github.com/derekchiang/etcdplus) - A set of distributed synchronization primitives built upon etcd 511 - [gleicon/goreman](https://github.com/gleicon/goreman/tree/etcd) - Branch of the Go Foreman clone with etcd support 512 - [garethr/hiera-etcd](https://github.com/garethr/hiera-etcd) - Puppet hiera backend using etcd 513 - [mattn/etcd-vim](https://github.com/mattn/etcd-vim) - SET and GET keys from inside vim 514 - [mattn/etcdenv](https://github.com/mattn/etcdenv) - "env" shebang with etcd integration 515 516 ## FAQ 517 518 ### What size cluster should I use? 519 520 Every command the client sends to the master is broadcast to all of the followers. 521 But, the command is not committed until the majority of the cluster machines receive that command. 522 523 Because of this majority voting property the ideal cluster should be kept small to keep speed up and be made up of an odd number of machines. 524 525 Odd numbers are good because if you have 8 machines the majority will be 5 and if you have 9 machines the majority with be 5. 526 The result is that an 8 machine cluster can tolerate 3 machine failures and a 9 machine cluster can tolerate 4 nodes failures. 527 And in the best case when all 9 machines are responding the cluster will perform at the speed of the fastest 5 nodes. 528 529 ## Project Details 530 531 ### Versioning 532 533 etcd uses [semantic versioning][semver]. 534 When we release v1.0.0 of etcd we will promise not to break the "v1" REST API. 535 New minor versions may add additional features to the API however. 536 537 You can get the version of etcd by issuing a request to /version: 538 539 ```sh 540 curl -L http://127.0.0.1:4001/version 541 ``` 542 543 During the v0 series of releases we may break the API as we fix bugs and get feedback. 544 545 [semver]: http://semver.org/ 546 547 ### License 548 549 etcd is under the Apache 2.0 license. See the [LICENSE][license] file for details. 550 551 [license]: https://github.com/coreos/etcd/blob/master/LICENSE