One of the ways a サービスメッシュをKubernetes環境でIngressコントローラーとは別に設定する必要がある場合、環境の管理がかえって複雑になることがあります。個別の設定は、単に時間がかかるだけではありません。適切なトラフィックルーティングを妨げる設定エラーが発生する可能性が高まり、悪意のある第三者がアクセス制限されたアプリに侵入するといったセキュリティ上の脆弱性や、許可されたアプリにお客さまがアクセスできないといったユーザー体験の低下につながることさえあります。個別の設定に時間がかかるだけでなく、エラーのトラブルシューティングにもさらに時間を費やすことになります。
これらの問題を回避して時間を節約するには、NGINX PlusベースのNGINX Ingress ControllerとNGINX Service Meshを統合し、受信と送信の両方のmTLSトラフィックを制御します。この動画デモでは、その手順を最初から最後までご紹介します。
関連ドキュメントについては、以下のセクションを参照してください。
- 前提条件
- NGINX Service Meshを使用したNGINX Ingress Controllerのデプロイ
- 標準のKubernetes Ingressリソースを使用してアプリを公開する
- NGINX VirtualServerリソースを使用したアプリの公開
- NGINX Ingress Controllerによるセキュアなエグレスルートの設定
前提条件(0:18)
実際のデモを開始する前に、以下の前提条件を満たしました。
- KubernetesクラスターにNGINX Server Meshコントロールプレーンをインストールし、サービスメッシュ用にmTLSと
strictポリシーを設定しました。 - Installed NGINX PlusベースのNGINX Ingress ControllerをKubernetesクラスターにDaemonSetではなくDeploymentとしてインストールし、egressを有効化して、タイプが
LoadBalancerのサービスとして公開しました。注:このデモは、NGINX Open SourceベースのNGINX Ingress Controllerでは動作しません。読みやすくするため、以降の本ブログでは、NGINX PlusベースのNGINX Ingress Controllerを単に「NGINX Ingress Controller」と表記します。 - F5の手順に従ってサンプル
bookinfoアプリをダウンロードし、NGINX Service Meshサイドカーを挿入して、アプリをデプロイしました。
ステップ1で作成したstrictポリシーにより、メッシュ外のクライアントからbookinfoアプリへのリクエストはサイドカーで拒否されます。デモでは、まず次のコマンドを実行してポートフォワーディングを設定し、この動作を示します。
> kubectl port-forward svc/product-page 9080Forwarding from 127.0.0.1:9080 -> 9080
Forwarding from [::1]:9080 -> 9080
Handling connection for 9080アプリにアクセスしようとすると、ローカルマシンがサービスメッシュに含まれていないため、ステータスコード 503 が返されます:
> curl localhost:9080503NGINX Service Meshを使用したNGINX Ingress Controllerのデプロイ(1:50)
アプリを公開するプロセスの最初の段階では、NGINX Ingress Controllerインスタンスをデプロイします。対応する手順については、チュートリアル「Deploy with NGINX Plus Ingress Controller for Kubernetes」をご覧ください。
この目的のために、NGINXではDeploymentとDaemonSetの両方のマニフェストを提供しています。このデモでは、Deploymentマニフェストの「nginx-plus-ingress.yaml」を使用します。このマニフェストには、受信トラフィックと送信トラフィックの両方を同じNGINX Ingress Controllerインスタンス経由でルーティングするためのアノテーションが含まれています。
コード例を読み込み中…
このマニフェストにより、NGINX Ingress ControllerをNGINX Service Meshの認証局(CA)であるSpireと直接統合できるため、NGINX Service MeshサイドカーをNGINX Ingress Controllerに挿入する必要がなくなります。代わりに、NGINX Ingress ControllerはSpire CAから証明書と鍵を直接取得し、メッシュ内のPodとのmTLSに使用します。このマニフェストでは、Spireエージェントのアドレスを指定します。
コード例を読み込み中…
さらに、SpireエージェントのUNIXソケットをNGINX Ingress Controllerポッドにマウントします。
コード例を読み込み中…
マニフェストについて最後に注目すべき点は、-enable-internal-routes CLI引数です。この引数により、egressサービスへのルーティングが可能になります。
コード例を読み込み中…
デモを開始する前に、kubectl apply -f nginx-plus-ingress.yamlコマンドを実行してNGINX Ingress Controllerをインストールしました。ここでは、nginx-ingress名前空間のデプロイを確認します。以下の出力のREADY列に示すように、NGINX Ingress ControllerポッドにはNGINX Service Meshサイドカーを挿入していないため、コンテナは1つだけです。
また、NGINX Ingress Controllerの外部IPアドレス(ここでは35.233.133.188)をクラスター外に公開するため、タイプがLoadBalancerのサービスもデプロイしました。このIPアドレスを使用して、サンプルbookinfoアプリケーションにアクセスします。
> kubectl get pods --namespace=nginx-ingressNAME READY STATUS RESTARTS AGE
pod/nginx-ingress-867f954b8f0fzdrm 1/1 Running 0 3d3h
NAME TYPE CLUSTER-IP EXTERNAL-IP ...
service-nginx-ingress LoadBalancer 10.31.245.207 35.233.133.188 ...
... PORT(S) AGE
... 80:31469/TCP,443:32481/TCP 4d2h
...標準のKubernetes Ingressリソースを使用してアプリを公開する(3:55)
次に、メッシュ内の「bookinfo」アプリを公開します。これには、bookinfo-ingress.yamlで定義されている標準のKubernetes Ingressリソースを使用します。対応する手順については、チュートリアル「NGINX Plus Ingress Controllerを使用したアプリケーションの公開」をご覧ください。
コード例を読み込み中…
このリソースは、10行目でbookinfoアプリのKubernetes Secretを参照し、bookinfo.example.comへのリクエストをproductpageサービスに送信するよう指定したルーティングルール(11~18行目)を含みます。このSecretはbookinfo-secret.yamlで定義されています。
コード例を読み込み中…
次のコマンドを実行して、キーと証明書を読み込みます。デモでは自己署名証明書を使用します。
> kubectl apply -f bookinfo-secret.yamlsecret/bookinfo-secret unchangedIngressリソースを有効化します:
> kubectl apply -f bookinfo-ingress.yamlingress.networking.k8s.io/bookinfo-ingress deleted出力の末尾にあるイベントを確認し、Ingress Controllerがリソースで定義されたルートを追加したことを検証します。
> kubectl describe ingress bookinfo-ingress...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 5s nginx-ingress-controller Configuration for ...
...default/bookinfo-ingress was added or updatedこのデモでは、ブラウザーを使用して、bookinfoアプリ(https://bookinfo.example.com/)にアクセスします。(前述のとおり、ローカルの/etc/hostsファイルには、Ingress ControllerサービスのIPアドレス(このデモでは35.233.133.188)とbookinfo.example.comのマッピングをあらかじめ追加しています。手順については、ドキュメントを参照してください。)ページのBook Reviewsセクションに表示される情報は、リクエストがbookinfo.yamlで定義されたreviewsサービスの3つのバージョンに順番に振り分けられるため、定期的に変わります(ダウンロード)。
次に、クラスターへの受信トラフィックを調査します。generate-traffic.shスクリプトを実行し、NGINX Ingress ControllerのパブリックIPアドレス経由でproductpageサービスにリクエストを送信します。その後、nginx-meshctlのtopコマンドを実行してトラフィックを監視します。
> nginxmesh-ctl top deploy/productpage-v1Deployment Direction Resource Success Rate P99 P90 P50 ...
productpage-v1
To details-v1 100.00% 3ms 3ms 2ms
To reviews-v2 100.00% 99ms 90ms 20ms
To reviews-v3 100.00% 99ms 85ms 18ms
To reviews-v1 100.00% 20ms 17ms 9ms
From nginx-ingress 100.00% 192ms 120ms 38ms
... NumRequests
... 14
... 5
... 5
... 12NGINX VirtualServerリソースを使用してアプリを公開する(6:45)
次に、アプリを公開する別の方法として、NGINX VirtualServerリソースを使用する方法を紹介します。これはNGINX Ingress Controllerのカスタムリソースで、トラフィック分割やコンテンツベースルーティングなど、より複雑なトラフィック処理をサポートします。
まず、標準のIngressリソースを削除します。
> kubectl delete -f bookinfo-ingress.yamlingress.networking.k8s.io "bookinfo-ingress" deletedbookinfo-vs.yamlファイルでは、bookinfo-ingress.yamlと同じSecretを使用してmTLSを構成しています(7~8行目)。9~12行目では、productpageサービスをアップストリームとして定義し、13~24行目では、GETメソッドでbookinfo.example.comに送信されたすべてのリクエストをそのアップストリームに転送するルートを定義しています。GET以外のHTTPメソッドに対しては、ステータスコード405を返します。
コード例を読み込み中…
リソースを適用します。
> kubectl apply -f bookinfo-vs.yamlvirtualserver.kubernetes.nginx.org/bookinfo-vs created次に、Ingressリソースの場合と同じ手順を実行します。つまり、kubectl describeコマンドを実行して正しくデプロイされていることを確認し、ブラウザーでアプリにアクセスします。アプリが正常に動作していることは、POSTメソッドが拒否されることでも確認できます。
> curl -k -X POST https://bookinfo.example.com/Method not allowedNGINX Ingress Controllerを使用したセキュアなエグレスルートの構成(8:44)
ここでは、NGINX Ingress Controllerを介してエグレストラフィックをルーティングする方法を説明します。チュートリアル「NGINX Plus Ingress Controllerを使用したセキュアなエグレスルートの構成」では、別のサンプルアプリを使用して、その手順を解説しています。
シンプルなbash Podをbash.yamlですでに定義し、リクエストの送信元となるdefault名前空間にデプロイしています。この出力のREADY列に示されているように、NGINX Service Meshサイドカーが挿入されています。
> kubectl get allNAME READY STATUS RESTARTS AGE
pod/bash-6ccb678958-zsgm7 2/2 Running 0 77s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.31.240.1 <none> 443/TCP 4d2h
...Pod内から、NGINX Service Meshに含まれないエンティティであるエグレスサービスへのリクエストを有効にするユースケースはいくつかあります。たとえば、次の場所にデプロイされたサービスです。
- クラスター外
- 別のクラスター上
- 同じクラスター上にあるが、NGINX Service Meshサイドカーがインジェクトされていない
このデモでは、最後のユースケースについて説明します。アプリケーションはlegacy名前空間にデプロイされています。この名前空間はNGINX Service Meshの制御下になく、NGINX Service Meshサイドカーの自動インジェクションも無効になっています。このアプリケーションでは、1つのPodのみが稼働しています。
> kubectl get all --namespaces=legacyNAME READY STATUS RESTARTS AGE
pod/target-5f7bcb96c6-km9lz 1/1 Running 0 27m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/target-svc ClusterIP 10.31.245.213 <none> 80/TCP,443/TCP 27m
...NGINX Service Meshにはstrict mTLSポリシーが設定されているため、bash Podからターゲットサービスにリクエストを直接送信できないことに注意してください。両者間で相互に認証できないためです。送信を試みると、次に示すようにステータスコード503が返されます。
> kubectl exec -it bash-6ccb678958-zsgm7 -c bash -- curl target-svc.legacycurl: (56) Recv failure: connection reset by peer
503command terminated with exit code 56解決するには、bash PodがNGINX Ingress Controller経由で外向きトラフィックを送信できるようにします。bash.yamlの14~15行目にあるアノテーションのコメントを解除します。
コード例を読み込み中…
次に、新しい設定を適用します。
> kubectl apply -f bash.yamldeployment.apps/bash configured新しいbash Podが起動したことを確認します:
> kubectl get podsNAME READY STATUS RESTARTS AGE
bash-678c8b4579-7sfml 2/2 Running 0 6s
bash-6ccb678958-zsgm7 2/2 Terminating 0 3m28sここで、前と同じkubectl execコマンドを実行し、bash Podからターゲットサービスにリクエストを送信すると、ステータスコードは503ではなく404になります。これは、bash PodからNGINX Ingress Controllerへのリクエスト送信には成功したものの、ルートが定義されていないため、NGINX Ingress Controllerが転送先を特定できないことを示しています。
legacy-route.yamlに次のIngressリソース定義を記述し、必要なルートを作成します。7行目の「internal-route」アノテーションは、ターゲットサービスがインターネットには公開されず、NGINX Service Mesh内のワークロードにのみ公開されることを意味します。
コード例を読み込み中…
新しいリソースを有効化し、NGINX Ingress Controllerがそのリソースで定義されたルートを追加したことを確認します。
> kubectl apply -f legacy-route.yamlingress.networking.k8s.io/target-internal-route created
> kubectl describe ingress target-internal-route -n legacy
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 6s nginx-ingress-controller Configuration for ...
...legacy/target-internal-route was added or updatedここで、kubectl execコマンドを実行すると、ターゲットサービスに到達できます。
{"req": {"method": "GET" "url": "/",
"host": "target-svc.legacy",
"remoteAddr": "10.28.2.76:56086"}}送信トラフィックをNGINX Ingress Controller経由でルーティングする利点は、クラスター内からアクセスできる外部サービスを厳密に制御できることです。アクセスできるのは、ルートを定義したサービスだけです。
デモの最後に、エグレス・トラフィックを監視する方法をご紹介します。まず、kubectl execコマンドを実行して複数のリクエストを送信し、次に以下のコマンドを実行します。
> nginxmesh-ctl top deploy/nginx-ingress -n nginx-ingressDeployment Direction Resource Success Rate P99 P90 P50 NumRequests
nginx-ingress
To target 100.00% 1ms 1ms 1ms 9
From bash 100.00% 0ms 0ms 0ms 9レイテンシーに「ノー」を — NGINX Service MeshとNGINX Ingress Controllerをお試しください
多くのサービスメッシュには、イングレスゲートウェイとエグレスゲートウェイのオプションがありますが、NGINXとの統合には、レイテンシーを低減できるというメリットもあります。ほとんどのメッシュでは、Ingressコントローラーにサイドカーを挿入する必要があるため、アプリケーションに到達するまでのトラフィックに余分なホップが発生します。わずかな遅延も重要です。この余分なホップによってデジタルエクスペリエンスが低下すると、顧客が他社のサービスを選ぶ可能性があります。NGINX Service Meshは、NGINX Ingress Controllerにサイドカーを挿入しないため、不要なレイテンシーを追加しません。代わりに、メッシュのCAであるSpireと直接統合することで、NGINX Ingress ControllerがNGINX Service Meshの一部になります。NGINX Ingress ControllerはSpireエージェントから証明書と鍵を取得し、それらを使用して、メッシュ化されたPodとのmTLS証明書交換に参加します。
NGINX Ingress Controller for Kubernetesには、NGINX Open SourceとNGINX Plusの2つのバージョンがあります。このブログで説明しているように、NGINX Ingress ControllerをNGINX Service Meshとともにデプロイするには、NGINX Plusバージョンを使用する必要があります。NGINX Plusは、30日間無料でお試しいただけます。
NGINX Service Meshは完全無料で、今すぐダウンロードできます。導入は10分未満で完了します。まずはドキュメントをご覧いただき、使用した感想をGitHubでお聞かせください。
関連するブログ記事
チュートリアル: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グループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります