Playing with Locks in Consul
Posted on September 13, 2015
Consul is a great piece of software, and I love building HA services with it at the heart of the distributed system. One of Consul’s features is a distributed locking mechanism, and I wanted to learn a little more about it. I also wanted to experiment with simple methods for running a one-time action, or a single instance of a service in a distributed system - potential solutions to the famous challenge: “who guards the guards?”
import sys
from time import sleep
import consul
import consul_lock
from docker import Client
'''
This is a PoC which uses consul's locking mechanism to ensure only
one instance of the named docker container is running. Requires:
a) pip install python-consul consul-lock
b) docker create --name my_container my/app
try it: python only-one.py container_name token
'''
pause = 3
container_name = sys.argv[1]
token = sys.argv[2]
cli = Client(base_url='unix://var/run/docker.sock')
consul_client = consul.Consul(token=token)
consul_lock.defaults.consul_client = consul_client
print 'starting up!'
while True:
ephemeral_lock = consul_lock.EphemeralLock(('only-one/%s' % container_name),
lock_timeout_seconds=3600,
acquire_timeout_ms=500)
try:
print 'acquiring distributed lock in consul..'
was_acquired = ephemeral_lock.acquire(fail_hard=False)
if was_acquired:
# do dangerous stuff here
print 'lock acquired!'
print ('starting container %s' % container_name)
response = cli.start(container=container_name)
print(response)
print 'will now wait/block until the container exits..'
cli.wait(container=container_name)
else:
print 'someone else has the lock :\ try again later'
finally:
print 'be sure there is no lock in consul..'
ephemeral_lock.release()
print ('sleeping for %d seconds' % pause)
sleep(pause)The original post can be seen in this gist.

