使用LXD搭建Web網站


歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐干貨哦~

本文由獨木橋先生 發表於雲+社區專欄

介紹

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地址,相互通信以及訪問網絡。

img

使用每個選項的默認值,但當被問及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.comwww.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_clusterweb2_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.lxdhaproxy.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》

問答

如何使用Kubernetes?

相關閱讀

安全報告 | 2018上半年互聯網惡意爬蟲分析:從全景視角看爬蟲與反爬蟲

安全報告 | SSH 暴力破解趨勢:從雲平台向物聯網設備遷移

給你的CVM安裝一個面板吧!

此文已由作者授權騰訊雲+社區發布,原文鏈接:https://cloud.tencent.com/developer/article/1177656?fromSource=waitui

歡迎大家前往騰訊雲+社區或關注雲加社區微信公眾號(QcloudCommunity),第一時間獲取更多海量技術實踐干貨哦~

海量技術實踐經驗,盡在雲加社區


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM