Ubuntu 16.04でLXDを使用してNginxとHAProxyで複数のWebサイトをホストする方法

前書き

Linux containerは、ネームスペースやコントロールグループなどのLinuxカーネルセキュリティ機能を使用して、システムの他の部分から分離されたプロセスのグループです。 これは仮想マシンに似た構造ですが、はるかに軽量です。追加のカーネルを実行したり、ハードウェアをシミュレートしたりするオーバーヘッドはありません。 つまり、同じサーバー上に複数のコンテナを簡単に作成できます。 Linuxコンテナを使用すると、オペレーティングシステム全体の複数のインスタンスを同じサーバー上で実行したり、システムの残りの部分に影響を与えずにアプリケーションとその依存関係をコンテナにバンドルしたりできます。

たとえば、サーバーがあり、クライアント用にWebサイトを含むいくつかのサービスを設定したとします。 従来のインストールでは、各WebサイトはApacheまたはNginx Webサーバーの同じインスタンスの仮想ホストになります。 ただし、Linuxコンテナの場合、各Webサイトは独自のWebサーバーを備えた独自のコンテナで構成されます。

LXDを使用して、これらのコンテナーを作成および管理できます。 LXDは、コンテナーのライフサイクル全体を管理するハイパーバイザーサービスを提供します。

このチュートリアルでは、LXDを使用して、同じサーバーに2つのNginxベースのWebサイトをインストールします。各Webサイトは独自のコンテナーに限定されます。 次に、リバースプロキシとして機能する3番目のコンテナにHAProxyをインストールします。 次に、トラフィックをHAProxyコンテナーにルーティングして、インターネットから両方のWebサイトにアクセスできるようにします。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • 1つのUbuntu 16.04サーバー。チュートリアルhttps://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04[Ubuntu 16.04での初期サーバーセットアップ]に従って構成され、sudo non -rootユーザーとファイアウォール。

  • 各DNS * A *レコードがサーバーのIPアドレスを指している2つの完全修飾ドメイン名(FQDN)。 これを設定するには、チュートリアルhttps://www.digitalocean.com/community/tutorials/how-to-set-up-a-host-name-with-digitalocean[DigitalOceanでホスト名を設定する方法]に従ってください。

  • 必要に応じて、チュートリアルhttps://www.digitalocean.com/community/tutorial_series/getting-started-with-digitalocean-block-storage[DigitalOceanブロックストレージの概要]に従って20GB以上のブロックストレージを追加します。 これを使用して、コンテナに関連するすべてのデータを保存できます。

ステップ1-ユーザーを「+ lxd +」グループに追加する

非rootユーザーアカウントを使用してサーバーにログインします。 この非ユーザーアカウントを使用して、すべてのコンテナー管理タスクを実行します。 これが機能するためには、まずこのユーザーを `+ lxd +`グループに追加する必要があります。 これを行うには、次のコマンドを使用します。

sudo usermod --append --groups lxd

サーバーからログアウトし、再度ログインして、新しいSSHセッションが新しいグループメンバーシップで更新されるようにします。 ログインしたら、LXDの設定を開始できます。

ステップ2-LXDの構成

LXDは、使用する前に適切に構成する必要があります。 最も重要な構成決定は、コンテナを保存するためのストレージバックエンドのタイプです。 LXDの推奨ストレージバックエンドはZFSファイルシステムで、事前に割り当てられたファイルに保存されるか、https://www.digitalocean.com/products/storage/ [ブロックストレージ]を使用して保存されます。 LXDでZFSサポートを使用するには、 `+ zfsutils-linux +`パッケージをインストールします。

sudo apt-get update
sudo apt-get install zfsutils-linux

これをインストールしたら、LXDを初期化する準備が整いました。 初期化中に、ZFSストレージバックエンドの詳細を指定するよう求められます。 事前に割り当てられたファイルを使用するか、ブロックストレージを使用するかに応じて、次の2つのセクションがあります。 ケースに適した手順に従ってください。 ストレージメカニズムを指定したら、コンテナのネットワークオプションを構成します。

