Cert-manager e Let's Encrypt con Gateway applicativo per contenitori - API in ingresso

Questa guida illustra come usare cert-manager per rilasciare e rinnovare automaticamente i certificati SSL/TLS a uno o più front-end del gateway applicazione di Azure per la distribuzione di contenitori. L'API in ingresso viene usata per configurare le risorse necessarie.

Ai fini di questo esempio, abbiamo configurato cert-manager per emettere certificati da Let's Encrypt per dimostrare una distribuzione end-to-end, in cui l'Application Gateway for Containers gestisce il carico TLS.

Un diagramma che mostra cert-manager recuperare un certificato da Let's Encrypt e archiviarlo nell'archivio segreto di Kubernetes per TLS con Application Gateway per i container.

Affinché i certificati vengano rilasciati da Let's Encrypt, è richiesta una richiesta dall'autorità per convalidare la proprietà del dominio. Questa convalida avviene consentendo a cert-manager di creare un pod e una risorsa in ingresso che espone un endpoint durante il rilascio del certificato, dimostrando la proprietà del nome di dominio.

Altre informazioni su cert-manager e Let's Encrypt with AKS in generale sono disponibili qui.

Prerequisiti

  1. Se si segue la strategia di distribuzione BYO, assicurarsi di configurare l'Application Gateway per le risorse del contenitore e il Controller ALB (Componente aggiuntivo o Helm)

  2. Se si segue la strategia di distribuzione gestita di ALB, assicurarsi di eseguire il provisioning del controller ALB (componente aggiuntivo o Helm) e delle risorse del gateway applicazione per contenitori tramite la risorsa personalizzata ApplicationLoadBalancer.

  3. Distribuire l'applicazione HTTP di esempio Applicare il file deployment.yaml seguente nel cluster per creare un'applicazione Web di esempio per illustrare la riscrittura dell'intestazione.

    kubectl apply -f https://raw.githubusercontent.com/MicrosoftDocs/azure-docs/refs/heads/main/articles/application-gateway/for-containers/examples/traffic-split-scenario/deployment.yaml
    

    Questo comando crea quanto segue nel cluster:

    • uno spazio dei nomi denominato test-infra
    • due servizi chiamati backend-v1 e backend-v2 nello spazio dei nomi test-infra
    • due distribuzioni chiamate backend-v1 e backend-v2 nello spazio dei nomi test-infra

Installare Cert-Manager

Installare cert-manager con Helm:

helm install \
  cert-manager oci://quay.io/jetstack/charts/cert-manager \
  --version v1.19.3 \
  --namespace cert-manager \
  --create-namespace \
  --set config.enableGatewayAPI=true \
  --set crds.enabled=true

Annotazioni

Anche se l'abilitazione del Gateway API non è necessaria, offre la flessibilità di sfruttare l'Application Gateway for Containers, il Gateway API e Cert-Manager, oltre alle configurazioni Ingress per le distribuzioni parallele nel Gateway API.

Creare un ClusterIssuer

Creare una risorsa ClusterIssuer per definire il modo in cui cert-manager comunica con Let's Encrypt. Per questo esempio viene usata una richiesta HTTP. Durante la verifica, cert-manager crea una risorsa Ingress e un pod corrispondente, fornendo un endpoint di convalida per dimostrare la proprietà del dominio. Questa operazione viene eseguita creando una risorsa Ingress temporanea con il http01 tipo di sfida. Questa risorsa Ingress e il pod corrispondente creato da cert-manager vengono eliminati al completamento della sfida di verifica.

Suggerimento

Altre sfide supportate da Let's Encrypt sono documentate in letsencrypt.org - Tipi di richiesta

Creare la risorsa ClusterIssuer

kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory # production endpoint
    #server: https://acme-staging-v02.api.letsencrypt.org/directory # staging endpoint
    email: your-email@example.com
    privateKeySecretRef:
      name: letsencrypt-private-key
    solvers:
        - http01:
            ingress:
              ingressClassName: azure-alb-external
              # This section is required for the Ingress resource created by cert-manager during the challenge
              ingressTemplate:
                metadata:
                  annotations:
                    alb.networking.azure.io/alb-name: alb-test
                    alb.networking.azure.io/alb-namespace: alb-test-infra
EOF

Verificare che la risorsa sia stata creata eseguendo il comando seguente:

kubectl get ClusterIssuer -A -o yaml

