すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:Alibaba Cloud Service Mesh でのクライアントソース IP の取得

最終更新日:Jun 22, 2026

このドキュメントでは、サービスへのアクセス時にクライアントソース IP を保持するように Service Mesh を設定する方法について説明します。

前提条件

背景情報

クライアントソース IP は、多くのシナリオで使用されます。次に例を示します。

  • アプリケーションのアクセス制御:例えば、多くのアプリケーションでは、ユーザーが異なるリージョンからログインする際に追加の認証を要求します。これにはクライアントの元の IP を取得する必要があります。

  • シンプルなセッション保持:ソース IP ベースの負荷分散を実行して、同じクライアントからのリクエストを同じサービスインスタンスに転送できます。

  • アクセスログとモニタリング:実際のソースアドレスを含むアクセスログと監視メトリクスは、開発者がトラフィックを分析し、統計を収集するのに役立ちます。

Server Load Balancer (SLB) のようなクラウドロードバランサーは、クライアントソース IP をバックエンドサービスに渡すことができます。Istio もこの機能を提供する必要があります。しかし、Istio を使用する場合、各 Pod にサイドカープロキシが挿入されます。このプロキシはすべてのインバウンドトラフィックをインターセプトし、ローカル接続 (127.0.0.1) を介してアプリケーションに転送します。その結果、アプリケーションは実際のクライアントソース IP を確認できなくなります。

サンプルアプリケーションのデプロイ

  1. sleep アプリケーションをデプロイします。

    1. 次の内容で sleep.yaml という名前のファイルを作成します。

      apiVersion: v1
      kind: ServiceAccount
      metadata:
        name: sleep
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: sleep
        labels:
          app: sleep
          service: sleep
      spec:
        ports:
        - port: 80
          name: http
        selector:
          app: sleep
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: sleep
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: sleep
        template:
          metadata:
            labels:
              app: sleep
          spec:
            terminationGracePeriodSeconds: 0
            serviceAccountName: sleep
            containers:
            - name: sleep
              image: curlimages/curl
              command: ["/bin/sleep", "3650d"]
              imagePullPolicy: IfNotPresent
              volumeMounts:
              - mountPath: /etc/sleep/tls
                name: secret-volume
            volumes:
            - name: secret-volume
              secret:
                secretName: sleep-secret
                optional: true
    2. 次のコマンドを実行して、sleep アプリケーションをデプロイします。

      kubectl -n default apply -f  sleep.yaml
  2. httpbin アプリケーションをデプロイします。

    1. 次の内容で httpbin.yaml という名前のファイルを作成します。

      apiVersion: v1
      kind: Service
      metadata:
        name: httpbin
        labels:
          app: httpbin
      spec:
        ports:
        - name: http
          port: 8000
        selector:
          app: httpbin
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: httpbin
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: httpbin
            version: v1
        template:
          metadata:
            labels:
              app: httpbin
              version: v1
          spec:
            containers:
            - image: docker.io/citizenstig/httpbin
              imagePullPolicy: IfNotPresent
              name: httpbin
              ports:
              - containerPort: 8000
    2. 次のコマンドを実行して、httpbin アプリケーションをデプロイします。

      kubectl -n default apply -f  httpbin.yaml

シナリオ 1:東西トラフィック

ステップ 1:デフォルトのクライアントソース IP 動作の確認

