Usare TLS con un controller di ingresso in servizio Azure Kubernetes (servizio Azure Kubernetes)

Il protocollo TLS (Transport Layer Security) usa certificati per garantire la sicurezza per la comunicazione, la crittografia, l'autenticazione e l'integrità. L'uso di TLS con un controller di ingresso nel servizio Azure Kubernetes consente di proteggere la comunicazione tra le applicazioni ed sperimentare i vantaggi di un controller di ingresso.

È possibile usare certificati personalizzati e integrarli con il driver CSI dell'archivio segreti. In alternativa, è possibile usare cert-manager, che genera e configura automaticamente i certificati Let's Encrypt . Due applicazioni vengono eseguite nel cluster del servizio Azure Kubernetes, ognuna delle quali è accessibile tramite un singolo indirizzo IP.

Importante

Il componente aggiuntivo Routing delle applicazioni è consigliato per l'ingresso nel servizio Azure Kubernetes. Per altre informazioni, vedere Ingresso nginx gestito con il componente aggiuntivo di routing dell'applicazione.

Importante

Microsoft non gestisce o supporta cert-manager e eventuali problemi derivanti dall'uso. Per problemi relativi a cert-manager, vedere la documentazione sulla risoluzione dei problemi di cert-manager.

Esistono due controller di ingresso open source per Kubernetes basati su Nginx: uno viene gestito dalla community di Kubernetes (kubernetes/ingress-nginx) e uno viene gestito da NGINX, Inc. (nginxinc/kubernetes-ingress). Questo articolo usa il controller di ingresso della community Kubernetes.

Operazioni preliminari

  • Questo articolo presuppone che sia configurato un controller di ingresso e applicazioni. Se è necessario un controller di ingresso o applicazioni di esempio, vedere Creare un controller di ingresso.

  • Questo articolo usa Helm 3 per installare il controller di ingresso NGINX in una versione supportata di Kubernetes. Assicurarsi di usare la versione più recente di Helm e di avere accesso ai ingress-nginx repository Helm e jetstack . I passaggi descritti in questo articolo potrebbero non essere compatibili con le versioni precedenti del grafico Helm, del controller di ingresso NGINX o di Kubernetes.

  • Questo articolo presuppone che sia presente un cluster del servizio Azure Kubernetes esistente con un Registro Azure Container integrato. Per altre informazioni sulla creazione di un cluster del servizio Azure Kubernetes con un registro Azure Container integrato, vedere Eseguire l'autenticazione con registro Azure Container dal servizio Azure Kubernetes.

  • Se si usa l'interfaccia della riga di comando di Azure, questo articolo richiede l'esecuzione dell'interfaccia della riga di comando di Azure versione 2.0.64 o successiva. Eseguire az --version per trovare la versione. Se è necessario eseguire l'installazione o l'aggiornamento, vedere Installare l'interfaccia della riga di comando di Azure.

  • Se si usa Azure PowerShell, questo articolo richiede l'esecuzione di Azure PowerShell versione 5.9.0 o successiva. Eseguire Get-InstalledModule -Name Az per trovare la versione. Se è necessario eseguire l'installazione o l'aggiornamento, vedere Installare Azure PowerShell.

Usare TLS con certificati personalizzati con il driver CSI dell'archivio segreti

Per usare TLS con certificati personalizzati con il driver CSI dell'archivio segreti, è necessario un cluster del servizio Azure Kubernetes con il driver CSI dell'archivio segreti configurato e un'istanza di Azure Key Vault.

Per altre informazioni, vedere Configurare il driver CSI dell'archivio segreti per abilitare il controller di ingresso NGINX con TLS.

Usare TLS con i certificati Let's Encrypt

Per usare TLS con i certificati Let's Encrypt , si distribuirà cert-manager, che genera e configura automaticamente i certificati Let's Encrypt.

