Passer au contenu principal

Exposer une application en interne via un load balancer privé

Par défaut, les applications d'un cluster Kubernetes sont exposées vers Internet via l'ingress public géré par la plateforme. Lorsque les outils de monitoring ou d'alerting sont hébergés dans un autre VPC (Virtual Private Cloud) — ou sur site via un peering (appairage) réseau —, il est préférable de les joindre par un endpoint privé, sans exposition publique.

Ce guide décrit la création d'un Service de type LoadBalancer interne : la plateforme provisionne un load balancer (équilibreur de charge) privé qui attribue des adresses IP (Internet Protocol) privées à l'application, joignables depuis le réseau du cluster et les réseaux appairés.

Prérequis

info

Load balancer public et load balancer interne

Par défaut, un Service de type LoadBalancer provisionne un load balancer public : la plateforme lui attribue des adresses IP publiques et l'expose vers Internet.

L'annotation service.beta.kubernetes.io/osc-load-balancer-internal: "true" crée un load balancer interne : il reçoit des adresses IP privées dans le subnet (sous-réseau) indiqué et n'est joignable que depuis le réseau du cluster et les réseaux appairés. La plateforme s'appuie sur ce même mécanisme pour ses propres composants internes.

Cycle de vie des adresses IP

Type d'adresse IPAttributionStabilité
IP privée (interne)Attribuée automatiquement dans le subnet au moment de la créationStable pendant toute la vie du load balancer, non épinglable, modifiée si le Service est recréé
IP pré-allouée statiqueAdresse IP du compte référencée par annotation avant la créationConserve la même adresse IP même si le load balancer est recréé

Les règles firewall ne doivent donc pas cibler une adresse IP privée en dur : préférez un filtrage par security group (groupe de sécurité) — une règle entrante autorisant le security group du load balancer — ou par CIDR (Classless Inter Domain Routing) — les plages des réseaux appairés.

Pour un endpoint privé avec une référence stable côté clients, utilisez un nom DNS (Domain Name System) privé : un enregistrement CNAME isole la valeur de l'adresse IP, et une recréation du load balancer ne demande la mise à jour que d'une seule entrée DNS.

Procédure

note

Les clés d'annotation de ce guide sont définies par le cloud controller manager de la plateforme : utilisez-les telles quelles, en respectant la casse. N'utilisez que les clés documentées sur cette page.

Étape 1 : Vérifier le peering réseau

Vérifiez que le VPC des outils de monitoring est appairé au réseau du cluster et que les route table (table de routage) des deux réseaux autorisent le trafic entre les plages CIDR concernées.

Étape 2 : Préparer le subnet et le security group

  1. Identifiez le subnet du réseau du cluster dans lequel le load balancer sera créé : c'est dans ce subnet que les adresses IP privées seront attribuées. Récupérez son identifiant depuis la console ou l'API réseau.
  2. Créez un security group dédié au load balancer et ajoutez une règle entrante autorisant les CIDR des réseaux appairés vers le port d'écoute du Service. Consultez Créer un security group ↗ et Ajouter une règle à un security group ↗.
  3. Si le trafic est filtré entre le load balancer et les nodes (nœuds) du cluster, ajoutez une règle autorisant le security group du load balancer à joindre le port cible de l'application.

Étape 3 : Déclarer le Service

Créez le namespace si nécessaire, appliquez le manifest décrit dans la section Manifestes d'exemple puis vérifiez le résultat :

kubectl create namespace demo
kubectl apply -f service-interne.yaml

Annotations principales

AnnotationValeur d'exempleDescription
service.beta.kubernetes.io/osc-load-balancer-internal"true"Crée un load balancer interne : adresses IP privées dans le subnet indiqué
service.beta.kubernetes.io/osc-load-balancer-subnet-id"11111111-2222-3333-4444-…"UUID (Universally Unique Identifier) du subnet de création du load balancer
service.beta.kubernetes.io/osc-load-balancer-name"lb-demo-interne"Nom fixe du load balancer, 32 caractères maximum
service.beta.kubernetes.io/osc-load-balancer-security-group"aaaaaaaa-bbbb-cccc-dddd-…"Security group principal du load balancer
service.beta.kubernetes.io/osc-load-balancer-extra-security-groups"11111111-…, 22222222-…"Security groups additionnels, séparés par des virgules
service.beta.kubernetes.io/load-balancer-source-ranges"198.51.100.0/24, 203.0.113.0/24"CIDR sources autorisés à joindre le load balancer, sans préfixe supplémentaire

