Déployer une passerelle de transmission TLS

Ce document explique comment déployer une ressource Gateway Kubernetes configurée pour le passthrough TLS afin d'activer le routage basé sur l'indication du nom du serveur (SNI) dans Google Kubernetes Engine (GKE). Cette approche préserve le chiffrement de bout en bout et le protocole TLS mutuel (mTLS) entre les clients et les pods de backend, accepte les protocoles non HTTP basés sur TLS et conserve les adresses IP.

Ce document s'adresse aux architectes cloud, aux spécialistes de la mise en réseau et aux développeurs qui conçoivent, déploient et gèrent la mise en réseau chiffrée pour les charges de travail conteneurisées. Pour en savoir plus sur les rôles courants et les exemples de tâches, consultez Rôles utilisateur et tâches courantes de GKE.

Présentation

En plus des équilibreurs de charge d'application HTTP et HTTPS de couche 7, le contrôleur de passerelle GKE est compatible avec les équilibreurs de charge réseau proxy de couche 4 (équilibreurs de charge proxy TCP) configurés avec le passthrough TLS.

Avec le passthrough TLS, l'équilibreur de charge n'interrompt pas et ne déchiffre pas la session TLS. Au lieu de cela, lorsqu'un client lance un handshake TLS, l'équilibreur de charge inspecte le message ClientHello non chiffré pour lire le nom d'hôte de l'indication du nom du serveur (SNI). En fonction de ce nom d'hôte SNI, l'équilibreur de charge achemine le flux TCP brut chiffré vers le service Kubernetes de backend approprié, où les pods de votre application mettent fin directement au protocole TLS.

Lorsque vous utilisez la transmission TLS avec l'API Gateway, vous pouvez effectuer les opérations suivantes :

  • Maintenir le chiffrement de bout en bout et assurer la conformité zéro confiance : chiffrez entièrement le trafic du client au pod de backend sans donner au l'équilibreur de charge l'accès aux clés privées ou aux données en texte brut.
  • Utiliser l'authentification TLS mutuelle (mTLS) : authentifiez les clients directement au niveau de la couche d'application du backend.
  • Conserver les adresses IPv4 : multiplexez plusieurs services TLS indépendants sur des domaines ou sous-domaines distincts à l'aide d'une seule adresse IP et d'un seul port de passerelle (par exemple, 443).
  • Prise en charge des protocoles non HTTP basés sur TLS : acheminez le trafic chiffré pour les charges de travail avec état, les bases de données, les services gRPC personnalisés ou les protocoles propriétaires exécutés sur TLS.

Ressources GatewayClass compatibles

Les GatewayClasses GKE suivantes sont compatibles avec les écouteurs de relais TLS et les ressources TLSRoute :

  • gke-l7-regional-external-managed
  • gke-l7-regional-external-managed-mc
  • gke-l7-rilb
  • gke-l7-rilb-mc
  • gke-l7-cross-regional-internal-managed-mc

Pour obtenir une comparaison complète des fonctionnalités de GatewayClass, consultez Fonctionnalités de GatewayClass.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Activez l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Si vous souhaitez utiliser la Google Cloud CLI pour cette tâche, installez puis initialisez la gcloud CLI. Si vous avez déjà installé la gcloud CLI, obtenez la dernière version en exécutant la commande gcloud components update. Il est possible que les versions antérieures de la gcloud CLI ne permettent pas d'exécuter les commandes de ce document.
  • Vérifiez que vous disposez d'un cluster Autopilot ou Standard existant exécutant GKE version 1.35 ou ultérieure avec l'API Gateway activée. Pour créer un cluster, consultez la page Créer un cluster Autopilot. Pour activer l'API Gateway sur un cluster existant, consultez Activer l'API Gateway dans votre cluster.
  • Vérifiez que l'outil de ligne de commande OpenSSL est installé. Vous utilisez cet outil pour générer des certificats TLS autosignés pour les exemples d'applications.

