Kubernetesは、コンテナ化されたマイクロサービスベースのアプリケーションをクラスター内で実行、管理するためにGoogleが開発したオープンソースシステムです。Kubernetesのユーザーは、Kubernetesで作成したサービスにKubernetesクラスターの外部からアクセスできるようにする必要がしばしばあります。
Although Kubernetesには、以下の「Kubernetesの組み込みソリューションによるサービスの公開」で説明するサービス公開用の組み込みソリューションがありますが、利用できるのはレイヤー4ロードバランシングまたはラウンドロビン方式のHTTPロードバランシングに限られます。
この記事では、NGINX Plusを高度なレイヤー7ロードバランシングソリューションとして使用し、クラウドと自社インフラストラクチャのどちらでKubernetesを実行している場合でも、Kubernetesサービスをインターネットに公開する方法を説明します。
Kubernetes(Pod、Service、ReplicationController、ラベル)に関する基本的な知識があり、Kubernetesクラスターが稼働していることを前提とします。Kubernetesの詳細については、公式の「Kubernetesユーザーガイド」をご覧ください。
組み込みソリューションによるKubernetesサービスの公開
Kubernetesには、サービスを外部に公開するためのオプションが複数用意されています。そのうちNodePortとLoadBalancerは、それぞれ特定のサービスタイプに対応します。3つ目のオプションであるIngress APIは、Kubernetes 1.1でベータ版として利用可能になりました。
NodePort
サービスタイプに「NodePort」を指定すると、各Kubernetesノードの同じポートでサービスを利用できるようになります。サービスをインターネットに公開するには、そのポートで1つ以上のノードを公開します。高可用性を確保するには、複数のノードを公開し、DNSベースの負荷分散を使用してノード間でトラフィックを分散するか、任意のロードバランサーの背後にノードを配置します。
受信トラフィックがそのポートでノードに到達すると、サービスのPod間で負荷分散されます。各ノードで実行されるKubernetesネットワークプロキシ(kube-proxy)による負荷分散は、TCP/UDP負荷分散に限定されます。
LoadBalancer
サービスタイプに「LoadBalancer」を指定すると、受信トラフィックをサービスのPod間で分散するクラウドロードバランサーが割り当てられます。
LoadBalancerソリューションをサポートしているのは、一部のクラウドプロバイダーとGoogle Container Engineのみです。独自のインフラストラクチャでKubernetesを実行している場合は利用できません。また、クラウドロードバランサーにセッション維持やリクエストマッピングなどの高度な機能が備わっていても、Kubernetesで構成できるのはラウンドロビン方式のTCPロードバランシングのみです。
Ingress API
Creating an Ingressリソースを作成すると、カスタムURL(たとえば、サービスAにはURL「/foo」、サービスBにはURL「/bar」)と複数の仮想ホスト名(たとえば、あるサービスグループには「foo.example.com」、別のサービスグループには「bar.example.com」)を使用して、サービスをインターネットに公開できます。IngressコントローラーはIngressリソースを取り込み、外部ロードバランサーを設定します。
Ingressコントローラーは、標準のKubernetesデプロイには含まれていません。ニーズに最適なコントローラーを選択するか、独自に実装してKubernetesクラスターに追加する必要があります。近いうちに多くのコントローラー実装が登場すると見込まれますが、現時点で利用できる唯一の実装は、Google Compute Engine HTTP Load Balancer用コントローラーです。このコントローラーは、KubernetesをGoogle Compute EngineまたはGoogle Container Engineで実行している場合にのみ動作します。実際のロードバランサーが高度な機能をサポートしている場合でも、Ingress APIがサポートするのはラウンドロビン方式のHTTP負荷分散のみです。
本稿執筆時点では、Ingress APIとGoogle Compute Engine HTTP Load Balancer用コントローラーはいずれもベータ版です。
更新情報 – NGINXとNGINX Plusの両方に対応するNGINX Ingress Controllerが、F5のGitHubリポジトリで利用できるようになりました。製品の詳細については、NGINX Ingress Controllerをご覧ください。
前述のソリューションは簡単にセットアップでき、すぐに使用できますが、高度な機能、特にレイヤー7の負荷分散に関する機能は提供していません。
NGINX PlusによるKubernetesサービスの公開
[編集者注 – このセクションは、当初ここで説明していた独立した動的構成モジュールを置き換え、非推奨とするNGINX Plus APIについて記載するよう更新されています。]
NGINX PlusをKubernetesと統合するには、NGINX Plusの設定をKubernetesと常に同期し、ポッドの追加や削除など、Kubernetesサービスへの変更が反映されるようにする必要があります。NGINX Open Sourceでは、NGINX設定ファイルを手動で変更し、設定を再読み込みします。NGINX Plusでは、設定を動的に更新する方法が2つあります。
- APIを使用する方法 – この方法では、NGINX Plus APIを使用してNGINX Plusの設定にKubernetes Podのエントリを追加または削除し、Kubernetes APIを使用してPodのIPアドレスを取得します。この方法ではコードを記述する必要があるため、ここでは詳しく説明しません。詳細については、Kelsey Hightowerのウェビナー「NGINX PlusでKubernetesをエッジへ」をご覧ください。このウェビナーでは、APIについて解説し、それらを利用するアプリケーションを作成しています。
- By DNS名の再解決による方法 – この方法では、次のセクションで説明するように、NGINX Plusを一度適切に設定するだけで済みます。
DNSベースの再構成の利用
すでに稼働中のKubernetesクラスターと、そのクラスターを管理するためのkubectlユーティリティを使用できるホストがあることを前提としています。手順については、お使いのクラスタタイプに対応する「Kubernetes入門ガイド」を参照してください。また、NGINX PlusのDockerイメージをビルドしておく必要があります。手順については、F5のブログ記事「DockerによるNGINXおよびNGINX Plusのデプロイ」を参照してください。
実施する内容の概要は次のとおりです。
- NGINX Plusポッドを構成し、ステップ2で作成するサービスを公開して負荷分散します。
- サービスとして使用するシンプルなWebアプリケーションを作成します。
- サービスをスケールアップ/スケールダウンし、NGINX Plusが自動的に再構成される様子を確認します。
注:このブログで説明するソリューションは、Google Compute Engine上で稼働するKubernetes 1.0.6とローカルのVagrant環境でテストしました。以下では、このローカル環境を使用します。
コマンド内では、Kubernetes環境によって異なる可能性がある値を斜体で示しています。
NGINX Plus Podの設定
インターネットに公開するノード上のKubernetes PodにNGINX Plusを配置します。このPodは、併せて設定するレプリケーションコントローラーによって作成されます。Kubernetes固有のNGINX Plus設定ファイルは、NGINX Plus Podとノードで共有するフォルダーに配置するため、メンテナンスが容易になります。
NGINX Plus Podをホストするノードの選択
NGINX Plus Podを実行するノードを指定するには、そのノードにラベルを追加します。すべてのノードの一覧を取得するには、次のコマンドを実行します。
$ kubectl get nodesNAME LABELS STATUS
10.245.1.3 Kubernetes.io/hostname=10.245.1.3 Ready
10.245.1.4 Kubernetes.io/hostname=10.245.1.4 Ready
10.245.1.5 Kubernetes.io/hostname=10.245.1.5 Ready最初のノードを選択し、次のコマンドを実行してラベルを追加します。
$ kubectl label node 10.245.1.3 role=nginxplusNGINX Plus Pod用レプリケーションコントローラーの構成
NGINX Plus Podは直接作成せず、レプリケーションコントローラーを介して作成します。NGINX Plus Pod用のレプリケーションコントローラーは、Kubernetes宣言ファイル「nginxplus-rc.yaml」で構成します。
- We set the number of
replicasの数を1に設定します。これにより、KubernetesはNGINX Plusポッドが常に1つ稼働するようにします。ポッドに障害が発生した場合は、新しいポッドに置き換えられます。 - In the
nodeSelectorフィールドでは、NGINX Plus Podが次のラベルを持つノード上に作成されるよう指定します:role:nginxplus。 - NGINX Plusコンテナでは80と8080の2つのポートを公開し、それぞれをノード上のポート80と8080にマッピングします。
- また、NGINX Plusコンテナは、ノード上の「/etc/nginx/conf.d」フォルダーも共有します。以下の「NGINX Plusの設定」で詳しく説明するように、このフォルダーを共有することで、コンテナイメージを再ビルドせずにNGINX Plusを再設定できます。
apiVersion: v1
kind: ReplicationController
metadata:
name: nginxplus-rc
spec:
replicas: 1
selector:
app: nginxplus
template:
metadata:
labels:
app: nginxplus
spec:
nodeSelector:
role: nginxplus
containers:
- name: nginxplus
imagePullPolicy: IfNotPresent
image: nginxplus
ports:
- name: http
containerPort: 80
hostPort: 80
- name: http-alt
containerPort: 8080
hostPort: 8080
volumeMounts:
- mountPath: "/etc/nginx/conf.d"
name: etc-nginx-confd
volumes:
- hostPath:
path: "/etc/nginx/conf.d"
name: etc-nginx-confdNGINX Plus Dockerイメージをノードで利用可能にする
前述のとおり、NGINX Plus Dockerイメージはすでにビルド済みです。次に、このイメージをノードで使用できるようにします。ここでは簡略化のため、プライベートDockerリポジトリは使用せず、イメージをノードに手動でロードします。
Dockerイメージをビルドしたホストで、次のコマンドを実行してイメージをファイルに保存します。
$ docker save -o nginxplus.tar nginxplusWe transfer nginxplus.tarをノードに転送し、ノード上で次のコマンドを実行してファイルからイメージを読み込みます。
$ docker load -i nginxplus.tarNGINX Plusの設定
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ファイルを作成し、以下のディレクティブを記述します。
resolver– NGINX Plusがアップストリームサーバーの識別に使用するドメイン名を定期的に再解決するためのDNSサーバーを定義します(次の箇条書きで説明する、serverディレクティブ内のupstreamブロック)。このDNSサーバーは、ドメイン名kube-dns.kube-system.svc.cluster.localで指定します。validパラメーターは、NGINX Plusが5秒ごとに再解決リクエストを送信するよう指定します。(このディレクティブの名前解決プロセスは、アップストリームサーバーのものとは異なります。このドメイン名はNGINXの起動時または再読み込み時にのみ解決され、NGINX Plusは/etc/resolv.confファイルで定義されたシステムDNSサーバーを使用して名前解決します。)upstream– 公開するKubernetesサービスを提供するサーバーを格納する、backendという名前のアップストリームグループを作成します。サーバーを個別に列挙する代わりに、1つのserverディレクティブで完全修飾ホスト名を使用してサーバーを指定します。resolveパラメーターは、resolverディレクティブで指定された設定に従って、実行時にホスト名を再解決するようNGINX Plusに指示します。Kubernetes DNSとNGINX Plus(R10以降)はどちらもDNSサービス(SRV)レコードをサポートしているため、NGINX PlusはDNS経由でアップストリームサーバーのポート番号を取得できます。serviceパラメーターを指定して、NGINX PlusがSRVレコードを要求するようにし、サービスが公開するポートの名前(_http)とプロトコル(_tcp)を指定します。これらの値は、以下の「webapp-svc.yaml」ファイルについて説明する「サービス用レプリケーションコントローラーの作成」で宣言します。DNSを使用したサービスディスカバリの詳細については、F5のブログ記事「NGINXおよびNGINX PlusでDNSを使用したサービスディスカバリ」をご覧ください。server(2回)– 2つの仮想サーバーを定義します:- 1つ目のサーバーはポート80でリッスンし、/webapp(このサービス)への受信リクエストを、サービスインスタンスを実行しているPod間で負荷分散します。また、アクティブヘルスチェックも設定します。
- 2台目のサーバーはポート8080でリッスンします。ここでは、ライブアクティビティ監視をNGINX Plusに設定します。後ほど、NGINX Plusが正しく再構成されたことを確認するために使用します。[編集者注:この2台目のサーバーの構成は、従来使用していた個別のステータスモジュールに代わるNGINX Plus APIを使用するよう更新されています。これに伴い、従来のステータスモジュールは非推奨となりました。]
resolver kube-dns.kube-system.svc.cluster.local valid=5s;
upstream backend {
zone upstream-backend 64k;
server webapp-svc.default.svc.cluster.local service=_http._tcp resolve;
}
server {
listen 80;
status_zone backend-servers;
location /webapp {
proxy_pass http://backend;
health_check;
}
}
server {
listen 8080;
root /usr/share/nginx/html;
location = /dashboard.html { }
location = / {
return 302 /dashboard.html;
}
location /api {
api write=on;
}
}レプリケーションコントローラーの作成
これで準備が整いました。次のコマンドを実行してレプリケーションコントローラーを作成します。
$ kubectl create -f nginxplus-rc.yamlNGINX Plus Podが作成されたことを確認するため、次のコマンドを実行します。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginxplus-rc-0ts5t 1/1 Running 0 17sここでは、ローカルのVagrant環境でKubernetesを実行しているため、ノードの外部IPアドレスが10.245.1.3であることがわかっています。以降の例では、このアドレスを使用します。クラウドプロバイダー上でKubernetesを実行している場合は、次のコマンドを実行してノードの外部IPアドレスを取得できます。
$ kubectl get nodes node-name -o json | grep -i externalIP -A 1 "type": "ExternalIP",
"address": XXX.XXX.XXX.XXXクラウド上で実行している場合は、NGINX Plusノードが受信トラフィックを受け入れられるように、ファイアウォールルールを必ず設定してください。詳しくは、クラウドプロバイダーのドキュメントを参照してください。
ノードの外部IPアドレスのポート8080で利用できるNGINX Plusライブアクティビティ監視ダッシュボード(この例ではhttp://10.245.1.3:8080/dashboard.html)を表示すると、NGINX Plus Podが稼働していることを確認できます。ただし、この時点ではまだサービスを作成していないため、そのサービスのサーバーは表示されません。

シンプルなKubernetesサービスの作成
次に、Kubernetesサービスを作成します。このサービスは2台のWebサーバーで構成され、それぞれが稼働しているコンテナに関する情報を掲載したWebページを配信します。
サービス用Replication Controllerの作成
まず、指定した数のWebサーバーレプリカ(Pod)がクラスター内で常に稼働するように、レプリケーションコントローラーを作成します。宣言ファイル(webapp-rc.yaml)は次のとおりです。
apiVersion: v1kind: ReplicationController
metadata:
name: webapp-rc
spec:
replicas: 2
selector:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: hello
image: nginxdemos/hello
ports:
- containerPort: 80このコントローラーは2台のWebサーバーで構成されます。ポート80を公開する単一コンテナのPodで構成されたコントローラーを宣言します。nginxdemos/helloイメージはDocker Hubからプルされます。
レプリケーションコントローラーを作成するには、次のコマンドを実行します。
$ kubectl create -f webapp-rc.yamlPodが作成されたことを確認するには、次のコマンドを実行します。ラベルセレクターapp=webappを使用して、前の手順でレプリケーションコントローラーによって作成されたPodのみを取得します。
$ kubectl get pods -l app=webapp
NAME READY STATUS RESTARTS AGE
webapp-rc-544f1 1/1 Running 0 2m
webapp-rc-uk6pm 1/1 Running 0 2mServiceの作成
次に、レプリケーションコントローラーによって作成されたPod用のサービスを作成します。以下のファイル(webapp-service.yaml)でサービスを定義します。
apiVersion: v1kind: Service
metadata:
name: webapp-svc
spec:
clusterIP: None
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: webappここでは、ヘッドレスサービスという特殊なサービスを宣言するために、ClusterIPフィールドをNoneに設定しています。このタイプのサービスにはクラスターIPアドレスが割り当てられず、kube-proxy経由では利用できません。Kubernetes DNSにDNSクエリを送信すると、複数のAレコード(PodのIPアドレス)が返されます。
さらに、NGINX PlusがPodへの接続に使用するポートも宣言します。ポート番号とターゲットポート番号に加えて、名前(http)とプロトコル(TCP)を指定します。これらの値はNGINX Plusの設定ファイルで使用し、NGINX PlusがSRVレコードを使用してDNS経由でPodのポート番号を取得するように設定します。
By setting the selectorフィールドをapp: webappに設定することで、サービスに属するポッドを指定します。ここでは、NGINXレプリケーションコントローラー(webapp-rc.yamlで定義)によって作成されたポッドを指定しています。
次のコマンドを実行して、サービスを作成します。
$ kubectl create -f webapp-service.yamlここでダッシュボードページを更新し、右上隅にある[Upstreams]タブをクリックすると、追加した2台のサーバーが表示されます。

NGINX PlusがサービスのPod間でトラフィックを負荷分散していることも確認できます。負荷分散が機能している場合、ブラウザーで「http://10.245.1.3/webapp/」にアクセスすると、ホスト名やIPアドレスなど、Webサーバーが稼働しているコンテナの情報がページに表示されます。
このページを数回更新してステータスダッシュボードを確認すると、リクエストが2台のアップストリームサーバーにどのように分散されるかを確認できます。
Kubernetes Serviceのスケーリング
[編集者注 – このセクションは、当初使用されていた個別のステータスモジュールに代わり、同モジュールを非推奨とするNGINX Plus APIを使用するよう更新されています。]
次に、サービスにPodを2つ追加し、NGINX Plusの設定が再び自動的に更新されることを確認します。次のコマンドを実行してレプリケーションコントローラーをスケールし、Podの数を4つに変更します。
$ kubectl scale rc webapp-rc --replicas=4
scaledNGINX Plusが再構成されたことを確認するには、再度ダッシュボードを参照することもできますが、今回は代わりにNGINX Plus APIを使用します。次のコマンドを実行します。ここで、10.245.1.3はNGINX Plusノードの外部IPアドレス、3はNGINX Plus APIのバージョンです。JSON出力を見やすく整形するため、出力をjqにパイプします。
$ curl -s 10.245.1.3:8080/api/3/http/upstreams/backend/servers | jq{
"peers": [
{
"id": 1,
"server": "10.0.0.1:80",
"backup": false,
"weight": 1,
"state": "unhealthy",
"active": 0,
"requests": 1,
"responses": {
"1xx": 0,
"2xx": 0,
"3xx": 0,
"4xx": 0,
"5xx": 0,
"total": 0
},
"sent": 0,
"received": 0,
"fails": 0,
"unavail": 0,
"health_checks": {
"checks": 1,
"fails": 1,
"unhealthy": 1,
"last_passed": false
},
"downtime": 33965,
"downstart": 1445378182275,
"selected": 1445378131000
},
{
"id": 2,
"server": "10.246.1.6:80",
...
},
{
"id": 3,
"server": "10.246.3.2:80",
...
{
"id": 4,
"server": "10.0.0.2:80",
...
}
],
"keepalive": 0
}JSON出力のpeers配列には、各Webサーバーに対応する要素が1つずつ、合計4つ含まれています。
次に、Podの数を4つから1つに減らし、NGINX Plusのステータスをもう一度確認します。
$ kubectl scale rc webapp-rc --replicas=1scaled
$ curl -s 10.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日間の無料トライアルを今すぐ開始するか、お問い合わせのうえ、お客さまのユースケースについてご相談ください。
関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります