Configurer l'équilibrage de charge groupé avec MetalLB

Cette page explique comment configurer l'équilibrage de charge groupé avec MetalLB pour Google Distributed Cloud. Les équilibreurs de charge MetalLB s'exécutent sur un pool de nœuds de calcul dédié ou sur les mêmes nœuds que le plan de contrôle.

Pour obtenir des exemples de topologies d'équilibrage de charge disponibles dans Google Distributed Cloud, consultez la page Présentation des équilibreurs de charge.

Conditions requises

  • Tous les nœuds d'équilibreur de charge doivent se trouver dans le même sous-réseau de couche 2.
  • Tous les adresses IP virtuelles doivent se trouver dans le sous-réseau des nœuds d'équilibrage de charge et pouvoir être acheminés par la passerelle du sous-réseau.
  • La passerelle du sous-réseau d'équilibrage de charge doit écouter les messages ARP gratuits et transmettre les paquets ARP aux nœuds d'équilibrage de charge.

Champs de configuration

Modifiez la section cluster.spec.loadBalancer du fichier de configuration de cluster pour configurer l'équilibrage de charge groupé. Pour obtenir des informations sur les fichiers de configuration de cluster et pour obtenir des exemples de configurations valides, consultez l'une des pages suivantes :

loadBalancer.mode

Cette valeur doit être définie sur bundled pour activer l'équilibrage de charge groupé.

loadBalancer.ports.controlPlaneLBPort

Cette valeur spécifie le port de destination à utiliser pour le trafic envoyé au plan de contrôle Kubernetes (les serveurs d'API Kubernetes).

loadBalancer.vips.controlPlaneVIP

Cette valeur spécifie l'adresse IP de destination à utiliser pour le trafic envoyé au plan de contrôle Kubernetes (les serveurs d'API Kubernetes). Cette adresse IP doit se trouver dans le même sous-réseau de couche 2 que les nœuds du cluster. Ne répertoriez pas cette adresse dans la section address pools du fichier de configuration.

loadBalancer.vips.ingressVIP

Cette valeur spécifie l'adresse IP à utiliser pour les services placés derrière l'équilibreur de charge pour le trafic entrant. Ce champ n'est pas autorisé dans les fichiers de configuration du cluster d'administrateur. Cette adresse doit être répertoriée dans la section pools d'adresses de la configuration.

loadBalancer.addressPools

Cette section de la configuration contient un ou plusieurs pools d'adresses. Chaque pool d'adresses spécifie une liste de plages d'adresses IP. Lorsque vous créez un service de type LoadBalancer, les adresses IP externes du service sont choisies dans ces plages.

Les pools d'adresses sont spécifiés au format suivant:

- name: POOL_NAME
  avoidBuggyIPs: BOOLEAN
  manualAssign: BOOLEAN
  addresses:
  - IP_RANGE
  - IP_RANGE2
  • name: nom du pool d'adresses, pool-name, à des fins d'organisation. Ce champ est immuable.
  • avoidBuggyIPs: (facultatif) true ou false. Si la valeur est true, le pool omet les adresses IP se terminant par .0 et .255. Certains matériels réseau suppriment le trafic vers ces adresses spéciales. Vous pouvez omettre ce champ, dont la valeur par défaut est false. Ce champ est modifiable.
  • manualAssign: (facultatif) true ou false. Si la valeur est true, les adresses de ce pool ne sont pas automatiquement attribuées aux services Kubernetes. Si la valeur est true, une adresse IP de ce pool ne va être utilisée que si elle est spécifiée explicitement par un service. Vous pouvez omettre ce champ, dont la valeur par défaut est false. Ce champ est modifiable.
  • addresses : liste d'une ou de plusieurs plages d'adresses IP qui ne se chevauchent pas. ip-range peut être spécifié en notation CIDR (comme 198.51.100.0/24) ou en notation de plage (comme 198.51.100.0-198.51.100.10, sans espace autour du tiret). Ce champ est immuable.

Les plages d'adresses IP de la liste addresses ne doivent pas se chevaucher et doivent se trouver dans le même sous-réseau que les nœuds qui exécutent les équilibreurs de charge.

loadBalancer.nodePoolSpec

