This is the second part about etcd and completely geared towards etcd’s HTTP/JSON API and the command line utility etcdctl. Within the previous post on etcd, we described how etcd can bootstrap a new cluster with the help of an existing one. Further, we showed you two configuration opportunities: command line or #cloud-config.
Within this article, we deep-dive on etcd communication. That means, we’ll have a look at etcd’s API and available functionality to get, set, watch keys and their values. Additionally, we clarify the confusion about used ports by etcd.
CoreOS Series Overview
- etcd vs. etcd2, Configuration & Cluster Discovery
- Read and Write Values to etcd
Introduction
etcd is installed on every CoreOS node within your cluster and exposes a RESTful HTTP/JSON API to read and write data. Application containers can use etcd to share connection strings for service discovery. There are multiple ways to read and write data into etcd: directly via HTTP API with a tool like curl, language specific libraries or etcd’s command line utility etcdctl.
Ports
Before version 2.0, etcd exposed two different ports than today for client and server communication. Originally, etcd exposed port 4001 for client and port 7001 for server-to-server communication. With the launch of etcd 2.0, IANA assigned etcd two different ports than previously: 2379 for client and 2380 for server-to-server communication.
etcd has backwards compatibility and you can still use the old ports. If you’re new to CoreOS and etcd or just starting out, you can restrict yourself to only use the IANA assigned ports 2379 and 2380.
Within this series, we define etcd’s configuration to listen on the new as well as the old ports.
Communicate with etcd via etcdctl
etcd offers multiple configuration options and has an extensive functionality set. The data within the distributed key-value-store is stored in files within directories. This type of hierarchy is similar to a file system.
As already mentioned, you can use the command line utility etcdctl to get, set, or watch keys and their values. We’ll cover the HTTP/JSON API later within this post. For now, we walk through the basic commands to get, set and watch keys with the help of etcdctl.
Write to etcd: Set Values and Create Directories
Before we read values from etcd, we start with writing the typical foo-bar key-value-pair. This way, we can write our typical test values first and read them later to verify the operation succeeded successfully.
etcd handles the key-value-pairs like a file system and you can write keys as you would create files within a directory. Write your key-value-pairs with a leading slash. Let’s set the /foo key to illustrate the example.
etcdctl set /foo bar
Using a hierarchy will result in a key like /f1/f2/foo/bar.
etcdctl set /bar/foo "This is CoreOS"
You can’t override an existing key with a directory having the same name as the key. For example: creating a key /foo and afterwards trying to create a key /foo/bar will result in an error since the key foo already exists. You need to delete the key first to write the directory-style key-value-pair.
etcd allows to update values for existing keys.
etcdctl update /bar/foo "This is updated CoreOS"
There is a command to create a new directory: mkdir.
etcdctl mkdir /fooDir
Directories can also be updated and have a limited lifetime.
etcdctl updatedir /fooDir --ttl 10
Create new keys within a directory using either set or mk. The mk command only creates the new key if it doesn’t exist. The set command will override existing keys.
etcdctl set /fooDir/foo bar
etcdctl mk /fooDir/bar foo
Expiring Keys with TTL
etcd supports expiring keys. Define the time to live flag in seconds and etcd will automatically delete your key-value-pair once the time is up.
etcdctl set /foo bar --ttl 5
Read from etcd: Get Keys and Directories
You can get the value for a given key using etcdctl:
etcdctl get /foo
The command above just prints the current value if existing. You can extend the output of etcdctl using the -o extended flag. This will print out additional, parseble information.
etcdctl -o extended get /foo
Key: /foo
Created-Index: 14963
Modified-Index: 14963
TTL: 0
Etcd-Index: 14985
Raft-Index: 47174
Raft-Term: 67
bar
Directories can contain other further directories and keys. List the root directory with
etcdctl ls
/foo
/coreos.com
/bar
/f1
There can be directories and keys within a given directory. Distinct both types using the -p flag.
etcdctl ls -p
/bar/
/f1/
/foo
/coreos.com/
Distinguishable by the trailing slash, everything without one is a key. Here, /foo is just a key and everything else a directory.
etcdctl saves you time and can list the contents of every directory recursively.
etcdctl ls -recursive
/bar
/bar/foo
/f1
/f1/f2
/f1/f2/foo
/f1/f2/foo/bar
/foo
/coreos.com
/coreos.com/updateengine
/coreos.com/updateengine/rebootlock
/coreos.com/updateengine/rebootlock/semaphore
Delete Keys and Directories from etcd
etcdctl commands are oriented towards typical unix commands line instructions. You’ll find this behavior also when deleting keys and directories.
Deleting a key
etcdctl rm /foo
You’re completely right, if you’re intuitively thinking of the rmdir command to delete a directory.
Delete an empty directory:
etcdctl rmdir /foo/bar/dirname
You can also use the --dir flag for the rm command to delete an empty repository:
etcdctl rm /foo/bar/dirname --dir
Completely removing the hierarchy including all sub-directories and keys included:
etcdctl rm /foo/bar/dirname --recursive
etcd provides the functionality to conditionally delete key-value-pairs matching a given condition respective the value or raft index.
etcdctl rm /bar/foo --with-value "This is CoreOS"
etcdctl rm /foo --with-index 42
Watch Key-Value-Changes
etcd distributes keys and their values throughout the cluster. Every machine within the cluster shares the data with its peers. You’re able to watch specific keys for value changes and react to them properly.
Watch for a key change:
etcdctl watch /foo
The process will stop watching the key /foo once it changes its value. Further changes get distributed unnoticed. To listen forever, just add the --forever flag.
etcdctl watch /foo --forever
Continuously watching a key will grab the command line and you need to get out with CTRL/CMD+c.
Hidden Keys and Values
One feature of etcd that’s living in secret is hidden keys. These hidden keys get distributed like normal ones, but they don’t appear when listing keys and directories.
Hidden keys begin with an underscore.
You can use etcdctl to show them when directly specifying the name
etcdctl ls --recursive /_coreos.com
You can check the distribution across the cluster by setting a hidden key _foo:
etcdctl set _foo bar
Using another cluster member and getting the value of _foo will print bar, even though the key won’t get listed using ls.
etcdctl set _foo bar
bar
Communicate with etcd via HTTP/JSON API
etcd provides an easy to use HTTP/JSON API to get, set and watch keys and their values. Internally, etcd transparently redirects all reads to the leader. That means, you need to add the -L flag to every curl command to follow redirects and location headers from etcd. Response will be in JSON format.
Generally, every command available in etcdctl is also working when using the HTTP/JSON API. Use the HTTP verbs GET, PUT, DELETE to get, watch, set, and delete keys. You can also add flags by passing them as query parameters within the url with your request. Let’s just jump right into some examples.
Set a key and value:
curl -L -X PUT http://127.0.0.1:2379/v2/keys/foo -d value="bar"
Get the key and value:
curl -L http://127.0.0.1:2379/v2/keys/foo
You can list all existing keys within etcd:
curl -L http://127.0.0.1:2379/v2/keys/
{
"action":"get",
"node":{
"dir":true,
"nodes":[
{
"key":"/coreos.com",
"dir":true,
"modifiedIndex":6,
"createdIndex":6
},
{
"key":"/discovery",
"value":"",
"modifiedIndex":24836,
"createdIndex":24836
},
{
"key":"/foo",
"value":"bar",
"modifiedIndex":51366,
"createdIndex":51366
}
]
}
}
Remember the flags from etcdctl like --recursive when listing all existing keys? You can do that as well with the HTTP/JSON API by passing the flags as query parameters within the url.
curl -L http://127.0.0.1:2379/v2/keys/?recursive=true
{
"action":"get",
"node":{
"dir":true,
"nodes":[
{
"key":"/message",
"value":"Hello",
"modifiedIndex":59089,
"createdIndex":59089
},
{
"key":"/coreos.com",
"dir":true,
"nodes":[
{
"key":"/coreos.com/updateengine",
"dir":true,
"nodes":[
{
"key":"/coreos.com/updateengine/rebootlock",
"dir":true,
"nodes":[
{
"key":"/coreos.com/updateengine/rebootlock/semaphore",
"value":"{\"semaphore\":1,\"max\":1,\"holders\":[]}",
"modifiedIndex":54495,
"createdIndex":6
}
],
"modifiedIndex":6,
"createdIndex":6
}
],
"modifiedIndex":6,
"createdIndex":6
}
],
"modifiedIndex":6,
"createdIndex":6
},
{
"key":"/discovery",
"value":"",
"modifiedIndex":24836,
"createdIndex":24836
},
{
"key":"/foo",
"value":"bar",
"modifiedIndex":51366,
"createdIndex":51366
}
]
}
}
Watch a key for changes: wait=true
curl -L http://127.0.0.1:2379/v2/keys/foo?wait=true
Watching for values changes on keys is of course available via API. The thing is, that long polling operations may fail due to request timeouts or server restarts. Clients have to deal with this situations and retry the watch operations in such cases.
Delete a key:
curl http://127.0.0.1:2379/v2/keys/foo -XDELETE
Actually, there is much more functionality to cover for the HTTP/JSON API. We already guided you through most of the commands when touching etcdctl. If you want to soak up more about the HTTP/JSON API of etcd, head over to their API documents on GitHub.
Outlook
This post showed you the commands to get, set, watch and delete keys and directories. CoreOS ships with the command line utility etcdctl to interact with etcd. Additionally, you can use the HTTP/JSON API for client communication.
Within the next post, we’ll deep-dive into CoreOS’s distributed init system fleet.
Additional Resources
- etcd Configuration & Cluster Discovery
- etcd repository on GitHub
- etcd documentation on coreos.com
- etcdctl overview on GitHub