For AI agents: the complete documentation index is available at https://docs.ovhcloud.com/fr/llms.txt, the full documentation bundle is available at https://docs.ovhcloud.com/fr/llms-full.txt, and this page is available as Markdown at https://docs.ovhcloud.com/fr/guides/public-cloud/containers-orchestration/managed-kubernetes/getting-source-ip-behind-loadbalancer.md.

Récupérer l'adresse IP source derrière le LoadBalancer

Voir en Markdown

Découvrez comment récupérer l'adresse IP source derrière le LoadBalancer sur OVHcloud Managed Kubernetes

Warning

L'utilisation du Load Balancer Public Cloud avec Managed Kubernetes Service (MKS) est désormais disponible en General Availability. Cependant, ce LoadBalancer (basé sur le projet Octavia) n'est pas encore le LoadBalancer par défaut pour les clusters utilisant des versions de Kubernetes <1.31. Pour ces clusters, vous devez utiliser l'annotation loadbalancer.ovhcloud.com/class: octavia afin de déployer un LoadBalancer Octavia depuis votre cluster MKS.

Avant de commencer

Ce tutoriel suppose que vous disposez déjà d'un cluster OVHcloud Managed Kubernetes fonctionnel, et que vous y avez déployé une application utilisant le LoadBalancer OVHcloud Managed Kubernetes. Pour en savoir plus sur ces sujets, consultez la documentation Utiliser le LoadBalancer OVHcloud Managed Kubernetes.

Warning

Lorsqu'une ressource Service de type LoadBalancer est créée au sein d'un cluster Managed Kubernetes, un Load Balancer Public Cloud associé est automatiquement créé, permettant un accès public à votre application K8S. Le service Load Balancer Public Cloud est facturé à l'heure et apparaîtra dans votre projet Public Cloud. Pour plus d'informations, reportez-vous à la documentation suivante : Tarifs du Network Load Balancer

Le problème

Lorsque vous déployez vos services HTTP en mode NodePort, vous récupérez directement l'adresse Remote Address de la requête depuis le serveur (par exemple avec $_SERVER['REMOTE_ADDR'] en PHP ou $ENV{'REMOTE_ADDR'} en Perl). Cette adresse (généralement au format IP:port) correspond au demandeur d'origine ou au dernier proxy entre celui-ci et votre cluster.

Lorsque vous déployez les services en mode LoadBalancer, les choses sont un peu différentes : notre Load Balancer agit comme un proxy, et le Remote Address vous donnera l'adresse IP du Load Balancer. Comment récupérer l'adresse IP source de la requête dans ce cas ?

Ce tutoriel décrit comment déployer un service LoadBalancer sur OVHcloud Managed Kubernetes tout en préservant l'adresse IP source.

Récupérer l'adresse IP source de la requête derrière le LoadBalancer

Le moyen le plus simple de déployer des services derrière le Load Balancer tout en conservant l'adresse IP source consiste à placer vos services sous un Ingress, lui-même situé derrière le LoadBalancer.

L'Ingress est exposé à l'extérieur du cluster via un LoadBalancer, et il route le trafic entrant vers vos services selon des règles configurées. Cette configuration présente également un avantage en termes de coût : vous pouvez placer de nombreux services derrière un seul LoadBalancer.

Dans ce tutoriel, nous utilisons l'Ingress Controller le plus simple : NGINX Ingress Controller, où un serveur NGINX joue le rôle de reverse proxy.

1. Installation du NGINX Ingress Controller

Nous pouvons déployer le NGINX Ingress Controller officiel avec le fichier manifeste ou avec le chart Helm.
Choisissez l'une ou l'autre méthode et suivez le paragraphe correspondant.

Installation avec le fichier manifeste

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud/deploy.yaml

Cela crée le namespace, le serviceaccount, le role et tous les autres objets Kubernetes nécessaires à l'Ingress Controller, puis déploie le contrôleur :

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud/deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created
deployment.apps/ingress-nginx-controller created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created

Installation avec le chart Helm

helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx --create-namespace

Cela crée le namespace, le serviceaccount, le role et tous les autres objets Kubernetes nécessaires à l'Ingress Controller, puis déploie le contrôleur :

$ helm install ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx --create-namespace
NAME: ingress-nginx
LAST DEPLOYED: Fri Jun 11 14:13:09 2021
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller'

An example Ingress that makes use of the controller:

  apiVersion: networking.k8s.io/v1beta1
  kind: Ingress
  metadata:
    annotations:
      kubernetes.io/ingress.class: nginx
    name: example
    namespace: foo
  spec:
    rules:
      - host: www.example.com
        http:
          paths:
            - backend:
                serviceName: exampleService
                servicePort: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
        - hosts:
            - www.example.com
          secretName: example-tls

If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:

  apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: <base64 encoded cert>
    tls.key: <base64 encoded key>
  type: kubernetes.io/tls

Vérifiez votre déploiement

Vous pouvez utiliser kubectl pour obtenir l'état du service et récupérer l'adresse IP du Load Balancer :

kubectl get service ingress-nginx-controller -n ingress-nginx

Vous devriez voir votre service Ingress nouvellement créé :

$ kubectl get service ingress-nginx-controller -n ingress-nginx
NAME                       TYPE           CLUSTER-IP    EXTERNAL-IP       PORT(S)                      AGE
ingress-nginx-controller   LoadBalancer   10.3.81.157   xxx.xxx.xxx.xxx   80:xxxxx/TCP,443:xxxxx/TCP   4m32s
Warning

La création du LoadBalancer étant asynchrone, et le provisionnement du Load Balancer pouvant prendre plusieurs minutes, vous pouvez voir <pending> dans EXTERNAL-IP pendant que le Load Balancer se met en place. Dans ce cas, patientez quelques minutes et réessayez.

2. Patch de l'Ingress Controller

Vous devez maintenant patcher l'Ingress Controller pour qu'il prenne en charge le proxy protocol.

Warning

Selon que votre cluster Kubernetes fonctionne avec un réseau privé ou non, la configuration du proxy protocol diffère. Suivez les parties du tutoriel correspondant à votre configuration.

a. [RÉSEAU PUBLIC UNIQUEMENT] Récupérer la liste des adresses IP de sortie du Load Balancer

kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath="{.metadata.annotations.lb\.k8s\.ovh\.net/egress-ips}"

Vous devriez voir quelque chose comme ceci :

$ kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath="{.metadata.annotations.lb\.k8s\.ovh\.net/egress-ips}"
aaa.aaa.aaa.aaa/32,bbb.bbb.bbb.bbb/32,ccc.ccc.ccc.ccc/32,ddd.ddd.ddd.ddd/32

b. [RÉSEAU PRIVÉ UNIQUEMENT] Récupérer la liste des adresses IP de sortie du Load Balancer

Lorsque votre cluster Managed Kubernetes est attaché à un vRack, les Load Balancers utilisent chacun deux adresses IP aléatoires. Votre liste d'adresses IP de sortie correspond à la plage de votre sous-réseau.

Pour le reste de cette documentation, nous considérons que notre sous-réseau utilise la plage 10.0.0.0/20. N'oubliez pas de la remplacer par la vôtre !

Méthodes de patch

Nous pouvons mettre à jour la configuration du NGINX Ingress Controller avec des fichiers manifestes ou avec Helm. Choisissez l'une ou l'autre méthode et suivez le paragraphe correspondant.

Patch avec des fichiers manifestes

Copiez l'extrait YAML suivant dans un fichier patch-ingress-controller-service.yml :

metadata:
    annotations:
      # For Managed Kubernetes Service version < 1.31
      service.beta.kubernetes.io/ovh-loadbalancer-proxy-protocol: "v2"
      # For Managed Kubernetes Service version >= 1.31
      # loadbalancer.openstack.org/proxy-protocol : "v2"
spec:
  externalTrafficPolicy: Local

Puis appliquez-le dans votre cluster :