Istio では、各サービスのサイドカープロキシがすべての東西トラフィックをインターセプトします。このプロキシはリクエストをアプリケーションコンテナに転送するため、アプリケーションが確認できるソースアドレスはプロキシのループバックアドレスである 127.0.0.6 になります。

  1. 次のコマンドを実行して、Pod のステータスを確認します。

    kubectl -n default get pods -o wide

    期待される出力:

    NAME                            READY   STATUS        RESTARTS   AGE     IP             NODE                     NOMINATED NODE   READINESS GATES
    httpbin-c85bdb469-4ll2m         2/2     Running       0          3m22s   172.17.X.XXX   cn-hongkong.10.0.0.XX    <none>           <none>
    sleep-8f764df66-q7dr2           2/2     Running       0          3m9s    172.17.X.XXX   cn-hongkong.10.0.0.XX    <none>           <none>

    出力は、sleep アプリケーションのアドレスが 172.17.X.XXX であることを示しています。

  2. 次のコマンドを実行して、sleep コンテナからリクエストを送信します。

    kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip

    期待される出力:

    {
      "origin": "127.0.0.6"
    }

    出力は、httpbin アプリケーションが受信したリクエストのソースアドレスが、sleep アプリケーションのアドレスではなく、Envoy プロキシのアドレス 127.0.0.6 であることを示しています。

  3. ソケット情報を調べることで、ソース IP アドレスが 127.0.0.6 であることを確認します。

    1. httpbin コンテナにログインし、次のコマンドを実行して netstat をインストールします。

      apt update & apt install net-tools
    2. httpbin コンテナを終了し、次のコマンドを実行してポート 8000 の情報を表示します。

      kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 8000

      期待される出力:

      tcp        0      0 172.17.X.XXX:8000         127.0.0.6:42691         TIME_WAIT   -

      出力は、ソース IP アドレスが 127.0.0.6 であることを示しています。

  4. httpbin Pod のアクセスログの内容を表示します。

    以下は、フォーマットされたログエントリのサンプルです。

    {
      "trace_id":null,
      "bytes_received":0,
      "upstream_host":"172.17.X.XXX:8000",
      "authority":"httpbin:8000",
      "downstream_remote_address":"172.17.X.XXX:56160",
      "upstream_service_time":"1",
      "upstream_transport_failure_reason":null,
      "istio_policy_status":null,
      "path":"/ip",
      "bytes_sent":28,
      "request_id":"4501a50a-dab0-44c9-b52c-2a4f425a****",
      "protocol":"HTTP/1.1",
      "method":"GET",
      "duration":1,
      "start_time":"2022-11-22T16:09:30.394Z",
      "user_agent":"curl/7.86.0-DEV",
      "upstream_local_address":"127.0.0.6:42169",
      "response_flags":"-",
      "route_name":"default",
      "response_code":200,
      "upstream_cluster":"inbound|80||",
      "x_forwarded_for":null,
      "downstream_local_address":"172.17.X.XXX:8000",
      "requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local"
    }

    ログには次の情報が表示されます。

    • "downstream_remote_address":"172.17.X.XXX:56160":sleep アプリケーションのアドレス。

    • "downstream_local_address":"172.17.X.XXX:8000":sleep アプリケーションがアクセスする宛先アドレス。

    • "upstream_local_address":"127.0.0.6:42169":httpbin Envoy プロキシが httpbin アプリケーションに接続するために使用するローカルアドレス。この時点で、アプリケーションが確認できるソース IP は 127.0.0.6 です。

    • "upstream_host":"172.17.X.XXX:8000":httpbin Envoy プロキシがアクセスする宛先アドレス。

ステップ 2:ソース IP 保持の設定

方法 1:TPROXY モードの使用

httpbin の Deployment が TPROXY 透過的インターセプトモードを使用するように設定します。

  1. 次のコマンドを実行して、httpbin アプリケーションの Deployment を変更します。

    kubectl patch deployment -n default httpbin -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/interceptionMode":"TPROXY"}}}}}'                       
  2. 次のコマンドを実行して、sleep コンテナからリクエストを送信します。

    kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip

    期待される出力:

    {
      "origin": "172.17.X.XXX"
    }

    出力は、httpbin アプリケーションが sleep アプリケーションの実際の IP アドレスを取得できることを示しています。

  3. 次のコマンドを実行して、ポート 8000 の情報を表示します。

    説明

    Pod が再起動した後、netstat を再インストールする必要があります。

    kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 8000

    期待される出力:

    tcp        0      0 172.17.X.XXX:8000         172.17.X.XXX:36728      ESTABLISHED -

    出力は、ソース IP アドレスが 172.17.X.XXX であることを示しています。

  4. httpbin Pod のアクセスログの内容を表示します。

    以下は、フォーマットされたログエントリのサンプルです。

    {
      "route_name":"default",
      "bytes_received":0,
      "trace_id":null,
      "request_id":"1ccabe60-63cf-469b-8565-99cac546****",
      "upstream_cluster":"inbound|80||",
      "response_flags":"-",
      "protocol":"HTTP/1.1",
      "upstream_transport_failure_reason":null,
      "requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local",
      "response_code":200,
      "user_agent":"curl/7.86.0-DEV",
      "start_time":"2022-11-22T16:03:32.803Z",
      "path":"/ip",
      "authority":"httpbin:8000",
      "bytes_sent":31,
      "downstream_remote_address":"172.17.X.XXX:39058",
      "upstream_service_time":"1",
      "method":"GET",
      "downstream_local_address":"172.17.X.XXX:8000",
      "duration":1,
      "upstream_host":"172.17.X.XXX:8000",
      "istio_policy_status":null,
      "upstream_local_address":"172.17.X.XXX:46129",
      "x_forwarded_for":null
    }

    ログには次の情報が表示されます。

    • "downstream_remote_address":"172.17.X.XXX:39058":sleep アプリケーションのアドレス。

    • "downstream_local_address":"172.17.X.XXX:8000":sleep アプリケーションがアクセスする宛先アドレス。

    • "upstream_local_address":"172.17.X.XXX:46129":httpbin Envoy プロキシが httpbin アプリケーションに接続するために使用するローカルアドレス。これは sleep アプリケーションの IP アドレスです。

    • "upstream_host":"172.17.X.XXX:8000":httpbin Envoy プロキシがアクセスする宛先アドレス。

