Service Mesh (ASM) インスタンスのデータプレーン上の Kubernetes クラスターが、イングレスゲートウェイに対して externalTrafficPolicy: Local を設定したクラシックロードバランサー (CLB) を使用している場合、一部のノード上の Pod が CLB IP アドレスに到達できないことがあります。このトピックでは、その原因と 3 つのソリューションについて説明します。
現象
Kubernetes クラスターが ASM インスタンスに追加されます。イングレスゲートウェイには、externalTrafficPolicy が Local に設定された CLB インスタンスが構成されています。以下の動作が確認されます。
一部のノード上の Pod は、イングレスゲートウェイの CLB IP アドレスにアクセスできます。
その他のノード上の Pod は、同じ CLB IP アドレスにアクセスできません。
原因
externalTrafficPolicy が Local の場合、kube-proxy はイングレスゲートウェイサービスのバックエンド Pod を実行するノード上でのみ、iptables または IP Virtual Server (IPVS) の転送ルールをプログラムします。イングレスゲートウェイの Pod がないノードには転送ルールが存在しないため、CLB IP アドレスへのトラフィックは破棄されます。
CLB IP アドレスは、サービスの外部 IP として扱われます。kube-proxy は、トラフィックをロードバランサーにルーティングして戻すのではなく、ローカルの iptables または IPVS ルールを介してリクエストをショートサーキットします。externalTrafficPolicy: Local を使用すると、ローカルエンドポイントを持つノードのみがこれらのルールを取得します。
アップストリームの Kubernetes での議論については、Why kube-proxy add external-lb's address to node local iptables rule? をご参照ください。
問題の確認
修正を適用する前に、この根本原因がご自身の状況に当てはまるかを確認してください。
イングレスゲートウェイの Pod が実行されているノードを確認します。NODE 列に注目してください。これらのノード上の Pod は CLB IP にアクセスできます。他のノード上の Pod はアクセスできません。
kubectl get pods -n istio-system -l app=istio-ingressgateway -o wideイングレスゲートウェイサービスのエンドポイントを確認します。リストされている IP アドレスは、イングレスゲートウェイの Pod に対応しています。これらの Pod がないノードには、CLB IP に到達するために必要なローカル転送ルールがありません。
kubectl get endpoints -n istio-system istio-ingressgateway(オプション) アクセスに失敗するノードで、CLB IP に対する iptables ルールが存在しないことを確認します。
<CLB_IP>を実際の CLB IP アドレスに置き換えてください。何も出力が返されない場合、そのノードにはその IP に対する転送ルールがなく、問題が確認されます。iptables-save | grep <CLB_IP>
ソリューション
要件に基づいてソリューションを選択してください。
| ソリューション | ソース IP の保持 | ENI が必要 | 複雑さ |
|---|---|---|---|
| クラスター IP またはサービス名でイングレスゲートウェイにアクセス | はい | いいえ | 低 |
externalTrafficPolicy を Cluster | いいえ | いいえ | 低 |
Cluster と ENI ダイレクト接続を併用 | はい | はい | 中 |
ソリューション 1:クラスター IP またはサービス名でイングレスゲートウェイにアクセス (推奨)
クラスター内から CLB IP アドレスを使用する代わりに、クラスター IP アドレスまたは Kubernetes サービス名を使用してイングレスゲートウェイに到達します。
istio-ingressgateway.istio-systemこのアプローチは、イングレスゲートウェイの Pod がどこで実行されているかに関係なくすべてのノードで機能し、ソース IP アドレスを保持し、構成の変更は不要です。
ソリューション 2:externalTrafficPolicy を Cluster に設定
externalTrafficPolicy を Local から Cluster に変更します。これにより、kube-proxy はイングレスゲートウェイの Pod を実行しているノードだけでなく、すべてのノードで転送ルールをプログラムするようになります。
トレードオフ: ソース IP アドレスは保持されません。すべてのリクエストは、kube-proxy がトラフィックを転送するノードの IP から発信されているように見えます。
IstioGateway カスタムリソースを更新します。
apiVersion: istio.alibabacloud.com/v1beta1
kind: IstioGateway
metadata:
name: ingressgateway
namespace: istio-system
....
spec:
externalTrafficPolicy: Cluster
....フィールドの詳細については、「ゲートウェイの CRD フィールド」をご参照ください。
ソリューション 3:Cluster と ENI ダイレクト接続を併用
ご利用のクラスターが Terway の Elastic Network Interface (ENI) を使用しているか、包括的な ENI モードで実行されている場合は、externalTrafficPolicy: Cluster と service.beta.kubernetes.io/backend-type: eni アノテーションを組み合わせます。これにより、すべてのノードから CLB IP にアクセスできるようにしながら、ENI ダイレクト接続を介してソース IP の保持を復元します。
前提条件: クラスターは CNI プラグインとして Terway を使用し、ENI または包括的な ENI モードが有効になっている必要があります。
IstioGateway カスタムリソースを更新します。
apiVersion: istio.alibabacloud.com/v1beta1
kind: IstioGateway
metadata:
name: ingressgateway
namespace: istio-system
....
spec:
externalTrafficPolicy: Cluster
maxReplicas: 5
minReplicas: 2
ports:
- name: status-port
port: 15020
targetPort: 15020
- name: http2
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
- name: tls
port: 15443
targetPort: 15443
replicaCount: 2
resources:
limits:
cpu: '2'
memory: 2G
requests:
cpu: 200m
memory: 256Mi
runAsRoot: false
serviceAnnotations:
service.beta.kubernetes.io/backend-type: eni
serviceType: LoadBalancerserviceAnnotations: service.beta.kubernetes.io/backend-type: eni フィールドは、トラフィックを ENI を介して直接ルーティングし、ソース IP アドレスを保持します。
フィールドの詳細については、「ゲートウェイの CRD フィールド」をご参照ください。