kubectl -n ingress-nginx patch service ingress-nginx-controller -p "$(cat patch-ingress-controller-service.yml)"

Copiez l'extrait YAML suivant dans un fichier patch-ingress-controller-configmap.yml et modifiez le paramètre proxy-real-ip-cidr selon la configuration de votre cluster :

a. [RÉSEAU PUBLIC UNIQUEMENT]

data:
  use-proxy-protocol: "true"
  real-ip-header: "proxy_protocol"
  proxy-real-ip-cidr: "aaa.aaa.aaa.aaa/32,bbb.bbb.bbb.bbb/32,ccc.ccc.ccc.ccc/32,ddd.ddd.ddd.ddd/32"

b. [RÉSEAU PRIVÉ UNIQUEMENT]

data:
  use-proxy-protocol: "true"
  real-ip-header: "proxy_protocol"
  proxy-real-ip-cidr: "10.0.0.0/20"
Info

Remarque : 10.0.0.0/20 doit être remplacé par la plage de votre propre sous-réseau.

Puis appliquez-le dans votre cluster :

kubectl -n ingress-nginx patch configmap ingress-nginx-controller -p "$(cat patch-ingress-controller-configmap.yml)"

Vous devriez voir la configuration être patchée et le pod du contrôleur supprimé (puis recréé) :

$ kubectl -n ingress-nginx patch service  ingress-nginx-controller -p "$(cat patch-ingress-controller-configmap.yml)"
configmap/ ingress-nginx-controller patched
$ kubectl -n ingress-nginx patch configmap  ingress-nginx-controller -p "$(cat patch-ingress-controller-configmap.yml)"
configmap/ ingress-nginx-controller patched

Patch avec Helm

Copiez l'extrait YAML suivant dans un fichier values.yaml et modifiez le paramètre proxy-real-ip-cidr selon la configuration de votre cluster :

a. [RÉSEAU PUBLIC UNIQUEMENT]

controller:
  service:
    externalTrafficPolicy: "Local"
    annotations:
      # For Managed Kubernetes Service version < 1.31
      service.beta.kubernetes.io/ovh-loadbalancer-proxy-protocol: "v2"
      # For Managed Kubernetes Service version >= 1.31
      # loadbalancer.openstack.org/proxy-protocol : "v2"
  config:
    use-proxy-protocol: "true"
    real-ip-header: "proxy_protocol"
    proxy-real-ip-cidr: "aaa.aaa.aaa.aaa/32,bbb.bbb.bbb.bbb/32,ccc.ccc.ccc.ccc/32,ddd.ddd.ddd.ddd/32"

b. [RÉSEAU PRIVÉ UNIQUEMENT]

controller:
  service:
    externalTrafficPolicy: "Local"
    annotations:
      # For Managed Kubernetes Service version < 1.31
      service.beta.kubernetes.io/ovh-loadbalancer-proxy-protocol: "v2"
      # For Managed Kubernetes Service version >= 1.31
      # loadbalancer.openstack.org/proxy-protocol : "v2"
  config:
    use-proxy-protocol: "true"
    real-ip-header: "proxy_protocol"
    proxy-real-ip-cidr: "10.0.0.0/20"
Info

Remarque : 10.0.0.0/20 doit être remplacé par la plage de votre propre sous-réseau.

Puis mettez à jour votre release Helm :

helm upgrade ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx -f values.yaml

Vous devriez voir votre release Helm être mise à jour :

$ helm upgrade ingress-nginx ingress-nginx/ingress-nginx -n ingress-nginx -f values.yaml
Release "ingress-nginx" has been upgraded. Happy Helming!
NAME: ingress-nginx
LAST DEPLOYED: Fri Jun 11 17:08:00 2021
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 3
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace ingress-nginx get services -o wide -w ingress-nginx-controller'
An example Ingress that makes use of the controller:
  apiVersion: networking.k8s.io/v1beta1
  kind: Ingress
  metadata:
    annotations:
      kubernetes.io/ingress.class: nginx
    name: example
    namespace: foo
  spec:
    rules:
      - host: www.example.com
        http:
          paths:
            - backend:
                serviceName: exampleService
                servicePort: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
        - hosts:
            - www.example.com
          secretName: example-tls
