Uso de TLS con un controlador de entrada en Azure Kubernetes Service (AKS)

El protocolo de seguridad de la capa de transporte (TLS) usa certificados para proporcionar seguridad para la comunicación, el cifrado, la autenticación y la integridad. El uso de TLS con un controlador de entrada en AKS le permite proteger la comunicación entre las aplicaciones y experimentar las ventajas de un controlador de entrada.

Puede traer sus propios certificados e integrarlos con el controlador CSI del almacén de secretos. Como alternativa, puede usar cert-manager, que genera y configura automáticamente los certificados de Let's Encrypt. En el clúster de AKS se ejecutan dos aplicaciones, a las que se puede acceder con una sola dirección IP.

Importante

El complemento de enrutamiento de aplicaciones se recomienda para la entrada en AKS. Para obtener más información, consulte Entrada nginx administrada con el complemento de enrutamiento de aplicaciones.

Importante

Microsoft no administra ni da soporte a cert-manager ni a ningún problema derivado de su uso. Para problemas con cert-manager, consulte la documentación para solucionar problemas de cert-manager.

Hay dos controladores de entrada de código abierto para Kubernetes basados en Nginx: uno lo mantiene la comunidad de Kubernetes (kubernetes/ingress-nginx) y el otro, NGINX, Inc. (nginxinc/kubernetes-ingress). En este artículo se usa el controlador de entrada de la comunidad de Kubernetes.

Antes de empezar

  • En este artículo se supone que tiene configurados un controlador de entrada y aplicaciones. Si necesita un controlador de entrada o aplicaciones de ejemplo, consulte Creación de un controlador de entrada.

  • En este artículo se usa Helm 3 para instalar el controlador de entrada NGINX en una versión de Kubernetes compatible. Asegúrese de que usa la versión más reciente de Helm y de que tiene acceso a los repositorios ingress-nginx y jetstack de Helm. Es posible que los pasos descritos en este artículo no sean compatibles con versiones anteriores del gráfico de Helm, el controlador de entrada NGINX o Kubernetes.

  • En este artículo se da por hecho que ya tiene un clúster de AKS con Azure Container Registry (ACR) integrado. Para más información sobre cómo crear un clúster de Azure Kubernetes Service (AKS) con un Azure Container Registry (ACR) integrado, consulte Autenticación con ACR desde AKS.

  • Si usa la CLI de Azure, en este artículo es necesario que ejecute la versión 2.0.64 de la CLI de Azure o cualquier versión posterior. Ejecute az --version para encontrar la versión. Si necesita instalarla o actualizarla, vea Instalación de la CLI de Azure.

  • Si usa Azure PowerShell, en este artículo es necesario que ejecute la versión 5.9.0 de Azure PowerShell o cualquier versión posterior. Ejecute Get-InstalledModule -Name Az para encontrar la versión. Si necesita instalarla o actualizarla, consulte el artículo sobre la instalación de Azure PowerShell.

Uso de TLS con sus propios certificados con el controlador CSI del almacén de secretos

Para utilizar TLS con sus propios certificados con el controlador CSI del almacén de secretos, necesita un clúster de AKS con el controlador CSI del almacén de secretos configurado y una instancia de Azure Key Vault.

Para más información, consulte Configuración del controlador CSI del almacén de secretos para habilitar el controlador de entrada NGINX con TLS.

Uso de TLS con certificados de Let's Encrypt

Para utilizar TLS con los certificados de Let's Encrypt, implementará cert-manager, que genera y configura automáticamente los certificados de Let's Encrypt.

Importación de las imágenes de cert-manager usadas por el gráfico de Helm a ACR

  • Use az acr import para importar las imágenes siguientes en el ACR.

    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:

También puede importar gráficos de Helm en el ACR. Para más información, consulte Inserción y extracción de gráficos de Helm en ACR.

Opciones de configuración del controlador de entrada

Puede configurar el controlador de entrada NGINX mediante una dirección IP pública estática o una dirección IP pública dinámica. Si usa un dominio personalizado, debe agregar un registro A a la zona DNS. Si no usa un dominio personalizado, puede configurar un nombre de dominio completo (FQDN) para la dirección IP del controlador de entrada.

Crear una dirección IP pública estática o dinámica

Uso de una dirección IP pública estática

Puede configurar el controlador de entrada con una dirección IP pública estática. La IP pública estática se conserva si se elimina el controlador de entrada. La dirección IP no permanece si elimina el clúster de AKS.