Annotations complémentaires

AnnotationValeur d'exempleDescription
service.beta.kubernetes.io/osc-load-balancer-healthcheck-protocol"HTTP"Protocole du health check (vérification d'état) : HTTP ou TCP
service.beta.kubernetes.io/osc-load-balancer-healthcheck-port"8080"Port interrogé par le health check
service.beta.kubernetes.io/osc-load-balancer-healthcheck-path"/healthz"Chemin interrogé, pour un health check en HTTP
service.beta.kubernetes.io/osc-load-balancer-healthcheck-interval"30"Intervalle entre deux health checks, en secondes
service.beta.kubernetes.io/osc-load-balancer-healthcheck-timeout"5"Délai d'attente de chaque health check, en secondes
service.beta.kubernetes.io/osc-load-balancer-healthcheck-healthy-threshold"2"Nombre de succès consécutifs avant de déclarer la cible saine
service.beta.kubernetes.io/osc-load-balancer-healthcheck-unhealthy-threshold"3"Nombre d'échecs consécutifs avant de retirer la cible
service.beta.kubernetes.io/osc-load-balancer-ip-id"ffffffff-…"Adresse IP publique pré-allouée du compte, associée au load balancer
service.beta.kubernetes.io/osc-load-balancer-ip-pool"mon-pool-prod"Sélectionne une adresse IP du compte portant le tag (étiquette) OscK8sIPPool:<nom-du-pool>
service.beta.kubernetes.io/osc-load-balancer-ingress-address"ip"Adresse exposée par le Service : ip, hostname ou both
service.beta.kubernetes.io/osc-load-balancer-ingress-ipmode"Proxy"Mode d'adressage des cibles : Proxy ou VIP

Manifestes d'exemple

Load balancer interne complet

apiVersion: v1
kind: Service
metadata:
name: demo-interne
namespace: demo
annotations:
# Load balancer interne : adresses IP privées dans le subnet indiqué
service.beta.kubernetes.io/osc-load-balancer-internal: "true"
service.beta.kubernetes.io/osc-load-balancer-subnet-id: "11111111-2222-3333-4444-555555555555"
service.beta.kubernetes.io/osc-load-balancer-name: "lb-demo-interne"
service.beta.kubernetes.io/osc-load-balancer-security-group: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
# CIDR sources autorisés à joindre le load balancer
service.beta.kubernetes.io/load-balancer-source-ranges: "198.51.100.0/24, 203.0.113.0/24"
# Health check ajusté pour l'application
service.beta.kubernetes.io/osc-load-balancer-healthcheck-protocol: "HTTP"
service.beta.kubernetes.io/osc-load-balancer-healthcheck-port: "8080"
service.beta.kubernetes.io/osc-load-balancer-healthcheck-path: "/healthz"
service.beta.kubernetes.io/osc-load-balancer-healthcheck-interval: "30"
service.beta.kubernetes.io/osc-load-balancer-healthcheck-timeout: "5"
service.beta.kubernetes.io/osc-load-balancer-healthcheck-healthy-threshold: "2"
service.beta.kubernetes.io/osc-load-balancer-healthcheck-unhealthy-threshold: "3"
spec:
type: LoadBalancer
selector:
app: demo
ports:
- name: http
port: 8080
targetPort: 8080
protocol: TCP

Variante : IP pré-allouée statique

Cette variante répond au besoin d'une adresse IP fixe pour les règles firewall : l'adresse IP pré-allouée du compte est conservée même si le load balancer est recréé. L'exposition reste toutefois publique : appliquez un filtrage strict par load-balancer-source-ranges et par security group.

apiVersion: v1
kind: Service
metadata:
name: demo-statique
namespace: demo
annotations:
# Nom fixe et adresse IP pré-allouée : la valeur survit à la recréation du load balancer
service.beta.kubernetes.io/osc-load-balancer-name: "lb-demo-statique"
service.beta.kubernetes.io/osc-load-balancer-ip-id: "ffffffff-8888-9999-aaaa-bbbbbbbbbbbb"
spec:
type: LoadBalancer
selector:
app: demo
ports:
- name: https
port: 443
targetPort: 8443
protocol: TCP

L'adresse IP doit être pré-allouée avant la création du Service : consultez Allouer une IP publique ↗. À la place d'une adresse unique, l'annotation osc-load-balancer-ip-pool sélectionne automatiquement une adresse IP du compte portant le tag OscK8sIPPool:<nom-du-pool>.

Vérification

Récupérer l'adresse du load balancer

kubectl get service demo-interne -n demo

Pendant la création du load balancer, la colonne EXTERNAL-IP affiche <pending> puis l'adresse IP privée attribuée :

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo-interne LoadBalancer 10.100.0.42 192.0.2.17 8080:30691/TCP 2m

Pour consulter les annotations appliquées et les événements de création :

kubectl describe service demo-interne -n demo

Vérifier les cibles du load balancer

Les endpoints du Service doivent référencer les adresses IP des pods de l'application :

kubectl get endpoints demo-interne -n demo

Tester l'accès depuis un réseau appairé

Depuis une VM (Virtual Machine) du VPC distant, ou depuis le réseau sur site via le peering :

curl http://192.0.2.17:8080/healthz

Une réponse HTTP 200 confirme que l'application est joignable par le load balancer interne. Si le Service est exposé via un nom d'hôte (osc-load-balancer-ingress-address), testez la résolution DNS depuis le réseau appairé.

Limitations et bonnes pratiques

  • Créez un Service de type LoadBalancer dédié à chaque exposition interne : ne modifiez pas le Service géré par la plateforme pour l'ingress public du cluster.
  • Les adresses IP privées du load balancer interne sont stables pendant toute sa vie, mais ne sont pas épinglables : elles changent si le Service est supprimé puis recréé.
  • Ne ciblez pas une adresse IP privée en dur dans vos règles firewall : ciblez des security groups ou des plages CIDR.
  • Référencez l'adresse IP par un enregistrement CNAME dans une zone DNS privée plutôt que de la communiquer aux configurations clientes.
  • Fixez le nom du load balancer avec l'annotation osc-load-balancer-name pour garantir la reproductibilité avec vos outils d'automatisation.
  • Déclarez systématiquement load-balancer-source-ranges pour limiter l'accès aux seuls réseaux autorisés.
avertissement

L'adresse IP privée d'un load balancer interne change si le Service est supprimé puis recréé. Une règle firewall ciblant cette adresse en dur deviendra silencieusement obsolète : utilisez un filtrage par security group ou par plage CIDR.

Dépannage

Le Service reste en attente

Cause : une annotation est invalide — subnet inexistant, nom de load balancer de plus de 32 caractères, adresse IP non pré-allouée ou déjà associée à une autre ressource.

Solution : consultez les événements avec kubectl describe service demo-interne -n demo, corrigez l'annotation concernée puis recréez le Service.

Connexion impossible depuis le VPC distant

Cause : le peering, le routage ou le filtrage bloque le trafic entre le réseau distant et le load balancer.

Solution : vérifiez dans l'ordre :

  1. le peering entre les deux réseaux et les route tables associées ;
  2. la règle entrante du security group du load balancer (port d'écoute et CIDR source) ;
  3. la valeur de load-balancer-source-ranges, qui doit inclure le CIDR du réseau source ;
  4. l'état des cibles avec kubectl get endpoints demo-interne -n demo : des endpoints vides indiquent un health check en échec.

Le health check échoue

Cause : les annotations osc-load-balancer-healthcheck-* ne correspondent pas à l'application — protocole, port ou chemin incorrects.

Solution : alignez les annotations du health check sur l'application, par exemple HTTP, le port 8080 et le chemin /healthz, puis vérifiez que les endpoints se repeuplent.

L'adresse IP a changé

Cause : le Service a été supprimé puis recréé — comportement attendu pour une adresse IP privée, qui n'est pas épinglable.

Solution : utilisez un enregistrement CNAME dans une zone DNS privée et automatisez la mise à jour de l'adresse. Pour une adresse réellement fixe, utilisez la variante IP pré-allouée statique.