Lo stato deve visualizzare True e tipo Ready nelle condizioni.

  status:
    acme:
      lastPrivateKeyHash: x+xxxxxxxxxxxxxxxxxxxxxxx+MY4PAEeotr9XH3V7I=
      lastRegisteredEmail: your-email@example.com
      uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/190567584
    conditions:
    - lastTransitionTime: "2025-03-20T16:00:21Z"
      message: The ACME account was registered with the ACME server
      observedGeneration: 1
      reason: ACMEAccountRegistered
      status: "True"
      type: Ready

Distribuire la risorsa di ingresso richiesta

Creare un ingresso

kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-01
  namespace: test-infra
  annotations:
    alb.networking.azure.io/alb-name: alb-test
    alb.networking.azure.io/alb-namespace: alb-test-infra
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: azure-alb-external
  tls:
  - hosts:
    - backend-v1.contoso.com
    # - backend-v2.contoso.com # You can uncomment this and the host line to add an additional subject alternate name (SAN) to the certificate
    secretName: tls-backend
  rules:
    - host: backend-v1.contoso.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: backend-v1
                port:
                  number: 8080
    # - host: backend-v2.contoso.com
    #   http:
    #     paths:
    #       - path: /
    #         pathType: Prefix
    #         backend:
    #           service:
    #             name: backend-v2
    #             port:
    #               number: 8080
EOF

Dopo aver creato la risorsa di ingresso, verificare che lo stato mostri il nome host del servizio di bilanciamento del carico:

kubectl get ingress ingress-01 -n test-infra -o yaml

Output di esempio della creazione riuscita di un Ingress.

status:
  loadBalancer:
    ingress:
    - hostname: xxxxxxxxxxxxxxxx.fz13.alb.azure.com
      ports:
      - port: 443
        protocol: TCP

Come accennato in precedenza, cert-manager crea una risorsa Ingress temporanea e un pod temporaneo per eseguire la sfida.

kubectl get pods -n test-infra
NAME                          READY   STATUS    RESTARTS   AGE
backend-v1-56d99ddb49-mwmcc   1/1     Running   0          10m
backend-v2-8b5d4679b-rsfrg    1/1     Running   0          10m
cm-acme-http-solver-5lmmv     1/1     Running   0          2s

kubectl get ingress -n test-infra
NAME                        CLASS                HOSTS                         ADDRESS                               PORTS     AGE
cm-acme-http-solver-zrp47   azure-alb-external   backend-v1.contoso.com        xxxxxxxxxxxxxxxx.fz13.alb.azure.com   80        8s
ingress-01                  azure-alb-external   backend-v1.contoso.com        xxxxxxxxxxxxxxxx.fz13.alb.azure.com   80, 443   10s

È possibile controllare lo stato della richiesta eseguendo:

kubectl get challenges.acme.cert-manager.io -n test-infra
NAME                                   STATE     DOMAIN                        AGE
cert-backend-1-2982214480-3407407859   pending   backend-v1.contoso.com        16s

kubectl get certificaterequests.cert-manager.io -n test-infra
NAME             APPROVED   DENIED   READY   ISSUER              REQUESTER                                         AGE
cert-backend-1   True                False   letsencrypt-prod    system:serviceaccount:cert-manager:cert-manager   34s

Quando la richiesta di verifica ha esito positivo, lo stato cambia in READY=True e il certificato viene emesso:

kubectl get certificate -n test-infra
NAME           READY   SECRET         AGE
cert-backend   True    cert-backend   1m

Suggerimento

È possibile sincronizzare automaticamente i nomi host delle risorse Ingress create in AKS con le zone DNS di Azure utilizzando External DNS e Workload Identity.

Testare l'accesso all'applicazione

L'ambiente è ora configurato per instradare il traffico all'applicazione di esempio usando il nome host associato al certificato.

Importante

Assicurarsi di sostituire contoso.com con il nome di dominio a cui si prevede di emettere il certificato.

curl https://backend-v1.contoso.com -v 2>&1 | grep issuer

Verrà visualizzato l'output seguente:

* issuer: C=US; O=Let's Encrypt; CN=R11

È stato installato correttamente il controller ALB, è stata distribuita un'applicazione back-end, è stato ottenuto un certificato da Let's Encrypt usando cert-manager e configurato il routing del traffico all'applicazione tramite il gateway delle applicazioni per contenitori.