方法 2:XFF ヘッダーの使用

次の設定により、サーバー側のサイドカープロキシはインバウンドリクエストに X-Forwarded-For (XFF) ヘッダーを追加します。プロキシは、リクエストをアプリケーションに転送する前に、このヘッダーの値をクライアントの実際の IP アドレスに設定します。この方法には OS の制限はありませんが、アプリケーションが X-Forwarded-For (XFF) ヘッダーからクライアントのソース IP を読み取る必要があります。

  1. Envoy フィルターテンプレートを使用して、次の EnvoyFilter を ASM インスタンスに適用します。詳細については、「Envoy フィルターテンプレートを使用して Envoy フィルターを作成する」をご参照ください。

    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: enable-xff-for-sidecar-inbound
      namespace: istio-system  # これをゲートウェイが配置されている名前空間に変更します。
      labels:
        asm-system: "true"
        provider: "asm"
    spec:
      configPatches:
      - applyTo: NETWORK_FILTER
        match:
          proxy:
            proxyVersion: "^1.*"
          context: SIDECAR_INBOUND 
          listener:
            name: "virtualInbound"
            filterChain:
              filter:
                name: "envoy.filters.network.http_connection_manager"
        patch:
          operation: MERGE
          value:
            typed_config:
              "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
              use_remote_address: true
  2. 次のコマンドを実行して、sleep コンテナからリクエストを送信します。

    kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip
  3. 期待される出力:

    {
      "origin": "172.17.X.XXX"
    }

    出力は、httpbin が sleep アプリケーションの実際の IP アドレスを受信したことを示しています。httpbin アプリケーションは、ソース IP を X-Forwarded-For (XFF) ヘッダーから読み取るように設計されているため、これが可能です。サイドカープロキシがこのヘッダーを追加するようになりました。ご利用のアプリケーションが XFF ヘッダーを読み取れない場合、この方法は機能しません。

シナリオ 2:南北トラフィック

南北トラフィックの場合、リクエストはクライアントからロードバランサーと Istio イングレスゲートウェイを経由してバックエンドサービスに流れます。イングレスゲートウェイを介したこの余分なホップにより、クライアントソース IP の保持がより複雑になります。以下のセクションでは、HTTP および HTTPS リクエストのソース IP 保持を設定および検証する方法について説明します。

HTTP リクエスト

ソース IP 保持なし

  1. HTTP 経由で httpbin アプリケーションにアクセスするために、次の内容で http-demo.yaml という名前のファイルを作成します。

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: httpbin-gw-httpprotocol
      namespace: default
    spec:
      selector:
        istio: ingressgateway
      servers:
        - hosts:
            - '*'
          port:
            name: http
            number: 80
            protocol: HTTP
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
      namespace: default
    spec:
      gateways:
        - httpbin-gw-httpprotocol
      hosts:
        - '*'
      http:
        - route:
            - destination:
                host: httpbin
                port:
                  number: 8000
  2. 次のコマンドを実行して、Gateway と VirtualService をデプロイします。

    kubectl -n default apply -f  http-demo.yaml
  3. 次のコマンドを実行して、イングレスゲートウェイ経由で httpbin アプリケーションにアクセスします。

    export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    curl http://$GATEWAY_URL:80/ip

    期待される出力:

    {
      "origin": "10.0.0.93"
    }

    出力は、返された IP アドレスが Kubernetes ノードのアドレスであることを示しています。

  4. イングレスゲートウェイのアクセスログを表示します。

    以下は、ログエントリのサンプルです。

    {
      "upstream_service_time":"1",
      "response_code":200,
      "protocol":"HTTP/1.1",
      "bytes_sent":28,
      "upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local",
      "start_time":"2022-11-23T03:29:20.017Z",
      "istio_policy_status":null,
      "upstream_transport_failure_reason":null,
      "trace_id":null,
      "route_name":null,
      "request_id":"292903be-a889-4d5d-83a0-ab1f5d1a****",
      "method":"GET",
      "upstream_host":"172.17.X.XXX:8000",
      "duration":1,
      "path":"/ip",
      "downstream_local_address":"172.17.X.XXX:80",
      "authority":"47.242.XXX.XX",
      "user_agent":"curl/7.79.1",
      "downstream_remote_address":"10.0.0.93:5899",
      "upstream_local_address":"172.17.X.XXX:54322",
      "requested_server_name":null,
      "x_forwarded_for":"10.0.0.93",
      "response_flags":"-",
      "bytes_received":0
    }

    ログには次の情報が表示されます。

    • "downstream_remote_address":"10.0.0.93:5899":クライアントの実際のソース IP ではありません。

    • "downstream_local_address":"172.17.X.XXX:80":イングレスゲートウェイ Pod のアドレス。

    • "upstream_local_address":"172.17.X.XXX:54322":イングレスゲートウェイ Pod の IP アドレスは保持されますが、ポート番号は変更されます。

    • "upstream_host":"172.17.X.XXX:8000":httpbin Pod のアドレス。

