From 7bd67f640181afff74af1333777336dfa99a6e1a Mon Sep 17 00:00:00 2001 From: sspencerwire Date: Tue, 15 Aug 2023 13:07:55 -0500 Subject: [PATCH] # changes to `haproxy_apache_lxd.md` (#1416) * wording changes from @ganna * sentence style capitalization on headings * reword to eliminate conjunctions * remove passive voice as much as possible * replace "we" with "you" as much as possible * simplify some sentences further --- docs/guides/proxies/haproxy_apache_lxd.md | 131 +++++++++++----------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/docs/guides/proxies/haproxy_apache_lxd.md b/docs/guides/proxies/haproxy_apache_lxd.md index 62d053412e..3292f7f9df 100644 --- a/docs/guides/proxies/haproxy_apache_lxd.md +++ b/docs/guides/proxies/haproxy_apache_lxd.md @@ -4,30 +4,31 @@ author: Steven Spencer contributors: Ezequiel Bruni, Antoine Le Morvan tested_with: 8.5, 8.6, 9.0 --- -# HAProxy Load Balancing Apache using LXD Containers +# HAProxy load balancing Apache with LXD containers ## Introduction -HAProxy stands for "High Availability Proxy." This proxy can sit in front of any TCP application (such as web servers), but it is often used to act as a load-balancer between multiple instances of a website. +HAProxy stands for "High Availability Proxy." This proxy can sit before any TCP application (such as web servers), but it is often used as a load balancer between many website instances. -There might be a number of reasons for doing this. If you have a website that is being hit hard — adding another instance of that same website and placing HAProxy in front of both — allows you to distribute traffic between instances. Another reason might be to be able to update content on a website without any down time. HAProxy can also help mitigate DOS and DDOS attacks. -This guide is going to explore using HAProxy using two website instances, and load-balancing with round robin rotation, on the same LXD host. This might be a perfectly fine solution for ensuring that updates can be performed without downtime. +There might be many reasons for doing this. If you have a website that is being hit hard — adding another instance of that same website and placing HAProxy in front of both — allows you to distribute traffic between instances. Another reason might be to be able to update content on a website without any down time. HAProxy can also help mitigate DOS and DDOS attacks. -If your problem is website performance, however, you may need to distribute your multiple sites across actual bare metal or between multiple LXD hosts. It is certainly possible to do all of this on bare metal without using LXD at all, however LXD offers great flexibility and performance, plus it is great to use for lab testing. +This guide will explore using HAProxy with two website instances, and load balancing with round-robin rotation on the same LXD host. This might be a perfectly fine solution for ensuring that updates can be performed without downtime. -## Prerequisites and Assumptions +However, if your problem is website performance, you may need to distribute your multiple sites across actual bare metal or multiple LXD hosts. It is certainly possible to do all of this on bare metal without using LXD. However, LXD offers great flexibility and performance, and is also excellent for lab testing. + +## Prerequisites and assumptions * Complete comfort at the command line on a Linux machine -* Experience with a command line editor (we are using `vim` here) +* Experience with a command line editor (using `vim` here) * Experience with `crontab` -* Knowledge of LXD. For more information, you may want to consult the [LXD Server](../../books/lxd_server/00-toc.md) document. It is perfectly fine to install LXD on a laptop or workstation as well without doing the full-blown server install. This document is being written with a lab machine that is running LXD, but is not set up as a full server as the document linked above uses. -* Some knowledge on installing, configuring, and using web servers. +* Knowledge of LXD. For more information, you may want to consult the [LXD Server](../../books/lxd_server/00-toc.md) document. It is fine to install LXD on a notebook or workstation without doing the full-blown server install. This document is written with a lab machine running LXD, but is not set up as an entire server as the document linked above uses. +* Some knowledge of installing, configuring, and using web servers. * We will assume that LXD is already installed and ready to create containers. -## Installing Containers +## Installing containers -On your LXD host for this guide, we will need three containers. Obviously, there could be more web server containers if you wish. We will use **web1** and **web2** for our website containers and **proxyha** for our HAProxy container. To install these on your LXD host do: +On your LXD host for this guide, you will need three containers. There can be more web server containers if you want. You will use **web1** and **web2** for our website containers and **proxyha** for our HAProxy container. To install these on your LXD host do: ``` lxc launch images:rockylinux/8 web1 @@ -48,19 +49,19 @@ Running an `lxc list` should return something like this: +---------+---------+----------------------+------+-----------+-----------+ ``` -## Creating and Using the `macvlan` Profile +## Creating and using the `macvlan` profile -The containers are currently running on the default bridge interface with bridge assigned DHCP addresses. We are going to want to use DHCP addresses from our local LAN, so the first thing we need to do is to create and assign the `macvlan` profile. +The containers run on the default bridge interface with bridge-assigned DHCP addresses. These need to change to DHCP addresses from our local LAN. The first thing needed is to create and assign the `macvlan` profile. Start by creating the profile: `lxc profile create macvlan` -Make sure that your editor is set to your preferred editor, in this case `vim`: +Ensure that your editor is set to your preferred editor, in this case `vim`: `export EDITOR=/usr/bin/vim` -Next we need to modify the `macvlan` profile. But before we do, we need to know what interface the host is using for our LAN so run `ip addr` and look for the interface with the LAN IP assignment: +Next you need to change the `macvlan` profile. But before you do, you need to know what interface the host uses for our LAN. Run `ip addr` and look for the interface with the LAN IP assignment: ``` 2: eno1: mtu 1500 qdisc fq_codel state UP group default qlen 1000 @@ -69,13 +70,13 @@ Next we need to modify the `macvlan` profile. But before we do, we need to know ``` !!! Note - In this case, the interface we are looking for is "eno1" but this could be completely different on your system. Use **your** interface information! + In this case, the interface you are looking for is "eno1" but this could be completely different on your system. Use **your** interface information! -Now that we know the LAN interface, we can modify our `macvlan` profile. To do this, at the command line type: +Now that you know the LAN interface, you can change our `macvlan` profile. To do this, at the command line enter: `lxc profile edit macvlan` -We need to make our profile look something like this. We've excluded the comments at the top of the file, but if you are new to LXD, take a look at those: +Edit the profile to look something like this. The author excluded the comments at the top of the file, but if you are new to LXD, examine those: ``` config: {} @@ -89,9 +90,9 @@ devices: name: macvlan ``` -What happened when we created the `macvlan` profile is that the `default` profile was copied. The `default` profile cannot be changed. +When creating the `macvlan` profile, the system copies the `default` profile. Changing the `default` profile is not possible. -Now that we have the `macvlan` profile, we need to apply it to our three containers: +Now that the `macvlan` profile exists, you need to apply it to our three containers: ``` lxc profile assign web1 default,macvlan @@ -101,7 +102,7 @@ lxc profile assign proxyha default,macvlan Unfortunately, the default behavior of `macvlan` as implemented in the kernel, is inexplicably broken within an LXD container (see [this document](../../books/lxd_server/06-profiles.md)) `dhclient` on boot in each of the containers. -Doing this is pretty simple when using DHCP. Just follow this for each container: +Doing this is pretty simplistic when using DHCP. Just follow this for each container: * `lxc exec web1 bash` which will put you at the command line of the **web1** container * `crontab -e` which will edit root's `crontab` on the container @@ -113,7 +114,7 @@ Doing this is pretty simple when using DHCP. Just follow this for each container Repeat steps for **web2** and **proxyha**. -Once these steps are completed, restart the containers: +After completing these steps, restart the containers: ``` lxc restart web1 @@ -121,7 +122,7 @@ lxc restart web2 lxc restart proxyha ``` -and when you do an `lxc list` again, you should see that the DHCP addresses are now assigned from your LAN: +and when you do an `lxc list` again, you will see that the DHCP addresses are now assigned from your LAN: ``` +---------+---------+----------------------+------+-----------+-----------+ @@ -135,17 +136,17 @@ and when you do an `lxc list` again, you should see that the DHCP addresses are +---------+---------+----------------------+------+-----------+-----------+ ``` -## Installing Apache and Modifying the Welcome Screen +## Installing Apache and changing the welcome screen -Now that our environment is set, we need to install Apache (`httpd`) on each web container. This can be done without physically accessing them: +Our environment is ready. Next, install Apache (`httpd`) on each web container. You can do this without physically accessing them: ``` lxc exec web1 dnf install httpd lxc exec web2 dnf install httpd ``` -While it is understood that you will need a whole lot more than Apache for any modern web server, this is enough to run some tests. +You will need a whole lot more than Apache for any modern web server, but this is enough to run some tests. -Next, we need to enable `httpd`, start it, and then modify the default welcome screen, so we know which server we are hitting when we attempt to access via proxy. +Next, enable `httpd`, start it, and change the default welcome screen. In this way, you know the server that is responding when attempting to access by way of the proxy. Enable and start `httpd`: @@ -156,37 +157,37 @@ lxc exec web2 systemctl enable httpd lxc exec web2 systemctl start httpd ``` -Now that we have `httpd` enabled and started, let's modify the welcome screen. This is the screen that comes up when there is no website configured, essentially a default page that loads. In Rocky Linux, this page is located here `/usr/share/httpd/noindex/index.html`. To modify that file, again, there's no need for direct access to the container. Simply do the following: +With `httpd` running, change the welcome screen. This screen comes up when no website configured, essentially a default page that loads. In Rocky Linux, this page is here `/usr/share/httpd/noindex/index.html`. Changing that file requires no direct access to the container. Just do the following: `lxc exec web1 vi /usr/share/httpd/noindex/index.html` -and then do a search for the `

