Utiliser plusieurs certificats SSL dans l'équilibrage de charge HTTPS avec un objet Entrée

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Cette page vous explique comment utiliser plusieurs certificats SSL pour un objet Ingress avec des équilibrages de charge interne et externe.

Aperçu

Si vous souhaitez accepter les requêtes HTTPS émanant de vos clients, l'équilibreur de charge HTTP(S) interne ou externe doit disposer d'un certificat lui permettant de leur prouver son identité. L'équilibreur de charge doit également disposer d'une clé privée pour effectuer le handshake HTTPS.

Lorsque l'équilibreur de charge accepte une requête HTTPS d'un client, le trafic entre le client et l'équilibreur de charge est chiffré via TLS. Cependant, l'équilibreur de charge interrompt ce chiffrement TLS et transfère la requête sans chiffrement à l'application. Lorsque vous configurez un équilibreur de charge HTTP(S) via Ingress, vous pouvez le configurer pour qu'il présente au maximum dix certificats TLS au client.

L'équilibreur de charge utilise l'indication du nom du serveur SNI (Server Name Indication) pour déterminer le certificat à présenter au client, en fonction du nom de domaine figurant dans le handshake TLS. Si le client n'utilise pas SNI ou utilise un nom de domaine qui ne correspond pas au nom commun (CN) de l'un des certificats, l'équilibreur de charge utilise le premier certificat répertorié dans l'objet Entrée. Le diagramme suivant illustre l’équilibrage de charge qui envoie le trafic à différents backends, en fonction du nom de domaine utilisé dans la requête :

Certificats SSL multidomaines avec diagramme du système Ingress

Pour fournir un équilibreur de charge HTTPS avec des certificats SSL, vous pouvez utiliser l'une des trois méthodes suivantes :

  • Certificats SSL gérés par Google. Pour plus d'informations sur leur utilisation, reportez-vous à la page des certificats gérés.

  • Certificat SSL Google Cloud que vous gérez vous-même. Il utilise un certificat prépartagé que vous avez précédemment importé dans votre projet Google Cloud.

  • Secrets Kubernetes Le secret contient un certificat et une clé que vous créez vous-même. Pour utiliser un secret, ajoutez son nom dans le champ tls de votre fichier manifeste d'entrée.

Vous pouvez utiliser plusieurs méthodes dans la même entrée. Cela évite les temps d'arrêt entre les méthodes lors de la migration.

Version minimale de GKE

Vous devez utiliser GKE version 1.10.2 ou ultérieure pour utiliser des certificats prépartagés ou pour spécifier plusieurs certificats dans une entrée.

Prérequis

Pour réaliser les exercices de cette page, vous devez posséder deux noms de domaine. Vous pouvez utiliser Google Domains ou un autre bureau d'enregistrement.

L'essentiel

Voici une présentation du processus :

  1. Créez un déploiement.

  2. Créez un service.

  3. Créez deux fichiers de certificat et deux fichiers de clé ou deux objets ManagedCertificate. Veillez à configurer ces certificats dans le même projet et dans le même espace de noms que celui dans lequel l'équilibreur de charge est déployé.

  4. Créez une entrée qui utilise des Secrets ou des certificats prépartagés. Après avoir créé l'entrée, GKE crée et configure un équilibreur de charge HTTP(S).

  5. Testez l'équilibreur de charge HTTP(S).

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 Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI.

Créer un déploiement

Voici le fichier manifeste d'un déploiement :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-mc-deployment
spec:
  selector:
    matchLabels:
      app: products
      department: sales
  replicas: 3
  template:
    metadata:
      labels:
        app: products
        department: sales
    spec:
      containers:
      - name: hello
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0"
        env:
        - name: "PORT"
          value: "50001"
      - name: hello-again
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
        env:
        - name: "PORT"
          value: "50002"

Le déploiement comporte trois pods et chaque pod englobe deux conteneurs. Un conteneur exécute hello-app:1.0 et écoute sur le port TCP 50001. L'autre conteneur exécute hello-app:2.0 et écoute sur le port TCP 50002.

