Récupérer l'adresse IP source derrière le LoadBalancer
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 :
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.