{"id":22174981,"url":"https://github.com/morningspace/lab-load-balancing","last_synced_at":"2025-10-22T21:35:04.321Z","repository":{"id":103639672,"uuid":"151702691","full_name":"morningspace/lab-load-balancing","owner":"morningspace","description":null,"archived":false,"fork":false,"pushed_at":"2018-12-09T01:29:39.000Z","size":1678,"stargazers_count":16,"open_issues_count":0,"forks_count":11,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-10T20:54:34.535Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/morningspace.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-05T10:06:29.000Z","updated_at":"2024-08-07T08:08:19.000Z","dependencies_parsed_at":"2023-05-24T04:00:26.764Z","dependency_job_id":null,"html_url":"https://github.com/morningspace/lab-load-balancing","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/morningspace/lab-load-balancing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morningspace%2Flab-load-balancing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morningspace%2Flab-load-balancing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morningspace%2Flab-load-balancing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morningspace%2Flab-load-balancing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/morningspace","download_url":"https://codeload.github.com/morningspace/lab-load-balancing/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/morningspace%2Flab-load-balancing/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259654292,"owners_count":22890987,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-02T07:55:41.556Z","updated_at":"2025-10-22T21:35:04.260Z","avatar_url":"https://github.com/morningspace.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"## MorningSpace Lab\n\n晴耕实验室\n\n[![](https://morningspace.github.io/assets/images/banner.jpg)](https://morningspace.github.io)\n\n# HAProxy + Keepalived: Build Your Load Balancer in 30 Minutes!\n\nKeywords: HAProxy, Keepalived, Docker, SSL, nginx, Load Balance\n\nVideos: Check the [video](https://youtu.be/jzXzUojGneA) that helps you lively walk through the instructions on how to play this lab project. More videos on this lab project can be found [here](http://v.youku.com/v_show/id_XMzkyNTAzODg3Ng==.html?f=51967588).\n\n## Overview\n\nThis is the lab project to demonstrate how to set up highly available load balancing service using HAProxy and Keepalived.\n\nThis lab project is entirely based on Docker technology. You can play it in a sandbox at your local, which is composed by a few Docker containers.\n\nAs the figure depicted below, there are two web servers, `myweb1` and `myweb2`, which are the containers built from the image `morningspace/lab-web`. It uses nginx serving as web server. Both HTTP and HTTPS are enabled.\n\nIn front of the web servers, there are two load balancers, `mylb1` and `mhylb2`, which are the containers built from the image `morningspace/lab-lb`. Both haproxy and keepalived are installed. The haproxy connects to the two web servers, while keepalived is to check whether haproxy is available or not. We define `mylb` as master node, and `mylb2` as backup node to support haproxy failover. It also exposes a virutal IP that can be accessed by client.\n\n![](docs/images/architecture.png)\n\nPlease check the below instructions to learn how to play with it.\n\nYou can also find the online slides [here](https://morningspace.github.io/lab-load-balancing/slides).\n\nFor more lab projects from MorningSpace Lab, please check [morningspace.github.io](https://morningspace.github.io).\n\n## Instructions\n\n### Build or Pull Docker Images\n\nGo to the project root directory, and build docker images for both web server and load balancer:\n```shell\ndocker build -f docker/web/Dockerfile -t morningspace/lab-web .\ndocker build -f docker/lb/Dockerfile -t morningspace/lab-lb .\n```\n\nThe docker images have also been pushed to Docker Hub. So, you can pull them from there too.\n```\ndocker pull morningspace/lab-lb\ndocker pull morningspace/lab-web\n```\n\n### Launch Web Servers\n\nLaunch two docker containers for the image `morningspace/lab-web` as web servers:\n```\ndocker run -d --name myweb1 --hostname myweb1 --net=lab -p 18080:80 -p 18443:443 morningspace/lab-web\ndocker run -d --name myweb2 --hostname myweb2 --net=lab -p 19080:80 -p 19443:443 morningspace/lab-web\n```\n\nNote:\n* Make sure the network `lab` has been created beforehand by running below command:\n```\ndocker network create lab\n```\n\nRun `docker ps` to verify the docker containers are launched successfully.\n\nInput below URLs in browser to verify it returns expected messages:\n```\nhttp://localhost:18080/healthz\nhttp://localhost:19080/healthz\nhttps://localhost:18443/healthz\nhttps://localhost:19443/healthz\n```\nThe returned message looks like `Greeting from \u003chostname\u003e`, where the `hostname` is the value specified by `--hostname` option when launch the docker container.\n\n### Launch Load Balancers\n\nLaunch two docker containers for the image `morningspace/lab-lb` as load balancers:\n```\ndocker run -it --name mylb1 --hostname mylb1 --net=lab -p 28080:8080 -p 28443:8443 -p 28090:8090 --sysctl net.ipv4.ip_nonlocal_bind=1 --privileged morningspace/lab-lb\ndocker run -it --name mylb2 --hostname mylb2 --net=lab -p 29080:8080 -p 29443:8443 -p 29090:8090 --sysctl net.ipv4.ip_nonlocal_bind=1 --privileged morningspace/lab-lb\n```\n\nRun `docker ps` to verify the docker containers are launched successfully.\n\n### Configure and Run HAProxy\n\nAfter the load balancer container is launched, it will take you into the container. Make sure haproxy has not been started:\n```\nservice haproxy status\n```\nIt should return something as below:\n```\nhaproxy not running\n```\n\nGo to the directory `/etc/haproxy`, where there are sample configuration files for haproxy. Copy one of them to replace `haproxy.cfg`, e.g.\n```\ncp haproxy-ssl-termination.conf haproxy.cfg\n```\n\nStart haproxy as a service:\n```\nservice haproxy start\n```\n\nVerify haproxy started successfully by monitoring logs:\n```\ntail -f /var/log/haproxy.log\n```\n\nInput below URLs in browser to open the haproxy statistics report view:\n```\nhttp://localhost:28090/haproxy/stats\nhttp://localhost:29090/haproxy/stats\n```\nInput the predefined username and password, haproxy/passw0rd, when promted.\n\nRepeat the same steps in the other load balancer container.\n\nNote:\n* If you forget which load balancer container you are in, type `hostname` in the container.\n* If you exit the container for some reason, the container will be stopped as expected. To go back, e.g. `mylb1`, run below command:\n```\ndocker start -i mylb1\n```\n\n### Configure and Run Keepalived \n\nGo to the directory `/etc/keepalived`, where there are two sample configuration files for keepalived. One is for master node, and the other one is for backup node.\n\nRun `ping` command in container, or below command on host machine to get all the IP addresses for the containers involved in the current network:\n\n```\ndocker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -q)\n```\n\nThen use a new IP address as the virtual IP address that does not conflict with others, e.g.:\n\nNode\t\t| IP Address\n-------\t| -------------\nmyweb1\t| 172.18.0.2\nmyweb2\t| 172.18.0.3\nmylb1\t\t| 172.18.0.4\nmylb2\t\t| 172.18.0.5\nvirtual*| 172.18.0.6\n\nHere we use 172.18.0.6 as the virtual IP address. Replace `\u003cyour_virtual_ip\u003e` with the actual value in both `keepalived-master.conf` and `keepalived-backup.conf`.\n\nNote:\n* The value of `interface` defined in sample configuration files is `eth0`. It could be different depending on your system. To figure out the right value, you can run `ip addr show`.\n\nChoose one load balancer container as master, e.g. `mylb1`. Launch keepalived on master using master configuration:\n```\nkeepalived --dump-conf --log-console --log-detail --log-facility 7 --vrrp -f /etc/keepalived/keepalived-master.conf\n```\n\nIn backup container, launch keepalived using backup configuration:\n```\nkeepalived --dump-conf --log-console --log-detail --log-facility 7 --vrrp -f /etc/keepalived/keepalived-backup.conf\n```\n\nVerify keepalived started successfully by monitoring logs:\n```\ntail -f /var/log/syslog\n```\n\nVerify the virtual IP address is assigned successfully, run below command on master:\n```\nip addr show eth0\n```\nIf configured correctly, you will see the virtual IP address appeared in the output.\n\nRun `curl` in either of the two load balancer containers. Send request to the virutal IP and see if it returns the content retrieved from web servers, e.g. in the case where ssl is not enabled:\n```\ncurl -XGET http://\u003cvirtual_ip\u003e:8080/healthz\n```\nAnd ssl is enabled:\n```\ncurl --insecure --cert /etc/ssl/certs/my.crt --key /etc/ssl/private/my.key -XGET https://\u003cvirtual_ip\u003e:8443/healthz\n```\n\n## Test\n\n### Web Server\n\nTry to stop one of the web servers, e.g.:\n```\ndocker stop myweb1\n```\n\nWait for a moment then check the haproxy statistics report in browser, e.g. use the below URL, to see if `myweb1` is down:\n```\nhttp://localhost:28090/haproxy/stats\n```\n\nHit the `/healthz` endpoint exposed by load balancer either in browser or using `curl`. Make sure `myweb1` will never be hit.\n\nStart `myweb1` again:\n```\ndocker start myweb1\n```\n\nWait for a moment then check the haproxy statistics report in browser to see if `myweb1` is up.\n\nHit the `/healthz` endpoint again. Make sure both `myweb1` and `myweb2` will be hit.\n\n### Load balancer\n\nTry to stop the master haproxy service within the container, e.g. `mylb1`.\n```\nservice haproxy stop\n```\n\nWait for a moment then check the keepalived logs by monitoring `/var/log/syslog` in both load balancer containers. See if `mylb1` entered into `BACKUP` state, and `mylb2` transitioned to `MASTER` state.\n\nYou can also verify it using `ip` command in both containers:\n```\nip addr show eth0\n```\nIf it works correctly, you will see the virtual IP address appeared in the output in container `mylb2` instead of container `mylb1`.\n\nRun `curl` in either of the two load balancer containers. Send request to the virutal IP and see if it still returns the content retrieved from web servers.\n\nStart `mylb1` again:\n```\nservice haproxy start\n```\n\nWait for a moment then check the keepalived logs. See if `mylb1` gained `MASTER` state, and `mylb2` returned back to `BACKUP` state.\n\nYou can also verify it using `ip` command in both containers, to see if the virtual IP address appeared in the output in container `mylb1` instead of container `mylb2`.\n\nRun `curl` in either of the two load balancer containers. Send request to the virutal IP and see if it still returns the content retrieved from web servers.\n\n## Troubleshooting\n\n* Add `tune.ssl.default-dh-param 2048` if met \"[WARNING] 277/024013 (214) : Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value \u003e= 1024 to make this warning disappear.\"\n\n* Run `service rsyslog restart` if met \"[ALERT] 277/004806 (177) : sendmsg logger #1 failed: No such file or directory (errno=2)\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorningspace%2Flab-load-balancing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmorningspace%2Flab-load-balancing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorningspace%2Flab-load-balancing/lists"}