Using consul watch and git diff to track key value changes
03 Sep 2016In the previous post I introduced how consul is a simple, distributed and fault tolerant system for service discovery and configuration management.
Now, a common need is how do we track if someone has changed a key value or added or deleted a key? Solution is consul watch
command. We can use consul watch
for registering a handler which gets called whenever there is a key-value change. Its format is:
But there is a problem - everytime there is a change in a key value e.g. key global/redis/cacheA
is changed from 192.168.1.1
to 192.168.1.2
then consul watch handler gets invoked with latest values only i.e. 192.168.1.2
.
We felt that there is a need to know the change in full context i.e. old_value
and new_value
. After some searching and not finding a solution we devised a method (rather novel I’d say but I am blinded by bias) by using git
- the most awesome change control system - in local mode (no remote
set).
Idea is simple.
Following steps are to be done as part of the initial setup:
- On the node where you want to setup the alert system designate a directory say
/var/consul/data
. - Run following command to initialize this directory as a git repo.
- Run following command to save the latest snapshot of all key values for keys starting with prefix
global
tokvs.txt
.
- Add and commit to the local git repo
Once the above setup is done - run the consul watch
in daemon mode (via upstart preferably):
This ensures that when there is a change in any of the key values under the specified prefixed keys then it will trigger the execution of watch_handler.sh
. This script does following on each such trigger:
- Change directory to
/var/consul/data/
. - Run following command to get the latest (post change) key values:
- Execute
git diff
.
If empty (no change) then don’t do anything else trigger your alert mechanism with the output of
git diff
command (e.g. mail, slack, mattermost etc.)
- Now that the alert is already sent - commit the new change locally.
Note: You will need to do a bit more actually than just git diff
since the diff command gives values in base64 encoding
. To convert that into readable values you will need to use base64
utility and some play with sed
, awk
etc. Following is some code which can be handy:
This is a screenshot of the change alert in our slack:
Epilogue
In addition to providing the full context of change, this solution is also useful in keeping a local versioned history and is helpful in reverting to older values easily by using git revert
or git reset ...
commands.
Credit to use of git
for this goes to @kernelhacker.
I don’t yet know if there is any other builtin technique in consul-watch
to achieve the same thing. If you know please drop a tweet at @awmanoj. TIA.