etcdctl command translates its commands into REST calls. Usefully, it includes a
--debug option which will respond with data on the endpoints connected to and, more importantly for us, the equivalent
curl command which will perform the same operation. For example:
$ etcdctl --debug --no-sync --endpoints https://portal251-1.sproutsetc.compose-3.composedb.com:15293,https://portal234-0.sproutsetc.compose-3.composedb.com:15293 -u root:secret set /usefulkey usefulvalue Cluster-Endpoints: https://portal251-1.sproutsetc.compose-3.composedb.com:15293, https://portal234-0.sproutsetc.compose-3.composedb.com:15293 cURL Command: curl -X PUT https://portal251-1.sproutsetc.compose-3.composedb.com:15293/v2/keys/usefulkey -d "value=usefulvalue" usefulvalue
Use this to translate any
etcdctl command to its REST variant.
Entering the endpoints and user credentials every time can be tiresome. The etcdctl command has a number of environment variables which can be set to simplify things, specifically
$ export ETCDCTL_ENDPOINTS=https://portal251-1.sproutsetc.compose-3.composedb.com:15293,https://portal234-0.sproutsetc.compose-3.composedb.com:15293 $ export ETCDCTL_USERNAME=root:secret $ etcdctl --no-sync set /usefulkey usefulvalue ⏎ usefulvalue $
--no-sync parameter stops the command from attempting to synchronize with the entire cluster allowing it to return a result more quickly.
The command examples from this point on will assume these environment variables are set.
In version 2 of etcd, keys can represent directories of keys as well as values. This allows the database to be organized as a hierarchical structure. The
etcdctl command has a
mkdir command which allows you to create a directory. Key/value pairs in that directory can then be created and updated using the
$ etcdctl --no-sync mkdir /foo-service $ etcdctl --no-sync set /foo-service/container1 examplename > examplename
The 'set' command will also create the needed directories to set a key value if they don't exist. Assuming there's no directory called
master_configuration then trying to set the key
secret_passcode within it will create the
$ etcdctl --no-sync set /master_configuration/secret_passcode 123456 > 123456
You can verify the directory has been created using the
$ etcdctl --no-sync ls /master_configuration > /master_configuration/secret_passcode $ etcdctl --no-sync ls /foo-service > /foo-service/container1
etcd allows you to wait for changes on a key until its value changes. What happens, behind the scenes, is that a HTTP request is made for the value and it is not responded to unitilYou will know immediately when values in your deployment have changed. To monitor a key 'greeting' with current value 'Hello User', use the
watch command in etcdctl or a
wait=true in cURL.
$ etcdctl --no-sync watch greeting
The session should just sit, waiting for a response, or in this case, a change in the key. In a separate terminal session, change the value of 'greeting'.
$ etcdctl --no-sync set greeting 'Hello Watcher' >Hello Watcher
After the command in the second session has updated the key with the new value, both commands should return the new value and exit. Adding
--forever stops the watch command from exiting and restarts the watch automatically. Adding
--recursive will enable the watch to monitor changes in the key, and if the key is a directory, any changes in keys contained within that directory.
There is another etcdctl command
exec-watch which will run a script or command when the key's value has changed. It also always runs as
--forever. For example, this next command will make a Mac run the "say" speech command every time there's a change to the
$ etcdctl --no-sync exec-watch greeting -- say 'changes'
Keys can be created with a
TTL value - a set expiry time. This allows etcd to act as a time sensitive cache, automatically cleaning up values that are too old. Add the
--ttl tag and provide a value for how many seconds the key is required to live for.
$ etcdctl --no-sync set farewell "Be Seeing You" --ttl 60 > Be Seeing You
If you try to get the value of the key after the time expires, it will result in an error:
$ etcdctl --no-sync get farewell > Error: 100: Key not found (/farewell) 
For consistency, you can use
--swap-with-value to ensure that the value of a key is what you expect it to be. The comparison and, if the comparison is valid the swapping of the value, is done as a single atomic operation. If the comparison is invalid, an error is returned. For example:
# First set a value $ etcdctl --no-sync set critical 99 99 # Now we'll safely update it $ etcdctl --no-sync set critical 100 --swap-with-value 99 100 # If we try again $ etcdctl --no-sync set critical 100 --swap-with-value 99 Error: 101: Compare failed ([99 != 100])  # We get an error and saved from double incrementing a value.
This is known as the atomic compare-and-swap operation.
Deleting a key has a similar protection option;
--with-value as an option to the
rm command will only delete a key if its value is that given and, again it is carried out as an atomic operation. Carrying on from our previous example:
$ etcdctl --no-sync rm critical --with-value 99 Error: 101: Compare failed ([99 != 100])  $ etcdctl --no-sync rm critical --with-value 100 ⏎ $
If this article didn't solve things, summon a human and get some help!