Équilibrage de charge TCP/UDP interne

Cette page explique comment créer un équilibreur de charge TCP/UDP interne Compute Engine sur Google Kubernetes Engine.

Présentation

L'équilibrage de charge TCP/UDP interne rend les services du cluster accessibles aux applications qui s'exécutent sur le même réseau VPC, mais en dehors du cluster, et qui sont situées dans la même région Google Cloud. Par exemple, supposons que vous ayez un cluster dans la région us-west1 et que vous deviez rendre l'un de ses services accessible aux instances de VM Compute Engine s'exécutant dans cette région sur le même réseau VPC.

Vous pouvez créer un équilibreur de charge TCP/UDP interne en créant une ressource Service avec l'annotation cloud.google.com/load-balancer-type: "Internal" et une spécification type: LoadBalancer. Les instructions et l'exemple ci-dessous indiquent comment procéder.

Sans équilibrage de charge TCP/UDP interne, vous devez configurer un équilibreur de charge externe et des règles de pare-feu pour rendre l'application accessible en dehors du cluster.

L'équilibrage de charge TCP/UDP interne crée une adresse IP interne pour l'objet Service qui reçoit le trafic des clients dans le même réseau VPC et la même région de calcul. Si vous activez l'accès mondial, les clients de n'importe quelle région du même réseau VPC peuvent accéder à l'objet Service.

Tarifs

Les frais sont facturés d'après le modèle de tarification de Compute Engine. Pour plus d'informations, consultez la section sur la tarification de l'équilibrage de charge et des règles de transfert, ainsi que la page Compute Engine sur le Simulateur de coût Google Cloud.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

Configurez les paramètres gcloud par défaut à l'aide de l'une des méthodes suivantes :

  • Utilisez gcloud init pour suivre les instructions permettant de définir les paramètres par défaut.
  • Utilisez gcloud config pour définir individuellement l'ID, la zone et la région de votre projet.

Utiliser gcloud init

  1. Exécutez gcloud init et suivez les instructions :

    gcloud init

    Si vous utilisez SSH sur un serveur distant, utilisez l'option --console-only pour empêcher la commande d'ouvrir un navigateur :

    gcloud init --console-only
  2. Suivez les instructions pour autoriser gcloud à utiliser votre compte Google Cloud.
  3. Créez ou sélectionnez une configuration.
  4. Choisissez un projet Google Cloud.
  5. Choisissez une zone Compute Engine par défaut.

Utiliser gcloud config

  • Définissez votre ID de projet par défaut :
    gcloud config set project project-id
  • Si vous travaillez avec des clusters zonaux, définissez votre zone de calcul par défaut :
    gcloud config set compute/zone compute-zone
  • Si vous utilisez des clusters régionaux, définissez votre région de calcul par défaut :
    gcloud config set compute/region compute-region
  • Mettez à jour gcloud vers la dernière version :
    gcloud components update

Créer un objet Deployment

Le fichier manifeste suivant décrit un objet Deployment qui exécute 3 instances dupliquées d'une application Hello World.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app
spec:
  selector:
    matchLabels:
      app: hello
  replicas: 3
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
      - name: hello
        image: "gcr.io/google-samples/hello-app:2.0"

Le code source et le fichier Dockerfile de cet exemple d'application sont disponibles sur GitHub. Comme aucune variable d'environnement PORT n'est spécifiée, les conteneurs écoutent sur le port par défaut 8080.

Pour créer l'objet Deployment, créez le fichier my-deployment.yaml à partir du fichier manifeste, puis exécutez la commande suivante dans la fenêtre de votre terminal ou votre interface système :

kubectl apply -f my-deployment.yaml

Créer un équilibreur de charge TCP interne

Dans les sections suivantes, nous expliquons comment créer un équilibreur de charge TCP interne à l'aide d'un objet Service.

Écrire le fichier de configuration de l'objet Service

Dans l'exemple ci-dessous, un objet Service crée un équilibreur de charge TCP interne :

apiVersion: v1
kind: Service
metadata:
  name: ilb-service
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
  labels:
    app: hello
spec:
  type: LoadBalancer
  selector:
    app: hello
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

