欢迎你们前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~html
本文由 独木桥先生 发表于 云+社区专栏
Linux的容器是Linux的一组进程,经过使用Linux内核功能与系统隔离。它是一个相似于虚拟机的构造,但它的更轻量级。您能够在同一台服务器上轻松建立多个容器。使用Linux容器,您能够在同一服务器上运行多个实例,或者将应用程序及其依赖项捆绑到容器中,而不会影响系统的其他部分。前端
假设您有一台服务器,而且已为您的客户设置了多项服务,按照Web应用来讲,每一个Web站点都是Apache或NginxWeb服务器的同一实例的虚拟主机。可是对于Linux容器,每一个网站都在其本身的容器中配置,并具备本身的Web服务器。咱们可使用LXD来建立和管理这些容器。LXD提供管生命周期的容器管理。linux
在本教程中,您将使用LXD在同一服务器上安装两个基于Nginx的网站,每一个网站都限制在本身的容器中。而后,您将在第三个容器中安装HAProxy,该容器将充当反向代理。而后,您将网站路由到HAProxy容器,以便从Internet访问这两个网站。nginx
要完成本教程,您须要如下内容:web
sudo
命令的非root帐号的Ubuntu服务器,而且已开启防火墙。没有服务器的同窗能够在这里购买,不过我我的更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后在购买服务器。使用非root用户账户登陆服务器。咱们将使用此账户执行全部容器管理任务。为此,您必须先将此用户添加到lxd组。使用如下命令执行此操做:shell
sudo usermod --append --groups lxd sammy
注销服务器并从新登陆,以便使用新的组成员身份更新新的SSH会话。登陆后,您能够开始配置LXD。ubuntu
须要先配置LXD才能使用,最重要的配置取决于存储容器的后端类型。LXD的推荐存储后端是ZFS文件系统,请安装zfsutils-linux
包:后端
sudo apt-get update sudo apt-get install zfsutils-linux
安装完成后,您就能够初始化LXD了。在初始化期间,系统将提示您指定ZFS存储后端。接下来有两个部分,具体取决于您是要使用预分配文件仍是块存储。按照适合您状况的步骤进行操做。指定存储机制后,您将为容器配置网络选项。浏览器
请按照如下步骤配置LXD以使用预分配的文件来存储容器。首先,执行如下命令以启动LXD初始化:安全
sudo lxd init
系统将提示您提供信息,如如下输出所示。咱们将选择默认值,包括预分配文件的建议大小。
Name of the storage backend to use (dir or zfs) [default=zfs]: zfs Create a new ZFS pool (yes/no) [default=yes]? yes Name of the new ZFS pool [default=lxd]: lxd Would you like to use an existing block device (yes/no) [default=no]? no Size in GB of the new loop device (1GB minimum) [default=15]: 15 Would you like LXD to be available over the network (yes/no) [default=no]? no Do you want to configure the LXD bridge (yes/no) [default=yes]? yes Warning: Stopping lxd.service, but it can still be activated by: lxd.socket LXD has been successfully configured.
建议的大小将根据服务器的可用磁盘空间自动计算。配置设备后,您将配置网络设置。
初始化过程将为咱们提供一个GUI,以下图所示,让咱们为容器配置网络桥接,以便它们能够获取私有IP地址,相互通讯以及访问网络。
使用每一个选项的默认值,但当被问及IPv6网络时,请选择否,由于国内环境暂时不容许。
完成网络配置后,您就能够建立容器了。
咱们已成功配置LXD。咱们指定了存储后端的位置,并为任何新建立的容器配置了默认网络。咱们将准备建立和管理一些容器,咱们将使用lxc命令。
让咱们尝试咱们的第一个命令,它列出了可用的已安装容器:
lxc list
您将看到如下输出:
Generating a client certificate. This may take a minute... If this is your first time using LXD, you should also run: sudo lxd init To start your first container, try: lxc launch ubuntu:16.04 +------+-------+------+------+------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +------+-------+------+------+------+-----------+
因为这是lxc
命令第一次与LXD管理程序通讯,所以输出让咱们知道该命令会自动建立客户端证书与LXD进行安全通讯。而后,它显示了有关如何启动容器的一些信息。最后,该命令显示了一个空的容器列表,这很正常,咱们还没有建立任何容器。
让咱们来建立三个容器。咱们将建立两个web容器,并为反向代理建立第三个容器。反向代理的目的是未来自网络的传入链接定向到容器中的正确Web服务器。
咱们将使用lxc launch
命令建立并启动名为web1的Ubuntu 16.04(ubuntu:x
)容器。ubuntu:x
是预先配置的LXD镜像存储库的标识符
注意:您能够经过运行lxc image list images:
来运行镜像, lxc image list ubuntu:
命令找到全部可用Ubuntu映像的完整列表。
执行如下命令以建立容器:
lxc launch ubuntu:x web1 lxc launch ubuntu:x web2 lxc launch ubuntu:x haproxy
由于这是咱们第一次建立容器,因此第一个命令从网络下载容器映像。接下来的两个容器建立速度要快得多。
在这里,您能够看到建立容器web1
的示例输出结果。
Creating web1 Retrieving image: 100% Starting web1
如今咱们已经建立了三个空的vanilla容器,让咱们使用lxc list
命令来显示有关它们的信息:
lxc list
输出结果显示为一个表,其中包含每一个容器的名称,其当前状态,IP地址,类型以及是否存在快照。
+---------+---------+-----------------------+------+------------+-----------+ | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS | +---------+---------+-----------------------+------+------------+-----------+ | haproxy | RUNNING | 10.10.10.10 (eth0) | | PERSISTENT | 0 | +---------+---------+-----------------------+------+------------+-----------+ | web1 | RUNNING | 10.10.10.100 (eth0) | | PERSISTENT | 0 | +---------+---------+-----------------------+------+------------+-----------+ | web2 | RUNNING | 10.10.10.200 (eth0) | | PERSISTENT | 0 | +---------+---------+-----------------------+------+------------+-----------+
记下容器名称及其对应的IPv4地址。您须要它们来配置您的服务。
让咱们链接到web1
容器并配置第一个Web服务器。
要进行链接,咱们使用 lxc exec
命令,该命令须要容器的名称和要执行的命令。执行如下命令以链接到容器:
lxc exec web1 -- sudo --login --user ubuntu
--
字符串表示该命令参数lxc
应该停在那里,如在容器内将要执行的命令的行的其他部分将被传递。该命令是sudo --login --user ubuntu
,它为容器内的预配置账户ubuntu提供登陆shell 。
注意:若是须要以
root身份链接到容器,则可使用
lxc exec web1 --/bin/bash
命令。
进入容器后,咱们的shell提示如今以下所示。
ubuntu@web1:~$
容器中的这个ubuntu用户具备sudo
访问权限,而且能够在不提供密码的状况下运行sudo
命令。这个shell限制在容器的范围内。咱们在此shell中运行的任何内容都保留在容器中,没法转义到主机服务器。
让咱们更新容器内Ubuntu实例的包列表并安装Nginx:
sudo apt-get update sudo apt-get install nginx
让咱们编辑此站点的默认网页,并添加一些文本,清楚地代表该站点是在web1容器中托管的。打开文件/var/www/html/index.nginx-debian.html
:
sudo nano /var/www/html/index.nginx-debian.html
对文件进行如下更改:
<!DOCTYPE html> <html> <head> <title>Welcome to nginx on LXD container web1!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx on LXD container web1!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> ...
咱们在两个地方编辑了文件,并在on LXD container web1上专门添加了文本。保存文件并退出编辑器。
如今注销容器并返回主机服务器:
logout
对web2
容器重复此步骤。登陆,安装Nginx,而后编辑文件/var/www/html/index.nginx-debian.html
以及使用web2
。而后退出web2
容器。
让咱们使用curl
来测试容器中的Web服务器是否正常工做。咱们须要先前显示的Web容器的IP地址。
curl http://10.10.10.100/
输出结果应该是:
<!DOCTYPE html> <html> <head> <title>Welcome to nginx on LXD container web1!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx on LXD container web1!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> ...
一样测试第二个容器,使用curl
命令及其IP地址验证它是否也正确设置。配置好两个容器后,咱们能够继续设置HAProxy。
咱们将使用HAProxy设置这些容器的代理。根据咱们使用的域名将流量引导至每一个容器。咱们将在后面的配置示例中使用example.com
。咱们将在主机名example.com
和www.example.com
上提供第一个网站。第二个网站使用www2.example.com
。或用您本身的域名代替这些域名。
登陆haproxy
容器:
lxc exec haproxy -- sudo --login --user ubuntu
更新安装包列表并安装HAProxy:
sudo apt-get update sudo apt-get install haproxy
安装完成后,咱们须要配置HAProxy。HAProxy的配置文件位于/etc/haproxy/haproxy.cfg
中。使用您喜欢的文本编辑器打开文件。
sudo nano /etc/haproxy/haproxy.cfg
首先,咱们将对defaults
部分进行一些修改。咱们将添加forwardfor
选项,以便保留Web客户端的真实源IP,而且咱们将添加http-server-close
选项,从而实现会话重用和更低的延迟。
global ... defaults log global mode http option httplog option dontlognull option forwardfor option http-server-close timeout connect 5000 timeout client 50000 timeout server 50000 ...
接下来,咱们将配置前端指向咱们的两个后端容器。添加一个新的frontend
部分名为www_frontend
,以下所示:
frontend www_frontend bind *:80 # Bind to port 80 (www) on the container # It matches if the HTTP Host: field mentions any of the hostnames (after the '-i'). acl host_web1 hdr(host) -i example.com www.example.com acl host_web2 hdr(host) -i web2.example.com # Redirect the connection to the proper server cluster, depending on the match. use_backend web1_cluster if host_web1 use_backend web2_cluster if host_web2
使用acl
命令与Web服务器的主机名匹配,并将请求重定向到相应的backend
部分。
而后咱们定义两个新的backend
部分,每一个部分分别用于每一个Web服务器,分别命名它们为web1_cluster
和web2_cluster
。将如下代码添加到文件中以定义backend:
backend web1_cluster balance leastconn # We set the X-Client-IP HTTP header. This is useful if we want the web server to know the real client IP. http-request set-header X-Client-IP %[src] # This backend, named here "web1", directs to container "web1.lxd" (hostname). server web1 web1.lxd:80 check backend web2_cluster balance leastconn http-request set-header X-Client-IP %[src] server web2 web2.lxd:80 check
balance
选项表示负载均衡策略。在这种状况下,咱们选择最少数量的链接。http-request
选项使用真实Web客户端IP设置HTTP标头。若是咱们没有设置此标头,则Web服务器会将HAProxy IP地址记录为全部链接的源IP,从而使分析流量来源的位置。server
选项指定server(web1
)的任意名称,并跟着服务器的主机名和端口。
LXD为容器提供DNS服务器,所以 web1.lxd
解析为与web1
容器关联的IP。其余容器有本身的主机名,例如 web2.lxd
和haproxy.lxd
。
check
参数告诉HAPRoxy在Web服务器上执行运行情况。要测试配置是否有效,请运行如下命令:
/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c
输出结果应该是
Configuration file is valid
让咱们从新加载HAProxy,以便它读取新配置。
sudo systemctl reload haproxy
如今注销容器以便返回主机。
logout
咱们已将HAProxy配置为充当反向代理,将其在80
端口上接收的任何链接转发到其余两个容器中的相应Web服务器。让咱们测试haproxy
将请求转发到正确的Web容器。请执行如下命令:
curl --verbose --header 'Host: web2.example.com' http://10.10.10.10
这会向HAProxy发出请求并设置HTTP host
标头,HAProxy应使用该标头将链接重定向到相应的Web服务器。
输出结果应该是
... > GET / HTTP/1.1 > Host: web2.example.com > User-Agent: curl/7.47.0 > Accept: */* > ... < <!DOCTYPE html> <html> <head> <title>Welcome to nginx on LXD container web2!</title> <style> ...
HAProxy正确转发请求并将其转发给web2容器。Web服务器提供了咱们以前编辑的默认索引页面。如今让咱们将外部请求路由到HAProxy,可让全世界访问咱们的网站。
最后一个难题是将反向代理链接到网络。咱们须要设置咱们的服务器以将它从80
端口上的网络接收的任何链接转发到haproxy
容器中。
HAProxy安装在容器中,没法从Internet访问。为了解决这个问题,咱们将建立一个iptables
转发链接的规则。
iptables命令须要两个IP地址:服务器的公共IP地址(your_server_ip
)和haproxy容器的私有IP地址(your_haproxy_ip
),您可使用lxc list
命令获取该地址。
执行此命令以建立规则:
sudo iptables -t nat -I PREROUTING -i eth0 -p TCP -d your_server_ip/32 --dport 80 -j DNAT --to-destination your_haproxy_ip:80
这是命令分解的方式:
-t nat
指定咱们正在使用该nat表。-I PREROUTING
指定咱们将规则添加到PREROUTING链。-i eth0
指定接口eth0,它是Droplets上的默认公共接口。-p TCP
代表咱们正在使用TCP协议。-d your_server_ip/32
指定规则的目标IP地址。--dport 80
:指定目标端口。-j DNAT
代表咱们想要跳转到目标NAT(DNAT)。--to-destination your_haproxy_ip:80
代表咱们但愿请求使用HAProxy转到容器的IP地址。最后,要保存iptables
命令以便在从新启动后从新应用它,咱们将安装iptables-persistent
软件包:
sudo apt-get install iptables-persistent
安装软件包时,系统将提示您保存全部当前iptables
规则。若是您已设置了两个FQDN,那么您应该可以使用Web浏览器链接到每一个网站。
要测试两个Web服务器是否实际能够从Internet访问,请使用如下curl命令从本地计算机访问每一个Web服务器:
curl --verbose --header 'Host: example.com' 'http://your_server_ip' curl --verbose --header 'Host: web2.example.com' 'http://your_server_ip'
这些命令使HTTP链接到服务器的公共IP地址,并添加一个HTTP头字段,--header其中包含HAProxy将用于处理请求的选项。
这是第一个curl命令的输出结果:
* Trying your_server_ip... * Connected to your_server_ip (your_server_ip) port 80 (#0) > GET / HTTP/1.1 > Host: example.com > User-Agent: curl/7.47.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.10.0 (Ubuntu) ... <!DOCTYPE html> <html> <head> <title>Welcome to nginx on LXD container web1!</title> <style> body { ...
这是第二个curl
命令的输出结果:
* Trying your_server_ip... * Connected to your_server_ip (your_server_ip) port 80 (#0) > GET / HTTP/1.1 > Host: web2.example.com > User-Agent: curl/7.47.0 > Accept: */* > < HTTP/1.1 200 OK < Server: nginx/1.10.0 (Ubuntu) ... <!DOCTYPE html> <html> <head> <title>Welcome to nginx on LXD container web2!</title> <style> body { ...
在这两种状况下,都会显示正确的网站。
您已经设置了两个网站,每一个网站都在本身的容器中,并使用HAProxy重定向流量。您能够复制此过程以配置更多网站,每一个网站都限制在本身的容器中。
您还能够在新容器中添加MySQL,而后安装像WordPress这样的CMS来运行每一个网站。您还可使用此过程来支持旧版本的软件。最后,LXD提供了对容器的完整状态进行快照的功能,这使得之后能够轻松地建立备份和回滚容器。此外,若是咱们在两个不一样的服务器上安装LXD,则能够经过Internet链接它们并在服务器之间迁移容器。更多Linux教程请前往腾讯云+社区学习更多知识。
参考文献:《How to Host Multiple Web Sites with Nginx and HAProxy Using LXD on Ubuntu 16.04》
问答
相关阅读
安全报告 | 2018上半年互联网恶意爬虫分析:从全景视角看爬虫与反爬虫
此文已由做者受权腾讯云+社区发布,原文连接:https://cloud.tencent.com/dev...
欢迎你们前往腾讯云+社区或关注云加社区微信公众号(QcloudCommunity),第一时间获取更多海量技术实践干货哦~
海量技术实践经验,尽在云加社区!