WebSocket のような持続的接続に依存するリアルタイムアプリケーションでは、NGINX Ingress のデフォルトのタイムアウト設定が原因で、予期せず接続が切断されることがあります。安定した接続を確保するには、Ingress のアノテーションを使用してタイムアウト値を大きく設定する必要があります。
コア設定
NGINX Ingress のデフォルトのプロキシタイムアウトは、短時間の HTTP リクエスト向けに設計されています。オンラインゲームやリアルタイムダッシュボードなど、WebSocket を使用するアプリケーション持続的接続をサポートするには、Ingress リソースで以下の Annotations を調整してタイムアウト値を変更します。これらのタイムアウトは、レスポンス/リクエスト全体の送受信時間ではなく、2 つの成功した読み取り/書き込み操作間の最大間隔を指定します。
nginx.ingress.kubernetes.io/proxy-read-timeout: バックエンドサービスからのレスポンスの読み取りタイムアウトを設定します。デフォルト値は 60 秒です。WebSocket Service の場合は、この値を 3600 (1 時間) 以上に設定することを推奨します。nginx.ingress.kubernetes.io/proxy-send-timeout: バックエンドサービスへのリクエストの送信タイムアウトを設定します。デフォルト値は 60 秒です。WebSocket Service の場合は、この値を 3600 (1 時間) 以上に設定することを推奨します。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
name: ws
spec:
ingressClassName: nginx
# ... Ingress spec の残りの部分ステップ 1: サンプル WebSocket アプリケーションのデプロイ
このトピックでは、デモンストレーションのためにシンプルな WebSocket echo サーバーを使用します。完全なコードについては、「websocket-echo-server」をご参照ください。
コンソール
[クラスター] ページで、対象のクラスターを見つけてその名前をクリックします。左側のナビゲーションウィンドウで、 を選択します。
[Deployment] ページで、[YAML から作成] をクリックします。次の内容をテンプレートエリアにコピーし、[作成] をクリックします。
表示されたダイアログボックスで、対象の Deployment を見つけて [表示] をクリックし、Pod が
Runningであることを確認します。
kubectl
次の内容で
websocket.yamlという名前のファイルを作成し、Deployment と Service を定義します。apiVersion: apps/v1 kind: Deployment metadata: labels: app: ws name: websocket-server namespace: default spec: replicas: 1 selector: matchLabels: app: ws template: metadata: labels: app: ws spec: containers: - image: registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/websocket-echo-server:latest imagePullPolicy: IfNotPresent name: echo env: - name: BIND_PORT value: "3000" ports: - containerPort: 3000 protocol: TCP resources: limits: cpu: 1000m memory: 1000Mi requests: cpu: 100m memory: 100Mi --- apiVersion: v1 kind: Service metadata: labels: app: ws name: websocket-server namespace: default spec: ports: - name: ws port: 3000 protocol: TCP targetPort: 3000 selector: app: ws type: ClusterIPWebSocket アプリケーションをデプロイし、Service を作成します。
kubectl apply -f websocket.yamlターゲットアプリケーションの Pod が
Runningであることを確認します。kubectl get pod | grep websocket-server
ステップ 2: Ingress 設定による Service の公開
Ingress の プロキシ送信タイムアウト と プロキシ読み取りタイムアウト のルールを設定します。
Container Service for Kubernetes (ACK) コンソールにログインし、対象のクラスターをクリックします。左側のナビゲーションウィンドウで、[アドオン] をクリックします。
検索ボックスに
Nginx Ingress Controllerと入力してコンポーネントを検索します。コンポーネントカードで、[インストール] をクリックします。v1.2 より前のバージョンのコンポーネントはメンテナンスされなくなりました。NGINX Ingress Controller を最新バージョンに更新してください。
Ingress ルーティングルールとタイムアウトアノテーションを設定します。
コンソール
左側のナビゲーションウィンドウで、 を選択します。
default名前空間を選択し、[Ingress の作成] をクリックします。次の設定で Ingress を構成し、[OK] をクリックします。
ゲートウェイタイプ:
Nginx Ingressを選択します名前:
wsドメイン名:
test.example.comマッピング
パス:
/ルール:
ImplementationSpecific (デフォルト値)サービス:
websocket-serverポート:
3000
アノテーション: 2 つのアノテーションを追加します。
[名前] を
nginx.ingress.kubernetes.io/proxy-read-timeoutに、[値] を3600に設定します。[名前] を
nginx.ingress.kubernetes.io/proxy-send-timeoutに、[値] を3600に設定します。
[Ingress] 一覧ページで、新しい Ingress の [エンドポイント] を取得します。
NGINX Ingress の設定が有効になるまで約 10 秒かかります。しばらく待ってから更新ボタンをクリックして、エンドポイント情報を取得してください。長時間経ってもエンドポイント情報が表示されない場合は、Ingress 名をクリックして [イベント] タブに移動し、「例外のトラブルシューティング」の指示に従ってください。
kubectl
websocket-ingress.yamlという名前のファイルを次の内容で作成します。test.example.comを実際のドメインに置き換えてください。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" # プロキシ読み取りタイムアウト: 3600 秒 nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" # プロキシ送信タイムアウト: 3600 秒 name: ws namespace: default spec: ingressClassName: nginx rules: - host: test.example.com # Service のアクセスドメイン名 http: paths: - backend: service: name: websocket-server # 前のステップで作成した Service の名前 port: number: 3000 # 前のステップで作成した Service の公開ポート path: / pathType: ImplementationSpecificIngress リソースをデプロイします。
kubectl apply -f websocket-ingress.yamlアクセス [エンドポイント] を取得します。IP が割り当てられるまで少し時間がかかる場合があります。アドレスが返されない場合は、10 秒待ってから再試行してください。
ADDRESS=$(kubectl get ingress ws -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo $ADDRESS
ステップ 3: WebSocket Service へのアクセス
テスト目的で、ローカルの hosts ファイルにエントリを追加して、ドメインを Ingress の IP アドレスにマッピングします。
macOS/Linux:
sudo vi /etc/hostsWindows: 管理者としてメモ帳を開き、
C:\Windows\System32\drivers\etc\hostsを開きます。
次のアドレスをアクセス [エンドポイント] に置き換えます。次のドメイン名マッピングレコードをファイルの末尾に追加して保存します。
47.102.XX.XX test.example.comwebsocat をインストールし、WebSocket (WS) または WebSocket Secure (WSS) プロトコルを使用して Service にアクセスします。
WS プロトコル
暗号化されていない WebSocket の場合:
websocat ws://test.example.com接続後、任意のテキストを入力して Enter キーを押します。サーバーが正常であれば、入力したテキストがそのまま返されます。

WSS プロトコル
暗号化された WebSocket を使用するには、まず NGINX Ingress Controller の HTTPS アクセスを有効にする必要があります。
SSL 証明書を取得します。
本番環境: 認証局 (CA) から有効な証明書を購入するか、Alibaba Cloud から購入します。
テスト環境: 自己署名証明書を生成します。
(オプション) Alibaba Cloud から証明書を購入した場合は、「SSL 証明書をダウンロードする」をご参照ください。
証明書と秘密鍵を保存するための Kubernetes Secret を作成します。
コンソール
ACK コンソールにログインします。左側のナビゲーションウィンドウで、[クラスター] をクリックします。
[クラスター] ページで、変更したいクラスターの名前をクリックします。左側のナビゲーションウィンドウで、 を選択します。
[Secret] ページで、
default名前空間を選択し、左上隅の [作成] をクリックします。表示されるパネルで、Secret を設定します。設定が完了したら、[OK] をクリックします。名前:
nginx-ingress-tlsタイプ: TLS 証明書
[追加] をクリックします
名前: 証明書ファイル (
.crtまたは.pem) の全内容値: 秘密鍵ファイル (
.key) の全内容
kubectl
<PUBLIC_CERT>と<PRIVATE_KEY>を、それぞれ証明書ファイル (.crtまたは.pem) と秘密鍵ファイル (.key) のパスに置き換えます。次に、コマンドを実行して証明書と秘密鍵を Secret として保存します。# --key フラグは秘密鍵ファイルを指定し、--cert フラグは証明書ファイルを指定します。 kubectl create secret tls nginx-ingress-tls --cert <PUBLIC_CERT> --key <PRIVATE_KEY>作成した Secret を参照するように Ingress を更新します。
コンソール
左側のナビゲーションウィンドウで を選択し、
default名前空間を選択します。対象の Ingress の [操作] 列で、[更新] をクリックします。Ingress を以下の設定で更新し、[OK] をクリックします。
TLS 設定: このオプションを有効にします。
ドメイン名:
test.example.comSecret:
nginx-ingress-tls
kubectl
wsIngress にtlsセクションを追加しwebsocket-ingress.yamlを更新します。ドメイン名:
test.example.com証明書Secret:
nginx-ingress-tls
kubectl patch ingress ws -p '{"spec":{"tls":[{"hosts":["test.example.com"],"secretName":"nginx-ingress-tls"}]}}'WSS プロトコルを使用して WebSocket Service に接続します。
Service が自己署名証明書を使用している場合は、
-kフラグを使用して証明書の検証をスキップします。websocat wss://test.example.com接続後、任意のテキストを入力して Enter キーを押します。サーバーが正常であれば、入力したテキストがそのまま返されます。

よくある質問
テスト用に自己署名証明書を生成するにはどうすればよいですか?
次のコマンドを実行して、有効期間 365 日のドメイン名 test.example.com の自己署名証明書 (ws.crt) と秘密鍵 (ws.key) を生成します:
openssl req -x509 -newkey rsa:2048 -keyout ws.key -out ws.crt -days 365 -nodes \
-subj "/CN=test.example.com" \
-addext "subjectAltName=DNS:test.example.com"自己署名証明書は、デフォルトではブラウザや他のクライアントから信頼されておらず、セキュリティ警告が表示されます。本番環境では自己署名証明書を使用しないでください。
SSL 証明書と TLS 証明書の違いは何ですか?
Secure Sockets Layer (SSL) は古い暗号化プロトコルであり、より安全な Transport Layer Security (TLS) プロトコルに置き換えられました。
現代の用語では、「SSL 証明書」は、技術的には「TLS 証明書」を指す俗称としてよく使われます。
関連ドキュメント
ACK のどのゲートウェイが WebSocket プロトコルをサポートしているかについては、「NGINX Ingress、ALB Ingress、および MSE Ingress の比較」をご参照ください。
持続的な WebSocket 接続を維持するには、カスタムのタイムアウトを設定する必要があります。カスタムタイムアウトアノテーションの詳細については、「カスタムタイムアウト」をご参照ください。