For AI agents: the complete documentation index is available at https://docs.ovhcloud.com/fr/llms.txt, the full documentation bundle is available at https://docs.ovhcloud.com/fr/llms-full.txt, and this page is available as Markdown at https://docs.ovhcloud.com/fr/guides/public-cloud/containers-orchestration/managed-kubernetes/secure-nginx-ingress-cert-manager.md.

Sécuriser un Nginx Ingress avec cert-manager sur OVHcloud Managed Kubernetes

Voir en Markdown

Découvrez comment sécuriser un Nginx Ingress avec cert-manager sur OVHcloud Managed Kubernetes

Objectif

Dans ce tutoriel, vous allez :

  • déployer une application (un Deployment et un Service de type ClusterIP) sur votre cluster OVHcloud Managed Kubernetes
  • installer le Nginx Ingress Controller
  • déployer un Ingress pour configurer le Nginx Ingress Controller afin qu'il utilise SSL/TLS via cert-manager

Avant de commencer

Ce tutoriel suppose que vous disposez déjà d'un cluster OVHcloud Managed Kubernetes fonctionnel, ainsi que de connaissances de base sur son utilisation. Pour en savoir plus sur ces sujets, consultez le guide de démarrage rapide OVHcloud Managed Kubernetes Service.

Vous devez également avoir Helm installé sur votre poste de travail et sur votre cluster ; reportez-vous au tutoriel Comment installer Helm sur OVHcloud Managed Kubernetes Service.

Vous devez également installer cert-manager sur votre OVHcloud Managed Kubernetes.

En pratique

Déployer l'application

Dans ce guide, vous allez déployer une application qui exécute un serveur HTTP et affiche une page web.

Commencez par créer un fichier deployment.yaml avec le contenu suivant :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world-deployment
  labels:
    app: hello-world
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: hello-world
        image: ovhplatform/hello
        ports:
        - containerPort: 80

Ce manifeste de déploiement YAML indique que notre application, basée sur l'image ovhplatform/hello:latest, sera déployée avec 1 replica (1 pod).

Créez ensuite un fichier svc.yaml avec le contenu suivant pour définir notre service (un service expose un déploiement) :

apiVersion: v1
kind: Service
metadata:
  name: hello-world
  labels:
    app: hello-world
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: hello-world

Appliquez les fichiers manifeste de déploiement et de service à votre cluster avec les commandes suivantes :

kubectl apply -f deployment.yaml
kubectl apply -f svc.yaml

Le résultat devrait ressembler à ceci :

$ kubectl apply -f deployment.yaml
deployment.apps/hello-world-deployment created

$ kubectl apply -f svc.yaml
service/hello-world created

Vous pouvez vérifier que votre application fonctionne et que le service est créé en exécutant les commandes suivantes :

kubectl get pod -l app=hello-world
kubectl get svc -l app=hello-world

Le résultat devrait ressembler à ceci :

$ kubectl get pod -l app=hello-world
NAME                                      READY   STATUS    RESTARTS   AGE
hello-world-deployment-559d658ffb-qtxnl   1/1     Running   0          61s

$ kubectl get svc -l app=hello-world
NAME          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
hello-world   ClusterIP   10.3.213.111   `<none>`        80/TCP    68s

Installer le chart Helm du Nginx Ingress Controller

Pour ce tutoriel, nous utilisons le chart Helm du Nginx Ingress Controller disponible sur son propre repository Helm.

Le chart est entièrement configurable, mais nous utilisons ici la configuration par défaut.

Ajoutez le repository Helm Ingress Nginx :

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

Ces commandes ajoutent le repository Helm Ingress Nginx à votre repository Helm local et mettent à jour les repositories de charts installés :

$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

helm repo update
"ingress-nginx" has been added to your repositories
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "nvidia" chart repository
...
...Successfully got an update from the "ingress-nginx" chart repository
...
Update Complete. ⎈Happy Helming!⎈

Installez la dernière version d'Ingress Nginx avec la commande helm install :

helm -n ingress-nginx install ingress-nginx ingress-nginx/ingress-nginx --create-namespace

Le processus d'installation démarre et un nouveau namespace ingress-nginx est créé.

$ helm -n ingress-nginx install ingress-nginx ingress-nginx/ingress-nginx --create-namespace

NAME: ingress-nginx
LAST DEPLOYED: Thu Apr 11 10:54:34 2024
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
It may take a few minutes for the load balancer IP to be available.
You can watch the status by running 'kubectl get service --namespace ingress-nginx ingress-nginx-controller --output wide --watch'