If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:
  apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: <base64 encoded cert>
    tls.key: <base64 encoded key>
  type: kubernetes.io/tls

3. Test

Warning

En raison de la propagation DNS, la résolution effective du FQDN de votre Load Balancer peut nécessiter 2 à 5 minutes supplémentaires avant d'être pleinement utilisable. En attendant, vous pouvez utiliser l'adresse IP fournie pour accéder au Load Balancer.
Le nom de domaine généré pour le service et affiché dans le champ EXTERNAL-IP est réservé à un usage interne au cluster. Il ne doit pas être utilisé pour accéder au service depuis Internet.

Nous pouvons maintenant déployer un service echo simple pour vérifier que tout fonctionne. Le service utilisera l'image mendhak/http-https-echo, un conteneur Docker d'écho HTTPS très utile pour le débogage web.

Commencez par copier le manifeste suivant dans un fichier echo.yaml :

apiVersion: v1
kind: Namespace
metadata:
  name: echo

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deployment
  namespace: echo
  labels:
    app: echo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echo
        image: mendhak/http-https-echo
        ports:
        - containerPort: 80
        - containerPort: 443

---

apiVersion: v1
kind: Service
metadata:  
  name: echo-service
  namespace: echo
spec:
  selector:
    app: echo
  ports:  
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echo-ingress
  namespace: echo
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - http:
      paths:
        - path: "/"
          pathType: Prefix
          backend:
            service:
              name: echo-service
              port:
                number: 80

Puis déployez-le sur votre cluster :

kubectl apply -f echo.yaml
$ kubectl apply -f echo.yaml
namespace/echo created
deployment.apps/echo-deployment created
service/echo-service created
ingress.extensions/echo-ingress created

Vous pouvez maintenant le tester en utilisant l'URL du LoadBalancer :

curl  xxx.xxx.xxx.xxx

Vous devriez obtenir les paramètres HTTP de votre requête, incluant la bonne adresse IP source dans l'en-tête x-real-ip :

{
  "path": "/",
  "headers": {
    "host": "xxx.xxx.xxx.xxx",
    "x-request-id": "2126b343bc837ecbd07eca904c33daa3",
    "x-real-ip": "XXX.XXX.XXX.XXX",
    "x-forwarded-for": "XXX.XXX.XXX.XXX",
    "x-forwarded-host": "xxx.xxx.xxx.xxx",
    "x-forwarded-port": "80",
    "x-forwarded-proto": "http",
    "x-original-uri": "/",
    "x-scheme": "http",
    "user-agent": "curl/7.58.0",
    "accept": "*/*"
  },
  "method": "GET",
  "body": "",
  "fresh": false,
  "hostname": "xxx.xxx.xxx.xxx",
  "ip": "::ffff:10.2.1.2",
  "ips": [],
  "protocol": "http",
  "query": {},
  "subdomains": [
    "k8s",
    "gra",
    "c1",
    "lb",
    "6d6rslnrn8"
  ],
  "xhr": false,
  "os": {
    "hostname": "echo-deployment-6b6fdc96cf-hwqw6"
  }
}

Que faire si je souhaite utiliser un autre Ingress Controller ?

La méthode précédente devrait fonctionner de manière similaire avec n'importe quel Ingress Controller. Ce tutoriel sera bientôt mis à jour avec des informations plus détaillées sur d'autres Ingress Controllers, notamment Traefik.

Aller plus loin

  • Si vous avez besoin d'une formation ou d'une assistance technique pour la mise en oeuvre de nos solutions, contactez votre commercial ou cliquez sur ce lien pour obtenir un devis et demander une analyse personnalisée de votre projet à nos experts de l’équipe Professional Services.

  • Échangez avec notre communauté d'utilisateurs.

Cette page vous a-t-elle aidé ?