Tous les produits
Search
Centre de documentation

Alibaba Cloud Service Mesh:Obtenir l'adresse IP source du client dans Alibaba Cloud Service Mesh

Dernière mise à jour :Aug 24, 2026

Cette rubrique explique comment configurer Service Mesh afin de préserver l'adresse IP source du client lors de l'accès à vos services.

Prérequis

Contexte

L'adresse IP source du client est utilisée dans de nombreux scénarios, notamment :

  • Contrôle d'accès aux applications : par exemple, de nombreuses applications imposent une authentification supplémentaire lorsqu'un utilisateur se connecte depuis une région différente, ce qui nécessite l'obtention de l'adresse IP d'origine du client.

  • Affinité de session simple : vous pouvez effectuer un équilibrage de charge basé sur l'adresse IP source pour acheminer les requêtes provenant du même client vers la même instance de service.

  • Journalisation et surveillance des accès : les journaux d'accès et les métriques de surveillance contenant l'adresse source réelle aident les développeurs à analyser le trafic et à recueillir des statistiques.

Les équilibreurs de charge cloud tels que Server Load Balancer (SLB) peuvent transmettre l'adresse IP source du client aux services backend. Istio doit également offrir cette fonctionnalité. Toutefois, lorsque vous utilisez Istio, un proxy sidecar est injecté dans chaque pod. Ce proxy intercepte tout le trafic entrant et le transfère à votre application via une connexion locale (127.0.0.1). Par conséquent, votre application ne peut pas voir l'adresse IP source réelle du client.

Déployer des exemples d'applications

  1. Déployez l'application sleep.

    1. Créez un fichier nommé sleep.yaml avec le contenu suivant.

      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. Exécutez la commande suivante pour déployer l'application sleep.

      kubectl -n default apply -f  sleep.yaml
  2. Déployez l'application httpbin.

    1. Créez un fichier nommé httpbin.yaml avec le contenu suivant.

      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. Exécutez la commande suivante pour déployer l'application httpbin.

      kubectl -n default apply -f  httpbin.yaml

Scénario 1 : Trafic est-ouest

Étape 1 : Vérifier le comportement par défaut de l'adresse IP source du client

Dans Istio, le proxy sidecar de chaque service intercepte tout le trafic est-ouest. Ce proxy transfère ensuite les requêtes au conteneur d'application, de sorte que l'adresse source visible par l'application est l'adresse de bouclage du proxy, 127.0.0.6.

  1. Exécutez la commande suivante pour vérifier l'état des pods.

    kubectl -n default get pods -o wide

    Résultat attendu :

    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>

    Le résultat indique que l'adresse de l'application sleep est 172.17.X.XXX.

  2. Exécutez la commande suivante pour envoyer une requête depuis le conteneur sleep.

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

    Résultat attendu :

    {
      "origin": "127.0.0.6"
    }

    Le résultat montre que l'adresse source de la requête reçue par l'application httpbin est l'adresse du proxy Envoy 127.0.0.6, et non l'adresse de l'application sleep.

  3. Confirmez que l'adresse IP source est 127.0.0.6 en inspectant les informations de socket.

    1. Connectez-vous au conteneur httpbin et exécutez la commande suivante pour installer netstat.

      apt update & apt install net-tools
    2. Quittez le conteneur httpbin et exécutez la commande suivante pour afficher les informations relatives au port 8000.

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

      Résultat attendu :

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

      Le résultat indique que l'adresse IP source est 127.0.0.6.

  4. Consultez le contenu du journal d'accès dans le pod httpbin.

    Voici un exemple d'entrée de journal formatée :

    {
      "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"
    }

    Le journal affiche les informations suivantes :

    • "downstream_remote_address":"172.17.X.XXX:56160" : l'adresse de l'application sleep.

    • "downstream_local_address":"172.17.X.XXX:8000" : l'adresse de destination à laquelle l'application sleep accède.

    • "upstream_local_address":"127.0.0.6:42169" : l'adresse locale utilisée par le proxy Envoy httpbin pour se connecter à l'application httpbin. À ce stade, l'adresse IP source visible par l'application est 127.0.0.6.

    • "upstream_host":"172.17.X.XXX:8000" : l'adresse de destination à laquelle le proxy Envoy httpbin accède.