An example Ingress that makes use of the controller:
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    name: example
    namespace: foo
  spec:
    ingressClassName: nginx
    rules:
      - host: www.example.com
        http:
          paths:
            - pathType: Prefix
              backend:
                service:
                  name: exampleService
                  port:
                    number: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
      - hosts:
        - www.example.com
        secretName: example-tls

If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:

  apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: <base64 encoded cert>
    tls.key: <base64 encoded key>
  type: kubernetes.io/tls

La création du LoadBalancer étant asynchrone, et le provisionnement du load balancer pouvant prendre plusieurs minutes, vous obtiendrez très probablement un EXTERNAL-IP à l'état <pending>.

Si vous réessayez quelques minutes plus tard, vous devriez obtenir un EXTERNAL-IP :

$ kubectl get svc -n ingress-nginx ingress-nginx-controller
NAME                       TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)                      AGE
ingress-nginx-controller   LoadBalancer   10.3.232.157   xx.xx.xx.xx   80:30903/TCP,443:31546/TCP   19h

Vous pouvez ensuite accéder à votre nginx-ingress à l'adresse http://[YOUR_LOAD_BALANCER_IP] en HTTP ou https://[YOUR_LOAD_BALANCER_IP] en HTTPS.

Configurer le Nginx Ingress Controller pour utiliser SSL/TLS

Après avoir installé cert-manager sur votre cluster OVHcloud Managed Kubernetes, si vous avez suivi le guide, vous devriez avoir deux ClusterIssuer en cours d'exécution, un pour la production et un pour les usages de staging/développement :

$ kubectl get clusterissuer
NAME                  READY   AGE
letsencrypt-prod      True    7s
letsencrypt-staging   True    7s

Si ce n'est pas le cas, créez un fichier issuer.yaml avec le contenu suivant :

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: [YOUR_EMAIL]
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-prod
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class: nginx
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # The ACME server URL
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: [YOUR_EMAIL]
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: letsencrypt-staging
    # Enable the HTTP-01 challenge provider
    solvers:
    - http01:
        ingress:
          class: nginx
Info

nginx est le nom de la ressource Ingress que vous allez créer.

Déployez-le ensuite :

kubectl apply -f issuer.yaml

Pour certifier une ressource, l'Ingress dans notre cas, nous allons utiliser des annotations. Grâce à cela, cert-manager va créer la ressource Certificate qui représente une définition lisible d'une demande de certificat. Cert-manager utilise cette entrée pour générer une clé privée et une ressource CertificateRequest afin d'obtenir un certificat signé auprès d'un Issuer ou d'un ClusterIssuer. Le certificat signé et la clé privée sont ensuite stockés dans la ressource Secret spécifiée.

À cette étape, vous devez déployer une ressource Ingress et la configurer pour qu'elle utilise la terminaison SSL/TLS.

Créez un fichier ingress-tls.yaml avec le contenu suivant :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-staging"
  name: ingress
  namespace: default
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - [YOUR_DN]
      secretName: hello-world-tls # < cert-manager will store the created certificate in this secret.
  rules:
  - host: [YOUR_DN]
    http:
      paths:
      - backend:
          service:
            name: hello-world
            port:
              number: 80
        path: /
        pathType: Prefix
Info

N'oubliez pas de remplacer [YOUR_DN] par votre nom de domaine.

Dans ce fichier manifeste, vous pouvez constater que nous définissons une ressource Nginx Ingress avec plusieurs annotations. Pour en savoir plus sur ces annotations, reportez-vous à la documentation Securing Ingress Resources de cert-manager.

Appliquez le fichier manifeste de l'ingress à votre cluster avec la commande suivante :

kubectl apply -f ingress-tls.yaml

Le résultat devrait ressembler à ceci :

$ kubectl apply -f ingress-tls.yaml
ingress.networking.k8s.io/ingress configured

À cette étape, une ressource Certificate a été créée :

$ kubectl get certificate
NAME              READY   SECRET            AGE
hello-world-tls   False   hello-world-tls   111s

Vous pouvez afficher les événements du certificat pour vérifier qu'il a bien été créé et qu'il génère la ressource CertificateRequest nécessaire :

$ kubectl describe certificate
Name:         hello-world-tls
Namespace:    default
Labels:       `<none>`
Annotations:  `<none>`
API Version:  cert-manager.io/v1
Kind:         Certificate
Metadata:
  Creation Timestamp:  2022-06-27T11:14:40Z
  Generation:          1
  ...