Importare le immagini cert-manager usate dal grafico Helm nel Registro Azure Container

  • Usare az acr import per importare le immagini seguenti nel Registro Azure Container.

    REGISTRY_NAME=<REGISTRY_NAME>
    CERT_MANAGER_REGISTRY=quay.io
    CERT_MANAGER_TAG=v1.8.0
    CERT_MANAGER_IMAGE_CONTROLLER=jetstack/cert-manager-controller
    CERT_MANAGER_IMAGE_WEBHOOK=jetstack/cert-manager-webhook
    CERT_MANAGER_IMAGE_CAINJECTOR=jetstack/cert-manager-cainjector
    
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_CONTROLLER:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_CONTROLLER:$CERT_MANAGER_TAG
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_WEBHOOK:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_WEBHOOK:$CERT_MANAGER_TAG
    az acr import --name $REGISTRY_NAME --source $CERT_MANAGER_REGISTRY/$CERT_MANAGER_IMAGE_CAINJECTOR:$CERT_MANAGER_TAG --image $CERT_MANAGER_IMAGE_CAINJECTOR:$CERT_MANAGER_TAG
    

Nota

È anche possibile importare grafici Helm nel Registro Azure Container. Per altre informazioni, vedere Eseguire il push e il pull dei grafici Helm in un Registro Azure Container.

Opzioni di configurazione del controller in ingresso

È possibile configurare il controller di ingresso NGINX usando un indirizzo IP pubblico statico o un indirizzo IP pubblico dinamico. Se si usa un dominio personalizzato, è necessario aggiungere un record A alla zona DNS. Se non si usa un dominio personalizzato, è possibile configurare un nome di dominio completo (FQDN) per l'indirizzo IP del controller in ingresso.

Creare un indirizzo IP pubblico statico o dinamico

Usare un indirizzo IP pubblico statico

È possibile configurare il controller di ingresso con un indirizzo IP pubblico statico. L'indirizzo IP pubblico statico rimane se si elimina il controller di ingresso. L'indirizzo IP non rimane se si elimina il cluster del servizio Azure Kubernetes.

Quando si aggiorna il controller di ingresso, è necessario passare un parametro alla versione Helm per assicurarsi che il servizio controller in ingresso sia a conoscenza del servizio di bilanciamento del carico che verrà allocato. Per il corretto funzionamento dei certificati HTTPS, usare un'etichetta DNS per configurare un FQDN per l'indirizzo IP del controller di ingresso.

  1. Ottenere il nome del gruppo di risorse del cluster del servizio Azure Kubernetes con il az aks show comando .

    az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
    
  2. Creare un indirizzo IP pubblico con il metodo di allocazione statica usando il az network public-ip create comando . L'esempio seguente crea un indirizzo IP pubblico denominato myAKSPublicIP nel gruppo di risorse del cluster del servizio Azure Kubernetes ottenuto nel passaggio precedente.

    az network public-ip create --resource-group MC_myResourceGroup_myAKSCluster_eastus --name myAKSPublicIP --sku Standard --allocation-method static --query publicIp.ipAddress -o tsv
    

Nota

In alternativa, è possibile creare un indirizzo IP in un gruppo di risorse diverso, che è possibile gestire separatamente dal cluster del servizio Azure Kubernetes. Se si crea un indirizzo IP in un gruppo di risorse diverso, verificare che siano soddisfatte le condizioni seguenti:

  • L'identità del cluster usata dal cluster del servizio Azure Kubernetes ha autorizzazioni delegate al gruppo di risorse, ad esempio Collaboratore rete.
  • Aggiungere il --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="<RESOURCE_GROUP>" parametro . Sostituire <RESOURCE_GROUP> con il nome del gruppo di risorse in cui risiede l'indirizzo IP.
  1. Aggiungere il --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="<DNS_LABEL>" parametro . L'etichetta DNS può essere impostata quando il controller di ingresso viene distribuito per la prima volta oppure può essere configurato in un secondo momento.

  2. Aggiungere il --set controller.service.loadBalancerIP="<STATIC_IP>" parametro . Specificare il proprio indirizzo IP pubblico creato nel passaggio precedente.

    DNS_LABEL="<DNS_LABEL>"
    NAMESPACE="ingress-basic"
    STATIC_IP=<STATIC_IP>
    
    helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
      --namespace $NAMESPACE \
      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNS_LABEL \
      --set controller.service.loadBalancerIP=$STATIC_IP \
      --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz
    