Étape 2 : Configurer la préservation de l'adresse IP source

Méthode 1 : Utiliser le mode TPROXY

Configurez le déploiement httpbin pour utiliser le mode d'interception transparente TPROXY.

  1. Exécutez la commande suivante pour modifier le déploiement de l'application httpbin.

    kubectl patch deployment -n default httpbin -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/interceptionMode":"TPROXY"}}}}}'                       
  2. Exécutez la commande suivante pour envoyer une requête depuis le conteneur sleep.

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

    Résultat attendu :

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

    Le résultat montre que l'application httpbin peut obtenir l'adresse IP réelle de l'application sleep.

  3. Exécutez la commande suivante pour afficher les informations relatives au port 8000.

    Remarque

    Après le redémarrage du pod, vous devez réinstaller netstat.

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

    Résultat attendu :

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

    Le résultat indique que l'adresse IP source est 172.17.X.XXX.

  4. Consultez le contenu du journal d'accès dans le pod httpbin.

    Voici un exemple d'entrée de journal formatée :

    {
      "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
    }

    Le journal affiche les informations suivantes :

    • "downstream_remote_address":"172.17.X.XXX:39058" : l'adresse de l'application sleep.

    • "downstream_local_address":"172.17.X.XXX:8000" : l'adresse de destination à laquelle l'application sleep accède.

    • "upstream_local_address":"172.17.X.XXX:46129" : l'adresse locale utilisée par le proxy Envoy httpbin pour se connecter à l'application httpbin, qui correspond à l'adresse IP de l'application sleep.

    • "upstream_host":"172.17.X.XXX:8000" : l'adresse de destination à laquelle le proxy Envoy httpbin accède.

Méthode 2 : Utiliser l'en-tête XFF

La configuration suivante permet au proxy sidecar côté serveur d'ajouter un en-tête X-Forwarded-For (XFF) aux requêtes entrantes. Le proxy définit la valeur de cet en-tête sur l'adresse IP réelle du client avant de transférer la requête à l'application. Cette méthode ne présente aucune limitation liée au système d'exploitation, mais elle nécessite que votre application lise l'adresse IP source du client depuis l'en-tête X-Forwarded-For (XFF).

  1. Appliquez le EnvoyFilter suivant à l'instance ASM en utilisant un modèle EnvoyFilter. Pour plus d'informations, consultez la rubrique Créer un filtre Envoy à l'aide d'un modèle de filtre Envoy.

    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
      name: enable-xff-for-sidecar-inbound
      namespace: istio-system  # Change this to the namespace where your gateway is located.
      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. Exécutez la commande suivante pour envoyer une requête depuis le conteneur sleep.

    kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip
  3. Résultat attendu :

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

    Le résultat indique que httpbin reçoit l'adresse IP réelle de l'application sleep. L'application httpbin peut effectuer cette opération car elle est conçue pour lire l'adresse IP source depuis l'en-tête X-Forwarded-For (XFF), ajouté désormais par le proxy sidecar. Cette méthode ne fonctionnera pas si votre application ne peut pas lire l'en-tête XFF.

Scénario 2 : Trafic nord-sud

Pour le trafic nord-sud, les requêtes transitent du client vers le service backend en passant par un équilibreur de charge et la passerelle d'entrée Istio. Ce saut supplémentaire via la passerelle d'entrée complexifie la préservation de l'adresse IP source du client. Les sections suivantes décrivent comment configurer et vérifier la préservation de l'adresse IP source pour les requêtes HTTP et HTTPS.

Requêtes HTTP

Sans préservation de l'adresse IP source

  1. Créez un fichier nommé http-demo.yaml contenant le code suivant pour accéder à l'application httpbin via HTTP.

    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. Exécutez la commande suivante pour déployer la passerelle et le VirtualService.

    kubectl -n default apply -f  http-demo.yaml
  3. Exécutez la commande suivante pour accéder à l'application httpbin via la passerelle d'entrée.

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

    Résultat attendu :

    {
      "origin": "10.0.0.93"
    }

    Le résultat indique que l'adresse IP renvoyée correspond à celle d'un nœud Kubernetes.

  4. Consultez le journal d'accès de la passerelle d'entrée.

    Voici un exemple d'entrée de journal :

    {
      "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
    }

    Le journal affiche les informations suivantes :

    • "downstream_remote_address":"10.0.0.93:5899" : Il ne s'agit pas de l'adresse IP source réelle du client.

    • "downstream_local_address":"172.17.X.XXX:80" : Adresse du pod de la passerelle d'entrée.

    • "upstream_local_address":"172.17.X.XXX:54322" : L'adresse IP du pod de la passerelle d'entrée est conservée, mais le numéro de port est modifié.

    • "upstream_host":"172.17.X.XXX:8000" : Adresse du pod httpbin.

With source IP preservation

  1. Définissez la stratégie de trafic externe sur Local. (Vous pouvez ignorer cette étape pour les clusters utilisant le mode réseau Terway.)

    1. Connectez-vous à la console ASM. Dans le volet de navigation de gauche, choisissez Service Mesh > Mesh Management.

    2. Sur la page Mesh Management, cliquez sur le nom de l'instance ASM. Dans le volet de navigation de gauche, choisissez ASM Gateways > Ingress Gateway.

    3. Sur la page Ingress Gateway, cliquez sur View YAML à droite de la passerelle cible.

    4. Dans la boîte de dialogue Edit, recherchez la section spec, définissez le champ externalTrafficPolicy sur Local, puis cliquez sur OK.

      spec:
        affinity: {}
        autoCreateGatewayYaml: false
        clusterIds:
          - cf0243f2c3009406xxx
        compression: {}
        cpu: {}
        dnsPolicy: ClusterFirst
        externalTrafficPolicy: Local
        gatewayType: ingress
  2. Exécutez la commande suivante pour accéder à l'application httpbin via la passerelle d'entrée.

    curl http://$GATEWAY_URL:80/ip

    Résultat attendu :

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

    Le résultat indique que l'adresse IP renvoyée correspond à l'adresse IP source réelle du client.

  3. Consultez le journal d'accès de la passerelle d'entrée.

    Voici un exemple d'entrée de journal :

    {
      "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
    }

    Le journal affiche les informations suivantes :

    • "downstream_remote_address":"120.244.XXX.XXX:28504" : Adresse source du client, comme prévu.

    • "downstream_local_address":"172.17.X.XXX:80" : Adresse du pod de la passerelle d'entrée.

    • "upstream_local_address":"172.17.X.XXX:57498" : L'adresse du pod de la passerelle d'entrée est conservée, mais le numéro de port est modifié.

    • "upstream_host":"172.17.X.XXX:80" : Adresse du pod httpbin.

Requêtes HTTPS

La section précédente ayant détaillé les requêtes HTTP, cette section se concentre uniquement sur la configuration et la vérification des requêtes HTTPS.

  1. Configurer la préservation de l'adresse IP source.

  2. Créez un fichier nommé https-demo.yaml contenant le code suivant pour accéder à l'application httpbin via HTTPS.

    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. Exécutez la commande suivante pour déployer la passerelle et le VirtualService.

    kubectl -n default apply -f  https-demo.yaml
  4. Exécutez la commande suivante pour accéder à l'application httpbin via la passerelle d'entrée.

    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

    Résultat attendu :

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

    Le résultat indique que l'adresse IP renvoyée correspond à l'adresse IP source réelle du client.