load balancing multiple sites with varnish

Tim Dunphy bluethundr at gmail.com
Sun Mar 6 05:40:40 CET 2016


Hey guys,

 I have a varnish config that's been working pretty nicely for the last
year. But recently I had to build 3 Kibana (that's the logstash UI if
you're not aware) nodes on aws. And I wanted to load balance them and
perhaps do some caching on them.

However when I tried to add the new kibana hosts to the config, instead of
showing the kibana interface, it shows the default web page on my first
apache server from the previous load balancing pool. That belongs to a host
called 'web1' in the config.

Loading the 3 kibana nodes individually shows that it's loading and running
properly.

Here's what I've done to try to get this to work:

I added the 3 kibana nodes as logs1, 2 and 3 to the config:

backend logs1 {

  .host = "52.xx.xxx.180";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe =  healthcheck;

}

backend logs2 {

  .host = "52.xx.xx.78";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe =  healthcheck;

}

backend logs3 {

  .host = "52.xx.xxx.209";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe =  healthcheck;

}

And setup a new load balancing section:

sub vcl_init {

    new wiki = directors.round_robin();

    wiki.add_backend(web1);  ## <-- this is what shows up at
logs.exampledomain.com

    wiki.add_backend(web2);

    wiki.add_backend(web3);

}

*sub vcl_init {*

*    new logs = directors.round_robin();*

*    logs.add_backend(logs1);*

*    logs.add_backend(logs2);*

*    logs.add_backend(logs3);*

*}*

In my vcl_recv I have the following:

sub vcl_recv {

       # Authenticate the user using Apache basic auth

       if ( req.http.host ~ "^wiki\.exampledomain\.com$")  {

           set req.backend_hint = wiki.backend();

           if (!basicauth.match("/etc/httpd/auth",
req.http.Authorization)) {

               return(synth(401, "Authentication required"));

           }

       } else if ( req.http.host ~ "^beta\.exampledomain\.com$" ) {

          set req.http.backend_hint = wiki.backend();

       }

       if ( req.http.host ~ "^logs\.exampledomain\.com$")  {

           set req.backend_hint = logs.backend();

       }

       # Authenticate the user using Apache basic auth

       if ( req.http.host ~ "^wiki\.exampledomain\.com$")  {

           set req.backend_hint = wiki.backend();

           if (!basicauth.match("/etc/httpd/auth",
req.http.Authorization)) {

               return(synth(401, "Authentication required"));

           }

       } else if ( req.http.host ~ "^beta\.exampledomain\.com$" ) {

          set req.http.backend_hint = wiki.backend();

       }


       if ( req.http.host ~ "^logs\.exampledomain\.com$")  {

           set req.backend_hint = logs.backend();

       }


..... more stuff

        return(hash);

}


And instead of seeing this at logs.exampledomain.com:


I see a web page that looks like this:

How can I get varnish to serve the 'logs' load balancing pool correctly?


Here's my whole vcl_recv in case that helps :

vcl 4.0;

import std;

import directors;

import basicauth;



probe healthcheck {

  .url = "/healthcheck.php";

  .timeout =1m;

  .interval = 1s;

  .window = 10;

  .threshold = 8;

  }


backend default {

    .host = "107.xxx.xx.174";

    .port = "80";

    .connect_timeout = 1m;

    .first_byte_timeout = 1m;

    .between_bytes_timeout = 2s;

    .max_connections = 800;

    .probe = healthcheck;

}


backend web1 {

  .host = "107.xxx.xx.174";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe = healthcheck;

}


backend web2 {

  .host = "107.xxx.xxx.53";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe =  healthcheck;

}


backend web3 {

  .host = "107.xxx.xx.38";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe =  healthcheck;

}


backend logs1 {

  .host = "52.xx.xxx.180";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe =  healthcheck;

}


backend logs2 {

  .host = "52.xx.xx.78";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe =  healthcheck;

}


backend logs3 {

  .host = "52.xx.xxx.209";

  .port = "80";

  .connect_timeout = 1s;

  .first_byte_timeout = 5s;

  .between_bytes_timeout = 2s;

  .max_connections = 800;

  .probe =  healthcheck;

}


# access control list for "purge": open to only localhost and other local
nodes

acl purge {

    "127.0.0.1";

}


sub vcl_init {

    new wiki = directors.round_robin();

    wiki.add_backend(web1);

    wiki.add_backend(web2);

    wiki.add_backend(web3);

}


sub vcl_init {

    new logs = directors.round_robin();

    logs.add_backend(logs1);

    logs.add_backend(logs2);

    logs.add_backend(logs3);

}


# vcl_recv is called whenever a request is received

sub vcl_recv {



       # Authenticate the user using Apache basic auth

       if ( req.http.host ~ "^wiki\.exampledomain\.com$")  {

           set req.backend_hint = wiki.backend();

           if (!basicauth.match("/etc/httpd/auth",
req.http.Authorization)) {

               return(synth(401, "Authentication required"));

           }

       } else if ( req.http.host ~ "^beta\.exampledomain\.com$" ) {

          set req.http.backend_hint = wiki.backend();

       }


       if ( req.http.host ~ "^logs\.exampledomain\.com$")  {

           set req.backend_hint = logs.backend();

       }


        # Remove has_js and CloudFlare/Google Analytics __* cookies.

        set req.http.Cookie = regsuball(req.http.Cookie,
"(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");

        # Remove a ";" prefix, if present.

        set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");


        set req.http.X-Forwarded-For = client.ip;

        set req.backend_hint= default;


        # This uses the ACL action called "purge". Basically if a request to

        # PURGE the cache comes from anywhere other than localhost, ignore
it.

        if (req.method == "PURGE")

            {if (!client.ip ~ purge)

                {return(synth(405,"Not allowed."));}

            return(hash);}


        # Allows editing the wiki

        if (req.url ~ "&action=submit($|/)"   ) {

           return(pass);

        }


        # Pass any requests that Varnish does not understand straight to
the backend.

        if (req.method != "GET" && req.method != "HEAD" &&

            req.method != "PUT" && req.method != "POST" &&

            req.method != "TRACE" && req.method != "OPTIONS" &&

            req.method != "DELETE")

            {return(pipe);}     /* Non-RFC2616 or CONNECT which is weird. */


        # Pass anything other than GET and HEAD directly.

        if (req.method != "GET" && req.method != "HEAD")

           {return(pass);}      /* We only deal with GET and HEAD by
default */


        # Make images, etc cachable by unsetting cookie in request

        if (req.url ~ "^/images" ) {

                unset req.http.cookie;

        }


        # Pass requests from logged-in users directly.

        #if (req.http.Authorization || req.http.Cookie)

        if (req.http.Cookie)

           {return(pass);}      /* Not cacheable by default */


        # Pass any requests with the "If-None-Match" header directly.

        if (req.http.If-None-Match)

           {return(pass);}


        # Force lookup if the request is a no-cache request from the client.

        if (req.http.Cache-Control ~ "no-cache")

           {ban(req.url);}


        # normalize Accept-Encoding to reduce vary

        if (req.http.Accept-Encoding) {

          if (req.http.User-Agent ~ "MSIE 6") {

            unset req.http.Accept-Encoding;

          } elsif (req.http.Accept-Encoding ~ "gzip") {

            set req.http.Accept-Encoding = "gzip";

          } elsif (req.http.Accept-Encoding ~ "deflate") {

            set req.http.Accept-Encoding = "deflate";

          } else {

            unset req.http.Accept-Encoding;

          }

        }


        # Set the X-Forwarded-For header so the backend can see the original

        # IP address. If one is already set by an upstream proxy, we'll
just re-use that.

        if (client.ip ~ purge  && req.http.X-Forwarded-For) {

           set req.http.X-Forwarded-For = req.http.X-Forwarded-For;

        } else {

          set req.http.X-Forwarded-For = regsub(client.ip, ":.*", "");

         }


        return(hash);

}

Thanks,

Tim

​



-- 
GPG me!!

gpg --keyserver pool.sks-keyservers.net --recv-keys F186197B
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.varnish-cache.org/lists/pipermail/varnish-misc/attachments/20160305/3f5730ee/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screenshot 2016-03-05 23.35.25.png
Type: image/png
Size: 150608 bytes
Desc: not available
URL: <https://www.varnish-cache.org/lists/pipermail/varnish-misc/attachments/20160305/3f5730ee/attachment-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Screenshot 2016-03-05 23.37.29.png
Type: image/png
Size: 19480 bytes
Desc: not available
URL: <https://www.varnish-cache.org/lists/pipermail/varnish-misc/attachments/20160305/3f5730ee/attachment-0003.png>


More information about the varnish-misc mailing list