Events:
  Type    Reason     Age    From                                       Message
  ----    ------     ----   ----                                       -------
  Normal  Issuing    8m57s  cert-manager-certificates-trigger          Issuing certificate as Secret does not exist
  Normal  Generated  8m57s  cert-manager-certificates-key-manager      Stored new private key in temporary Secret resource "hello-world-tls-krzvj"
  Normal  Requested  8m57s  cert-manager-certificates-request-manager  Created new CertificateRequest resource "hello-world-tls-4fzl2"

Vous pouvez aussi vérifier qu'une ressource CertificateRequest, Order et Challenge ont bien été créées :

$ kubectl describe certificaterequest
Name:         hello-world-tls-4fzl2
Namespace:    default
Labels:       <none>
Annotations:  cert-manager.io/certificate-name: hello-world-tls
              cert-manager.io/certificate-revision: 1
              cert-manager.io/private-key-secret-name: hello-world-tls-krzvj
API Version:  cert-manager.io/v1
Kind:         CertificateRequest
Metadata:
  Creation Timestamp:  2024-01-18T14:34:41Z
  Generate Name:       hello-world-tls-
  Generation:          1
  ...
Events:
  Type    Reason           Age   From                                          Message
  ----    ------           ----  ----                                          -------
  Normal  cert-manager.io  18m   cert-manager-certificaterequests-approver     Certificate request has been approved by cert-manager.io
  Normal  OrderCreated     18m   cert-manager-certificaterequests-issuer-acme  Created Order resource default/hello-world-tls-4fzl2-2471308949
  Normal  OrderPending     18m   cert-manager-certificaterequests-issuer-acme  Waiting on certificate issuance from order default/hello-world-tls-4fzl2-2471308949: ""
$ kubectl describe order
Name:         hello-world-tls-4fzl2-2471308949
Namespace:    default
Labels:       <none>
Annotations:  cert-manager.io/certificate-name: hello-world-tls
              cert-manager.io/certificate-revision: 1
              cert-manager.io/private-key-secret-name: hello-world-tls-krzvj
API Version:  acme.cert-manager.io/v1
Kind:         Order
Metadata:
  Creation Timestamp:  2024-01-18T14:34:41Z
  Generation:          1
  ...
Events:
  Type    Reason   Age   From                 Message
  ----    ------   ----  ----                 -------
  Normal  Created  16m   cert-manager-orders  Created Challenge resource "hello-world-tls-4fzl2-2471308949-3172376200" for domain "example.com"
$ kubectl describe challenge
Name:         hello-world-tls-4fzl2-2471308949-3172376200
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  acme.cert-manager.io/v1
Kind:         Challenge
Metadata:
  Creation Timestamp:  2024-01-18T14:34:42Z
  Finalizers:
    finalizer.acme.cert-manager.io
  Generation:  1
  ...
Events:
  Type    Reason     Age   From                     Message
  ----    ------     ----  ----                     -------
  Normal  Started    16m   cert-manager-challenges  Challenge scheduled for processing
  Normal  Presented  16m   cert-manager-challenges  Presented challenge using HTTP-01 challenge mechanism

Vous devez maintenant faire correspondre le nom de domaine (DN) et le Load Balancer. Pour cela, créez un A-record pour [YOUR_DN] (votre nom de domaine) pointant vers la valeur de $INGRESS_URL.

Attendez que le challenge soit résolu :

dig +short [YOUR_DN]

Décrivez à nouveau le certificat et attendez de voir « Certificate issued successfully » lorsque vous décrivez le certificat.

Renouvellement du certificat

Cert-manager est un outil très puissant qui gère à la fois la création de certificats et leur renouvellement automatique.

Une fois qu'un certificat X.509 a été émis, cert-manager calcule le délai de renouvellement pour la ressource Certificate et définit le statut RenewalTime du certificat à l'heure à laquelle le renouvellement sera tenté.

Vous pouvez vérifier le renouvellement de votre certificat :

$ kubectl get certificate -o yaml | grep renew
    renewalTime: "2024-03-18T14:05:35Z"

Aller plus loin

  • Pour une formation ou une assistance technique sur la mise en œuvre de nos solutions, contactez votre commercial ou consultez la page Professional Services pour obtenir un devis et faire analyser votre projet par nos experts.

  • Échangez avec notre communauté d'utilisateurs.

Cette page vous a-t-elle aidé ?