Ubuntu16.04でLXDを使用してNginxとHAProxyで複数のWebサイトをホストする方法
序章
Linuxコンテナは、名前空間やコントロールグループなどのLinuxカーネルセキュリティ機能を使用して、システムの他の部分から分離されたプロセスのグループです。 これは仮想マシンに似た構造ですが、はるかに軽量です。 追加のカーネルを実行したり、ハードウェアをシミュレートしたりするオーバーヘッドはありません。 これは、同じサーバー上に複数のコンテナーを簡単に作成できることを意味します。 Linuxコンテナーを使用すると、オペレーティングシステム全体の複数のインスタンスを同じサーバー上で制限して実行したり、システムの他の部分に影響を与えることなく、アプリケーションとその依存関係をコンテナーにバンドルしたりできます。
たとえば、サーバーがあり、クライアント用にWebサイトを含むいくつかのサービスを設定しているとします。 従来のインストールでは、各WebサイトはApacheまたはNginxWebサーバーの同じインスタンスの仮想ホストになります。 ただし、Linuxコンテナーでは、各Webサイトは独自のWebサーバーを備えた独自のコンテナーで構成されます。
LXD を使用して、これらのコンテナーを作成および管理できます。 LXDは、コンテナーのライフサイクル全体を管理するハイパーバイザーサービスを提供します。
このチュートリアルでは、LXDを使用して、同じサーバーに2つのNginxベースのWebサイトをインストールし、それぞれが独自のコンテナーに限定されます。 次に、リバースプロキシとして機能する3番目のコンテナにHAProxyをインストールします。 次に、インターネットから両方のWebサイトにアクセスできるようにするために、トラフィックをHAProxyコンテナにルーティングします。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- チュートリアルUbuntu16.04を使用した初期サーバーセットアップに従って構成された1つのUbuntu16.04サーバー、sudo非rootユーザーとファイアウォール。
- 2つの完全修飾ドメイン名(FQDN)。各DNS AレコードはサーバーのIPアドレスを指しています。 これを構成するには、チュートリアルDigitalOceanを使用してホスト名を設定する方法に従ってください。
- 必要に応じて、チュートリアル DigitalOceanブロックストレージ入門に従って、20GB以上のブロックストレージを追加します。 これを使用して、コンテナに関連するすべてのデータを保存できます。
ステップ1—ユーザーをに追加する lxd
グループ
root以外のユーザーアカウントを使用してサーバーにログインします。 この非ユーザーアカウントを使用して、すべてのコンテナ管理タスクを実行します。 これを機能させるには、最初にこのユーザーをに追加する必要があります lxd
グループ。 次のコマンドでこれを行います。
- sudo usermod --append --groups lxd sammy
サーバーからログアウトして再度ログインすると、新しいSSHセッションが新しいグループメンバーシップで更新されます。 ログインすると、LXDの構成を開始できます。
ステップ2—LXDの構成
LXDを使用するには、適切に構成する必要があります。 最も重要な構成の決定は、コンテナーを格納するためのストレージバックエンドのタイプです。 LXDに推奨されるストレージバックエンドはZFSファイルシステムであり、事前に割り当てられたファイルに保存されるか、 BlockStorageを使用して保存されます。 LXDでZFSサポートを使用するには、 zfsutils-linux
パッケージ:
- sudo apt-get update
- sudo apt-get install zfsutils-linux
これをインストールすると、LXDを初期化する準備が整います。 初期化中に、ZFSストレージバックエンドの詳細を指定するように求められます。 事前に割り当てられたファイルを使用するか、ストレージをブロックするかによって、次の2つのセクションがあります。 ケースに適した手順に従ってください。 ストレージメカニズムを指定したら、コンテナのネットワークオプションを構成します。
オプション1-事前に割り当てられたファイルを使用する
以下の手順に従って、事前に割り当てられたファイルを使用してコンテナーを保管するようにLXDを構成します。 まず、次のコマンドを実行して、LXD初期化プロセスを開始します。
- sudo lxd init
次の出力に示すように、いくつかの情報を入力するように求められます。 ループデバイスと呼ばれる、事前に割り当てられたファイルの推奨サイズを含む、すべてのデフォルトを選択します。
OutputName 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.
推奨サイズは、サーバーの使用可能なディスク容量から自動的に計算されます。
デバイスを構成したら、ネットワーク設定を構成します。これについては、次のオプションのセクションで説明します。
オプション2–ブロックストレージの使用
ブロックストレージを使用する場合は、LXDの構成で指定するために、作成したブロックストレージボリュームを指すデバイスを見つける必要があります。 DigitalOceanコントロールペインlのVolumesタブに移動し、ボリュームを見つけて、 More ポップアップをクリックし、Configをクリックします。指示。
ボリュームをフォーマットするコマンドを見て、デバイスを見つけます。 具体的には、で指定されたパスを探します sudo mkfs.ext4 -F
指図。 次の図は、ボリュームの例を示しています。 下線が引かれている部分だけが必要です。
この場合、ボリューム名は /dev/disk/by-id/scsi-0D0_Volume_volume-fra1-01
、あなたのものは異なるかもしれませんが。
ボリュームを特定したら、端末に戻り、次のコマンドを発行してLXD初期化プロセスを開始します。
- sudo lxd init
一連の質問が表示されます。 次の出力に示すように、質問に答えてください。
OutputName 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
既存のブロックデバイスの使用についてプロンプトが表示されたら、次を選択します yes
デバイスへのパスを指定します。
Output of the "lxd init" commandWould you like to use an existing block device (yes/no) [default=no]? yes
Path to the existing block device: /dev/disk/by-id/scsi-0DO_Volume_volume-fra1-01
次に、残りの質問にデフォルト値を使用します。
Output of the "lxd init" commandWould 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.
プロセスが完了したら、ネットワークを構成します。
ネットワーキングの構成
初期化プロセスでは、次の図のような一連の画面が表示されます。これらの画面では、コンテナのネットワークブリッジを構成して、コンテナがプライベートIPアドレスを取得し、相互に通信し、インターネットにアクセスできるようにします。
各オプションにはデフォルト値を使用しますが、IPv6ネットワーキングについて尋ねられた場合は、このチュートリアルでは使用しないため、いいえを選択します。
ネットワーク構成が完了すると、コンテナを作成する準備が整います。
ステップ3—コンテナの作成
LXDの構成に成功しました。 ストレージバックエンドの場所を指定し、新しく作成されたコンテナのデフォルトのネットワークを構成しました。 いくつかのコンテナを作成して管理する準備が整いました。 lxc
指図。
インストールされている利用可能なコンテナを一覧表示する最初のコマンドを試してみましょう。
- lxc list
次の出力が表示されます。
Output of the "lxd list" commandGenerating 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との安全な通信のためにクライアント証明書を自動的に作成したことを通知します。 次に、コンテナを起動する方法に関する情報が表示されます。 最後に、コマンドはコンテナの空のリストを表示します。これは、まだ作成していないために予想されます。
3つのコンテナを作成しましょう。 Webサーバーごとに1つ作成し、リバースプロキシ用に3つ目のコンテナーを作成します。 リバースプロキシの目的は、インターネットからの着信接続をコンテナ内の正しいWebサーバーに転送することです。
を使用します lxc launch
Ubuntu 16.04を作成して起動するコマンド(ubuntu:x
)という名前のコンテナ web1
. The x
の ubuntu:x
は、Ubuntu16.04のコードネームであるXenialの最初の文字のショートカットです。 ubuntu:
LXDイメージの事前設定されたリポジトリの識別子です。
注:実行すると、利用可能なすべてのUbuntuイメージの完全なリストを見つけることができます lxc image list ubuntu:
および実行することによる他のディストリビューション lxc image list images:
.
次のコマンドを実行して、コンテナを作成します。
- lxc launch ubuntu:x web1
- lxc launch ubuntu:x web2
- lxc launch ubuntu:x haproxy
コンテナを作成するのはこれが初めてなので、最初のコマンドはインターネットからコンテナイメージをダウンロードし、ローカルにキャッシュします。 次の2つのコンテナは、大幅に高速に作成されます。
ここでは、コンテナの作成からのサンプル出力を見ることができます web1
.
OutputCreating web1
Retrieving image: 100%
Starting web1
空のバニラコンテナを3つ作成したので、 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アドレスをメモします。 サービスを構成するためにそれらが必要になります。
ステップ4—Nginxコンテナを構成する
に接続しましょう web1
コンテナを作成し、最初のWebサーバーを構成します。
接続するには、 lxc exec
コマンド。コンテナの名前と実行するコマンドを受け取ります。 次のコマンドを実行して、コンテナに接続します。
- lxc exec web1 -- sudo --login --user ubuntu
The --
文字列は、 lxc
ここで停止する必要があり、残りの行はコンテナ内で実行されるコマンドとして渡されます。 コマンドは sudo --login --user ubuntu
、事前設定されたアカウントのログインシェルを提供します ubuntu
コンテナ内。
注: root としてコンテナーに接続する必要がある場合は、コマンドを使用できます lxc exec web1 -- /bin/bash
代わりは。
コンテナ内に入ると、シェルプロンプトは次のようになります。
Outputubuntu@web1:~$
コンテナ内のこのubuntuユーザーは事前設定されています sudo
アクセスし、実行することができます sudo
パスワードを指定せずにコマンドを実行します。 このシェルは、コンテナの範囲内に制限されています。 このシェルで実行するものはすべてコンテナーに残り、ホストサーバーにエスケープできません。
コンテナ内のUbuntuインスタンスのパッケージリストを更新して、Nginxをインストールしましょう。
- sudo apt-get update
- sudo apt-get install nginx
このサイトのデフォルトのWebページを編集して、このサイトがでホストされていることを明確にするテキストを追加しましょう。 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>
...
ファイルを2か所で編集し、具体的にテキストを追加しました 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/
出力は次のようになります。
Output of "curl http://10.10.10.100/" command<!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>
...
を使用して、2番目のコンテナもテストします curl
コマンドとそのIPアドレスも正しく設定されていることを確認します。 両方のコンテナを設定したら、HAProxyの設定に進むことができます。
ステップ5—HAProxyコンテナを設定する
これらのコンテナの前にプロキシとしてHAProxyを設定します。 これがどのように機能するかについてさらに背景が必要な場合は、チュートリアルHAProxyと負荷分散の概念の概要を確認してください。 使用するドメイン名に基づいて、トラフィックを各コンテナに転送します。 ドメインを使用しますexample.com
次の構成例では、このチュートリアルのようなドキュメント用の特別予約ドメインです。 ホスト名で最初のウェブサイトを利用できるようにします example.com
と www.example.com
. 2番目のウェブサイトは 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
...
次に、2つのバックエンドコンテナを指すようにフロントエンドを構成します。 新しいを追加します 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
The acl
コマンドはWebサーバーのホスト名と一致し、対応するリクエストをリダイレクトします backend
セクション。
次に、2つの新しい定義をします backend
セクション(Webサーバーごとに1つ)、およびそれらに名前を付けます web1_cluster
と web2_cluster
それぞれ。 次のコードをファイルに追加して、バックエンドを定義します。
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
The balance
オプションは、負荷分散戦略を示します。 この場合、接続数を最小限に抑えます。 The http-request
オプションは、実際のWebクライアントIPでHTTPヘッダーを設定します。 このヘッダーを設定しなかった場合、Webサーバーはすべての接続の送信元IPとしてHAProxy IPアドレスを記録するため、トラフィックの発信元を分析することがより困難になります。 The server
オプションはサーバーの任意の名前を指定します(web1
)、続いてサーバーのホスト名とポート…
LXDはコンテナ用のDNSサーバーを提供するため、 web1.lxd
に関連付けられたIPに解決されます web1
容器。 他のコンテナには、次のような独自のホスト名があります。 web2.lxd
と haproxy.lxd
.
The check
パラメータは、HAPRoxyにWebサーバーでヘルスチェックを実行して、それが利用可能であることを確認するように指示します。
構成が有効であることをテストするには、次のコマンドを実行します。
- /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c
出力は次のようになります
Configuration file is valid
新しい構成を読み取るようにHAProxyをリロードしてみましょう。
- sudo systemctl reload haproxy
次に、ホストに戻るためにコンテナからログアウトします。
- logout
ポートで受信した接続を転送するリバースプロキシとして機能するようにHAProxyを構成しました 80
他の2つのコンテナ内の適切なWebサーバーに接続します。 それをテストしてみましょう haproxy
実際には、リクエストを正しいWebコンテナに転送することができます。 次のコマンドを実行します。
- curl --verbose --header 'Host: web2.example.com' http://10.10.10.10
これにより、HAProxyにリクエストが送信され、HTTPが設定されます host
ヘッダー。HAProxyが接続を適切なWebサーバーにリダイレクトするために使用する必要があります。
出力は次のようになります
Output of "curl --verbose --header 'Host: web2.example.com' http://10.10.10.10" command...
> 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サーバーは、以前に編集したデフォルトのインデックスページを提供し、テキストを表示します。 on LXD container web2
. それでは、外部リクエストをHAProxyにルーティングして、世界中が私たちのWebサイトにアクセスできるようにしましょう。
ステップ6—着信接続をHAProxyコンテナに転送する
パズルの最後のピースは、リバースプロキシをインターネットに接続することです。 ポートでインターネットから受信する可能性のある接続を転送するようにサーバーを設定する必要があります 80
に haproxy
容器。
HAProxyはコンテナにインストールされ、デフォルトではインターネットからアクセスできません。 これを解決するために、 iptables
接続を転送するルール。
The iptables
コマンドには2つのIPアドレスが必要です。サーバーのパブリックIPアドレス(your_server_ip
)およびのプライベートIPアドレス haproxy
容器 (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を指定します。-p TCP
TCPプロトコルを使用していると言います。-d your_server_ip/32
ルールの宛先IPアドレスを指定します。--dport 80
:宛先ポートを指定します。-j DNAT
宛先NAT(DNAT)へのジャンプを実行したいと言います。--to-destination your_haproxy_ip:80
HAProxyを使用してリクエストをコンテナのIPアドレスに送信することを示しています。
IPTablesの詳細については、IptablesFirewallの仕組みおよびIPtablesEssentials:一般的なファイアウォールルールとコマンドをご覧ください。
最後に、これを保存するには iptables
再起動後に再適用されるようにコマンドを実行し、 iptables-persistent
パッケージ:
- sudo apt-get install iptables-persistent
パッケージをインストールすると、現在のiptablesルールを保存するように求められます。 現在のすべてを受け入れて保存します iptables
ルール。
2つのFQDNを設定している場合は、Webブラウザを使用して各Webサイトに接続できるはずです。 やってみよう。
2つのWebサーバーが実際にインターネットからアクセス可能であることをテストするには、ローカルコンピューターからそれぞれにアクセスします。 curl
このようなコマンド:
- curl --verbose --header 'Host: example.com' 'http://your_server_ip'
- curl --verbose --header 'Host: web2.example.com' 'http://your_server_ip'
これらのコマンドは、サーバーのパブリックIPアドレスへのHTTP接続を確立し、HTTPヘッダーフィールドを追加します。 --header
手順5で行ったように、HAProxyがリクエストを処理するために使用するオプション。
これが最初の出力です curl
指図:
Output* 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 {
...
これが2番目の出力です curl
指図:
Output* 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 {
...
どちらの場合も、正しいWebサイトが表示されます。
結論
HAProxyがトラフィックを転送する、それぞれ独自のコンテナ内に2つのWebサイトを設定しました。 このプロセスを複製して、それぞれが独自のコンテナーに限定された、さらに多くのWebサイトを構成できます。
MySQLを新しいコンテナに追加してから、WordPressなどのCMSをインストールして各Webサイトを実行することもできます。 このプロセスを使用して、古いバージョンのソフトウェアをサポートすることもできます。 たとえば、CMSのインストールにPHP5などの古いバージョンのソフトウェアが必要な場合は、Ubuntu 14.04をコンテナーにインストールできます(lxc launch ubuntu:t
)、Ubuntu16.04で利用可能なパッケージマネージャーのバージョンをダウングレードしようとする代わりに。
最後に、LXDは、コンテナーの完全な状態のスナップショットを作成する機能を提供します。これにより、バックアップを作成し、後でコンテナーをロールバックすることが容易になります。 さらに、LXDを2つの異なるサーバーにインストールすると、それらを接続して、インターネットを介してサーバー間でコンテナーを移行することができます。