Hi,

First, that you, Willie and everyone else who has contributed to this tool that we use heavily in production.

I can imagine quite a lot of work under the covers had to happen to enable this. Here is what I am thinking of and some background about it. Obviously, we are just one use case. Please view this as just some ideas to help seed the discussion.

We are building a run-time orchestrater (honcho) that will manage the running apps inside a kubernetes pod. We have large complex apps and we often need to do various things that don't fit the typical "docker run" model. Honcho also does all the monitoring of the app, so we will be using the agent addr/port hooks for each host so that haproxy talks to honcho for health checks but feeds connections to the app address/port. (thanks for having the flexibility to do this.) When kubernetes starts up an instance of an app, either a kubernetes hook or honcho will do a dynamic DNS insert of the records into the zone for the data center.

TXT records are always a hack, but its the way I came up with to allow per target information to get into haproxy from DNS.

We use lots of alternate ports as well as the regulars, so we would expect to use the nonstandard _portnum._tcp.name form as well as the _https._tcp standard form. A couple examples of the names I expect to use:

_12354._tcp.service1.datacenter.soundhound.com
_https._tcp.web2.datacenter.soundhound.com

The entire record set might look like:

($origin datacenter.soundhound.com)

_12354._tcp.service1  in  SRV  10 50  23465 target1.service1
target1.service1  in  A  10.1.2.3
t1honcho.service1  in  A 10.1.2.2
target1.service1._12354._tcp.service1 in TXT "addr t1honcho.service1" "port 19999"

The config might look like this

frontend service1fe
  bind *.12354
  default_backend service1be

backend service1be
txt_labels 2 # prepend this many labels from the name of the target to look for txt records
  server _12354._tcp.service1

You could even just do a one liner, since the srv record name specifies what to list on and the targets.
listen xxx
   srv _12354._tcp.service1

This would assume that you are listening on all interfaces...

One last thing. We want to be able to make it so as soon as the DNS zone is updated, haproxy rereads the DNS for these. DNS has a feature called notify where a zone master can tell the slaves to do zone transfer so you can minimize the skew across a set of nameservers.

As a simple first step, I can write a tiny python app that can receive DNS notify messages when a zone is updated. It would then want to kick haproxy to reread the DNS. I don't know haproxy well, there may already be a signal or message that exists that can do this. It would be a small "nice to have" to teach haproxy to accept notify messages and update automatically. (You don't need to do the zone transfer, you just need to receive the message for the new SOA and reply with the correct response.)

I hope all this helps,
jerry

On 12/19/16 4:15 AM, Baptiste wrote:
Hi Jerry,

Thanks a lot for your email and your nice feedback!

When checking SRV records, I first did not really know what to do with the "priority" field, then I though we could use it to know which set of servers to use first (as for the 'backup' keyword), exactly as you mentioned!