Per altre informazioni, vedere Usare un indirizzo IP pubblico statico e un'etichetta DNS con il servizio di bilanciamento del carico del servizio Azure Kubernetes.

Usare un indirizzo IP pubblico dinamico

Al momento della creazione viene creato un indirizzo IP pubblico di Azure per il controller di ingresso. L'indirizzo IP pubblico è statico per la durata del controller di ingresso. L'indirizzo IP pubblico non rimane se si elimina il controller di ingresso. Se si crea un nuovo controller di ingresso, verrà assegnato un nuovo indirizzo IP pubblico. L'output dovrebbe essere simile all'output di esempio seguente.

  • Usare il kubectl get service comando per ottenere l'indirizzo IP pubblico per il controller di ingresso.

    # Get the public IP address for your ingress controller
    
    kubectl --namespace ingress-basic get services -o wide -w nginx-ingress-ingress-nginx-controller
    
    # Sample output
    
    NAME                                     TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE   SELECTOR
    nginx-ingress-ingress-nginx-controller   LoadBalancer   10.0.74.133   EXTERNAL_IP     80:32486/TCP,443:30953/TCP   44s   app.kubernetes.io/component=controller,app.kubernetes.io/instance=nginx-ingress,app.kubernetes.io/name=ingress-nginx
    

Aggiungere un record A alla zona DNS

Se si usa un dominio personalizzato, è necessario aggiungere un record A alla zona DNS. Se non si usa un dominio personalizzato, è possibile configurare l'indirizzo IP pubblico con un nome di dominio completo.

  • Aggiungere un record A alla zona DNS con l'indirizzo IP esterno del servizio NGINX usando az network dns record-set a add-record.

    az network dns record-set a add-record \
        --resource-group myResourceGroup \
        --zone-name MY_CUSTOM_DOMAIN \
        --record-set-name "*" \
        --ipv4-address MY_EXTERNAL_IP
    

Configurare un FQDN per il controller di ingresso

Facoltativamente, è possibile configurare un FQDN per l'indirizzo IP del controller in ingresso anziché un dominio personalizzato impostando un'etichetta DNS. Il nome di dominio completo deve seguire questo formato: <CUSTOM DNS LABEL>.<AZURE REGION NAME>.cloudapp.azure.com.

Importante

L'etichetta DNS deve essere univoca all'interno della posizione di Azure.

È possibile configurare il nome di dominio completo usando uno dei metodi seguenti:

  • Impostare l'etichetta DNS usando l'interfaccia della riga di comando di Azure o Azure PowerShell.
  • Impostare l'etichetta DNS usando le impostazioni del grafico Helm.

Per altre informazioni, vedere Etichette dei nomi DNS dell'indirizzo IP pubblico.

Impostare l'etichetta DNS usando l'interfaccia della riga di comando di Azure o Azure PowerShell

Assicurarsi di sostituire <DNS_LABEL> con l'etichetta DNS univoca.

# Public IP address of your ingress controller
IP="MY_EXTERNAL_IP"

# Name to associate with public IP address
DNSLABEL="<DNS_LABEL>"

# Get the resource-id of the public IP
PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv)

# Update public IP address with DNS name
az network public-ip update --ids $PUBLICIPID --dns-name $DNSLABEL

# Display the FQDN
az network public-ip show --ids $PUBLICIPID --query "[dnsSettings.fqdn]" --output tsv

Impostare l'etichetta DNS usando le impostazioni del grafico Helm

È possibile passare un'impostazione di annotazione alla configurazione del grafico Helm usando il --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name" parametro . Questo parametro può essere impostato quando il controller di ingresso viene distribuito per la prima volta oppure può essere configurato in un secondo momento.

Nell'esempio seguente viene illustrato come aggiornare questa impostazione dopo la distribuzione del controller. Assicurarsi di sostituire <DNS_LABEL> con l'etichetta DNS univoca.

DNSLABEL="<DNS_LABEL>"
NAMESPACE="ingress-basic"

helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
  --namespace $NAMESPACE \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNSLABEL \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz

Installare cert-manager