ソース IP 保持あり

  1. 外部トラフィックポリシーを Local に設定します。(Terway ネットワークモードを使用するクラスターでは、このステップをスキップできます。)

    1. ASM コンソールにログインします。左側のナビゲーションウィンドウで、Service Mesh > メッシュ管理を選択します。

    2. [メッシュ管理] ページで、対象の ASM インスタンスの名前をクリックします。左側のナビゲーションウィンドウで、ASM ゲートウェイ > イングレスゲートウェイを選択します。

    3. Ingress Gateway ページで、対象のゲートウェイの右側にある View YAML をクリックします。

    4. Edit ダイアログボックスで、spec セクションを見つけ、externalTrafficPolicy フィールドを Local に設定し、OK をクリックします。

      spec:
        affinity: {}
        autoCreateGatewayYaml: false
        clusterIds:
          - cf0243f2c3009406xxx
        compression: {}
        cpu: {}
        dnsPolicy: ClusterFirst
        externalTrafficPolicy: Local
        gatewayType: ingress
  2. 次のコマンドを実行して、イングレスゲートウェイ経由で httpbin アプリケーションにアクセスします。

    curl http://$GATEWAY_URL:80/ip

    期待される出力:

    {
      "origin": "120.244.xxx.xxx"
    }

    出力は、返された IP アドレスが実際のクライアントソース IP であることを示しています。

  3. イングレスゲートウェイのアクセスログを表示します。

    以下は、ログエントリのサンプルです。

    {
      "istio_policy_status":null,
      "upstream_transport_failure_reason":null,
      "path":"/ip",
      "x_forwarded_for":"120.244.XXX.XXX",
      "route_name":null,
      "method":"GET",
      "duration":2,
      "downstream_remote_address":"120.244.XXX.XXX:28504",
      "bytes_received":0,
      "upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local",
      "bytes_sent":34,
      "protocol":"HTTP/1.1",
      "response_flags":"-",
      "upstream_local_address":"172.17.X.XXX:57498",
      "upstream_service_time":"2",
      "request_id":"9c0295d4-e77f-4a3a-b292-e5c58d92****",
      "start_time":"2022-11-23T03:24:04.413Z",
      "response_code":200,
      "trace_id":null,
      "authority":"47.242.XXX.XX",
      "user_agent":"curl/7.79.1",
      "downstream_local_address":"172.17.X.XXX:80",
      "upstream_host":"172.17.X.XXX:80",
      "requested_server_name":null
    }

    ログには次の情報が表示されます。

    • "downstream_remote_address":"120.244.XXX.XXX:28504":期待どおりのクライアントソースアドレス。

    • "downstream_local_address":"172.17.X.XXX:80":イングレスゲートウェイ Pod のアドレス。

    • "upstream_local_address":"172.17.X.XXX:57498":イングレスゲートウェイ Pod のアドレスは保持されますが、ポート番号は変更されます。

    • "upstream_host":"172.17.X.XXX:80":httpbin Pod のアドレス。

HTTPS リクエスト

前のセクションでは HTTP リクエストについて詳しく説明したため、このセクションでは HTTPS リクエストの設定と検証のみに焦点を当てます。

  1. ソース IP 保持を設定します

  2. HTTPS 経由で httpbin アプリケーションにアクセスするために、次の内容で https-demo.yaml という名前のファイルを作成します。

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: httpbin-gw-https
      namespace: default
    spec:
      selector:
        istio: ingressgateway
      servers:
        - hosts:
            - '*'
          port:
            name: https
            number: 443
            protocol: HTTPS
          tls:
            credentialName: myexample-credential
            mode: SIMPLE
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin-https
      namespace: default
    spec:
      gateways:
        - httpbin-gw-https
      hosts:
        - '*'
      http:
        - route:
            - destination:
                host: httpbin
                port:
                  number: 8000
  3. 次のコマンドを実行して、Gateway と VirtualService をデプロイします。

    kubectl -n default apply -f  https-demo.yaml
  4. 次のコマンドを実行して、イングレスゲートウェイ経由で httpbin アプリケーションにアクセスします。

    export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    curl -k https://$GATEWAY_URL:443/ip

    期待される出力:

    {
      "origin": "120.244.XXX.XXX"
    }

    出力は、返された IP アドレスが実際のクライアントソース IP であることを示しています。