From 154e2781d9debe5417bdec14689ace88eb4ea3e3 Mon Sep 17 00:00:00 2001 From: Lars Kellogg-Stedman Date: Sat, 4 Oct 2014 17:54:03 -0400 Subject: [PATCH] added hautoproxy auto-configuring haproxy This image configures haproxy to forward connections for all available kubernetes services. It is meant to be run alongside other contains in a kubernetes pod to provide access to "remote" services at a consistent address so that keystone api endpoints can be configured in a sane fashion. Change-Id: Ic923c6a772f1bdf36b97b05a1d04de9e5b841ddd --- docker/hautoproxy/Dockerfile | 8 ++++ docker/hautoproxy/build | 1 + docker/hautoproxy/haproxy.cfg.tmpl | 26 ++++++++++++ docker/hautoproxy/start.py | 65 ++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 docker/hautoproxy/Dockerfile create mode 120000 docker/hautoproxy/build create mode 100644 docker/hautoproxy/haproxy.cfg.tmpl create mode 100755 docker/hautoproxy/start.py diff --git a/docker/hautoproxy/Dockerfile b/docker/hautoproxy/Dockerfile new file mode 100644 index 0000000000..b2bb560df4 --- /dev/null +++ b/docker/hautoproxy/Dockerfile @@ -0,0 +1,8 @@ +FROM fedora + +RUN yum -y install haproxy python-jinja2; yum clean all +RUN mkdir -p /etc/haproxy/templates +ADD haproxy.cfg.tmpl /etc/haproxy/templates/haproxy.cfg.tmpl +ADD start.py /start.py +CMD ["/start.py"] + diff --git a/docker/hautoproxy/build b/docker/hautoproxy/build new file mode 120000 index 0000000000..d2accf7d39 --- /dev/null +++ b/docker/hautoproxy/build @@ -0,0 +1 @@ +../../tools/build-docker-image \ No newline at end of file diff --git a/docker/hautoproxy/haproxy.cfg.tmpl b/docker/hautoproxy/haproxy.cfg.tmpl new file mode 100644 index 0000000000..cd1174b219 --- /dev/null +++ b/docker/hautoproxy/haproxy.cfg.tmpl @@ -0,0 +1,26 @@ +global + daemon + maxconn 4096 + pidfile /var/run/haproxy.pid + +defaults + mode tcp + timeout connect 5s + timeout client 1m + timeout server 1m + option redispatch + balance roundrobin + +listen stats :1936 + mode http + stats enable + stats hide-version + #stats realm Haproxy\ Statistics + stats uri / + #stats auth Username:Password + +{% for service in services %} +listen {{ service.service_name }} + bind 127.0.0.1:{{service.local_port}} + server {{ service.remote_name }} {{ service.remote_addr }}:{{ service.remote_port}} check inter 2s rise 3 fall 2 +{% endfor %} diff --git a/docker/hautoproxy/start.py b/docker/hautoproxy/start.py new file mode 100755 index 0000000000..877b22157b --- /dev/null +++ b/docker/hautoproxy/start.py @@ -0,0 +1,65 @@ +#!/usr/bin/python + +'''This script configures and starts a local haproxy instances, bound to +127.0.0.1, that forwards connections all of the discovered +docker/kubernetes environment variables.''' + +import argparse +import os +import sys +from jinja2 import Environment, FileSystemLoader +import re +import urlparse + +re_url = re.compile( + '^(?P.*)_PORT_(?P\d+)_(?P(UDP|TCP))$') + +def parse_args(): + p = argparse.ArgumentParser() + p.add_argument('--output', '-o', + default='/etc/haproxy/haproxy.cfg') + p.add_argument('--no-start', '-n', + action='store_true') + p.add_argument('--template-dir', '-t', + default='/etc/haproxy/templates') + return p.parse_args() + +def discover_services(): + services = [] + for k in os.environ: + mo = re_url.match(k) + + if mo: + parts = urlparse.urlparse(os.environ[k]) + remote_host,remote_port = parts.netloc.split(':') + service_name = '%(name)s-%(port)s' % mo.groupdict() + + services.append({ + 'remote_name': mo.group('name'), + 'remote_addr': remote_host, + 'remote_port': remote_port, + 'remote_proto': parts.scheme, + 'local_port': mo.group('port'), + 'service_name': service_name, + }) + + return services + +def main(): + args = parse_args() + services = discover_services() + + env = Environment(loader=FileSystemLoader(['.', + args.template_dir])) + template = env.get_template('haproxy.cfg.tmpl') + with open(args.output, 'w') as fd: + fd.write(template.render(services=services)) + + if args.no_start: + return + + os.execlp('haproxy', 'haproxy', '-f', args.output, '-db') + +if __name__ == '__main__': + main() +