Al actualizar el controlador de entrada, debe pasar un parámetro a la versión de Helm para asegurarse de que el servicio del controlador de entrada tenga en cuenta el equilibrador de carga que se le asignará. Para que los certificados HTTPS funcionen correctamente se usa una etiqueta DNS para configurar un FQDN para la dirección IP del controlador de entrada.

  1. Obtenga el nombre del grupo de recursos del clúster de AKS con el comando az aks show.

    az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
    
  2. Cree una IP pública con el método de asignación estático mediante el comando az network public-ip create. En el ejemplo siguiente se crea una dirección IP pública denominada myAKSPublicIP en el grupo de recursos del clúster AKS obtenido en el paso anterior.

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

Nota

Como alternativa, puede crear una dirección IP en otro grupo de recursos que se pueda administrar de forma independiente del clúster de AKS. Si crea una dirección IP en otro grupo de recursos, asegúrese de que lo siguiente sea verdadero:

  • La identidad de clúster que usa el clúster de AKS tiene permisos delegados para el grupo de recursos, como Colaborador de la red.
  • Agregue el parámetro --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="<RESOURCE_GROUP>". Reemplace <RESOURCE_GROUP> por el nombre del grupo de recursos donde reside la dirección IP.
  1. Agregue el parámetro --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="<DNS_LABEL>". La etiqueta DNS se puede establecer cuando el controlador de entrada se implementa por primera vez, o bien más adelante.

  2. Agregue el parámetro --set controller.service.loadBalancerIP="<STATIC_IP>". Especifique su propia dirección IP pública creada en el paso anterior.

    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
    

Para obtener más información, consulte Uso de una dirección IP pública estática y una etiqueta DNS con el equilibrador de carga de AKS.

Uso de una dirección IP pública dinámica

Se crea una IP pública de Azure para el controlador de entrada tras la creación. Esta IP pública es estática durante el período de vida del controlador de entrada. La IP pública no permanece si elimina el controlador de entrada. Si crea un nuevo controlador de entrada, se le asignará una nueva IP pública. El resultado debería ser similar al ejemplo siguiente.

  • Use el comando kubectl get service para obtener la IP pública para el controlador de entrada.

    # 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
    

Adición de un registro A a la zona DNS

Si usa un dominio personalizado, debe agregar un registro A a la zona DNS. Si no usa un dominio personalizado, puede configurar la IP pública con un FQDN.

  • Agregue un registro A a la zona DNS con la dirección IP externa del servicio de NGINX mediante 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
    

Configurar un FQDN para el controlador de entrada

Si quiere, puede configurar un FQDN para la dirección IP del controlador de entrada en lugar de un dominio personalizado configurando una etiqueta DNS. El FQDN debería seguir este formato: <CUSTOM DNS LABEL>.<AZURE REGION NAME>.cloudapp.azure.com.

Importante

La etiqueta DNS debe ser única dentro de su ubicación de Azure.

Para configurar el FQDN, emplee uno de los métodos siguientes:

  • Establezca la etiqueta DNS mediante la CLI de Azure o Azure PowerShell.
  • Establezca la etiqueta DNS mediante la configuración del gráfico de Helm.

Para más información, consulte Etiquetas de nombre DNS de dirección IP pública.

Establecer la etiqueta DNS mediante la CLI de Azure o Azure PowerShell

Asegúrese de reemplazar <DNS_LABEL> por la etiqueta de DNS única.

# 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

Establecer la etiqueta DNS mediante la configuración del gráfico de Helm

Puede pasar una configuración de anotación a la configuración del gráfico de Helm mediante el parámetro --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name". Este parámetro se puede establecer cuando el controlador de entrada se implementa por primera vez, o bien más adelante.

En el ejemplo siguiente se muestra cómo actualizar esta configuración una vez implementado el controlador. Asegúrese de reemplazar <DNS_LABEL> por la etiqueta de DNS única.

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

Instalar cert-manager

El controlador de entrada NGINX es compatible con la terminación de TLS. Hay varias maneras de recuperar y configurar certificados para HTTPS. En este artículo se usa cert manager, que proporciona la generación automática de certificados Lets Encrypt y la funcionalidad de administración.

Para instalar el controlador de cert-manager, use los comandos siguientes.

# 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

Para obtener más información sobre la configuración cert-manager, consulte el proyecto cert-manager.

Creación de un emisor de clúster de entidad de certificación

Antes de que se puedan emitir los certificados, cert-manager requiere uno de los siguientes emisores de certificado:

  • Un emisor, que funciona en un único espacio de nombres.
  • Un recurso ClusterIssuer, que funciona en todos los espacios de nombres.

Para obtener más información, consulte la documentación de cert-manager issuer.

  1. Cree un emisor de clúster, como cluster-issuer.yaml, con el manifiesto de ejemplo siguiente. Reemplace MY_EMAIL_ADDRESS por una dirección válida de su organización.

    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. Aplique el emisor mediante el comando kubectl apply.

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

