歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~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服務器,而且已開啓防火牆。沒有服務器的同窗能夠在這裏購買,不過我我的更推薦您使用免費的騰訊雲開發者實驗室進行試驗,學會安裝後在購買服務器。使用非root用戶賬戶登陸服務器。咱們將使用此賬戶執行全部容器管理任務。爲此,您必須先將此用戶添加到lxd組。使用如下命令執行此操做:ubuntu
sudo usermod --append --groups lxd sammy
複製代碼
註銷服務器並從新登陸,以便使用新的組成員身份更新新的SSH會話。登陸後,您能夠開始配置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地址。您須要它們來配置您的服務。
讓咱們鏈接到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/developer/article/1177656?fromSource=waitui
歡迎你們前往騰訊雲+社區或關注雲加社區微信公衆號(QcloudCommunity),第一時間獲取更多海量技術實踐乾貨哦~
海量技術實踐經驗,盡在雲加社區!