Kubernetes は、コンテナ化されたマイクロサービス ベースのアプリケーションをクラスター内で実行および管理するために Google が開発したオープン ソース システムです。 Kubernetes を使用する人は、Kubernetes で作成したサービスを Kubernetes クラスターの外部からアクセスできるようにする必要があることがよくあります。
Kubernetes には、以下の「組み込みソリューションを使用した Kubernetes サービスの公開」で説明されているように、サービスを公開するための組み込みソリューションが用意されていますが、これらのソリューションでは、レイヤー 4 の負荷分散またはラウンドロビン HTTP 負荷分散に制限されます。
この投稿では、Kubernetes をクラウドで実行している場合でも、独自のインフラストラクチャで実行している場合でも、Kubernetes サービスをインターネットに公開するための高度なレイヤー 7 負荷分散ソリューションとしてNGINX Plus を使用する方法を説明します。
ここでは、Kubernetes (ポッド、サービス、レプリケーション コントローラー、ラベル) と実行中の Kubernetes クラスターについて基本的な知識があることを前提としています。 Kubernetes の詳細については、公式のKubernetes ユーザー ガイドを参照してください。
Kubernetes は、サービスを公開するためのいくつかのオプションを提供します。 そのうちの 2 つ (NodePort と LoadBalancer) は、特定のタイプのサービスに対応します。 3 番目のオプションである Ingress API は、Kubernetes リリース 1.1 でベータ版として利用可能になりました。
サービス タイプをNodePortとして指定すると、各 Kubernetes ノードの同じポートでサービスが利用できるようになります。 サービスをインターネットに公開するには、そのポートで 1 つ以上のノードを公開します。 高可用性を実現するために、複数のノードを公開し、DNS ベースの負荷分散を使用してそれらの間でトラフィックを分散したり、任意のロードバランサーの背後にノードを配置したりすることができます。
着信トラフィックがポート上のノードに到達すると、サービスのポッド間で負荷分散されます。 各ノードで実行されている Kubernetes ネットワーク プロキシ ( kube-proxy
) によって実行される負荷分散は、TCP/UDP 負荷分散に制限されます。
サービス タイプをLoadBalancerとして指定すると、サービスのポッド間で着信トラフィックを分散するクラウド ロード バランサーが割り当てられます。
LoadBalancer ソリューションは、特定のクラウド プロバイダーとGoogle Container Engineでのみサポートされており、独自のインフラストラクチャで Kubernetes を実行している場合は使用できません。 さらに、クラウド ロード バランサーにセッション永続性やリクエスト マッピングなどの高度な機能がある場合でも、Kubernetes ではラウンドロビン TCP ロード バランシングのみを構成できます。
Ingressリソースを作成すると、カスタム URL (たとえば、サービス A は URL /foo 、サービス B は URL /bar ) と複数の仮想ホスト名 (たとえば、あるサービス グループの場合はfoo.example.com 、別のサービス グループの場合はbar.example.com ) でサービスをインターネットに公開できます。 Ingress コントローラは Ingress リソースを消費し、外部ロードバランサを設定します。
Ingress コントローラーは標準の Kubernetes デプロイメントの一部ではありません。ニーズに最適なコントローラーを選択するか、自分で実装して Kubernetes クラスターに追加する必要があります。 すぐに多くのコントローラ実装が登場すると予想されますが、現時点で利用可能な実装はGoogle Compute Engine HTTP ロードバランサ用のコントローラのみであり、これはGoogle Compute EngineまたはGoogle Container Engine上で Kubernetes を実行している場合にのみ機能します。 実際のロードバランサーが高度な機能をサポートしている場合でも、Ingress API はラウンドロビン HTTP ロードバランシングのみをサポートします。
この記事の執筆時点では、Ingress API と Google Compute Engine HTTP ロードバランサのコントローラはどちらもベータ版です。
更新– NGINX と NGINX Plus の両方に対応した NGINX Ingress Controller が、 GitHub リポジトリで利用できるようになりました。 製品の詳細については、 NGINX Ingress Controllerを参照してください。
上記のソリューションはセットアップが簡単で、すぐに使用できますが、高度な機能、特にレイヤー 7 の負荷分散に関連する機能は提供されません。
[編集者 – このセクションは、NGINX Plus APIを参照するように更新されました。NGINX Plus API は、ここで最初に説明した個別の動的設定モジュールを置き換え、廃止します。]
NGINX Plus を Kubernetes と統合するには、NGINX Plus の構成が Kubernetes と同期され、ポッドの追加や削除などの Kubernetes サービスの変更が反映されるようにする必要があります。 NGINX Open Source では、NGINX 構成ファイルを手動で変更し、構成を再読み込みします。 NGINX Plus では、設定を動的に更新する方法が 2 つあります。
すでに実行中の Kubernetes クラスターと、クラスターの管理に使用できるkubectl
ユーティリティを備えたホストがあることを前提としています。手順については、クラスターの種類に応じた Kubernetes スタートガイドを参照してください。 また、NGINX Plus Docker イメージを構築しておく必要もあります。手順については、弊社のブログの「Docker を使用した NGINX および NGINX Plus のデプロイ」をご覧ください。
私たちが行うことの概要は次のとおりです。
注: このブログで説明されているソリューションは、Google Compute Engine で実行されているKubernetes 1.0.6と、以下で使用しているローカルVagrantセットアップを使用してテストしました。
コマンドでは、Kubernetes 設定によって異なる可能性がある値は斜体で表示されます。
私たちは、インターネットに公開するノード上の Kubernetes ポッドに NGINX Plus を配置しています。 ポッドはレプリケーション コントローラーによって作成され、これも設定されています。 Kubernetes 固有の NGINX Plus 構成ファイルは、NGINX Plus ポッドとノード間で共有されるフォルダーに保存されるため、保守が簡単になります。
NGINX Plus ポッドが実行されるノードを指定するには、そのノードにラベルを追加します。 次のコマンドを実行すると、すべてのノードのリストが取得されます。
$ kubectl get nodes名前 ラベル ステータス 10.245.1.3 Kubernetes.io/hostname=10.245.1.3 準備完了 10.245.1.4 Kubernetes.io/hostname=10.245.1.4 準備完了 10.245.1.5 Kubernetes.io/hostname=10.245.1.5 準備完了
最初のノードを選択し、次のコマンドを実行してラベルを追加します。
$ kubectl ラベルノード10.245.1.3役割=nginxplus
NGINX Plus ポッドを直接作成するのではなく、レプリケーション コントローラーを介して作成します。 NGINX Plus ポッドのレプリケーション コントローラーは、 nginxplus-rc.yamlという Kubernetes 宣言ファイルで設定します。
レプリカ
の数を 1 に設定しました。つまり、Kubernetes は 1 つの NGINX Plus ポッドが常に実行されるようにします。ポッドに障害が発生した場合は、新しいポッドに置き換えられます。nodeSelector
フィールドでは、NGINX Plus ポッドがrole:
nginxplus という
ラベルの付いたノード上に作成されるように指定します。apiバージョン: v1
種類: ReplicationController
メタデータ:
名前: nginxplus-rc
仕様:
レプリカ: 1
セレクタ:
アプリ: nginxplus
テンプレート:
メタデータ:
ラベル:
アプリ: nginxplus
仕様:
ノードセレクタ:
ロール: nginxplus
コンテナ:
-名前: nginxplus
imagePullPolicy: IfNotPresent
イメージ: nginxplus
ポート:
- 名前: http
コンテナポート: 80
ホストポート: 80
- 名前: http-alt
コンテナポート: 8080
ホストポート: 8080
ボリュームマウント:
- マウントパス: "/etc/nginx/conf.d"
名前: etc-nginx-confd
ボリューム:
- ホストパス:
パス: "/etc/nginx/conf.d"
名前: etc-nginx-confd
上で述べたように、NGINX Plus Docker イメージはすでに構築されています。 これでノード上で利用できるようになります。 簡単にするために、プライベート Docker リポジトリは使用せず、イメージを手動でノードにロードするだけです。
Docker イメージをビルドしたホストで、次のコマンドを実行してイメージをファイルに保存します。
$ docker save -o nginxplus.tar nginxplus
nginxplus.tar をノードに転送し、ノード上で次のコマンドを実行してファイルからイメージをロードします。
$ docker load -i nginxplus.tar
NGINX Plus コンテナの/etc/nginxフォルダには、NGINX Plus パッケージに付属するデフォルトのメインnginx.conf構成ファイルが保持されています。 デフォルト ファイルのinclude
ディレクティブは、 /etc/nginx/conf.dフォルダーから他の構成ファイルを読み取ります。 NGINX Plus レプリケーション コントローラーの宣言ファイル( nginxplus-rc.yaml ) で指定されているように、NGINX Plus ノード上の/etc/nginx/conf.dフォルダーをコンテナーと共有しています。 共有とは、コンテナ内にフォルダーを直接作成した場合には必要となる NGINX Plus Docker イメージを再構築することなく、フォルダー (ノード上) に保存されている構成ファイルを変更できることを意味します。 Kubernetes 固有の構成ファイル ( backend.conf ) を共有フォルダーに配置します。
まず、ノードに/etc/nginx/conf.dフォルダーを作成しましょう。
$ sudo mkdir -p /etc/nginx/conf.d
次に、そこにbackend.confファイルを作成し、次のディレクティブを含めます。
リゾルバ
– NGINX Plus がアップストリーム サーバーを識別するために使用するドメイン名を定期的に再解決するために使用する DNS サーバーを定義します (次の箇条書きで説明するアップストリーム
ブロック内のserver
ディレクティブ内)。 この DNS サーバーは、ドメイン名kube-dns.kube-system.svc.cluster.localで識別します。 有効な
パラメータは、NGINX Plus に 5 秒ごとに再解決リクエストを送信するように指示します。
(このディレクティブの解決プロセスはアップストリーム サーバーの解決プロセスとは異なることに注意してください。このドメイン名は NGINX が起動またはリロードされたときにのみ解決され、NGINX Plus は/etc/resolv.confファイルで定義されたシステム DNS サーバーまたはサーバーを使用して解決します。)
アップストリーム
– 公開する Kubernetes サービスを提供するサーバーを含めるために、バックエンドと呼ばれるアップストリーム グループを作成します。 サーバーを個別にリストするのではなく、単一のサーバー
ディレクティブで完全修飾ホスト名を使用してサーバーを識別します。 resolve
パラメータは、 resolver
ディレクティブで指定された設定に従って、実行時にホスト名を再解決するように NGINX Plus に指示します。
Kubernetes DNS と NGINX Plus (R10 以降) はどちらも DNS サービス ( SRV
) レコードをサポートしているため、NGINX Plus は DNS 経由でアップストリーム サーバーのポート番号を取得できます。 NGINX Plus にSRV
レコードを要求させるために、サービス
パラメータを追加し、サービスによって公開されるポートの名前 ( _http
) とプロトコル ( _tcp
) を指定します。 これらの値は、以下の「サービスのレプリケーション コントローラーの作成」で説明するwebapp-svc.yamlファイルで宣言します。
DNS を使用したサービス検出の詳細については、ブログの「NGINX および NGINX Plus でのサービス検出に DNS を使用する」を参照してください。
サーバー
(2回) – 2つの仮想サーバーを定義します。
最初のサーバーはポート 80 をリッスンし、サービス インスタンスを実行しているポッド間で/webapp (当社のサービス) への受信要求を負荷分散します。 アクティブヘルスチェックも設定しました。
2 番目のサーバーはポート 8080 でリッスンします。 ここでは、NGINX Plus のライブ アクティビティ モニタリングを設定します。 後でこれを使用して、NGINX Plus が適切に再構成されたことを確認します。
[編集者注 – この 2 番目のサーバーの構成は、 NGINX Plus API を使用するように更新されました。これにより、元々使用されていた個別のステータス モジュールが置き換えられ、非推奨になります。]
リゾルバー kube-dns.kube-system.svc.cluster.local valid=5s;
アップストリーム バックエンド {
ゾーン アップストリーム バックエンド 64k;
サーバー webapp-svc.default.svc.cluster.local service=_http._tcp 解決;
}
サーバー {
listen 80;
status_zone backend-servers;
location /webapp {
proxy_pass http://backend;
health_check;
}
}
サーバー {
listen 8080;
root /usr/share/nginx/html;
location = /dashboard.html { }
location = / {
return 302 /dashboard.html;
}
location /api {
api write=on;
}
}
これで、次のコマンドを実行してレプリケーション コントローラーを作成する準備が整いました。
$ kubectl 作成 -f nginxplus-rc.yaml
NGINX Plus ポッドが作成されたことを確認するには、次のコマンドを実行します。
$ kubectl get pods NAME READY STATUS RESTARTS AGE nginxplus-rc-0ts5t 1/1 実行中 0 17s
Kubernetes をローカル Vagrant セットアップで実行しているため、ノードの外部 IP アドレスは 10.245.1.3 であることがわかっており、この例の残りの部分ではそのアドレスを使用します。 クラウド プロバイダーで Kubernetes を実行している場合は、次のコマンドを実行してノードの外部 IP アドレスを取得できます。
$ kubectl get nodesノード名-o json | grep -i externalIP -A 1 "type": 「外部IP」、「アドレス」: XXX.XXX.XXX.XXX
クラウド上で実行している場合は、NGINX Plus ノードが着信トラフィックを受け入れるようにファイアウォール ルールを設定することを忘れないでください。 クラウド プロバイダーのドキュメントを参照してください。
NGINX Plus ポッドが稼働しているかどうかは、ノードの外部 IP アドレスのポート 8080 で利用可能な NGINX Plus ライブ アクティビティ監視ダッシュボード (この場合はhttp://10.245.1.3:8080/dashboard.html ) を確認することで確認できます。 ただし、この時点では、まだサービスを作成していないため、サービス用のサーバーが表示されません。
次に、Kubernetes サービスを作成します。 当社のサービスは 2 つの Web サーバーで構成されており、各サーバーは実行中のコンテナーに関する情報を含む Web ページを提供します。
まず、Kubernetes が指定された数の Web サーバー レプリカ (ポッド) が常にクラスター内で実行されていることを確認するために、レプリケーション コントローラーを作成します。 宣言ファイル ( webapp-rc.yaml ) は次のとおりです。
apiバージョン: v1種類: ReplicationController
メタデータ:
名前: webapp-rc
仕様:
レプリカ: 2
セレクタ:
アプリ: webapp
テンプレート:
メタデータ:
ラベル:
アプリ: webapp
仕様:
コンテナ:
- 名前: hello
イメージ: nginxdemos/hello
ポート:
- コンテナポート: 80
コントローラーは 2 つの Web サーバーで構成されています。 ポート 80 を公開する、単一のコンテナーを持つポッドで構成されるコントローラーを宣言します。 nginxdemos/helloイメージは Docker Hub から取得されます。
レプリケーション コントローラーを作成するには、次のコマンドを実行します。
$ kubectl 作成 -f webapp-rc.yaml
ポッドが作成されたことを確認するには、次のコマンドを実行します。 ラベル セレクターapp=webapp を
使用して、前の手順でレプリケーション コントローラーによって作成されたポッドのみを取得します。
$ kubectl get pods -l app=webapp名前 準備完了 ステータス 再起動 経過時間 webapp-rc-544f1 1/1 実行中 0 2m webapp-rc-uk6pm 1/1 実行中 0 2m
次に、レプリケーション コントローラーによって作成されたポッド用のサービスを作成します。 次のファイル ( webapp-service.yaml ) を使用してサービスを宣言します。
apiバージョン: v1種類: サービス
メタデータ:
名前: webapp-svc
仕様:
clusterIP: なし
ポート:
- ポート: 80
ターゲットポート: 80
プロトコル: TCP
名前: http
セレクタ:
アプリ: webapp
ここでは、 ClusterIP
フィールドをNone
に設定して、特別なヘッドレス サービスを宣言しています。 このタイプのサービスでは、クラスター IP アドレスは割り当てられず、kube プロキシ経由でサービスを利用することはできません。 Kubernetes DNS への DNS クエリは、複数のA
レコード (ポッドの IP アドレス) を返します。
また、NGINX Plus がポッドを接続するために使用するポートも宣言します。 ポートとターゲット ポート番号を指定するだけでなく、名前 ( http
) とプロトコル ( TCP
) も指定します。 これらの値は NGINX Plus 構成ファイルで使用し、NGINX Plus にSRV
レコードを使用して DNS 経由でポッドのポート番号を取得するように指示します。
セレクター
フィールドをapp:
webapp
に設定することで、どのポッドがサービスに属するか、つまり NGINX レプリケーション コントローラー ( webapp-rc.yamlで定義) によって作成されたポッドを宣言します。
次のコマンドを実行して、サービスを作成します。
$ kubectl 作成 -f webapp-service.yaml
ここで、ダッシュボード ページを更新し、右上隅の [ Upstreams]タブをクリックすると、追加した 2 つのサーバーが表示されます。
NGINX Plus がサービスのポッド間でトラフィックを負荷分散していることも確認できます。 そうであれば、ブラウザでhttp://10.245.1.3/webapp/にアクセスすると、ホスト名や IP アドレスなど、Web サーバーが実行されているコンテナーに関する情報がページに表示されます。
このページを数回更新してステータス ダッシュボードを見ると、リクエストが 2 つのアップストリーム サーバー間でどのように分散されているかがわかります。
[編集者 – このセクションは、元々使用されていた個別のステータス モジュールを置き換えて非推奨とするNGINX Plus API を使用するように更新されました。]
ここで、サービスにさらに 2 つのポッドを追加し、NGINX Plus 構成が再度自動的に更新されることを確認しましょう。 レプリケーション コントローラーをスケーリングしてポッドの数を 4 に変更するには、次のコマンドを実行します。
$ kubectl scale rc webapp-rc --replicas=4スケール
NGINX Plus が再構成されたことを確認するには、ダッシュボードを再度確認することもできますが、今回は代わりにNGINX Plus API を使用します。 次のコマンドを実行します。10.245.1.3
NGINX Plusノードの外部IPアドレスであり、3
NGINX Plus APIのバージョン。JSON 出力をきちんとフォーマットするには、それをjq
にパイプします。
$カール -s10.245.1.3 :8080/api/3 /http/upstreams/backend/servers | jq { "peers": [ { "id": 1、「サーバー」: "10.0.0.1:80", "バックアップ": false, "重み": 1、「状態」:「不健康」、「アクティブ」: 0、「リクエスト」: 1、「応答」:{「1xx」: 0、「2xx」: 0、「3xx」: 0、「4xx」: 0、「5xx」: 0、「合計」: 0 }, "送信済み": 0、「受信済み」: 0、「失敗」: 0、「利用不可」: 0, "health_checks": { "checks": 1、「失敗」: 1、「不健康」: 1, "last_passed": false }, "ダウンタイム": 33965、「ダウンスタート」: 1445378182275、「選択済み」: 1445378131000 }, { "id": 2、「サーバー」: "10.246.1.6:80"、... }、{ "id": 3、「サーバー」: "10.246.3.2:80"、... { "id": 4、「サーバー」: "10.0.0.2:80", ... } ], "キープアライブ": 0 }
JSON 出力のpeers
配列には、各 Web サーバーに 1 つずつ、合計 4 つの要素があります。
次に、ポッドの数を 4 から 1 に減らして、NGINX Plus のステータスを再度確認します。
$ kubectl scale rc webapp-rc --replicas=1スケール $ curl -s10.245.1.3 :8080/api/3 /http/upstreams/backend/servers | jq
これで、JSON 出力のpeers
配列には 1 つの要素のみが含まれます (出力は、前のサンプル コマンドの ID 1 のピアの場合と同じです)。
NGINX Plus が稼働したので、セッション永続性、 SSL/TLS 終了、リクエスト ルーティング、高度な監視などの高度な機能を活用し始めることができます。
NGINX Plus で利用可能なオンザフライ再構成オプションを使用すると、API 経由でプログラム的に、または DNS のみを使用して、簡単に Kubernetes と統合できます。 NGINX Plus を使用して Kubernetes サービスをインターネットに公開すると、現在の組み込み Kubernetes 負荷分散ソリューションに欠けている多くの機能が提供されます。
NGINX Plus が Kubernetes とどのように連携するかを確認するには、今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、ユースケースについてご相談ください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"