Before being able to add SRV records in HAProxy, we had to had more flexibility (IE: ability to change a server's port...). Now, everything seems to be ready for SRV records and we can move forward on the design.

I have an etherpad running somewhere where I'll summarize this design and share it with the people interested (you, Conrad, Pavlos, HAProxy Technologies devs, etc...). So we can modify it live, find an agreement and let the people who want to code it, code it.
This will be "phase 1", using SRV records to update a unique server.

Then, we'll have to work on phase 2: use a DNS query to fill up servers in the backend. As Willy explained already, there will be a discussion on the ML too, because the design is not that simple and we expect the people with experience like you to help us on this stage!

Baptiste


On Mon, Dec 19, 2016 at 6:29 AM, jerry <[email protected] <mailto:[email protected]>> wrote:

    Igor,

    thanks for the pointer tot he email thread. We have too many
    pieces of automation going on and adding consul really isn't an
    option.

    Baptiste, if you are open to discussing some requirements I would
    love to talk. I am an old hand at DNS and have some specific ideas
    of how it could work with haproxy, If you folks are working toward
    using SRV records as a way of specifying the current backend
    server set, I will take that as a significant opinion that this is
    not a bad idea.

    thanks again,

    jerry

    On 2016-12-18 8:45 pm, Igor Cicimov wrote:



    On Mon, Dec 19, 2016 at 11:43 AM, jerry <[email protected]
    <mailto:[email protected]>> wrote:

        Hi,

        We use haproxy quite a but at soundhound for fronting our
        various external and internal services. We are i the process
        of moving to a container based deployment model. With
        kubernetes in particular, it's as easy as editing 1 line to
        add a new server to a replication set. In one of our
        applications, we have 50+ partitions, so when a new instance
        is added, it  is actually 50+ containers and 50+ proxy
        configs to edit. Clearly we need to automate this more than
        we have so far.

        I was looking around at how to do this and came up with an
        unusual idea. Everybody uses DNS, but almost no one
        uses/knows about SRV records. SRV records have the form of
        _(service)._(protocol).name and return a target DNS name
        (like CNAME), priority, weight and destination port. This is
        like MX records on steroids.


    For SRV records specifically, I'm using Consul and dnsmasq so on
    the haproxy instances I can do:

    $ dig +short srv tomcat.service.consul
    1 1 8080 ip-192.168-0-45.node.dc-prod.consul.
    1 1 8080 ip-192.168-1-226.node.dc-prod.consul.

    and update the appropriate backend section of the config file and
    reload in case of changes. I keep the config file "modular"
    meaning multiple parts (mostly for the backends) that I can
    update based on some criteria and then glue together to create
    the final haproxy.cfg. How do you implement the updates, the
    triggers and the config file setup depends on your architecture
    and needs.

    If you google for "consul-template + haproxy" I'm sure you will
    also come across several solutions.

    The dynamic DNS update is coming to haproxy in version 1.7, check
    this discussion for details
    https://www.mail-archive.com/[email protected]/msg23579.html
    <https://www.mail-archive.com/[email protected]/msg23579.html>


        This seems to have everything I need for the dynamic parts of
        a configuration. The original name defines the port to listen
        on (this can be a name that gets looked up in /etc/services
        or _31112 for a hard port number). The set of records
        returned is the backend set. The ones that have the lowest
        priority are active and the rest are backups. If you want to
        do per backend commands, those can be put in as TXT records
        for the name backend.system.name._(service)._(protocol).name.
        Similarly, dynamic parts of the frontend and backend could be
        done with TXT records for _frontend and _backend prefixes to
        the SRV name.

        For now, we can assume that there is only one level of backup
        rather than the arbitrary number that DNS allows.

        There is an extra little bit that DNS can do for us. DNS has
        a notify capability. When a zone updates, the dns server can
        notify it's slaves with the new SOA record. It turns out that
        all you need to do is generate a response that is almost an
        exact copy of the query you got, in DNS wire form to make DNS
        happy and then do the lookups again.

        My thought is that the typical thing you configure for a
        given proxy would remain in the config file as now (what to
        check, connection mode...). The front end becomes the SRV
        name and the backend is either empty of have some command
        that says expand the SRV record and put it as the backends.



        The reason I like it is there are 75 different
        orchestration/automation systems that could want to drive
        haproxy. They all talk to DNS already. With this, there is a
        single interface that I need for the automation from the view
        of both an orchestration system and haproxy. We have a custom
        load balancer that we plan to drive the same way.


        Here are my questions:
        Do people think this is a interesting/good idea?
        Is there anything that is missing and would make this a
        terrible idea?
        If not fatally flawed, should this be run outside of haproxy
        as an automation tool or should haproxy do this itself?

        thanks,
        jerry





-- Igor Cicimov |DevOps


    p. +61 (0) 433 078 728
    e. [email protected] <http://encompasscorporation.com/>
    w*.* www.encompasscorporation.com
    <http://www.encompasscorporation.com>
    a. Level 4, 65 York Street, Sydney 2000



Reply via email to