Conditions requises pour le contrôleur GKE Gateway

  • L'API Gateway n'est compatible qu'avec les clusters de VPC natif.
  • Si vous utilisez les GatewayClasses régionales ou interrégionales, vous devez activer un sous-réseau proxy réservé.
  • Le module complémentaire HttpLoadBalancing doit être activé sur votre cluster.
  • Si vous utilisez Istio, vous devez mettre à niveau Istio vers l'une des versions suivantes :
    • 1.15.2 ou ultérieure
    • 1.14.5 ou ultérieure
    • 1.13.9 ou ultérieure
  • Si vous utilisez un VPC partagé, vous devez attribuer le rôle Compute Network User au compte de service GKE du projet de service dans le projet hôte.

Restrictions et limitations

Lorsque vous déployez des passerelles de passthrough TLS et des ressources TLSRoute, tenez compte des limites suivantes :

  • Lorsque vous configurez le paramètre protocol: TLS sur un écouteur, vous devez définir explicitement le champ tls.mode sur la valeur Passthrough. GKE n'est pas compatible avec le mode Terminate par défaut pour les écouteurs TLS.
  • Sur un écouteur TLS, ne définissez pas le champ certificateRefs. La validation du certificat client au niveau de la passerelle (champ spec.tls.frontendValidation) ne s'applique pas aux écouteurs TLS. Pour utiliser mTLS, validez les certificats clients dans votre backend.
  • Un écouteur TLS ne peut partager un port qu'avec d'autres écouteurs TLS. Vous ne pouvez pas configurer d'écouteurs HTTP ou HTTPS sur le même port qu'un écouteur TLS.
  • Dans le champ TLSRoute.spec.hostnames, vous devez spécifier une liste de 1 à 1 024 noms d'hôte SNI (nom d'hôte exact ou préfixe générique, tel que *.example.com). Chaque entrée ne peut pas dépasser 253 caractères et ne peut pas être une adresse IP.
  • Dans le champ TLSRoute.spec.rules, vous pouvez configurer au maximum une règle.
  • Chaque règle n'accepte qu'une seule entrée backendRef. Les backends de proxy de couche 4 ne sont pas compatibles avec la répartition pondérée du trafic entre plusieurs backends.
  • Les ressources GatewayClass à cluster unique n'acceptent que les backends de service, et les ressources GatewayClass multiclusters n'acceptent que les backends ServiceImport.
  • Dans le champ TLSRoute.spec.rules.backendRefs, définissez le champ port sur un port déclaré par la ressource Service ou ServiceImport cible, et non sur le port du conteneur.
  • Le service Kubernetes de backend (y compris les services exportés en tant que ServiceImport) référencé par une ressource TLSRoute doit utiliser la valeur TCP pour son protocole de port.
  • Vous ne pouvez pas associer une ressource BackendTLSPolicy, Identity-Aware Proxy ou une stratégie de sécurité Google Cloud Armor à un backend TLSRoute, car le contrôleur rejette les configurations de ce type.
  • Lorsque vous associez une ressource GCPBackendPolicy à un Service ou à un ServiceImport référencé par une ressource TLSRoute, vous devez définir le champ spec.protocol sur la valeur TCP (l'omission du champ spec.protocol est définie par défaut sur la valeur HTTP, qui ne s'applique qu'aux backends HTTPRoute). Un objet Service ou ServiceImport peut être associé à une règle HTTP et à une règle TCP en même temps. Si plusieurs règles ayant la même valeur spec.protocol ciblent le même objet Service ou ServiceImport, la règle la plus ancienne est prioritaire et les règles plus récentes ne sont pas associées.
  • Une ressource GCPBackendPolicy dont le champ spec.protocol est défini sur TCP n'accepte que les champs suivants dans le champ spec.default (lorsque vous ciblez une ressource ServiceImport, vous pouvez définir les trois derniers champs par cluster, zone ou région dans le champ spec.default.scopes à la place) :

    • timeoutSec
    • connectionDraining
    • logging.enabled et logging.sampleRate
    • sessionAffinity.type (les valeurs valides sont CLIENT_IP ou NONE)
    • capacityScalerPercent
    • balancingMode: CONNECTION
    • maxConnectionsPerEndpoint

    Vous ne pouvez pas créer de règle TCP incluant d'autres champs, ni de règle HTTP incluant des champs réservés à TCP (balancingMode: CONNECTION et maxConnectionsPerEndpoint). Le serveur d'API Kubernetes rejette la règle lors de sa création. Pour en savoir plus, consultez Configurer des ressources Gateway à l'aide de règles.

  • Si une ressource HTTPRoute et une ressource TLSRoute font référence au même Service ou ServiceImport, l'association d'une ressource HealthCheckPolicy à cette cible remplace les vérifications d'état par défaut distinctes et applique la même configuration de vérification de l'état d'état aux backends des deux routes. Pour configurer les vérifications d'état indépendamment (par exemple, des vérifications d'état HTTP pour les backends HTTPRoute et des vérifications d'état SSL ou TCP pour les backends TLSRoute), créez un service distinct pour chaque route et associez une ressource HealthCheckPolicy à chaque service. Les deux services peuvent sélectionner les mêmes pods.

  • Les fonctionnalités de couche 7 (telles que les réécritures d'URL, le routage basé sur le chemin d'accès et les transformations d'en-tête HTTP) ne s'appliquent pas aux équilibreurs de charge proxy TCP de couche 4.

Configurer un sous-réseau proxy réservé

Une ressource Gateway régionale nécessite un sous-réseau proxy réservé (purpose=REGIONAL_MANAGED_PROXY) dans chaque région où vous la déployez. Un sous-réseau proxy réservé dessert tous les équilibreurs de charge régionaux basés sur Envoy dans cette région. Si votre région n'en possède pas déjà un, consultez Configurer un sous-réseau proxy réservé.

Réserver une adresse IP statique

Avant de déployer la passerelle, réservez une adresse IP statique régionale afin que l'adresse de la passerelle ne change pas et que vous puissiez résoudre vos exemples de noms d'hôte vers cette adresse. Pour savoir comment créer une adresse IP statique, consultez Créer une ressource Gateway HTTP(S) externe régionale.

Déployer une passerelle avec des écouteurs de transmission TLS

La passerelle de cette section configure deux écouteurs TLS qui partagent le port 443. Chaque écouteur correspond à un nom d'hôte SNI différent et transfère les connexions en mode passthrough aux ressources TLSRoute associées.

  1. Enregistrez le manifeste suivant sous le nom store-gateway.yaml :

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-tls
    spec:
      gatewayClassName: gke-l7-regional-external-managed
      listeners:
      # Accept TLS connections for store.example.com without decrypting them.
      - name: store
        protocol: TLS
        port: 443
        hostname: "store.example.com"
        tls:
          mode: Passthrough
        allowedRoutes:
          kinds:
          - kind: TLSRoute
      # A second listener on the same port, selected by a different SNI name.
      - name: store-german
        protocol: TLS
        port: 443
        hostname: "store-de.example.com"
        tls:
          mode: Passthrough
        allowedRoutes:
          kinds:
          - kind: TLSRoute
      addresses:
      - type: NamedAddress
        value: IP_ADDRESS_NAME
    

    Remplacez IP_ADDRESS_NAME par le nom de l'adresse IP statique que vous avez réservée.

    Notez que le bloc tls ne comporte pas de champ certificateRefs. En mode Passthrough, le certificat TLS réside dans vos pods de backend plutôt que sur l'équilibreur de charge.

  2. Appliquez le fichier manifeste Gateway :

    kubectl apply -f store-gateway.yaml
    
  3. Vérifiez que la passerelle est programmée :

    kubectl get gateway store-tls
    

    Le provisionnement de l'équilibreur de charge prend quelques minutes. Le résultat ressemble à ce qui suit :

    NAME        CLASS                              ADDRESS         PROGRAMMED   AGE
    store-tls   gke-l7-regional-external-managed   35.118.32.224   True         53s
    

Utiliser une passerelle interne

Pour conserver le trafic au sein de votre réseau VPC, remplacez la valeur du champ gatewayClassName par gke-l7-rilb et supprimez le champ addresses du fichier manifeste de la passerelle. GKE crée ensuite un équilibreur de charge réseau proxy interne régional et attribue une adresse IP interne à partir du sous-réseau de votre cluster. Les autres étapes de cette page restent inchangées. Envoyez vos requêtes de test depuis une instance Compute Engine du même réseau VPC, car l'adresse IP interne n'est pas accessible depuis Internet.

Déployer des exemples d'applications TLS

Dans cette section, vous allez déployer deux déploiements NGINX (store-v1 et store-german) qui arrêtent TLS sur le port 8443. Chaque déploiement diffuse un certificat TLS différent et signale le nom d'hôte SNI qu'il a reçu, ce qui vous permet de vérifier que le routage a eu lieu en fonction du SNI.

  1. Générez un certificat TLS autosigné et une clé privée pour chaque nom d'hôte :

    openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 \
        -keyout store.key -out store.crt \
        -subj '/CN=store.example.com' \
        -addext 'subjectAltName=DNS:store.example.com'
    openssl req -x509 -newkey rsa:2048 -nodes -sha256 -days 365 \
        -keyout store-de.key -out store-de.crt \
        -subj '/CN=store-de.example.com' \
        -addext 'subjectAltName=DNS:store-de.example.com'
    

    Utilisez les certificats de votre autorité de certification en production. Les certificats autosignés permettent de conserver cet exemple autonome.

  2. Stockez chaque certificat et chaque clé dans un secret Kubernetes en exécutant les commandes suivantes :

    kubectl create secret tls store-cert \
        --cert=store.crt --key=store.key
    kubectl create secret tls store-de-cert \
        --cert=store-de.crt --key=store-de.key
    
  3. Enregistrez le manifeste suivant sous le nom store-tls-app.yaml :

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: store-nginx
    data:
      default.conf: |
        server {
          listen 8443 ssl;
          ssl_certificate     /etc/nginx/ssl/tls.crt;
          ssl_certificate_key /etc/nginx/ssl/tls.key;
          default_type text/plain;
          # Report which Pod answered and which SNI name it received.
          return 200 "backend: $hostname\nsni: $ssl_server_name\n";
        }
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: store-v1
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: store-v1
      template:
        metadata:
          labels:
            app: store-v1
        spec:
          containers:
          - name: nginx
            image: nginx:1.27
            ports:
            - containerPort: 8443
            volumeMounts:
            - name: config
              mountPath: /etc/nginx/conf.d
            - name: cert
              mountPath: /etc/nginx/ssl
              readOnly: true
          volumes:
          - name: config
            configMap:
              name: store-nginx
          - name: cert
            secret:
              secretName: store-cert
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store-v1
    spec:
      selector:
        app: store-v1
      ports:
      - port: 443
        targetPort: 8443
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: store-german
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: store-german
      template:
        metadata:
          labels:
            app: store-german
        spec:
          containers:
          - name: nginx
            image: nginx:1.27
            ports:
            - containerPort: 8443
            volumeMounts:
            - name: config
              mountPath: /etc/nginx/conf.d
            - name: cert
              mountPath: /etc/nginx/ssl
              readOnly: true
          volumes:
          - name: config
            configMap:
              name: store-nginx
          - name: cert
            secret:
              secretName: store-de-cert
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store-german
    spec:
      selector:
        app: store-german
      ports:
      - port: 443
        targetPort: 8443
    

    Les services n'ont pas besoin d'un champ appProtocol. GKE transfère le trafic TLSRoute vers le backend en tant que TCP. Le champ n'a donc aucun effet.

  4. Appliquez le fichier manifeste à votre cluster :

    kubectl apply -f store-tls-app.yaml
    
  5. Vérifiez que les pods sont en cours d'exécution :

    kubectl get pods -l 'app in (store-v1,store-german)'
    

    Le résultat ressemble à ce qui suit :

    NAME                            READY   STATUS    RESTARTS   AGE
    store-german-7d9f8c5b47-2xqkd   1/1     Running   0          41s
    store-german-7d9f8c5b47-h6tzn   1/1     Running   0          41s
    store-v1-6c4b9d8f65-kp8vr       1/1     Running   0          41s
    store-v1-6c4b9d8f65-wm2ls       1/1     Running   0          41s
    

Déployer des ressources TLSRoute pour le routage basé sur SNI

Une ressource TLSRoute s'associe à un écouteur de passerelle et achemine les connexions correspondant à ses noms d'hôte vers un seul service de backend.

  1. Enregistrez le manifeste suivant sous le nom store-tls-routes.yaml :

    kind: TLSRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store
    spec:
      parentRefs:
      - kind: Gateway
        name: store-tls
        sectionName: store
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 443
    ---
    kind: TLSRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-german
    spec:
      parentRefs:
      - kind: Gateway
        name: store-tls
        sectionName: store-german
      hostnames:
      - "store-de.example.com"
      rules:
      - backendRefs:
        - name: store-german
          port: 443
    

    Le champ sectionName sélectionne l'écouteur cible sur la passerelle. Le champ port spécifie le port du service (443), et non le port du conteneur.

  2. Appliquez le fichier manifeste TLSRoute :

    kubectl apply -f store-tls-routes.yaml
    
  3. Vérifiez que le contrôleur de passerelle a accepté la route :

    kubectl get tlsroute store -o yaml
    

    Le champ status ressemble à ce qui suit :

    status:
      parents:
      - controllerName: networking.gke.io/gateway
        parentRef:
          name: store-tls
          sectionName: store
        conditions:
        - type: ResolvedRefs
          status: "True"
          reason: ResolvedRefs
        - type: Accepted
          status: "True"
          reason: Accepted
        - type: Reconciled
          status: "True"
          reason: ReconciliationSucceeded
    

    La condition Reconciled est une condition d'état spécifique à GKE qui indique si le contrôleur Gateway a créé les ressourcesGoogle Cloud sous-jacentes.

  4. Vérifiez que l'écouteur de la passerelle a accepté la route :

    kubectl get gateway store-tls -o yaml
    

    Chaque entrée du champ status.listeners est semblable à ce qui suit :

    - name: store
      supportedKinds:
      - group: gateway.networking.k8s.io
        kind: TLSRoute
      attachedRoutes: 1
      conditions:
      - type: ResolvedRefs
        status: "True"
        reason: ResolvedRefs
      - type: Accepted
        status: "True"
        reason: Accepted
      - type: Programmed
        status: "True"
        reason: Programmed
    

Vérifier le routage du trafic

GKE vérifie l'état d'un backend passthrough TLS en effectuant un handshake TLS avec lui. La vérification d'état initiale de vos pods peut prendre quelques minutes.

  1. Récupérez l'adresse IP de la passerelle :

    kubectl get gateway store-tls -o jsonpath='{.status.addresses[0].value}'
    
  2. Envoyez une requête à chaque nom d'hôte, en remplaçant GATEWAY_IP par l'adresse IP de l'étape précédente :

    curl --resolve store.example.com:443:GATEWAY_IP \
        --cacert store.crt https://store.example.com
    curl --resolve store-de.example.com:443:GATEWAY_IP \
        --cacert store-de.crt https://store-de.example.com
    

    Chaque réponse nomme le pod qui a répondu et renvoie le nom d'hôte SNI qui l'a atteint :

    backend: store-v1-6c4b9d8f65-kp8vr
    sni: store.example.com
    backend: store-german-7d9f8c5b47-2xqkd
    sni: store-de.example.com
    

    Étant donné que chaque requête a utilisé un fichier d'autorité de certification différent et que les deux ont réussi, chaque backend a diffusé son propre certificat. L'équilibreur de charge a transféré la connexion chiffrée sans l'interrompre.

  3. Vérifiez que le routage se produit lors du handshake TLS, avant que le client n'envoie une requête HTTP :

    openssl s_client -connect GATEWAY_IP:443 \
        -servername store-de.example.com </dev/null 2>/dev/null \
        | openssl x509 -noout -subject
    

    Le résultat affiche le certificat du backend store-german :

    subject=CN=store-de.example.com
    

    La modification de la valeur de l'option -servername modifie le certificat renvoyé, ce qui confirme que l'équilibreur de charge a sélectionné le backend en fonction du SNI uniquement.

  4. Envoyez une requête avec un nom d'hôte SNI qui ne correspond à aucun écouteur :

    curl --resolve other.example.com:443:GATEWAY_IP \
        https://other.example.com
    

    La connexion est fermée, car aucun écouteur sur le port 443 ne correspond au nom d'hôte SNI other.example.com.

Configurer la capacité de connexion du backend

Pour les services GKE référencés par les ressources TLSRoute, le contrôleur de passerelle GKE configure un service de backend TCP à l'aide du mode d'équilibrage CONNECTION et définit la valeur par défaut du champ maxConnectionsPerEndpoint sur 100,000,000 (1e8).

Étant donné que le contrôleur de passerelle ne peut pas déterminer automatiquement la limite de connexions simultanées d'un conteneur, vous pouvez utiliser une ressource GCPBackendPolicy pour remplacer la valeur par défaut du champ maxConnectionsPerEndpoint (de 1 à 1,000,000,000). Pour déterminer la limite de connexion optimale pour vos pods de backend, évaluez les éléments suivants :

  • Limites logicielles : vérifiez la configuration de votre serveur ou de votre application, par exemple la directive Apache MaxRequestWorkers, les paramètres NGINX worker_processes * worker_connections, l'attribut Tomcat maxConnections ou les limites du pool de connexions à la base de données.
  • Tests de charge : augmentez progressivement le nombre de connexions simultanées à un pod isolé tout en surveillant le processeur, la mémoire, la latence et les limites de descripteurs de sockets ou de fichiers.

Appliquer une règle GCPBackendPolicy personnalisée

Pour remplacer la valeur par défaut du champ maxConnectionsPerEndpoint sur un service de backend TLSRoute, associez une ressource GCPBackendPolicy avec le champ spec.protocol défini sur TCP et le champ balancingMode défini sur CONNECTION :

  1. Enregistrez le manifeste suivant sous le nom backend-policy.yaml :

    apiVersion: networking.gke.io/v1
    kind: GCPBackendPolicy
    metadata:
      name: store-v1-backend-policy
    spec:
      protocol: TCP
      default:
        balancingMode: CONNECTION
        maxConnectionsPerEndpoint: 1000
      targetRef:
        group: ""
        kind: Service
        name: store-v1
    
  2. Appliquez la règle :

    kubectl apply -f backend-policy.yaml
    

Pour en savoir plus sur la configuration des règles de backend, consultez Configurer des ressources de passerelle à l'aide de règles.

Configurer les vérifications d'état pour le passthrough TLS

Par défaut, pour les services de backend associés à des ressources TLSRoute de passthrough TLS, le contrôleur GKE Gateway provisionne automatiquement une vérification de l'état'état de type SSL.

Gérer l'absence d'extensions SNI dans les vérificateurs

Lorsque vous configurez des vérifications d'état pour les backends passthrough TLS, vous devez tenir compte de la manière dont les vérificateurs d'état Google Cloud interagissent avec les points de terminaison TLS.

Si vos applications de backend nécessitent un nom d'hôte SNI valide pour effectuer un handshake TLS, les vérifications d'état SSL par défaut échoueront. Pour résoudre ce problème, utilisez l'une des approches suivantes :

  • Configurer des certificats de remplacement : configurez votre serveur ou pod de backend pour qu'il diffuse un certificat TLS de remplacement par défaut lorsqu'une connexion TLS arrive sans extension SNI.
  • Utiliser des vérifications d'état TCP avec HealthCheckPolicy : associez une ressource HealthCheckPolicy (avec le champ config.type défini sur TCP) à votre service pour vérifier la connectivité brute du port TCP et éviter le handshake TLS.

Appliquer une règle HealthCheckPolicy personnalisée

Pour configurer des paramètres de vérification de l'état d'état personnalisés ou passer à la vérification d'état TCP, utilisez une ressource HealthCheckPolicy :

  1. Enregistrez le manifeste suivant sous le nom health-check-policy.yaml :

    apiVersion: networking.gke.io/v1
    kind: HealthCheckPolicy
    metadata:
      name: store-health-check
    spec:
      default:
        checkIntervalSec: 10
        timeoutSec: 5
        healthyThreshold: 2
        unhealthyThreshold: 3
        config:
          type: TCP
          tcpHealthCheck:
            port: 8443
      targetRef:
        group: ""
        kind: Service
        name: store-service
    
  2. Appliquez la règle :

    kubectl apply -f health-check-policy.yaml
    

Pour en savoir plus sur la configuration des vérifications d'état, consultez Configurer des ressources Gateway à l'aide de règles.

Configurations avancées

Cette section décrit les modèles de routage avancés, les configurations mutualisées et les déploiements multiclusters compatibles avec les ressources Gateway de passthrough TLS et TLSRoute.

Correspondance de nom d'hôte avec des caractères génériques

Les ressources TLSRoute sont compatibles avec la mise en correspondance des préfixes génériques pour les noms d'hôte et suivent des règles de priorité déterministes lorsque plusieurs routes correspondent au même trafic entrant.

Enregistrez le fichier manifeste suivant pour définir une ressource TLSRoute avec un caractère générique :

apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
  name: wildcard-tls-route
spec:
  parentRefs:
  - name: store-tls
    sectionName: store
  hostnames:
  - "*.example.com"
  rules:
  - backendRefs:
    - name: store-v1
      port: 443

Règles de priorité et de résolution des conflits

Lorsque plusieurs ressources TLSRoute sont associées au même écouteur Gateway et revendiquent des noms d'hôte identiques ou qui se chevauchent, le contrôleur GKE Gateway résout les conflits en utilisant les mêmes règles de spécificité de nom d'hôte et de code temporel de création que les autres routes Gateway :

  • Les correspondances exactes de noms d'hôte (telles que store.example.com) sont prioritaires sur les correspondances de caractères génériques (telles que *.example.com), et les correspondances de caractères génériques plus longues sont prioritaires sur les correspondances de caractères génériques plus larges (telles que *.com).
  • Si deux ressources TLSRoute ou plus déclarent exactement le même nom d'hôte, la route avec le code temporel de création le plus ancien (metadata.creationTimestamp) est prioritaire. Si les codes temporels de création correspondent, l'identifiant <namespace>/<name> lexicographiquement plus petit départage les éléments. Le contrôleur Gateway n'accepte pas les routes en conflit, qui signalent une condition Accepted: False avec le motif Conflicted.

Pour en savoir plus sur la priorité des routes, consultez Fusion, priorité et validation des routes.

Routage entre espaces de noms avec ReferenceGrant

Dans les environnements mutualisés, une équipe de plate-forme centralisée peut gérer la passerelle dans un espace de noms d'infrastructure (tel que gateway-infra), tandis que les équipes d'application gèrent les ressources TLSRoute et Service dans les espaces de noms de développeur (tels que store-ns).

  1. Dans l'écouteur de la passerelle, autorisez les routes de tous les espaces de noms (ou des espaces de noms sélectionnés) :

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: shared-tls-gateway
      namespace: gateway-infra
    spec:
      gatewayClassName: gke-l7-regional-external-managed
      listeners:
      - name: tls-passthrough
        protocol: TLS
        port: 443
        tls:
          mode: Passthrough
        allowedRoutes:
          namespaces:
            from: All
          kinds:
          - kind: TLSRoute
    
  2. Dans l'espace de noms de l'application (store-ns), créez une ressource ReferenceGrant qui autorise la passerelle de l'espace de noms gateway-infra à référencer la ressource TLSRoute ou Service :

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: ReferenceGrant
    metadata:
      name: allow-gateway-infra
      namespace: store-ns
    spec:
      from:
      - group: gateway.networking.k8s.io
        kind: Gateway
        namespace: gateway-infra
      to:
      - group: ""
        kind: Service
    
  3. Dans l'espace de noms de l'application (store-ns), créez la ressource TLSRoute faisant référence à la passerelle partagée :

    apiVersion: gateway.networking.k8s.io/v1
    kind: TLSRoute
    metadata:
      name: store-tls-route
      namespace: store-ns
    spec:
      parentRefs:
      - name: shared-tls-gateway
        namespace: gateway-infra
        sectionName: tls-passthrough
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-service
          port: 443
    

Passerelle de transmission TLS multicluster

Vous pouvez déployer des passerelles multiclusters avec un passthrough TLS sur plusieurs clusters GKE d'un parc :

  1. Utilisez une GatewayClass multicluster compatible (gke-l7-regional-external-managed-mc, gke-l7-rilb-mc ou gke-l7-cross-regional-internal-managed-mc).
  2. Exportez votre service de backend vers le parc à l'aide d'une ressource ServiceExport.
  3. Dans votre ressource TLSRoute, référencez le backend multicluster à l'aide d'une ressource ServiceImport :

    apiVersion: gateway.networking.k8s.io/v1
    kind: TLSRoute
    metadata:
      name: mc-store-tls-route
    spec:
      parentRefs:
      - name: mc-tls-gateway
        sectionName: tls-passthrough
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - group: net.gke.io
          kind: ServiceImport
          name: store-service
          port: 443
    

Plusieurs adresses IP dans les ressources Gateway multiclusters

Lorsque vous déployez des passerelles multiclusters interrégionales (par exemple, lorsque vous utilisez la classe GatewayClass gke-l7-cross-regional-internal-managed-mc), vous pouvez définir plusieurs adresses IP dans le champ spec.addresses pour exposer une adresse IP virtuelle interne dans différentes régions.

Lorsque vous configurez plusieurs adresses IP dans une même ressource Gateway, le contrôleur GKE Gateway traduit chaque adresse IP en une règle de transfert distincte. En même temps, le contrôleur fait référence à un proxy cible partagé et réutilise la même configuration de routage sous-jacente. Le contrôleur ne multiplie pas les ressources TLSRoute sous-jacentes par le nombre d'adresses IP, ce qui permet d'éviter la duplication des routes et l'épuisement des quotas.

L'exemple suivant montre une passerelle multicluster configurée avec des adresses IP éphémères dans deux régions :

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: internal-cross-region-tls-gateway
spec:
  gatewayClassName: gke-l7-cross-regional-internal-managed-mc
  addresses:
  - type: networking.gke.io/ephemeral-ipv4-address/us-west1
    value: "us-west1"
  - type: networking.gke.io/ephemeral-ipv4-address/us-east1
    value: "us-east1"
  listeners:
  - name: tls-passthrough
    protocol: TLS
    port: 443
    tls:
      mode: Passthrough
    allowedRoutes:
      kinds:
      - kind: TLSRoute

Pour en savoir plus sur le déploiement de passerelles multiclusters internes, consultez Déployer une passerelle multicluster interne.

Coalescence de connexion HTTP

Selon la norme RFC 7540 (section 9.1.1), les navigateurs Web et les clients HTTP/2 peuvent réutiliser une connexion TLS établie pour plusieurs requêtes si les deux conditions suivantes sont remplies :

  • Les noms d'hôte cibles sont résolus en une même adresse IP.
  • Le certificat TLS présenté par le serveur fait autorité pour les deux noms d'hôte. Par exemple, un certificat peut couvrir plusieurs noms d'hôte lorsque vous utilisez des certificats génériques tels que *.example.com ou des noms d'objet de remplacement (SAN) multidomaines.

Étant donné qu'un équilibreur de charge proxy TCP de couche 4 n'inspecte pas les en-têtes de requête HTTP après le handshake TLS initial, il transfère les requêtes coalescées via la connexion existante au pod de backend initialement mis en correspondance.

Pour éviter les problèmes de coalescence de connexion :

  • Utilisez des certificats TLS distincts qui ne se chevauchent pas : ne partagez pas de certificats génériques ni d'identités SAN communes entre différents services de backend multiplexés derrière la même adresse IP de passerelle.
  • Renvoyer une requête HTTP 421 (Misdirected Request) : configurez vos serveurs HTTPS de backend pour qu'ils vérifient l'en-tête HTTP :authority (ou Host). Si l'hôte demandé ne correspond pas au domaine attendu du serveur, renvoyez un code d'état HTTP 421 Misdirected Request, invitant le client à ouvrir une nouvelle connexion.
  • Activer le frame ORIGIN HTTP/2 : adoptez la compatibilité avec le frame ORIGIN RFC 8336 sur vos serveurs d'origine et déclarez explicitement les noms d'hôte valides pour la réutilisation des connexions.

Effectuer un nettoyage

Pour éviter que les ressources utilisées sur cette page ne soient facturées sur votre compte Google Cloud , supprimez-les :

  1. Supprimez les ressources TLSRoute :

    kubectl delete tlsroute store store-german
    
  2. Supprimez la ressource Gateway :

    kubectl delete gateway store-tls
    
  3. Supprimez les exemples de ressources Deployment, Service et Secret :

    kubectl delete -f store-tls-app.yaml
    kubectl delete secret store-cert store-de-cert
    

Étapes suivantes