Configuration minimale de l'objet Service

Le fichier manifeste doit contenir les éléments suivants :

  • name, qui est le nom de l'objet Service (dans cet exemple, ilb-service)
  • L'annotation cloud.google.com/load-balancer-type: "Internal", qui spécifie qu'un équilibreur de charge TCP/UDP interne doit être configuré
  • type: LoadBalancer
  • Un champ spec: selector, afin de spécifier les pods que l'objet Service doit cibler, par exemple app: hello
  • port, qui est le port sur lequel l'objet Service est exposé, et targetPort, qui est le port sur lequel les conteneurs écoutent

Déployer l'objet Service

Pour créer l'équilibreur de charge TCP interne, créez le fichier my-service.yaml à partir du fichier manifeste, puis exécutez la commande suivante dans la fenêtre de votre terminal ou votre interface système :

kubectl apply -f my-service.yaml

Inspecter l'objet Service

Après le déploiement, inspectez l'objet Service pour vérifier qu'il a été configuré correctement.

Pour obtenir des informations détaillées sur l'objet Service, exécutez la commande suivante :

kubectl get service ilb-service --output yaml

Dans le résultat, vous pouvez voir l'adresse IP de l'équilibreur de charge interne sous status.loadBalancer.ingress. Notez qu'elle est différente de la valeur de clusterIP. Dans cet exemple, l'adresse IP de l'équilibreur de charge est 10.128.15.193 :

apiVersion: v1
kind: Service
metadata:
  ...
  labels:
    app: hello
  name: ilb-service
  ...
spec:
  clusterIP: 10.0.9.121
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 30835
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: hello
  sessionAffinity: None
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 10.128.15.193

Tous les pods comportant le libellé app: hello sont membres de cet objet Service. Il s'agit des pods pouvant être les destinataires finaux des requêtes envoyées à votre équilibreur de charge interne.

Les clients appellent l'objet Service à l'aide de l'adresse IP loadBalancer et du port TCP spécifié dans le champ port de son fichier manifeste. La requête est transmise à l'un des pods membres du port TCP spécifié dans le champ targetPort. Ainsi, dans l'exemple précédent, un client appelle l'objet Service à l'adresse 10.128.15.193 sur le port TCP 80. La requête est transmise à l'un des pods membres sur le port TCP 8080. Notez que le pod membre doit avoir un conteneur qui écoute sur le port 8080.

La valeur nodePort de 30835 est superflue. Elle n'est pas pertinente pour votre équilibreur de charge interne.

Afficher la règle de transfert de l'équilibreur de charge

Un équilibreur de charge interne est mis en œuvre en tant que règle de transfert. La règle de transfert comporte un service de backend, qui possède un groupe d'instances.

L'adresse de l'équilibreur de charge interne, 10.128.15.193 dans l'exemple précédent, est identique à l'adresse de la règle de transfert. Pour afficher la règle de transfert qui met en œuvre votre équilibreur de charge interne, commencez par répertorier toutes les règles de transfert de votre projet :

gcloud compute forwarding-rules list --filter="loadBalancingScheme=INTERNAL"

Dans le résultat, recherchez la règle de transfert qui possède la même adresse que votre équilibreur de charge interne, 10.128.15.193 dans cet exemple.

NAME                          ... IP_ADDRESS  ... TARGET
...
aae3e263abe0911e9b32a42010a80008  10.128.15.193   us-central1/backendServices/aae3e263abe0911e9b32a42010a80008

Le résultat affiche le service de backend associé (ae3e263abe0911e9b32a42010a80008, dans cet exemple).

Décrivez le service de backend :

gcloud compute backend-services describe aae3e263abe0911e9b32a42010a80008 --region us-central1

Le résultat affiche le groupe d'instances associé (k8s-ig--2328fa39f4dc1b75, dans cet exemple) :

backends:
- balancingMode: CONNECTION
  group: .../us-central1-a/instanceGroups/k8s-ig--2328fa39f4dc1b75
...
kind: compute#backendService
loadBalancingScheme: INTERNAL
name: aae3e263abe0911e9b32a42010a80008
...

Fonctionnement de l'abstraction Service

Lorsqu'un paquet est géré par votre règle de transfert, il est transféré vers l'un de vos nœuds de cluster. Lorsque le paquet arrive sur le nœud de cluster, les adresses et le port sont les suivants :

Adresse IP de destination Règle de transfert (10.128.15.193 dans cet exemple)
Port TCP de destination Champ port du service (80 dans cet exemple)

Notez que la règle de transfert (soit votre équilibreur de charge interne) ne modifie pas l'adresse IP de destination ni le port de destination. À la place, les règles iptables du nœud de cluster acheminent le paquet vers un pod approprié. Les règles iptables remplacent l'adresse IP de destination par une adresse IP de pod et le port de destination par la valeur targetPort de l'objet Service (8080 dans cet exemple).

Vérifier l'équilibreur de charge TCP interne

Connectez-vous via SSH à une instance de VM et exécutez la commande suivante :

curl load-balancer-ip

load-balancer-ip correspond à votre adresse IP LoadBalancer Ingress.

La réponse affiche le résultat de hello-app :

Hello, world!
Version: 2.0.0
Hostname: hello-app-77b45987f7-pw54n

L'exécution de la commande à l'extérieur du même réseau VPC ou de la même région entraîne une erreur de dépassement de délai. Si vous configurez l'accès mondial, les clients de n'importe quelle région du même réseau VPC peuvent accéder à l'équilibreur de charge.

Effectuer un nettoyage

Vous pouvez supprimer les objets Deployment et Service à l'aide de kubectl delete ou de Cloud Console.

kubectl

Supprimer l'objet Deployment

Pour supprimer l'objet Deployment, exécutez la commande suivante :

kubectl delete deployment hello-app

Supprimer l'objet Service

Pour supprimer l'objet Service, exécutez la commande suivante :

kubectl delete service ilb-service

Console

Supprimer l'objet Deployment

Pour supprimer l'objet Deployment, procédez comme suit :

  1. Accédez au menu "Charges de travail" de Google Kubernetes Engine dans Cloud Console.

    Accéder au menu "Charges de travail"

  2. Dans le menu, sélectionnez la charge de travail souhaitée.

  3. Cliquez sur Supprimer.

  4. Dans le menu de confirmation, cliquez sur Supprimer.

Supprimer l'objet Service

Pour supprimer l'objet Service, procédez comme suit :

  1. Accédez au menu "Services" de Google Kubernetes Engine dans Cloud Console.

    Accéder au menu "Services"

  2. Dans le menu, sélectionnez l'objet Service souhaité.

  3. Cliquez sur Supprimer.

  4. Dans le menu de confirmation, cliquez sur Supprimer.

Informations spécifiques aux objets Ingress existants

L'équilibreur de charge TCP/UDP interne n'est pas compatible avec les objets Ingress utilisant le mode d'équilibrage UTILIZATION. Pour utiliser l'équilibrage de charge TCP/UDP interne avec des objets Ingress existants, celles-ci doivent utiliser le mode d'équilibrage RATE.

Si votre cluster dispose d'une ressource Ingress existante créée avec Kubernetes 1.7.1 ou version antérieure, celle-ci n'est pas compatible avec les équilibreurs de charge TCP/UDP internes. Les ressources BackendService antérieures générées par des objets de la ressource Ingress de Kubernetes ont été créées sans mode d'équilibrage spécifié. Par défaut, l'API utilisait le mode d'équilibrage UTILIZATION pour les équilibreurs de charge HTTP. Cependant, les équilibreurs de charge TCP/UDP internes ne peuvent pas être pointés vers des groupes d'instances avec d'autres équilibreurs de charge utilisant UTILIZATION.

Déterminer le mode d'équilibrage utilisé par l'objet Ingress

Pour déterminer le mode d'équilibrage utilisé par l'objet Ingress, exécutez les commandes suivantes à partir de la fenêtre d'interface système ou de terminal :

GROUPNAME=`kubectl get configmaps ingress-uid -o jsonpath='k8s-ig--{.data.uid}' --namespace=kube-system`
gcloud compute backend-services list --format="table(name,backends[].balancingMode,backends[].group)" | grep $GROUPNAME