Cette section de la configuration spécifie une liste de nœuds sur lesquels exécuter les équilibreurs de charge. Les nœuds d'équilibrage de charge peuvent exécuter des charges de travail standards par défaut. Il n'existe pas de rejet spécial sur ces nœuds. Bien que les nœuds du pool de nœuds de l'équilibreur de charge puissent exécuter des charges de travail, ils sont distincts des nœuds des pools de nœuds de calcul. Vous ne pouvez pas inclure un nœud de cluster donné dans plusieurs pools de nœuds. Le chevauchement d'adresses IP de nœuds entre les pools de nœuds bloque la création de clusters et d'autres opérations de cluster.

Si vous souhaitez empêcher l'exécution de charges de travail sur un nœud du pool de nœuds de l'équilibreur de charge, ajoutez le rejet suivant au nœud:

node-role.kubernetes.io/load-balancer:NoSchedule

Google Distributed Cloud ajoute des tolérances pour ce rejet aux pods requis pour l'équilibrage de charge.

L'exemple suivant montre un pool de nœuds d'équilibrage de charge avec deux nœuds. Le premier nœud dispose d'une adresse IP standard nodePoolSpec.nodes.address ("1.2.3.4") et d'une adresse IP Kubernetes nodePoolSpec.nodes.k8sIP (10.0.0.32). Lorsque vous spécifiez l'adresse k8sIP facultative pour un nœud, elle est dédiée à la gestion du trafic de données pour le nœud, telles que les requêtes et les réponses pour l'API Kubernetes, le kubelet et les charges de travail. Dans ce cas, l'adresse IP standard nodePoolSpec.nodes.address est utilisée pour les connexions SSH au nœud pour les opérations de cluster administratives. Si vous ne spécifiez pas d'adresse k8sIP, l'adresse IP de nœud standard gère tout le trafic du nœud.

nodePoolSpec:
  nodes:
  - address: 1.2.3.4
    k8sIP: 10.0.0.32
  - address: 10.0.0.33

Par défaut, tous les nœuds du pool de nœuds de l'équilibreur de charge doivent se trouver dans le même sous-réseau de couche 2 que les adresses IP virtuelles de l'équilibreur de charge configurées dans la section loadBalancer.addressPools du fichier de configuration. Toutefois, si vous spécifiez une adresse IP Kubernetes k8sIP pour un nœud, seule cette adresse doit se trouver dans le même sous-réseau de couche 2 que les autres adresses IP virtuelles de l'équilibreur de charge.

Si nodePoolSpec n'est pas défini, les équilibreurs de charge groupés s'exécutent sur les nœuds du plan de contrôle. Si possible, nous vous recommandons d'exécuter des équilibreurs de charge sur des pools de nœuds distincts.

Équilibrage de charge du plan de contrôle

L'équilibreur de charge du plan de contrôle diffuse l'adresse IP virtuelle (VIP) du plan de contrôle. Google Distributed Cloud exécute Keepalived et HAProxy en tant que pods statiques Kubernetes sur les nœuds de l'équilibreur de charge pour annoncer l'adresse IP virtuelle de plan de contrôle. Keepalived utilise le protocole VRRP (Virtual Router Redundancy Protocol) sur les nœuds d'équilibrage de charge, pour une haute disponibilité.

Équilibrage de charge du plan de données

L'équilibreur de charge du plan de données est destiné à tous les services Kubernetes de type LoadBalancer. Google Distributed Cloud utilise MetalLB en mode couche 2 pour l'équilibrage de charge du plan de données. L'équilibrage de charge du plan de données ne peut être configuré que via Google Distributed Cloud. Ne modifiez pas directement le fichier ConfigMap de MetalLB. Vous pouvez utiliser toutes les fonctionnalités de MetalLB, y compris le partage d'adresses IP entre plusieurs services. Pour plus d'informations sur les fonctionnalités, consultez la documentation de MetalLB.

MetaLB exécute un pod d'enceintes sur chaque nœud avec un daemonset, en utilisant memberlist pour la haute disponibilité. Chaque service Kubernetes dispose d'un nœud d'équilibrage de charge dédié à metalLB, plutôt qu'un nœud pour l'ensemble du cluster. De cette façon, le trafic est réparti entre les nœuds d'équilibrage de charge s'il existe plusieurs services.

Les équilibreurs de charge du plan de données peuvent s'exécuter sur les nœuds du plan de contrôle ou sur un sous-ensemble de nœuds de calcul. En regroupant les équilibreurs de charge du plan de données sur les nœuds du plan de contrôle, vous augmentez l'utilisation de ces nœuds du plan de contrôle. De plus, le regroupement sur les nœuds du plan de contrôle augmente également le risque de surcharger le plan de contrôle et augmente le profil de risque des informations confidentielles du plan de contrôle, telles que les clés SSH.

Séparation de l'équilibreur de charge

Avant la version 1.32, lorsque vous configurez l'équilibrage de charge de couche 2 avec MetalLB, les équilibreurs de charge du plan de contrôle et du plan de données s'exécutent sur les mêmes nœuds. Selon votre configuration, les équilibreurs de charge s'exécutent tous sur les nœuds du plan de contrôle ou dans le pool de nœuds de l'équilibreur de charge.

Le schéma suivant montre la configuration par défaut de l'équilibreur de charge groupé, avec des équilibreurs de charge du plan de contrôle et du plan de données exécutés sur des nœuds du plan de contrôle ou les deux exécutés dans le pool de nœuds de l'équilibreur de charge:

Configuration par défaut de l'équilibreur de charge

Avec les clusters de la version 1.32, vous pouvez configurer les équilibreurs de charge du plan de contrôle pour qu'ils s'exécutent sur les nœuds du plan de contrôle et les équilibreurs de charge du plan de données pour qu'ils s'exécutent dans le pool de nœuds de l'équilibreur de charge. Vous pouvez spécifier cette séparation des équilibreurs de charge lorsque vous créez un cluster de la version 1.32, ou mettre à jour un cluster de la version 1.32 pour migrer les équilibreurs de charge du plan de données des nœuds du plan de contrôle vers le pool de nœuds de l'équilibreur de charge.

La configuration du cluster pour les équilibreurs de charge distincts doit ressembler à l'exemple suivant:

apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: hybrid-ha-lb
  namespace: cluster-hybrid-ha-lb
spec:
  type: hybrid
  profile: default
  anthosBareMetalVersion: 1.32
  gkeConnect:
    projectID: project-fleet
  controlPlane:
    loadBalancer:
      mode: bundled
    nodePoolSpec:
      nodes:
      - address: 10.200.0.2
      - address: 10.200.0.3
      - address: 10.200.0.4
  clusterNetwork:
    pods:
      cidrBlocks:
      - 192.168.0.0/16
    services:
      cidrBlocks:
      - 10.96.0.0/20
  ...
  loadBalancer:
    mode: bundled
    ...
    nodePoolSpec:
      nodes:
      - address: 10.200.0.5
      - address: 10.200.0.6
      - address: 10.200.0.7
  clusterOperations:
  ...

Équilibreurs de charge distincts lors de la création d'un cluster

Si vous créez un cluster de version 1.32 ou ultérieure, vous pouvez configurer les équilibreurs de charge pour exécuter les équilibreurs de charge du plan de contrôle sur les nœuds du plan de contrôle et les équilibreurs de charge du plan de données sur le pool de nœuds de l'équilibreur de charge.

Le schéma suivant montre les équilibreurs de charge du plan de contrôle et du plan de données séparés sur différents nœuds:

Équilibreurs de charge du plan de contrôle et du plan de données distincts

Pour séparer les équilibreurs de charge lorsque vous créez un cluster, procédez comme suit:

  1. Dans le fichier de configuration du cluster, spécifiez un pool de nœuds d'équilibrage de charge avec loadBalancer.nodePoolSpec, comme décrit dans la section loadBalancer.nodePoolSpec de ce document.

  2. Ajoutez controlPlane.loadBalancer.mode au fichier de configuration du cluster et définissez la valeur mode sur bundled.

  3. Terminez de configurer votre cluster, puis exécutez bmctl create cluster pour le créer.

Migrer les équilibreurs de charge du plan de données hors du plan de contrôle

Si vous disposez d'un cluster de version 1.32 ou ultérieure où ni controlPlane.loadBalancer.mode ni loadBalancer.nodePoolSpec n'est défini, l'équilibreur de charge du plan de contrôle et l'équilibreur de charge du plan de données s'exécutent dans le pool de nœuds du plan de contrôle. Vous pouvez mettre à jour le cluster pour migrer l'équilibreur de charge du plan de données vers un pool de nœuds d'équilibreur de charge.

Le schéma suivant montre les équilibreurs de charge du plan de contrôle et du plan de données séparés après la migration de l'équilibreur de charge du plan de données hors des nœuds du plan de contrôle:

Équilibreur de charge du plan de données migré vers le pool de nœuds de l'équilibreur de charge

Pour migrer l'équilibreur de charge du plan de données vers un pool de nœuds d'équilibreur de charge lorsque vous mettez à jour un cluster, procédez comme suit:

  1. Dans le fichier de configuration du cluster, spécifiez un pool de nœuds d'équilibrage de charge avec loadBalancer.nodePoolSpec, comme décrit dans la section loadBalancer.nodePoolSpec de ce document.

  2. Ajoutez controlPlane.loadBalancer.mode au fichier de configuration du cluster et définissez la valeur mode sur bundled.

  3. Mettez à jour le cluster en exécutant la commande suivante:

    bmctl update cluster -c CLUSTER_NAME --kubeconfig=ADMIN_KUBECONFIG
    

    Remplacez les éléments suivants :

    • CLUSTER_NAME: nom du cluster que vous mettez à jour.

    • ADMIN_KUBECONFIG : chemin d'accès au fichier kubeconfig du cluster d'administrateur

Conserver l'adresse IP source du client

Le Service LoadBalancer créé avec la solution groupée d'équilibrage de charge de couche 2 utilise le paramètre Cluster par défaut pour la règle de trafic externe. Ce paramètre, spec.externalTrafficPolicy: Cluster, achemine le trafic externe vers les points de terminaison à l'échelle du cluster, mais il masque également l'adresse IP source du client.

Google Distributed Cloud propose deux méthodes pour conserver l'adresse IP source du client:

  • Définissez le mode de transfert pour l'équilibrage de charge sur "Direct Server Return" (DSR). Pour en savoir plus sur le mode de transfert DSR, y compris des instructions pour l'activer, consultez la section Configurer le mode de transfert d'équilibrage de charge.

  • Définissez la stratégie de trafic externe sur "local" pour le service LoadBalancer, puis configurez les services et l'Ingress associés en conséquence. Les sections suivantes expliquent comment configurer votre cluster pour utiliser cette méthode.

LoadBalancer services

Lorsque vous utilisez externalTrafficPolicy: Local dans vos Services LoadBalancer, configurez les pods de votre application pour qu'ils s'exécutent exactement sur les nœuds d'équilibreur de charge. Ajoutez le nodeSelector suivant aux pods de votre application pour effectuer cette modification :

apiVersion: v1
kind: Pod
...
spec:
  nodeSelector:
      baremetal.cluster.gke.io/lbnode: "true"
...

NodePort services

Kubernetes effectue la traduction d'adresse réseau source (SNAT) pour les Services NodePort. Pour conserver les adresses IP sources du client, définissez service.spec.externalTrafficPolicy sur Local. Kubernetes n'effectuera plus de traduction NAT source, mais vous devez vous assurer que des pods s'exécutent exactement sur l'adresse IP du nœud que vous avez choisi.

Entrée

Si vos applications sont des services HTTP, vous pouvez obtenir une visibilité sur l'adresse IP du client en configurant des composants d'entrée :

  1. Ouvrez le Service istio-ingress pour le modifier :

    kubectl edit service -n gke-system istio-ingress
    
  2. Ajoutez externalTrafficPolicy: Local au fichier spec, enregistrez et quittez l'éditeur.

    apiVersion: v1
    kind: Service
    ...
    spec:
    ...
      externalTrafficPolicy: Local
    
  3. Ouvrez le Déploiement istio-ingress pour le modifier :

    kubectl edit deployment -n gke-system istio-ingress
    
  4. Ajoutez l'élément nodeSelector suivant au Déploiement. enregistrez et quittez l'éditeur.

    apiVersion: apps/v1
    kind: Deployment
    ...
    spec:
      ...
      template:
        ...
        spec:
          ...
          nodeSelector:
              baremetal.cluster.gke.io/lbnode: "true"
    ...
    

Tous vos services derrière Ingress affichent désormais un en-tête X-Forwarded-For avec l'adresse IP du client, comme dans l'exemple suivant :

X-Forwarded-For: 21.0.104.4