Il controller di ingresso NGINX supporta la terminazione TLS. Esistono diversi modi per recuperare e configurare i certificati per HTTPS. Questo articolo usa cert-manager, che fornisce funzionalità automatiche di generazione e gestione dei certificati Per crittografare i certificati.

Per installare il controller cert-manager, usare i comandi seguenti.

# Set variable for ACR location to use for pulling images
ACR_URL=<REGISTRY_URL>

# Label the ingress-basic namespace to disable resource validation
kubectl label namespace ingress-basic cert-manager.io/disable-validation=true

# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io

# Update your local Helm chart repository cache
helm repo update

# Install the cert-manager Helm chart
helm install cert-manager jetstack/cert-manager \
  --namespace ingress-basic \
  --version=$CERT_MANAGER_TAG \
  --set installCRDs=true \
  --set nodeSelector."kubernetes\.io/os"=linux \
  --set image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_CONTROLLER \
  --set image.tag=$CERT_MANAGER_TAG \
  --set webhook.image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_WEBHOOK \
  --set webhook.image.tag=$CERT_MANAGER_TAG \
  --set cainjector.image.repository=$ACR_URL/$CERT_MANAGER_IMAGE_CAINJECTOR \
  --set cainjector.image.tag=$CERT_MANAGER_TAG

Per altre informazioni sulla configurazione di cert-manager, vedere progetto cert-manager.

Creare un'autorità di certificazione (CA) cluster

Prima che i certificati possano essere rilasciati, cert-manager richiede uno dei seguenti emittenti:

Per altre informazioni, vedere la documentazione relativa all'autorità di certificazione cert-manager.

  1. Creare un'autorità di certificazione del cluster, ad esempio cluster-issuer.yaml, tramite il manifesto di esempio seguente. Sostituire MY_EMAIL_ADDRESS con un indirizzo valido dell'organizzazione.

    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        email: MY_EMAIL_ADDRESS
        privateKeySecretRef:
          name: letsencrypt
        solvers:
        - http01:
            ingress:
              class: nginx
              podTemplate:
                spec:
                  nodeSelector:
                    "kubernetes.io/os": linux
    
  2. Applicare l'autorità emittente usando il kubectl apply comando .

    kubectl apply -f cluster-issuer.yaml --namespace ingress-basic
    

Aggiornare le route di ingresso

È necessario aggiornare le route in ingresso per gestire il traffico verso il nome di dominio completo o il dominio personalizzato.

Nell'esempio seguente il traffico viene instradato come tale:

  • Traffico verso hello-world-ingress. MY_CUSTOM_DOMAIN viene instradato al servizio aks-helloworld-one .
  • Traffico verso hello-world-ingress. MY_CUSTOM_DOMAIN/hello-world-two viene instradato al servizio aks-helloworld-two .
  • Traffico verso hello-world-ingress. MY_CUSTOM_DOMAIN/static viene instradato al servizio denominato aks-helloworld-one per gli asset statici.

Nota

Se è stato configurato un FQDN per l'indirizzo IP del controller in ingresso anziché un dominio personalizzato, usare il nome di dominio completo anziché hello-world-ingress. MY_CUSTOM_DOMAIN.