Actualización de las rutas de entrada

Debe actualizar las rutas de entrada para administrar el tráfico al nombre de dominio completo o al dominio personalizado.

En el ejemplo siguiente, el tráfico se enruta de esta manera:

  • El tráfico a hello-world-ingress.MY_CUSTOM_DOMAIN se enruta al servicio aks-helloworld-one.
  • El tráfico a hello-world-ingress.MY_CUSTOM_DOMAIN/hello-world-two se enruta al servicio aks-helloworld-two.
  • El tráfico a hello-world-ingress.MY_CUSTOM_DOMAIN/static se enruta al servicio denominado aks-helloworld-one para los recursos estáticos.

Nota

Si ha configurado FQDN para la dirección IP del controlador de entrada en lugar de un dominio personalizado, use FQDN en lugar de hello-world-ingress.MY_CUSTOM_DOMAIN.

Por ejemplo, si el FQDN es demo-aks-ingress.eastus.cloudapp.azure.com, reemplace hello-world-ingress.MY_CUSTOM_DOMAIN por demo-aks-ingress.eastus.cloudapp.azure.com en hello-world-ingress.yaml.

  1. Cree o actualice el archivo hello-world-ingress.yaml con el siguiente archivo YAML de ejemplo. Actualice los spec.tls.hosts y el spec.rules.host al nombre DNS que creó en un paso anterior.

    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. Actualice el recurso de entrada con el comando kubectl apply.

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

Verificación de la creación de un objeto de certificado

A continuación, se debe crear un recurso de certificado. El recurso de certificado define el certificado X.509 deseado. Para obtener más información, consulte los certificados de cert-manager.

Cert-manager crea automáticamente un objeto de certificado mediante las correcciones de compatibilidad (shim) de entrada, que se implementan automáticamente con el elemento cert-manager desde v0.2.2. Para obtener más información, consulte la documentación sobre corrección de compatibilidad (shim) de entrada.

Para verificar que el certificado se haya creado correctamente, use el comando kubectl get certificate --namespace ingress-basic y compruebe que la opción LISTO esté establecida en True. El resultado puede tardar varios minutos.

kubectl get certificate --namespace ingress-basic

En la salida siguiente se muestra el estado del certificado.

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

Prueba de la configuración de entrada

Abra un explorador web en la dirección hello-world-ingress.MY_CUSTOM_DOMAIN o el nombre de dominio completo del controlador de entrada de Kubernetes. Asegúrese de que lo siguiente sea cierto:

  • Se le redirige para usar HTTPS.
  • El certificado es de confianza.
  • La aplicación de demostración se muestra en el explorador web.
  • Agregue /hello-world-two al final del dominio y asegúrese de que se muestra la segunda aplicación de demostración con el título personalizado.

Limpieza de recursos

En este artículo, se usa Helm para instalar los componentes de entrada, los certificados y las aplicaciones de ejemplo. Al implementar un gráfico de Helm, se crean muchos recursos de Kubernetes. Estos recursos incluyen pods, implementaciones y servicios. Para limpiar estos recursos, puede eliminar el espacio de nombres de ejemplo completo o los recursos individuales.

Eliminación del espacio de nombres de ejemplo y de todos los recursos

Al eliminar el espacio de nombres de ejemplo también se eliminan todos los recursos que contiene.

  • Para eliminar el espacio de nombres de ejemplo completo, use el comando kubectl delete y especifique el nombre.

    kubectl delete namespace ingress-basic
    

Eliminación de recursos individualmente

Como alternativa, puede eliminar el recurso individualmente.

  1. Quite los recursos del emisor del clúster.

    kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
    
  2. Despliegue una lista de las versiones de Helm con el comando helm list. Busque los gráficos denominados nginx y cert-manager, tal y como se muestra en la salida del ejemplo siguiente.

    $ 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. Desinstale las versiones con el comando helm uninstall. En el ejemplo siguiente se desinstalan las implementaciones de entrada de NGINX y de cert-manager.

    $ helm uninstall cert-manager nginx --namespace ingress-basic
    
    release "cert-manager" uninstalled
    release "nginx" uninstalled
    
  4. Quite las dos aplicaciones de ejemplo.

    kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
    
  5. Elimine la ruta de entrada que dirige el tráfico a las aplicaciones de ejemplo.

    kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
    
  6. Elimine el propio espacio de nombres. Use el comando kubectl delete y especifique el nombre del espacio de nombres.

    kubectl delete namespace ingress-basic
    

Pasos siguientes

En este artículo se incluyen algunos componentes externos a AKS. Para más información sobre estos componentes, consulte las siguientes páginas del proyecto:

También puede: