使用LXD搭建Web網站

歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~html

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

介紹

Linux的容器是Linux的一組進程,經過使用Linux內核功能與系統隔離。它是一個相似於虛擬機的構造,但它的更輕量級。您能夠在同一臺服務器上輕鬆建立多個容器。使用Linux容器,您能夠在同一服務器上運行多個實例,或者將應用程序及其依賴項捆綁到容器中,而不會影響系統的其他部分。linux

假設您有一臺服務器,而且已爲您的客戶設置了多項服務,按照Web應用來講,每一個Web站點都是Apache或NginxWeb服務器的同一實例的虛擬主機。可是對於Linux容器,每一個網站都在其本身的容器中配置,並具備本身的Web服務器。咱們可使用LXD來建立和管理這些容器。LXD提供管生命週期的容器管理。nginx

在本教程中,您將使用LXD在同一服務器上安裝兩個基於Nginx的網站,每一個網站都限制在本身的容器中。而後,您將在第三個容器中安裝HAProxy,該容器將充當反向代理。而後,您將網站路由到HAProxy容器,以便從Internet訪問這兩個網站。web

準備

要完成本教程,您須要如下內容:shell

  • 一臺已經設置好可使用sudo命令的非root帳號的Ubuntu服務器,而且已開啓防火牆。沒有服務器的同窗能夠在這裏購買,不過我我的更推薦您使用免費的騰訊雲開發者實驗室進行試驗,學會安裝後在購買服務器
  • 兩個域名,若是你沒有域名,建議您先去這裏註冊一個域名,您須要將域名解析到您的服務器,您可使用騰訊云云解析進行快速設置。
  • 20GB以上存儲空間,建議您使用騰訊雲的雲硬盤進行擴容。

第一步 - 將您的用戶添加到lxd組

使用非root用戶賬戶登陸服務器。咱們將使用此賬戶執行全部容器管理任務。爲此,您必須先將此用戶添加到lxd組。使用如下命令執行此操做:ubuntu

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),第一時間獲取更多海量技術實踐乾貨哦~

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

相關文章
相關標籤/搜索