<% # This template can be configure the following way with environment variables # Environment variables to filter services/instances # SERVICES_TAG_FILTER: basic tag filter for service (default HTTP) # INSTANCE_MUST_TAG: Second level of filtering (optional, default to SERVICES_TAG_FILTER) # INSTANCE_EXCLUDE_TAG: Exclude instances having the given tag (default: canary) # EXCLUDE_SERVICES: comma-separated services to exclude (default: consul-agent-http,mesos-slave,mesos-agent-watcher) # Environment variables to configure HaProxy # PORT0 : HaProxy main port (default to 8000) # PORT1 : HaProxy admin port (default to 8001) # HAPROXY_ADMIN_PORT: Port to listen # HAPROXY_ADMIN_USER_PASSWORD: User:Password to access to stats (default: none) # HAPROXY_SOCKET_FILE: HaProxy socket to control HaProxy service_tag_filter = ENV['SERVICES_TAG_FILTER'] || 'http' instance_must_tag = ENV['INSTANCE_MUST_TAG'] || service_tag_filter instance_exclude_tag = ENV['INSTANCE_EXCLUDE_TAG'] || 'canary' # Services to hide services_blacklist = (ENV['EXCLUDE_SERVICES'] || 'consul-agent-http,mesos-slave,mesos-agent-watcher,mesos-exporter-slave').split(',') # Compute the health of a Service def compute_state(node) states = ['passing', []] node['Checks'].each do |chk| st = chk['Status'] states[1] << st if st == 'critical' states[0] = st elsif st == 'warning' && states[0] == 'passing' states[0] = st end end states end def compute_attributes(node) w = 100 node['Service']['Tags'].each do |tag| match = /^weight-([1-9][0-9])*$/.match(tag) w = match[1].to_i if match end attributes = "" states = compute_state(node) attributes = "#{attributes} disabled" if states[0] == 'critical' if states[0] == 'warning' w = w / 8 end attributes = "#{attributes} weight #{w}" if w.positive? end backends = {} services(tag: service_tag_filter).each do |service_name, tags| if !services_blacklist.include?(service_name) && tags.include?(instance_must_tag) the_backends = [] service(service_name, tag:'http').sort {|a,b| a['Node']['Node'] <=> b['Node']['Node'] }.each do |node| tags_of_instance = node['Service']['Tags'] if tags_of_instance.include?(instance_must_tag) && !tags_of_instance.include?(instance_exclude_tag) the_backends << node if node['Service']['Port'] end end # We add the backend ONLY if at least one valid instance does exists backends[service_name] = the_backends end end %> # This HaProxy configuration is generated by consul-templaterb # Service/Instances filtering # Service tag MUST be <%= service_tag_filter %> # Instance tag MUST be <%= instance_must_tag %> # Instance tag excluded: <%= instance_exclude_tag %> # Found <%= backends.keys.count %> different services with <%= backends.values.flatten.count %> nodes global maxconn 1024 <% socket_file = ENV['HAPROXY_SOCKET_FILE'] if socket_file %> stats socket <%= socket_file %> mode 600 level admin <% end %> defaults timeout connect 1000 timeout client 5000 timeout server 15000 <% backends.each_pair do |service_name, nodes| %> backend backend_http__<%= service_name %> mode http balance leastconn <% nodes.each do |node| %> server <%= node['Node']['Node']%>_<%= node['Service']['Port'] %> <%= node['Node']['Address']%>:<%= node['Service']['Port'] %><%= compute_attributes(node) %> <% end end %> frontend fontend_http mode http bind *:<%= ENV['PORT0'] || 8000 %> option httplog log 127.0.0.1:534 local5 option dontlognull option forwardfor <% backends.each_pair do |service_name, nodes| %> acl host__<%= service_name %> hdr_beg(host) -i <%= service_name %>. use_backend backend_http__<%= service_name %> if host__<%= service_name%> <% end %> listen stats bind :<%= ENV['PORT1'] || 8001 %> mode http log global maxconn 10 timeout client 100s timeout server 100s timeout connect 100s timeout queue 100s stats enable stats hide-version stats refresh 30s stats show-node stats uri /haproxy?stats <% user_password = ENV['HAPROXY_ADMIN_USER_PASSWORD'] if user_password %> stats auth <%= user_password %> <% end %>