` tag, which should show this: +search for the `

` tag, which will show this: `

HTTP Server Test Page

` -Simply change that line to read: +Change that line to read: `

SITE1 HTTP Server Test Page

` -Now repeat the process for web2. Going to these machines by IP in a browser should now return the correct welcome page for each. There's more to do on the web servers, but let's leave them and go on to the proxy server next. +Repeat the process for web2. Going to these machines by IP in a browser will now return the correct welcome page for each. There is more to do with the web servers, but leave them and go to the proxy server for now. -## Installing HAProxy on proxyha and LXD Proxy Configuration +## Installing HAProxy on proxyha and LXD proxy configuration -It is just as easy to install HAProxy on the proxy container as well. Again, no need to access that container directly: +It is simplistic to install HAProxy on the proxy container. Again, no need to access that container directly: `lxc exec proxyha dnf install haproxy` -The next thing we want to do is configure `haproxy` to listen on port 80 and port 443 for the web services. This is done with the configure sub-command of `lxc`: +Next you want to configure `haproxy` to listen on port 80 and port 443 for the web services. Do this with the configure subcommand of `lxc`: ``` lxc config device add proxyha http proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80 lxc config device add proxyha https proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:443 ``` -For our testing, we are only going to use port 80, or HTTP traffic, but this shows you how you would configure the container to listen on the default web ports for both HTTP and HTTPS. Using this command also ensures that restarting the **proxyha** container will maintain those listening ports. +For our testing, you are only going to use port 80, or HTTP traffic, but this shows you how you configure the container to listen on the default web ports for HTTP and HTTPS. Using this command also ensures that restarting the **proxyha** container will maintain those listening ports. -## The HAProxy Configuration +## The HAProxy configuration -We've already installed HAProxy on the container, but we have done nothing with the configuration. Before we do anything, we need to do something to resolve our hosts. Normally we would be using fully qualified domain names, but in this lab environment, we are just using IPs. To get some names associated with the machines, we are going to add some host file records to the **proxyha** container. +You have already installed HAProxy on the container, but you have done nothing with the configuration. Before configuring, you need to do something to resolve your hosts. Normally you would use fully qualified domain names, but in this lab environment, you use IPs. To get some names associated with the machines, you are going to add some host file records to the **proxyha** container. `lxc exec proxyha vi /etc/hosts` @@ -197,17 +198,17 @@ Add the following records to the bottom of the file: 192.168.1.101 site2.testdomain.com site2 ``` -Which should allow the **proxyha** container to resolve those names. +Which allows the **proxyha** container to resolve those names. -Once that is complete, let's edit the `haproxy.cfg` file. There is so much in the original file that we are not going to be using, that we are simply going to make a backup of it first by moving it to a different name: +Edit the `haproxy.cfg` file. You are not using much of the original file. You need to make a backup of the file first by moving it to a different name: `lxc exec proxyha mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.orig` -Now let's create a new configuration file: +Create a new configuration file: `lxc exec proxyha vi /etc/haproxy/haproxy.cfg` -Note that we have commented out all the HTTPS protocol lines for now. In a production environment, you'd want to use a wildcard certificate that would cover your web servers and enable HTTPS: +Note, the commenting out of HTTPS protocol lines for now. In a production environment, you will want to use a wildcard certificate that covers your web servers and enable HTTPS: ``` global @@ -281,21 +282,21 @@ backend subdomain2 server site1 site1.testdomain.com:80 check ``` -A little explanation of what's going on above. You should see this in your testing, when you get to the testing section of this guide (below): +A little explanation of what is going on above. You should see this in your testing, when you get to the testing section of this guide (below): -Both **site1** and **site2** are defined in the "acl" section. Then both **site1** and **site2** are included in each other's "roundrobin" for their respective back ends. What happens when you go to site1.testdomain.com in the test, the URL does not change, but the page inside will switch each time you access the page from the **site1** to the **site2** test pages. Same goes for site2.testdomain.com. +Definitions for **site1** and **site2** are in the "acl" section. Each site is in each other's round-robins for their respective back ends. What happens when you go to site1.testdomain.com in the test, the URL does not change, but the page inside will switch each time you access the page from the **site1** to the **site2** test pages. Same goes for site2.testdomain.com. -This is done to show you the switch is occurring, but in reality, your website content will look exactly the same regardless of which server you are hitting. Keep in mind that we are showing how you might want to distribute traffic between multiple hosts. You can also use "leastcon" in the balance line, and instead of switching based on the previous hit, it will load the site with the least number of connections. +Doing this shows you the switch is occurring, but in reality, your website content will look exactly the same regardless of which server you are hitting. Note the document is showing how you might want to distribute traffic between multiple hosts. You can also use "leastcon" in the balance line, and instead of switching based on the previous hit, it will load the site with the least number of connections. -### The Error Files +### The error files Some versions of HAProxy come with a standard set of web error files, however the version that comes from Rocky Linux (and the upstream vendor), does not have these files. You probably **do** want to create them, as they may help you troubleshoot any problems. These files go in the directory `/etc/haproxy/errors` which does not exist. -The first thing we need to do is create that directory: +First, create that directory: `lxc exec proxyha mkdir /etc/haproxy/errors` -Then we need to create each of these files in that directory. Note that you can do this with each filename from your LXD host with the command `lxc exec proxyha vi /etc/haproxy/errors/filename.http`, where "filename.http" references one of the file names below. In a production environment, your company may have more specific errors that they would like to use: +Create each of these files in that directory. Note that you can do this with each filename from your LXD host with the command `lxc exec proxyha vi /etc/haproxy/errors/filename.http`, where "filename.http" references one of the file names below. In a production environment, your company may have more specific errors that they want to use: File name `400.http`: @@ -388,13 +389,13 @@ The server didn't respond in time. ``` -## Running The Proxy +## Running the proxy -We need to create a "run" directory for `haproxy` before we start the service: +Create a "run" directory for `haproxy` before starting the service: `lxc exec proxyha mkdir /run/haproxy` -Next, we need to enable the service and start it: +Next, enable the service and start it: ``` lxc exec proxyha systemctl enable haproxy lxc exec proxyha systemctl start haproxy @@ -403,24 +404,24 @@ If you get any errors, research the reason by using: `lxc exec proxyha systemctl status haproxy` -If everything starts and runs without issue, we are ready to move on to testing. +If everything starts and runs without issue, you are ready to move on to testing. -## Testing The Proxy +## Testing the proxy -As with the hosts (`/etc/hosts`) setup that we used so that our **proxyha** container can resolve the web servers, and since in our lab environment we don't have a local DNS server running, we need to set the IP values on our local machine for both the site1 and site2 websites, to correspond to our haproxy container. +As with the hosts (`/etc/hosts`) setup used so that our **proxyha** container can resolve the web servers, and since our lab environment does not have a local DNS server running, set the IP values on our local machine for each the websites, to correspond to our haproxy container. -To do this, we need to modify our `/etc/hosts` file on our local machine. Consider this method of domain resolution a "poor man's DNS." +To do this, change your `/etc/hosts` file on your local machine. Consider this method of domain resolution a "poor man's DNS." `sudo vi /etc/hosts` -Then just add these two lines: +Add these two lines: ``` 192.168.1.149 site1.testdomain.com site1 192.168.1.149 site2.testdomain.com site2 ``` -If you ping either **site1** or **site2** on your local machine now, you should get a response from **proxyha**: +If you ping either **site1** or **site2** on your local machine now, you will get a response from **proxyha**: ``` PING site1.testdomain.com (192.168.1.149) 56(84) bytes of data. @@ -428,18 +429,18 @@ PING site1.testdomain.com (192.168.1.149) 56(84) bytes of data. 64 bytes from site1.testdomain.com (192.168.1.149): icmp_seq=2 ttl=64 time=0.430 ms ``` -Now open your web browser and type site1.testdomain.com (or site2.testdomain.com) as the URL in the address bar. You should get a response back from one of the two test pages and if you load the page again, you should get the next server's test page. Note that the URL does not change, but the returned page will change alternately between servers. +Open your web browser and type site1.testdomain.com (or site2.testdomain.com) as the URL in the address bar. You will get a response back from one of the two test pages and if you load the page again, you will get the next server's test page. Note that the URL does not change, but the returned page will change alternately between servers. ![screenshot of web1 being loaded and showing the second server test message](../images/haproxy_apache_lxd.png) ## Logging -Even though our configuration file is set up correctly for logging, we need two things: First, we need a directory in /var/lib/haproxy/ called "dev": +Even though our configuration file is set up correctly for logging, you need two things: First, a directory in /var/lib/haproxy/ called "dev": `lxc exec proxyha mkdir /var/lib/haproxy/dev` -Next, we need to create a system process for `rsyslogd` to grab instances from the socket (`/var/lib/haproxy/dev/log` in this case) and store those in `/var/log/haproxy.log`: +Next, create a system process for `rsyslogd` to grab instances from the socket (`/var/lib/haproxy/dev/log` in this case) and store those in `/var/log/haproxy.log`: `lxc exec proxyha vi /etc/rsyslog.d/99-haproxy.conf` @@ -454,19 +455,19 @@ $AddUnixListenSocket /var/lib/haproxy/dev/log stop } ``` -Save the file and exit, then restart `rsyslog`: +Save the file and exit, and restart `rsyslog`: `lxc exec proxyha systemctl restart rsyslog` -And to populate that log file with something right away, restart `haproxy` again: +To populate that log file with something right away, restart `haproxy` again: `lxc exec proxyha systemctl restart haproxy` -To take a look at the log file created: +View the log file created: `lxc exec proxyha more /var/log/haproxy.log` -Which should show you something like this: +Which will show you something like this: ``` Sep 25 23:18:02 proxyha haproxy[4602]: Proxy http_frontend started. @@ -479,8 +480,8 @@ Sep 25 23:18:02 proxyha haproxy[4602]: Proxy subdomain2 started. ## Conclusions -HAProxy is a powerful proxy engine that can be used for many things. It is a high-performance, open-source load balancer and reverse proxy for TCP and HTTP applications. We have shown in this document how to use load balancing of two web server instances. +HAProxy is a powerful proxy engine used for many things. It is a high-performance, open source load balancer and reverse proxy for TCP and HTTP applications. This document demonstrated how to use load balancing of two web server instances. -It can also be used for other applications, including databases. It works within LXD containers, as well as on bare metal and standalone servers. +Using it for other applications, including databases, is also possible. It works within LXD containers, and on standalone servers. There are plenty of uses not covered in this document. Check out the [official manual for HAProxy here.](https://cbonte.github.io/haproxy-dconv/1.8/configuration.html)