Ces commandes exportent une variable d'interface système, GROUPNAME, qui récupère le nom du groupe d'instances du cluster. Ensuite, les ressources Compute Engine backend service du projet sont interrogées, et les résultats sont affinés en fonction du contenu de $GROUPNAME.

Le résultat ressemble à ce qui suit :

k8s-be-31210--...  [u'RATE']       us-central1-b/instanceGroups/k8s-ig--...
k8s-be-32125--...  [u'RATE']       us-central1-b/instanceGroups/k8s-ig--...

Si le résultat renvoie des entrées RATE ou ne renvoie aucune entrée, les équilibreurs de charge internes sont compatibles et aucune tâche supplémentaire n'est nécessaire.

Si le résultat renvoie des entrées marquées UTILIZATION, vos objets Ingress ne sont pas compatibles.

Pour mettre à jour vos ressources Ingress afin de les rendre compatibles avec un équilibreur de charge TCP/UDP interne, vous pouvez créer un cluster exécutant Kubernetes 1.7.2 ou version ultérieure, puis migrer vos services vers ce cluster.

Paramètres de l'objet Service

Les paramètres suivants sont compatibles avec les services LoadBalancer internes de GKE.

Fonctionnalité Résumé Champ de service Compatibilité avec les versions de GKE
Règle de trafic externe local Détermine si la charge du trafic externe est équilibrée ou non sur les nœuds GKE. spec:externalTrafficPolicy:Local GKE 1.14+
Plages sources d'équilibreur de charge Configure des règles de pare-feu facultatives dans GKE et dans le VPC pour n'autoriser que certaines plages sources. spec:loadBalancerSourceRanges Toutes les versions compatibles
Adresse IP d'équilibreur de charge Spécifie une adresse IP pour les équilibreurs de charge. spec:loadBalancerIP Toutes les versions compatibles
Sous-réseau d'équilibreur de charge Spécifie le sous-réseau à partir duquel l'équilibreur de charge doit provisionner automatiquement une adresse IP. metadata:annotations: networking.gke.io/internal-load-balancer-subnet En version bêta dans GKE 1.17+ et 1.16.8-gke.10+
Accès mondial Rend l'adresse IP virtuelle de l'équilibreur de charge TCP/UDP accessible par les clients de toutes les régions GCP. metadata:annotations: networking.gke.io/internal-load-balancer-allow-global-access En version bêta dans GKE 1.16+
Tous les ports Permet à l'équilibreur de charge TCP/UDP de transférer tous les ports plutôt que des ports spécifiques ND Pas de compatibilité native

Règle de trafic externe

externalTrafficPolicy est une option de l'objet Service standard qui définit comment et si la charge du trafic entrant sur un nœud GKE est équilibrée. Cluster est la règle par défaut, mais Local est souvent utilisée pour conserver l'adresse IP source du trafic entrant dans un nœud de cluster. En effet, Local désactive l'équilibrage de charge sur le nœud du cluster afin que le trafic reçu par un pod local voie l'adresse source d'origine.

externalTrafficPolicy est compatible avec les services LoadBalancer internes (via l'équilibreur de charge TCP/UDP), mais le comportement de l'équilibrage de charge dépend de l'origine du trafic et de la règle de trafic configurée.

Pour le trafic provenant de l'extérieur du cluster et destiné à un équilibreur de charge TCP/UDP, il aura le comportement suivant s'il existe au moins un pod de l'objet Service opérationnel dans le cluster :

  • Règle Cluster : la charge du trafic sera équilibrée sur n'importe quel nœud GKE opérationnel du cluster, puis le service kube-proxy l'enverra à un nœud avec le pod.
  • Règle Local : les nœuds qui ne possèdent pas l'un des pods backend apparaîtront comme non opérationnels pour l'équilibreur de charge TCP/UDP. Le trafic ne sera envoyé qu'à l'un des nœuds de cluster opérationnels restants qui disposent du pod. Le trafic n'est pas acheminé à nouveau par le service kube-proxy et sera envoyé directement au pod local avec ses informations d'en-tête d'adresse IP intactes.

Si le trafic vers une adresse IP de service LoadBalancer donnée provient d'un nœud GKE à l'intérieur du cluster, son comportement est différent. Le tableau suivant récapitule le comportement du trafic provenant d'un nœud ou d'un pod à l'intérieur du cluster et destiné à un pod membre d'un service LoadBalancer :

externalTrafficPolicy Le pod membre de l'objet Service s'exécute-t-il sur le même nœud que celui d'où provient le trafic ? Comportement du trafic
Cluster Oui Les paquets sont transmis à tout pod membre, soit sur le même nœud, soit sur un nœud différent.
Cluster Non Les paquets sont transmis à tout pod membre, qui doit se trouver sur un nœud différent.
Local Oui Les paquets sont transmis à tout pod membre sur le même nœud.
Local Non

Kubernetes 1.14 et versions antérieures : les paquets sont supprimés.

Kubernetes 1.15 et versions ultérieures : les paquets sont transmis à tout pod membre, qui doit se trouver sur un nœud différent.

Plages sources d'équilibreur de charge

Le tableau spec: loadBalancerSourceRanges spécifie une ou plusieurs plages d'adresses IP internes. loadBalancerSourceRanges limite le trafic qui transite par l'équilibreur de charge aux adresses IP spécifiées dans ce champ. Avec cette configuration, kube-proxy crée les règles iptables correspondantes dans les nœuds Kubernetes. GKE crée également automatiquement une règle de pare-feu dans votre réseau VPC. Si vous omettez de renseigner ce champ, votre objet Service accepte le trafic provenant de n'importe quelle adresse IP (0.0.0.0/0).

Pour plus d'informations sur la configuration de loadBalancerSourceRanges afin de restreindre l'accès à votre équilibreur de charge TCP/UDP interne, consultez la page Configurer les pare-feu du fournisseur cloud. Pour en savoir plus sur la spécification de l'objet Service, consultez la documentation de référence de l'API Service.

Adresse IP d'équilibreur de charge

Le paramètre spec: loadBalancerIP vous permet de choisir une adresse IP spécifique pour l'équilibreur de charge. L'adresse IP ne doit pas être utilisée par un autre équilibreur de charge TCP/UDP interne ou un autre objet Service. Par défaut, une adresse IP éphémère est attribuée. Pour plus d'informations, consultez la page Réserver une adresse IP interne statique.

Sous-réseau d'équilibreur de charge (version bêta)

Par défaut, GKE déploie un équilibreur de charge TCP/UDP interne à l'aide de la plage du sous-réseau de nœud. Le sous-réseau peut être spécifié par l'utilisateur pour chaque objet Service à l'aide de l'annotation networking.gke.io/internal-load-balancer-subnet. Cela permet de mettre en place des pare-feu séparés pour les adresses IP d'équilibreurs de charge internes et pour les adresses IP de nœuds, ou de partager le même sous-réseau de l'objet Service sur plusieurs clusters GKE. Ce paramètre n'est pertinent que pour les services LoadBalancer TCP/UDP internes.

Le sous-réseau doit exister avant d'être référencé par la ressource Service, car GKE ne gère pas le cycle de vie du sous-réseau lui-même. Le sous-réseau doit également se trouver dans le même VPC et la même région que le cluster GKE. Dans cette étape, il est créé hors bande depuis GKE :

gcloud compute networks subnets create gke-vip-subnet \
    --network=default \
    --range=10.23.0.0/24 \
    --region=us-central1

La définition de l'objet Service suivante utilise internal-load-balancer-subnet pour référencer le sous-réseau par son nom. Par défaut, une adresse IP disponible du sous-réseau est automatiquement sélectionnée. Vous pouvez également spécifier loadBalancerIP, mais il doit faire partie du sous-réseau référencé.

Il existe plusieurs façons de partager ce sous-réseau d'équilibreur de charge interne pour exécuter différents cas d'utilisation :

  • Plusieurs sous-réseaux pour des groupes d'objets Service dans le même cluster
  • Un seul sous-réseau pour tous les objets Service d'un cluster
  • Un seul sous-réseau partagé entre plusieurs clusters et plusieurs objets Service
apiVersion: v1
kind: Service
metadata:
  name: ilb-service
  annotations:
    networking.gke.io/load-balancer-type: "Internal"
    networking.gke.io/internal-load-balancer-subnet: "gke-vip-subnet"
  labels:
    app: hello
spec:
  type: LoadBalancer
  loadBalancerIP: 10.23.0.15
  selector:
    app: hello
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

Accès mondial (version bêta)

L'accès mondial est un paramètre facultatif pour les services LoadBalancer internes. Il permet aux clients de n'importe quelle région de votre réseau VPC d'accéder à l'équilibreur de charge TCP/UDP interne. Sans accès mondial, le trafic provenant des clients de votre réseau VPC doit se trouver dans la même région que l'équilibreur de charge. L'accès mondial permet aux clients de n'importe quelle région d'accéder à l'équilibreur de charge. Les instances backend doivent toujours se trouver dans la même région que l'équilibreur de charge.

L'accès mondial est activé pour chaque objet Service à l'aide de l'annotation suivante : networking.gke.io/internal-load-balancer-allow-global-access: "true".

L'accès mondial n'est pas compatible avec les anciens réseaux. Les coûts normaux du trafic interrégional s'appliquent lorsque l'accès mondial est utilisé entre les régions. Pour plus d'informations sur la tarification du réseau liée à la sortie entre les régions, consultez la page Tarifs du réseau. L'accès mondial est disponible en version bêta sur les clusters GKE 1.16 et versions ultérieures.

Tous les ports

Si vous créez un équilibreur de charge TCP/UDP interne à l'aide d'un service annoté, il est impossible de configurer une règle de transfert qui utilise tous les ports. Toutefois, en procédant manuellement, vous pouvez choisir le groupe d'instances de vos nœuds Google Kubernetes Engine comme backend. Les services Kubernetes de type: NodePort sont disponibles via l'ILB.

Restrictions applicables aux équilibreurs de charge TCP/UDP internes

  • Pour les clusters exécutant Kubernetes 1.7.3 et versions antérieures, vous ne pouvez utiliser que des équilibreurs de charge TCP/UDP internes avec des sous-réseaux en mode automatique. Par contre, pour les clusters exécutant Kubernetes 1.7.4 et versions ultérieures, vous pouvez utiliser des équilibreurs de charge internes avec des sous-réseaux en mode personnalisé, en plus des sous-réseaux en mode automatique.
  • Pour les clusters exécutant Kubernetes 1.7.X ou versions ultérieures, lorsque l'adresse ClusterIP reste inchangée, les équilibreurs de charge TCP/UDP internes ne peuvent pas utiliser d'adresses IP réservées. Le champ spec.loadBalancerIP peut tout de même être défini à l'aide d'une adresse IP inutilisée afin d'attribuer une adresse IP interne spécifique. Les modifications apportées aux ports, aux protocoles ou à l'affinité de session peuvent entraîner la modification de ces adresses IP.

Restrictions applicables aux équilibreurs de charge UDP internes

  • Les équilibreurs de charge UDP internes ne sont pas compatibles avec sessionAffinity: ClientIP.

Limites

Un service Kubernetes avec type: Loadbalancer et l'annotation cloud.google.com/load-balancer-type: Internal crée un ILB qui cible le service Kubernetes. Le nombre de ces objets Service est limité par le nombre de règles de transfert internes que vous pouvez créer dans un réseau VPC. Pour plus d'informations, consultez la section Par réseau.

Dans un cluster GKE, une règle de transfert interne pointe vers tous les nœuds du cluster. Chaque nœud de cluster est une VM de backend pour l'ILB. Le nombre maximal de ces VM pour un ILB est de 250, quelle que soit la manière dont elles sont associées aux groupes d'instances. Le nombre maximal de nœuds dans un cluster GKE avec un ILB est donc de 250. Si l'autoscaling est activé sur votre cluster, assurez-vous qu'il ne dépasse pas 250 nœuds.

Pour en savoir plus sur ces limites, consultez la page Quotas de ressources du VPC.

Étapes suivantes