オプション1-事前割り当てファイルの使用

事前に割り当てられたファイルを使用してコンテナを保存するようにLXDを設定するには、次の手順に従います。 まず、次のコマンドを実行してLXD初期化プロセスを開始します。

sudo lxd init

次の出力に示すように、いくつかの情報を提供するよう求められます。 * loop device *と呼ばれる事前割り当てファイルの推奨サイズを含む、すべてのデフォルトを選択します。

OutputName of the storage backend to use (dir or zfs) [default=zfs]:
Create a new ZFS pool (yes/no) [default=yes]?
Name of the new ZFS pool [default=lxd]:
Would you like to use an existing block device (yes/no) [default=no]?
Size in GB of the new loop device (1GB minimum) [default=15]:
Would you like LXD to be available over the network (yes/no) [default=no]?
Do you want to configure the LXD bridge (yes/no) [default=yes]?
Warning: Stopping lxd.service, but it can still be activated by:
 lxd.socket
LXD has been successfully configured.

推奨サイズは、サーバーの使用可能なディスク容量から自動的に計算されます。

デバイスを構成したら、ネットワーク設定を構成します。これについては、次のオプションセクションの後で説明します。

オプション2 –ブロックストレージの使用

Block Storageを使用する場合は、LXDの構成で指定するために、作成したブロックストレージボリュームを指すデバイスを見つける必要があります。 https://cloud.digitalocean.com [DigitalOceanコントロールペイン] lの* Volumes タブに移動し、ボリュームを見つけて、 More ポップアップをクリックし、 Config instructions *をクリックします。

ボリュームをフォーマットするコマンドを見て、デバイスを見つけます。 具体的には、 `+ sudo mkfs.ext4 -F +`コマンドで指定されたパスを探します。 次の図は、ボリュームの例を示しています。 下線が引かれている部分だけが必要です。

image:https://assets.digitalocean.com/articles/lxd_containers_ubuntu_1604/6rDyC1l.png [構成手順は、作成されたブロックストレージのデバイスを示しています。]

この場合、ボリューム名は「+ / 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]:
Create a new ZFS pool (yes/no) [default=yes]?
Name of the new ZFS pool [default=lxd]:

既存のブロックデバイスの使用についてプロンプトが表示されたら、「+ yes +」を選択し、デバイスへのパスを指定します。

Output of the "lxd init" commandWould you like to use an existing block device (yes/no) [default=no]?
Path to the existing block device:

次に、残りの質問にデフォルト値を使用します。

Output of the "lxd init" commandWould you like LXD to be available over the network (yes/no) [default=no]?
Do you want to configure the LXD bridge (yes/no) [default=yes]?
Warning: Stopping lxd.service, but it can still be activated by:
 lxd.socket
LXD has been successfully configured.

プロセスが完了したら、ネットワークを構成します。

ネットワークの構成

初期化プロセスでは、次の図のような一連の画面が表示され、コンテナのネットワークブリッジを構成して、プライベートIPアドレスを取得し、相互に通信し、インターネットにアクセスできるようにします。

image:https://assets.digitalocean.com/articles/lxd_containers_ubuntu_1604/u9D79uB.png [LXDネットワーク構成]

各オプションにはデフォルト値を使用しますが、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 +`コマンドを使用して、 `+ web1 +`という名前のUbuntu 16.04( `+ ubuntu:x +)コンテナーを作成して起動します。 `+ ubuntu:x `の ` x `は、Ubuntu 16.04のコードネームであるXenialの最初の文字へのショートカットです。 ` ubuntu:+`は、LXDイメージの事前構成済みリポジトリの識別子です。

次のコマンドを実行して、コンテナを作成します。

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

`-`文字列は、 `+ lxc `のコマンドパラメータがそこで停止することを示し、残りの行はコンテナ内で実行されるコマンドとして渡されます。 コマンドは ` sudo --login --user ubuntu `で、コンテナ内の事前設定されたアカウント ` ubuntu +`にログインシェルを提供します。