Ad esempio, se il nome di dominio completo è demo-aks-ingress.eastus.cloudapp.azure.com, sostituire hello-world-ingress. MY_CUSTOM_DOMAIN con demo-aks-ingress.eastus.cloudapp.azure.com in hello-world-ingress.yaml.

  1. Creare o aggiornare il hello-world-ingress.yaml file usando il file YAML di esempio seguente. Aggiornare e spec.tls.hostsspec.rules.host al nome DNS creato in un passaggio precedente.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$2
        nginx.ingress.kubernetes.io/use-regex: "true"
        cert-manager.io/cluster-issuer: letsencrypt
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
        - hello-world-ingress.MY_CUSTOM_DOMAIN
        secretName: tls-secret
      rules:
      - host: hello-world-ingress.MY_CUSTOM_DOMAIN
        http:
          paths:
          - path: /hello-world-one(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
          - path: /hello-world-two(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-two
                port:
                  number: 80
          - path: /(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress-static
      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: "false"
        nginx.ingress.kubernetes.io/rewrite-target: /static/$2
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
        - hello-world-ingress.MY_CUSTOM_DOMAIN
        secretName: tls-secret
      rules:
      - host: hello-world-ingress.MY_CUSTOM_DOMAIN
        http:
          paths:
          - path: /static(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
    
  2. Aggiornare la risorsa in ingresso usando il kubectl apply comando .

    kubectl apply -f hello-world-ingress.yaml --namespace ingress-basic
    

Verificare che sia stato creato un oggetto certificato

Successivamente, è necessario creare una risorsa certificato. La risorsa certificato definisce il certificato X.509 desiderato. Per altre informazioni, vedere cert-manager certificates (Certificati cert-manager).

Cert-manager crea automaticamente un oggetto certificato per l'utente usando ingress-shim, che viene distribuito automaticamente con cert-manager a partire dalla versione 0.2.2. Per altre informazioni, consultare la documentazione su ingress-shim.

Per verificare che il certificato sia stato creato correttamente, usare il kubectl get certificate --namespace ingress-basic comando e verificare che READY sia True. Potrebbero essere necessari alcuni minuti per ottenere l'output.

kubectl get certificate --namespace ingress-basic

L'output seguente mostra lo stato del certificato.

NAME         READY   SECRET       AGE
tls-secret   True    tls-secret   11m

Testare la configurazione di ingresso

Aprire un Web browser per l'ingresso hello-world. MY_CUSTOM_DOMAIN o il nome di dominio completo del controller di ingresso Kubernetes. Verificare che siano soddisfatte le condizioni seguenti:

  • Si viene reindirizzati all'uso di HTTPS.
  • Il certificato è attendibile.
  • L'applicazione demo viene visualizzata nel Web browser.
  • Aggiungere /hello-world-two alla fine del dominio e assicurarsi che venga visualizzata la seconda applicazione demo con il titolo personalizzato.

Pulire le risorse

Questo articolo ha usato Helm per installare i componenti di ingresso, i certificati e le app di esempio. Quando si distribuisce un grafico Helm, vengono create molte risorse Kubernetes. Queste risorse includono pod, distribuzioni e servizi. Per pulire queste risorse, è possibile eliminare l'intero spazio dei nomi di esempio o le singole risorse.

Eliminare lo spazio dei nomi di esempio e tutte le risorse

L'eliminazione dello spazio dei nomi di esempio elimina anche tutte le risorse nello spazio dei nomi .

  • Eliminare l'intero spazio dei nomi di esempio usando il kubectl delete comando e specificando il nome dello spazio dei nomi.

    kubectl delete namespace ingress-basic
    

Eliminare le risorse singolarmente

In alternativa, è possibile eliminare la risorsa singolarmente.

  1. Rimuovere le risorse dell'autorità di certificazione del cluster.

    kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
    
  2. Elencare le versioni helm con il helm list comando . Cercare grafici denominati nginx e cert-manager, come illustrato nell'output di esempio seguente.

    $ helm list --namespace ingress-basic
    
    NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
    cert-manager            ingress-basic   1               2020-01-15 10:23:36.515514 -0600 CST    deployed        cert-manager-v0.13.0    v0.13.0
    nginx                   ingress-basic   1               2020-01-15 10:09:45.982693 -0600 CST    deployed        nginx-ingress-1.29.1    0.27.0
    
  3. Disinstallare le versioni usando il helm uninstall comando . L'esempio seguente disinstalla le distribuzioni NGINX in ingresso e cert-manager.

    $ helm uninstall cert-manager nginx --namespace ingress-basic
    
    release "cert-manager" uninstalled
    release "nginx" uninstalled
    
  4. Rimuovere le due applicazioni di esempio.

    kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
    
  5. Rimuovere la route in ingresso che indirizza il traffico alle app di esempio.

    kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
    
  6. Eliminare lo spazio dei nomi stesso. Usare il comando e specificare il kubectl delete nome dello spazio dei nomi.

    kubectl delete namespace ingress-basic
    

Passaggi successivi

In questo articolo sono stati inclusi alcuni componenti esterni ad servizio Azure Kubernetes. Per altre informazioni su questi componenti, vedere le pagine di progetto seguenti:

È anche possibile: