Implementing Web Load Balancing on a Shoestring Budget
26 Oct 2011
I made a presentation at this month's LOPSA Baltimore meeting about my recent web load balancing implementation using off-the-shelf software. The (short) deck is available below.
Configs
Absent from the deck are the configuration files that I reviewed with the group when describing my implementation. Those files are available below.
Nginx
# nginx.conf
user nginx nginx ;
# worker_processes should be equal to the number of CPU cores
worker_processes 4 ;
# default values of log: main == error; http == crit
# server == crit
# levels avail: debug, info, notice, warn, error, crit
# error_log /path/ level
error_log /var/log/nginx/error.log error ;
events {
# each worker_process will manage 1024 connections
worker_connections 1024 ; # limited to 4096 (4*1024) connections
} # end events()
http {
# compress content
gzip on ; # enable compression
gzip_min_length 1100 ; # anything shorter than 1100 bytes will not be compressed
gzip_buffers 4 8k ; # set the number and size of the buffers
gzip_types text/plain text/css text/js ; # the MIME types we want to compress
# No need to display the version of our server
server_tokens off ;
# use requested Host header for redirects
server_name_in_redirect off ;
# setting timeout for the proxy (haproxy)
#proxy_read_timeout 180;
proxy_read_timeout 1500 ; # 60 sec * 25 min = 1500 sec; required for long-running web reports
# allowing us to upload more than 1MB of data
client_max_body_size 10M ;
# nginx should service SSL requests and forward them to haproxy (bound on the HTTP port)
# Site www.example.com;
# 192.168.1.2 www.example.com
upstream www.example.com {
server 192.168.1.2 : 80 ;
}
server {
listen 192.168.1.2 : 443 ;
access_log /var/log/nginx/access.log ;
ssl on ; # go!
ssl_certificate /usr/local/ssl/wildcard.example.com.cert ;
ssl_certificate_key /usr/local/ssl/wildcard.example.com.key ;
ssl_prefer_server_ciphers on ; # prefer SSLv3 and TLSv1 ciphers
ssl_ciphers HIGH:+MEDIUM:!ADH:!MD5 ; # use 128-bit and higher ciphers; exclude ADH and MD5
ssl_protocols TLSv1 SSLv3 ; # guarantee only TLSv1 and SSLv3 protocols
# match all HTTP requests
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
proxy_set_header secureCookie YES ;
proxy_pass http://www.example.com ;
}
} # end server www.example.com 192.168.1.2
} # end http
Haproxy
#
# haproxy.conf
#
global
log 127 .0.0.1 local1 info
log 127 .0.0.1 local2 emerg notice
#maxconn 5000
maxconn 32500
nbproc 1
chroot /var/chroot/haproxy
pidfile /var/run/haproxy.pid
user haproxy
group haproxy
daemon
stats socket /tmp/haproxy.stat
defaults
# log all proxy instances
log global
# enable verbose HTTP-related logging
option httplog
# run as a layer 7 proxy
mode http
# force closed active connections after response is transferred
#option forceclose
# try a downed server 2 times before sending request to good server
# 2 retries x 2s connect timeout = 4s until haproxy finds a good server
# NOTE: The 'retries' + 'timeout connect' combo operates independently
# of the 'listen' block's declaration (i.e. health checks). The below
# options govern how haproxy handles current incoming connections and
# the health checks in the backend declarations govern whether or not
# haproxy decides to use the defined backends in the farm. If a
# given backend host is currently down while a connection request is
# being made, the below options are in effect. Once that host is
# down "hard", as far as haproxy is concerned, it's no longer used in
# the farm (until it recovers) and subsequent requests don't even
# attempt to use that backend. -ryanfrantz 1/14/2010
# P.S. We've decided to configure the 'retries' + 'timeout connect'
# values to be as close to the health check timers as possible to
# ensure a fluid experience for the end user. -ryanfrantz 1/14/2010
retries 2
timeout connect 2s
# redispatch requests originally sent to downed backend servers
option redispatch
# expect that the response from the client doesn't take longer than 5s
timeout client 5s
# expect that the response from the server doesn't take longer than 5s
#timeout server 5s
#timeout server 90s
#timeout server 180s
# expect that the response from the server doesn't take longer than 25 mins; required for long-running reports; matches nginx's config
timeout server 1500s
# simple round rooin algo
balance roundrobin
#balance leastconn
# set X-Forward-For HTTP header
option forwardfor
# force all HTTP connections closed so haproxy analyzes/logs all traffic
option httpclose
listen statsWWW2 192.168.1.1 : 8080
# enable the haproxy stats page (uri-stem = /haproxy?stats)
stats enable
stats auth god:sex
stats refresh 120s
# Site www.example.com
listen www.example.com
bind 192.168.1.2 : 80
acl acl_port_80 dst_port eq 80
acl acl_secure hdr(secureCookie) YES
acl acl_sourceLocal src 192 .168.1.2
acl acl_excludeCSS url_dir -i CSS
acl acl_excludeImages url_dir -i images
redirect location https://www.example.com/sslRedirect.asp code 301 if acl_port_80 !acl_secure !acl_sourceLocal !acl_excludeCSS !acl_excludeImages
cookie SERVERID insert indirect nocache
server www1 192 .168.1.3 cookie www1 weight 1 check inter 1s fall 3 rise 2
server www2 192 .168.1.4 cookie www2 weight 1 check inter 1s fall 3 rise 2
server www3 192 .168.1.5 cookie www3 weight 1 check inter 1s fall 3 rise 2
option httpchk GET /ping.htm HTTP/1.1 \ r \ nHost:www.example.com
capture request header X-Forwarded-For len 15
###############################################################################
# Site www.foo.com
listen www.foo.com
...
Keepalived
#Configuration for lb1
global_defs {
notification_email {
admin@example.com
}
notification_email_from lb1@example.com
smtp_server mail.example.com
smtp_connect_timeout 30
lvs_id lb1
}
vrrp_sync_group virtualGroup1 {
group {
virtualInstance1
}
}
vrrp_instance virtualInstance1 {
notify_master /usr/local/bin/keepalivedMaster.sh
notify_fault /usr/local/bin/keepalivedFault.sh
notify_backup /usr/local/bin/keepalivedBackup.sh
interface eth0
advert_int 1 # advertise interval in sec; 1 is default
state BACKUP # either MASTER or BACKUP
virtual_router_id 1 # MUST be between 1 and 255
priority 100 # 101 on MASTER, 100 on BACKUP
smtp_alert
authentication {
auth_type AH
auth_pass "<yeah right...>"
}
virtual_ipaddress {
192.168.1.1/24 brd 192 .168.1.255 dev eth0 # comment
192 .168.1.2/24 brd 192 .168.1.255 dev eth0 # comment
192 .168.1.3/24 brd 192 .168.1.255 dev eth0
192 .168.1.4/24 brd 192 .168.1.255 dev eth0
192 .168.1.5/24 brd 192 .168.1.255 dev eth0
192 .168.1.6/24 brd 192 .168.1.255 dev eth0
192 .168.1.7/24 brd 192 .168.1.255 dev eth0
192 .168.1.8/24 brd 192 .168.1.255 dev eth0
192 .168.1.9/24 brd 192 .168.1.255 dev eth0
192 .168.1.10/24 brd 192 .168.1.255 dev eth0
192 .168.1.11/24 brd 192 .168.1.255 dev eth0
192 .168.1.12/24 brd 192 .168.1.255 dev eth0
192 .168.1.13/24 brd 192 .168.1.255 dev eth0
192 .168.1.14/24 brd 192 .168.1.255 dev eth0
192 .168.1.15/24 brd 192 .168.1.255 dev eth0
192 .168.1.16/24 brd 192 .168.1.255 dev eth0
192 .168.1.17/24 brd 192 .168.1.255 dev eth0
192 .168.1.18/24 brd 192 .168.1.255 dev eth0
192 .168.1.19/24 brd 192 .168.1.255 dev eth0
}
}
...
Tags