github.com/kafkaliu/etcd@v0.1.2-0.20131007164923-44c16dd30d69/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