コンテナ内に入ると、シェルプロンプトは次のようになります。

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

ファイルに次の変更を加えます。

編集済みファイル/var/www/html/index.nginx-debian.html

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx !</title>
<style>
   body {
       width: 35em;
       margin: 0 auto;
       font-family: Tahoma, Verdana, Arial, sans-serif;
   }
</style>
</head>
<body>
<h1>Welcome to nginx !</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 !</title>
<style>
   body {
       width: 35em;
       margin: 0 auto;
       font-family: Tahoma, Verdana, Arial, sans-serif;
   }
</style>
</head>
<body>
<h1>Welcome to nginx !</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
...

`+ curl +`コマンドとそのIPアドレスを使用して2番目のコンテナーもテストし、正しく設定されていることを確認します。 両方のコンテナを設定したら、HAProxyのセットアップに進むことができます。

ステップ5-HAProxyコンテナーの構成

これらのコンテナの前に、プロキシとしてHAProxyを設定します。 これがどのように機能するかについてさらに背景が必要な場合は、チュートリアルhttps://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts[HAProxyと負荷分散の概要]を参照してください。コンセプト]。 使用するドメイン名に基づいて、各コンテナにトラフィックを誘導します。 このチュートリアルのようなドキュメントでは、https://tools.ietf.org/html/rfc2606 [特別な予約ドメイン]であるドメイン `+ example.com `を次の構成例で使用します。 最初のウェブサイトをホスト名「 example.com 」と「 www.example.com 」で利用できるようにします。 2番目のWebサイトは「 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 `セクションにいくつかの変更を加えます。 Webクライアントの実際のソースIPを保持するように「 forwardfor 」オプションを追加し、セッションの再利用と低レイテンシを可能にする「 http-server-close +」オプションを追加します。

/etc/haproxy/haproxy.conf

global
...
defaults
   log global
   mode    http
   option  httplog
   option  dontlognull


   timeout connect 5000
   timeout client  50000
   timeout server  50000
...

次に、2つのバックエンドコンテナーを指すようにフロントエンドを構成します。 次のような「+ www_frontend 」という新しい「 frontend +」セクションを追加します。

/etc/haproxy/haproxy.conf

        # Bind to port 80 (www) on the container

   # It matches if the HTTP Host: field mentions any of the hostnames (after the '-i').



   # Redirect the connection to the proper server cluster, depending on the match.

`+ acl `コマンドはWebサーバーのホスト名と一致し、リクエストを対応する ` backend +`セクションにリダイレクトします。

次に、Webサーバーごとに2つの新しい「+ backend 」セクションを定義し、それぞれ「 web1_cluster 」と「 web2_cluster +」という名前を付けます。 次のコードをファイルに追加して、バックエンドを定義します。

/etc/haproxy/haproxy.conf

   # We set the X-Client-IP HTTP header. This is useful if we want the web server to know the real client IP.

   # This backend, named here "web1", directs to container "web1.lxd" (hostname).

+ balance +`オプションは、負荷分散戦略を示します。 この場合、接続の最小数を選択します。 `+ http-request`オプションは、実際のWebクライアントIPでHTTPヘッダーを設定します。 このヘッダーを設定しなかった場合、Webサーバーはすべての接続のソースIPとしてHAProxy IPアドレスを記録するため、トラフィックの発信元を分析するのが難しくなります。 `+ 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

ポート `+ 80 `で受信した接続を他の2つのコンテナの適切なWebサーバーに転送するリバースプロキシとして機能するようにHAProxyを設定しました。 ` 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:
> User-Agent: curl/7.47.0
> Accept: */*
>
...
<
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx !</title>
<style>
...

HAProxyはリクエストを正しく理解し、 `+ web2 `コンテナに転送しました。 そこで、Webサーバーは以前に編集したデフォルトのインデックスページを提供し、テキスト「 on LXD container web2 +」を表示します。 次に、外部リクエストをHAProxyにルーティングして、世界がWebサイトにアクセスできるようにします。

ステップ6-着信接続をHAProxyコンテナーに転送する

パズルの最後のピースは、リバースプロキシをインターネットに接続することです。 ポート「80」でインターネットから受信する接続を「+ haproxy +」コンテナに転送するようにサーバーを設定する必要があります。

HAProxyはコンテナにインストールされ、デフォルトではインターネットからアクセスできません。 これを解決するために、接続を転送するための「+ iptables +」ルールを作成します。

+ iptables +`コマンドには、サーバーのパブリックIPアドレス( ``)と `+ haproxy +`コンテナのプライベートIPアドレス( `)の2つのIPアドレスが必要です。 + lxc list + `コマンド。

次のコマンドを実行して、ルールを作成します。

sudo iptables -t nat -I PREROUTING -i eth0 -p TCP -d /32 --dport 80 -j DNAT --to-destination :80

コマンドの内訳は次のとおりです。

  • `+ -t nat `は、 ` nat +`テーブルを使用することを指定します。

  • `+ -I PREROUTING +`は、ルールをPREROUTINGチェーンに追加することを指定します。

  • `+ -i eth0 +`は、ドロップレットのデフォルトのパブリックインターフェイスであるインターフェイス* eth0 *を指定します。

  • 「+ -p TCP +」は、TCPプロトコルを使用していることを示します。

  • `+ -d / 32 +`は、ルールの宛先IPアドレスを指定します。

  • +-dport 80 +:宛先ポートを指定します。

  • `+ -j DNAT +`は、Destination NAT(DNAT)へのジャンプを実行したいことを示しています。

  • `+-to-destination:80 +`は、リクエストをHAProxyを使用してコンテナのIPアドレスに送信することを望んでいることを示しています。

IPTablesの詳細については、https://www.digitalocean.com/community/tutorials/how-the-iptables-firewall-works [Iptables Firewallの仕組み]およびhttps://www.digitalocean.com/community/tutorials/をご覧ください。 iptables-essentials-common-firewall-rules-and-commands [IPtables Essentials:Common Firewall Rules and Commands]。

最後に、この `+ 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://'
curl --verbose --header 'Host: web2.example.com' 'http://'

これらのコマンドは、サーバーのパブリックIPアドレスへのHTTP接続を作成し、ステップ5で行ったように、HAProxyがリクエストの処理に使用する `+-header +`オプションでHTTPヘッダーフィールドを追加します。

最初の `+ curl +`コマンドの出力は次のとおりです。

Output*   Trying ...
* Connected to  () 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 !</title>
<style>
   body {
...

2番目の `+ curl +`コマンドの出力は次のとおりです。

Output*   Trying ...
* Connected to  () 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 !</title>
<style>
   body {
...

どちらの場合も、正しいWebサイトが表示されます。

結論

HAProxyがトラフィックを誘導する2つのWebサイトを、それぞれ独自のコンテナーに設定しました。 このプロセスを複製して、より多くのWebサイトを構成し、各Webサイトを独自のコンテナーに限定することができます。

新しいコンテナにMySQLを追加してから、WordPressなどのCMSをインストールして、各Webサイトを実行することもできます。 このプロセスを使用して、古いバージョンのソフトウェアをサポートすることもできます。 たとえば、CMSのインストールにPHP5などの古いバージョンのソフトウェアが必要な場合、Ubuntuで利用可能なパッケージマネージャーバージョンをダウングレードする代わりに、コンテナにUbuntu 14.04をインストールできます( + lxc launch ubuntu:t +) 16.04。

最後に、LXDはコンテナの完全な状態のスナップショットを取得する機能を提供します。これにより、後でバックアップを作成し、コンテナを簡単にロールバックできます。 さらに、LXDを2つの異なるサーバーにインストールすると、それらを接続し、インターネットを介してサーバー間でコンテナーを移行することができます。

Related