歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐干貨哦~
介紹
Linux的容器是Linux的一組進程,通過使用Linux內核功能與系統隔離。它是一個類似於虛擬機的構造,但它的更輕量級。您可以在同一台服務器上輕松創建多個容器。使用Linux容器,您可以在同一服務器上運行多個實例,或者將應用程序及其依賴項捆綁到容器中,而不會影響系統的其余部分。
假設您有一台服務器,並且已為您的客戶設置了多項服務,按照Web應用來說,每個Web站點都是Apache或NginxWeb服務器的同一實例的虛擬主機。但是對於Linux容器,每個網站都在其自己的容器中配置,並具有自己的Web服務器。我們可以使用LXD來創建和管理這些容器。LXD提供管生命周期的容器管理。
在本教程中,您將使用LXD在同一服務器上安裝兩個基於Nginx的網站,每個網站都限制在自己的容器中。然后,您將在第三個容器中安裝HAProxy,該容器將充當反向代理。然后,您將網站路由到HAProxy容器,以便從Internet訪問這兩個網站。
准備
要完成本教程,您需要以下內容:
- 一台已經設置好可以使用
sudo
命令的非root賬號的Ubuntu服務器,並且已開啟防火牆。沒有服務器的同學可以在這里購買,不過我個人更推薦您使用免費的騰訊雲開發者實驗室進行試驗,學會安裝后在購買服務器。 - 兩個域名,如果你沒有域名,建議您先去這里注冊一個域名,您需要將域名解析到您的服務器,您可以使用騰訊雲雲解析進行快速設置。
- 20GB以上存儲空間,建議您使用騰訊雲的雲硬盤進行擴容。
第一步 - 將您的用戶添加到lxd組
使用非root用戶帳戶登錄服務器。我們將使用此帳戶執行所有容器管理任務。為此,您必須先將此用戶添加到lxd組。使用以下命令執行此操作:
sudo usermod --append --groups lxd sammy
注銷服務器並重新登錄,以便使用新的組成員身份更新新的SSH會話。登錄后,您可以開始配置LXD。
第二步 - 配置LXD
需要先配置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地址。您需要它們來配置您的服務。
第四步 - 配置Nginx容器
讓我們連接到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容器
我們將使用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,可以讓全世界訪問我們的網站。
第六步 - 將傳入連接轉發到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/developer/article/1177656?fromSource=waitui
歡迎大家前往騰訊雲+社區或關注雲加社區微信公眾號(QcloudCommunity),第一時間獲取更多海量技術實踐干貨哦~
海量技術實踐經驗,盡在雲加社區!