Copiez le fichier manifeste dans un fichier nommé my-mc-deployment.yaml, puis créez le déploiement :

kubectl apply -f my-mc-deployment.yaml

Créer un service

Voici un fichier manifeste de service :

apiVersion: v1
kind: Service
metadata:
  name: my-mc-service
spec:
  type: NodePort
  selector:
    app: products
    department: sales
  ports:
  - name: my-first-port
    protocol: TCP
    port: 60001
    targetPort: 50001
  - name: my-second-port
    protocol: TCP
    port: 60002
    targetPort: 50002

Le champ selector du fichier manifeste de service indique que tous les pods comportant les étiquettes app: products et department: sales sont membres de ce service. Les pods du déploiement que vous avez créés à l'étape précédente sont donc membres du service.

Le champ ports du fichier manifeste de service est un tableau d'objets ServicePort. Lorsqu'un client envoie une requête au service sur my-first-port, la requête est transmise à l'un des pods membres sur le port 50001. Lorsqu'un client envoie une requête au service sur my-second-port, la requête est transmise à l'un des pods membres sur le port 50002.

Copiez le fichier manifeste dans un fichier nommé my-mc-service.yaml, puis créez le service :

kubectl apply -f my-mc-service.yaml

Créer des certificats et des clés

Pour faire les exercices de cette page, vous avez besoin de deux certificats, chacun avec une clé correspondante. Chaque certificat doit avoir un nom commun (CN) correspondant à un nom de domaine que vous possédez. Vous pouvez créer ces certificats manuellement ou utiliser des certificats gérés par Google. Si vous avez déjà deux fichiers de certificat avec les valeurs appropriées pour le nom commun, vous pouvez passer à la section suivante.

Certificats gérés par l'utilisateur

  1. Créez votre première clé :

    openssl genrsa -out test-ingress-1.key 2048
    
  2. Créez votre première requête de signature de certificat :

    openssl req -new -key test-ingress-1.key -out test-ingress-1.csr \
        -subj "/CN=FIRST_DOMAIN"
    

    Remplacez FIRST_DOMAIN par un nom de domaine que vous possédez.

    Par exemple, supposons que vous souhaitiez que l'équilibreur de charge réponde aux requêtes provenant du domaine example.com. Votre requête de signature de certificat devrait se présenter comme suit :

    openssl req -new -key test-ingress-1.key -out test-ingress-1.csr \
        -subj "/CN=example.com"
    
  3. Créez votre premier certificat :

    openssl x509 -req -days 365 -in test-ingress-1.csr -signkey test-ingress-1.key \
        -out test-ingress-1.crt
    
  4. Créez votre deuxième clé :

    openssl genrsa -out test-ingress-2.key 2048
    
  5. Créez votre deuxième requête de signature de certificat :

    openssl req -new -key test-ingress-2.key -out test-ingress-2.csr \
        -subj "/CN=SECOND_DOMAIN"
    

    Remplacez SECOND_DOMAIN par un autre nom de domaine que vous possédez.

    Par exemple, supposons que vous souhaitiez que l'équilibreur de charge réponde aux requêtes provenant du domaine examplepetstore.com. Votre requête de signature de certificat devrait se présenter comme suit :

    openssl req -new -key test-ingress-2.key -out test-ingress-2.csr \
        -subj "/CN=examplepetstore.com"
    
  6. Créez votre deuxième certificat :

    openssl x509 -req -days 365 -in test-ingress-2.csr -signkey test-ingress-2.key \
        -out test-ingress-2.crt
    

Pour en savoir plus sur les certificats et les clés, consultez la présentation des certificats SSL.

Vous possédez maintenant deux fichiers de certificat et deux fichiers de clé.

Les tâches restantes utilisent les espaces réservés suivants pour désigner vos domaines, certificats et clés :

  • FIRST_CERT_FILE : chemin d'accès à votre premier fichier de certificat.
  • FIRST_KEY_FILE : chemin d'accès au fichier de clé qui accompagne votre premier certificat.
  • FIRST_DOMAIN : un nom de domaine que vous possédez.
  • FIRST_SECRET_NAME : nom du secret contenant votre premier certificat et votre première clé.
  • SECOND_CERT_FILE : chemin d'accès à votre deuxième fichier de certificat.
  • SECOND_KEY_FILE : chemin d'accès au fichier de clé qui accompagne votre deuxième certificat.
  • SECOND_DOMAIN : un deuxième nom de domaine que vous possédez.
  • SECOND_SECRET_NAME : nom du secret contenant votre deuxième certificat et votre deuxième clé.

Certificats gérés par Google

Pour créer des certificats gérés par Google, vous devez ajouter des objets ManagedCertificate à l'espace de noms de votre objet Ingress. Vous pouvez vous servir du modèle suivant pour définir des certificats pour vos domaines :

  apiVersion: networking.gke.io/v1
  kind: ManagedCertificate
  metadata:
    name: FIRST_CERT_NAME
  spec:
    domains:
      - FIRST_DOMAIN
  ---
  apiVersion: networking.gke.io/v1
  kind: ManagedCertificate
  metadata:
    name: SECOND_CERT_NAME
  spec:
    domains:
      - SECOND_DOMAIN

Remplacez les éléments suivants :

  • FIRST_CERT_NAME : nom de votre premier objet ManagedCertificate.
  • FIRST_DOMAIN : premier domaine que vous possédez.
  • SECOND_CERT_NAME : nom du deuxième objet ManagedCertificate.
  • SECOND_DOMAIN : deuxième domaine que vous possédez.

Spécifier des certificats pour votre entrée

L'étape suivante consiste à créer un objet Entrée. Dans le fichier manifeste d'entrée, vous pouvez utiliser l'une des méthodes suivantes pour fournir des certificats à l'équilibreur de charge :

  • Secrets
  • Certificats prépartagés
  • Certificats gérés par Google

Choisissez l'une des méthodes en sélectionnant l'un des onglets :

Secrets

Créer des Secrets

  1. Créez un Secret contenant votre premier certificat et votre première clé :

    kubectl create secret tls FIRST_SECRET_NAME \
        --cert FIRST_CERT_FILE --key FIRST_KEY_FILE
    
  2. Créez un Secret contenant votre deuxième certificat et votre deuxième clé :

    kubectl create secret tls SECOND_SECRET_NAME \
        --cert SECOND_CERT_FILE --key SECOND_KEY_FILE
    

Créer une Entrée

Voici un exemple de manifeste pour une entrée :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-mc-ingress
spec:
  tls:
  - secretName: FIRST_SECRET_NAME
  - secretName: SECOND_SECRET_NAME
  rules:
  - host: FIRST_DOMAIN
    http:
      paths:
      - pathType: ImplementationSpecific
        backend:
          service:
            name: my-mc-service
            port:
              number: 60001
  - host: SECOND_DOMAIN
    http:
      paths:
      - pathType: ImplementationSpecific
        backend:
          service:
            name: my-mc-service
            port:
              number: 60002
  1. Copiez le fichier manifeste dans un fichier nommé my-mc-ingress.yaml. Remplacez FIRST_DOMAIN et SECOND_DOMAIN par des noms de domaine que vous possédez, par exemple example.com et examplepetstore.com.

  2. Créez l'entrée :

    kubectl apply -f my-mc-ingress.yaml
    

    Lorsque vous créez un objet Ingress, le contrôleur GKE Ingress crée un équilibreur de charge HTTP(S). Attendez une minute pour que GKE attribue une adresse IP externe à l'équilibreur de charge.

  3. Décrivez votre entrée :

    kubectl describe ingress my-mc-ingress
    

    Le résultat montre que deux Secrets sont associés à l'entrée. La sortie affiche également l'adresse IP externe de l'équilibreur de charge.

    Name: my-mc-ingress
    Address: 203.0.113.1
    ...
    TLS:
      FIRST_SECRET_NAME terminates
      SECOND_SECRET_NAME terminates
    Rules:
      Host              Path  Backends
      ----              ----  --------
      FIRST_DOMAIN
                         my-mc-service:my-first-port (<none>)
      SECOND_DOMAIN
                         my-mc-service:my-second-port (<none>)
    Annotations:
    ...
    Events:
      Type    Reason  Age   From                     Message
      ----    ------  ----  ----                     -------
      Normal  ADD     3m    loadbalancer-controller  default/my-mc-ingress
      Normal  CREATE  2m    loadbalancer-controller  ip: 203.0.113.1
    

Certificats prépartagés

Créer des certificats prépartagés

  1. Créez une ressource de certificat dans votre projet Google Cloud :

    gcloud compute ssl-certificates create FIRST_CERT_NAME \
        --certificate FIRST_CERT_FILE  --private-key FIRST_KEY_FILE
    

    Remplacez les éléments suivants :

    • FIRST_CERT_NAME : nom de votre premier certificat.
    • FIRST_CERT_FILE : votre premier fichier de certificat.
    • FIRST_KEY_FILE : votre premier fichier de clé.
  2. Créez une deuxième ressource de certificat dans votre projet Google Cloud :

    gcloud compute ssl-certificates create SECOND_CERT_NAME \
        --certificate SECOND_CERT_FILE --private-key SECOND_KEY_FILE
    

    Remplacez les éléments suivants :

    • SECOND_CERT_NAME : nom de votre deuxième certificat.
    • SECOND_CERT_FILE : votre deuxième fichier de certificat.
    • SECOND_KEY_FILE : votre deuxième fichier de clé.
  3. Affichez vos ressources de certificat :

    gcloud compute ssl-certificates list
    

    La sortie indique que vous disposez de ressources de certificat nommées FIRST_CERT_NAME et SECOND_CERT_NAME :

    NAME                   CREATION_TIMESTAMP
    FIRST_CERT_NAME      2018-11-03T12:08:47.751-07:00
    SECOND_CERT_NAME     2018-11-03T12:09:25.359-07:00
    

Créer un objet Ingress GKE

Voici un fichier manifeste d'Ingress qui liste les ressources de certificat prépartagées dans une annotation :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-psc-ingress
  annotations:
    ingress.gcp.kubernetes.io/pre-shared-cert: "FIRST_CERT_NAME,SECOND_CERT_NAME"
spec:
  rules:
  - host: FIRST_DOMAIN
    http:
      paths:
      - pathType: ImplementationSpecific
        backend:
          service:
            name: my-mc-service
            port:
              number: 60001
  - host: SECOND_DOMAIN
    http:
      paths:
      - pathType: ImplementationSpecific
        backend:
          service:
            name: my-mc-service
            port:
              number: 60002
  1. Copiez le fichier manifeste dans un fichier nommé my-psc-ingress.yaml. Remplacez FIRST_DOMAIN et SECOND_DOMAIN par vos noms de domaine.

  2. Créez l'entrée :

    kubectl apply -f my-psc-ingress.yaml
    

    Attendez une minute pour que GKE attribue une adresse IP externe à l'équilibreur de charge.

  3. Décrivez votre entrée :

    kubectl describe ingress my-psc-ingress
    

    La sortie montre que l'Ingress est associé à des certificats prépartagés nommés FIRST_CERT_NAME et SECOND_CERT_NAME. La sortie affiche également l'adresse IP externe de l'équilibreur de charge.

    Name:             my-psc-ingress
    Address:          203.0.113.2
    ...
    Rules:
      Host              Path  Backends
      ----              ----  --------
      FIRST_DOMAIN
                         my-mc-service:my-first-port (<none>)
      SECOND_DOMAIN
                         my-mc-service:my-second-port (<none>)
    Annotations:
      ...
      ingress.gcp.kubernetes.io/pre-shared-cert:    FIRST_CERT_NAME,SECOND_CERT_NAME
      ...
      ingress.kubernetes.io/ssl-cert:               FIRST_CERT_NAME,SECOND_CERT_NAME
    Events:
      Type    Reason  Age   From                     Message
      ----    ------  ----  ----                     -------
      Normal  ADD     2m    loadbalancer-controller  default/my-psc-ingress
      Normal  CREATE  1m    loadbalancer-controller  ip: 203.0.113.2
    

Certificats gérés par Google

Créer un objet Ingress GKE

Voici un fichier manifeste d'Ingress qui liste les ressources de certificat prépartagées dans une annotation :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-gmc-ingress
  annotations:
    networking.gke.io/managed-certificates: "FIRST_CERT_NAME,SECOND_CERT_NAME"
spec:
  rules:
  - host: FIRST_DOMAIN
    http:
      paths:
      - pathType: ImplementationSpecific
        backend:
          service:
            name: my-mc-service
            port:
              number: 60001
  - host: SECOND_DOMAIN
    http:
      paths:
      - pathType: ImplementationSpecific
        backend:
          service:
            name: my-mc-service
            port:
              number: 60002
  1. Copiez le fichier manifeste dans un fichier nommé my-gmc-ingress.yaml. Remplacez FIRST_DOMAIN et SECOND_DOMAIN par vos noms de domaine.

  2. Créez l'entrée :

    kubectl apply -f my-gmc-ingress.yaml
    

    Attendez une minute pour que GKE attribue une adresse IP externe à l'équilibreur de charge.

  3. Décrivez votre entrée :

    kubectl describe ingress my-gmc-ingress
    

    La sortie montre que l'Ingress est associé à des certificats gérés nommés FIRST_CERT_NAME et SECOND_CERT_NAME. GKE remplit automatiquement les annotations ingress.gcp.kubernetes.io/pre-shared-cert et ingress.kubernetes.io/ssl-cert pour qu'elles pointent vers les certificats gérés par Google que vous avez créés à l'aide des objets ManagedCertificate. La sortie affiche également les adresses IP externes de l'équilibreur de charge :

    Name:             my-gmc-ingress
    Address:          203.0.113.2
    ...
    Rules:
      Host              Path  Backends
      ----              ----  --------
      FIRST_DOMAIN
                         my-mc-service:my-first-port (<none>)
      SECOND_DOMAIN
                         my-mc-service:my-second-port (<none>)
    Annotations:
      ...
      ingress.gcp.kubernetes.io/pre-shared-cert:    mcrt-a6e41ce4-2b39-4334-84ce-867ff543c424,mcrt-bbff4116-f014-4800-a43a-4095bffeb4f4
      ...
      ingress.kubernetes.io/ssl-cert:               mcrt-a6e41ce4-2b39-4334-84ce-867ff543c424,mcrt-bbff4116-f014-4800-a43a-4095bffeb4f4
      networking.gke.io/managed-certificates:       FIRST_CERT_NAME,SECOND_CERT_NAME
    Events:
      Type    Reason  Age   From                     Message
      ----    ------  ----  ----                     -------
      Normal  ADD     2m    loadbalancer-controller  default/my-gmc-ingress
      Normal  CREATE  1m    loadbalancer-controller  ip: 203.0.113.2
    

Tester l'équilibreur de charge

Attendez environ cinq minutes que GKE ait fini de configurer l'équilibreur de charge. En cas de certificats gérés par Google, l'exécution de la configuration peut prendre plus de temps, car le système doit provisionner les certificats et vérifier la configuration DNS pour des domaines donnés.

Pour effectuer cette étape, vous devez posséder deux noms de domaine et vos deux noms de domaine doivent résoudre l'adresse IP externe de l'équilibreur de charge HTTP(S).

Envoyez une requête à l'équilibreur de charge en utilisant votre premier nom de domaine :

curl -v https://FIRST_DOMAIN

La sortie indique que votre premier certificat a été utilisé lors de l'établissement du handshake TLS. Si votre premier domaine est example.com, le résultat ressemble à ceci :

...
*   Trying 203.0.113.1...
...
* Connected to example.com (203.0.113.1) port 443 (#0)
...
* TLSv1.2 (IN), TLS handshake, Certificate (11):
...
* Server certificate:
*  subject: CN=example.com
...
> Host: example.com
...
Hello, world!
Version: 1.0.0
...

Envoyez une requête à l'équilibreur de charge en utilisant votre deuxième nom de domaine :

curl -v https://SECOND_DOMAIN

Le résultat indique que votre deuxième certificat a été utilisé lors de l'établissement du handshake TLS. Si votre deuxième domaine est examplepetstore.com, le résultat ressemble à ceci :

...
*   Trying 203.0.113.1...
...
* Connected to examplepetstore.com (203.0.113.1) port 443 (#0)
...
* Server certificate:
*  subject: CN=examplepetstore.com
...
> Host: examplepetstore.com
...
Hello, world!
Version: 2.0.0

Le champ "hosts" d'un objet Entrée

Un objet IngressSpec possède un champ tls qui est un tableau d'objets IngressTLS. Chaque objet IngressTLS possède un champ hosts et un champ SecretName. Dans GKE, le champ hosts n'est pas utilisé. GKE lit le nom commun (CN) du certificat dans le Secret. Si le nom commun correspond au nom de domaine dans une requête de client, l'équilibreur de charge présente le certificat correspondant au client.

Quel certificat est présenté ?

L'équilibreur de charge choisit un certificat en fonction des règles suivantes :

  • Si les secrets et les certificats prépartagés sont répertoriés dans l'objet Ingress (entrée), les certificats prépartagés sont prioritaires sur les secrets. En d'autres termes, les secrets sont toujours inclus, mais les certificats prépartagés sont présentés en premier.

  • Si aucun certificat ne possède de nom commun (CN) correspondant au nom de domaine dans une requête de client, l'équilibreur de charge présente le certificat principal.

  • Pour les secrets répertoriés dans le bloc tls, le certificat principal figure dans le premier secret de la liste.

  • Pour les certificats prépartagés répertoriés dans l'annotation, le certificat principal est le premier certificat de la liste.

Bonnes pratiques concernant la rotation des certificats

Si vous souhaitez alterner le contenu de votre certificat (secret ou prépartagé), voici quelques bonnes pratiques :

  • Créez un certificat secret ou prépartagé avec un autre nom, contenant les nouvelles données de certificat. Associez cette ressource (ainsi que la ressource existante) à votre entrée (objet Ingress) en suivant les instructions fournies précédemment. Une fois que vous êtes satisfait des modifications, vous pouvez supprimer l'ancien certificat de l'entrée.
  • Si cela ne vous dérange pas de perturber le trafic, vous pouvez supprimer l'ancienne ressource de l'entrée, provisionner une nouvelle ressource avec le même nom, mais avec un contenu différent, puis la réassocier à l'entrée.

Pour éviter de gérer vous-même la rotation des certificats, consultez la fonctionnalité Certificats SSL gérés par Google.

Dépannage

Si vous renseignez des résultats de certificats Secrets incorrects ou inexistants, une erreur d'événement Kubernetes est renvoyée. Vous pouvez consulter les événements Kubernetes pour un objet Entrée en procédant comme suit :

kubectl describe ingress

Le résultat ressemble à ceci :

Name:             my-ingress
Namespace:        default
Address:          203.0.113.3
Default backend:  hello-server:8080 (10.8.0.3:8080)
TLS:
  my-faulty-Secret terminates
Rules:
  Host  Path  Backends
  ----  ----  --------
  *     *     my-service:443 (10.8.0.3:443)
Events:
   Error during sync: cannot get certs for Ingress default/my-ingress:
 Secret "my-faulty-ingress" has no 'tls.crt'

Étapes suivantes