Crear un controlador de entrada no administrado

Un controlador de entrada es un software que proporciona el proxy inverso, el enrutamiento del tráfico configurable y la terminación de TLS para los servicios de Kubernetes. Los recursos de entrada de Kubernetes se usan para configurar las reglas de entrada y las rutas de los distintos servicios de Kubernetes. Cuando se usan un controlador de entrada y reglas de entrada, se puede usar una sola dirección IP para enrutar el tráfico a varios servicios en un clúster de Kubernetes.

En este artículo se muestra cómo implementar el controlador de entrada NGINX en un clúster de Azure Kubernetes Service (AKS). Se ejecutan dos aplicaciones en el clúster de AKS, 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.

Nota:

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 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 al repositorio de Helm ingress-nginx. 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 una información más detallada sobre cómo crear un clúster de AKS con ACR integrado, consulte Autenticación con Azure Container Registry desde Azure Kubernetes Service.
  • El punto de conexión de estado de la API de Kubernetes healthz está en desuso en Kubernetes v1.16. En su lugar, puede reemplazar este punto de conexión por los puntos de conexión livez y readyz. Consulte Puntos de conexión de API de Kubernetes para el estado para determinar qué punto de conexión se va a usar para su escenario.
  • 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.

Configuración básica

Para crear un controlador de entrada NGINX básico sin personalizar los valores predeterminados, usará Helm. La configuración siguiente usa la configuración predeterminada para simplificar. Puede agregar parámetros para personalizar la implementación, por ejemplo, --set controller.replicaCount=3.

Nota:

Si quiere habilitar la conservación de direcciones IP de origen del cliente para las solicitudes a los contenedores de su clúster, agregue --set controller.service.externalTrafficPolicy=Local al comando de instalación de Helm. La dirección IP de origen del cliente se almacena en el encabezado de la solicitud en X-Forwarded-For. Al usar un controlador de entrada con la conservación de direcciones IP de origen del cliente habilitada, el tránsito de TLS no funciona.

NAMESPACE=ingress-basic

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

helm install ingress-nginx ingress-nginx/ingress-nginx \
  --create-namespace \
  --namespace $NAMESPACE \
  --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
  --set controller.service.externalTrafficPolicy=Local

Nota:

En este tutorial, service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path se establece en /healthz. Esto significa que si el código de respuesta de las solicitudes a /healthz no es 200, todo el controlador de entrada estará inactivo. Puede modificar el valor a otro URI en su propio escenario. No se puede eliminar esta parte o anular el valor, o el controlador de entrada seguirá estando inactivo. El paquete ingress-nginx usado en este tutorial, proporcionado por Kubernetes oficial, siempre devolverá el código de respuesta 200 si se solicita /healthz, ya que está diseñado como back-end predeterminado para que los usuarios tengan un inicio rápido, a menos que las reglas de entrada lo sobrescriban.

Configuración personalizada

Como alternativa a la configuración básica presentada en la sección anterior, el siguiente conjunto de pasos mostrará cómo implementar un controlador de entrada personalizado. Tendrá la opción de usar una dirección IP estática interna o usar una dirección IP pública dinámica.

Importación de las imágenes usadas por el gráfico de Helm en el ACR

Para controlar las versiones de la imagen, querrá importarlas en su propia instancia de Azure Container Registry. El gráfico de Helm de controladores de entrada NGINX se basa en tres imágenes de contenedor. Use az acr import para importar esas imágenes en el ACR.

REGISTRY_NAME=<REGISTRY_NAME>
SOURCE_REGISTRY=registry.k8s.io
CONTROLLER_IMAGE=ingress-nginx/controller
CONTROLLER_TAG=v1.8.1
PATCH_IMAGE=ingress-nginx/kube-webhook-certgen
PATCH_TAG=v20230407
DEFAULTBACKEND_IMAGE=defaultbackend-amd64
DEFAULTBACKEND_TAG=1.5

az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$CONTROLLER_IMAGE:$CONTROLLER_TAG --image $CONTROLLER_IMAGE:$CONTROLLER_TAG
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$PATCH_IMAGE:$PATCH_TAG --image $PATCH_IMAGE:$PATCH_TAG
az acr import --name $REGISTRY_NAME --source $SOURCE_REGISTRY/$DEFAULTBACKEND_IMAGE:$DEFAULTBACKEND_TAG --image $DEFAULTBACKEND_IMAGE:$DEFAULTBACKEND_TAG

Nota

Además de importar imágenes de contenedor en el ACR, 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 Azure Container Registry.

Crear un controlador de entrada

Para crear el controlador de entrada, use Helm para instalar ingress-nginx. El controlador de entrada se debe programar en un nodo con Linux. Los nodos de Windows Server no deben ejecutar el controlador de entrada. Un selector de nodos se especifica mediante el parámetro --set nodeSelector para indicar al programador de Kubernetes que ejecute el controlador de entrada NGINX en un nodo basado en Linux.

Para obtener redundancia adicional, se implementan dos réplicas de los controladores de entrada NGINX con el parámetro --set controller.replicaCount. Para sacar el máximo provecho de las réplicas en ejecución del controlador de entrada, asegúrese de que hay más de un nodo en el clúster de AKS.

En el siguiente ejemplo se crea un espacio de nombres de Kubernetes para los recursos de entrada denominado ingress-basic y está diseñada para funcionar en el espacio de nombres. Especifique un espacio de nombres para su propio entorno según sea necesario. Si el clúster de AKS no está habilitado para el control de acceso basado en roles de Kubernetes, agregue --set rbac.create=false a los comandos de Helm.

Nota

Si quiere habilitar la conservación de direcciones IP de origen del cliente para las solicitudes a los contenedores de su clúster, agregue --set controller.service.externalTrafficPolicy=Local al comando de instalación de Helm. La dirección IP de origen del cliente se almacena en el encabezado de la solicitud en X-Forwarded-For. Al usar un controlador de entrada con la conservación de direcciones IP de origen del cliente habilitada, el tránsito de TLS no funciona.

# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Set variable for ACR location to use for pulling images
ACR_LOGIN_SERVER=<REGISTRY_LOGIN_SERVER>

# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
    --version 4.7.1 \
    --namespace ingress-basic \
    --create-namespace \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.image.registry=$ACR_LOGIN_SERVER \
    --set controller.image.image=$CONTROLLER_IMAGE \
    --set controller.image.tag=$CONTROLLER_TAG \
    --set controller.image.digest="" \
    --set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
    --set controller.service.externalTrafficPolicy=Local \
    --set controller.admissionWebhooks.patch.image.registry=$ACR_LOGIN_SERVER \
    --set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE \
    --set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG \
    --set controller.admissionWebhooks.patch.image.digest="" \
    --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
    --set defaultBackend.image.registry=$ACR_LOGIN_SERVER \
    --set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
    --set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
    --set defaultBackend.image.digest=""

Crear un controlador de entrada mediante una dirección IP interna

De manera predeterminada, se crea un controlador de entrada NGINX con una asignación de dirección IP pública y dinámica. Un requisito de configuración común es usar una red y una dirección IP internas y privadas. Este enfoque permite restringir el acceso a los servicios a los usuarios internos, sin acceso externo.

Use los parámetros --set controller.service.loadBalancerIP y --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true para asignar una dirección IP interna al controlador de entrada. Proporcione su propia dirección IP interna para su uso con el controlador de entrada. Asegúrese de que esta dirección IP no esté ya en uso dentro de la red virtual. Si usa una red virtual y una subred existentes, debe configurar el clúster de AKS con los permisos correctos para administrarlas. Para más información, consulte Uso de redes kubenet con intervalos de direcciones IP propios en Azure Kubernetes Service (AKS) o Configuración de redes de Azure CNI en Azure Kubernetes Service (AKS).

# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Set variable for ACR location to use for pulling images
ACR_LOGIN_SERVER=<REGISTRY_LOGIN_SERVER>

# Use Helm to deploy an NGINX ingress controller
helm install ingress-nginx ingress-nginx/ingress-nginx \
    --version 4.7.1 \
    --namespace ingress-basic \
    --create-namespace \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.image.registry=$ACR_LOGIN_SERVER \
    --set controller.image.image=$CONTROLLER_IMAGE \
    --set controller.image.tag=$CONTROLLER_TAG \
    --set controller.image.digest="" \
    --set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
    --set controller.service.loadBalancerIP=10.224.0.42 \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-internal"=true \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
    --set controller.admissionWebhooks.patch.image.registry=$ACR_LOGIN_SERVER \
    --set controller.admissionWebhooks.patch.image.image=$PATCH_IMAGE \
    --set controller.admissionWebhooks.patch.image.tag=$PATCH_TAG \
    --set controller.admissionWebhooks.patch.image.digest="" \
    --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
    --set defaultBackend.image.registry=$ACR_LOGIN_SERVER \
    --set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
    --set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
    --set defaultBackend.image.digest="" 

Comprobación del servicio de equilibrador de carga

Compruebe el servicio del equilibrador de carga mediante kubectl get services.

kubectl get services --namespace ingress-basic -o wide -w ingress-nginx-controller

Cuando se crea el servicio del equilibrador de carga de Kubernetes para el controlador de entrada NGINX, se asigna una dirección IP en EXTERNAL-IP, como se muestra en la salida del ejemplo siguiente:

NAME                       TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                      AGE   SELECTOR
ingress-nginx-controller   LoadBalancer   10.0.65.205   EXTERNAL-IP     80:30957/TCP,443:32414/TCP   1m   app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx

Si navega a la dirección IP externa en esta fase, verá una página 404 mostrada. Esto se debe a que todavía necesita configurar la conexión a la dirección IP externa, que se realiza en las secciones siguientes.

Ejecución de aplicaciones de demostración

Para ver el controlador de entrada en acción, ejecute dos aplicaciones de demostración en el clúster de AKS. En este ejemplo, use kubectl apply para implementar dos instancias de una aplicación Hola mundo sencilla.

  1. Cree el archivo aks-helloworld-one.yaml y cópielo en el ejemplo siguiente de YAML:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-one  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-one
      template:
        metadata:
          labels:
            app: aks-helloworld-one
        spec:
          containers:
          - name: aks-helloworld-one
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "Welcome to Azure Kubernetes Service (AKS)"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-one  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-one
    
  2. Cree el archivo aks-helloworld-two.yaml y cópielo en el ejemplo siguiente de YAML:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-two  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-two
      template:
        metadata:
          labels:
            app: aks-helloworld-two
        spec:
          containers:
          - name: aks-helloworld-two
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "AKS Ingress Demo"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-two  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-two
    
  3. Ejecute las dos aplicaciones de demostración mediante kubectl apply:

    kubectl apply -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl apply -f aks-helloworld-two.yaml --namespace ingress-basic
    

Creación de una ruta de entrada

Ambas aplicaciones ahora se ejecutan en el clúster de Kubernetes. Para enrutar el tráfico a cada aplicación, cree un recurso de entrada de Kubernetes. El recurso de entrada configura las reglas de enrutamiento del tráfico a una de las dos aplicaciones.

En el ejemplo siguiente, el tráfico a la dirección EXTERNAL_IP/hello-world-one se enruta al servicio denominado aks-helloworld-one. El tráfico a la dirección EXTERNAL_IP/hello-world-two se enruta al servicio aks-helloworld-two. El tráfico a la dirección EXTERNAL_IP/static se enruta al servicio denominado aks-helloworld-one para los recursos estáticos.

  1. Cree un archivo denominado hello-world-ingress.yaml y cópielo en el ejemplo siguiente de YAML:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: hello-world-ingress
      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: "false"
        nginx.ingress.kubernetes.io/use-regex: "true"
        nginx.ingress.kubernetes.io/rewrite-target: /$2
    spec:
      ingressClassName: nginx
      rules:
      - 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
      rules:
      - http:
          paths:
          - path: /static(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port: 
                  number: 80
    
  2. Cree el recurso de entrada con el comando kubectl apply.

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

Prueba del controlador de entrada

Para probar las rutas para el controlador de entrada, vaya a las dos aplicaciones. Abra un explorador web en la dirección IP de su controlador de entrada NGINX, como EXTERNAL_IP. La primera aplicación de demostración aparece en el explorador web, como se muestra en el ejemplo siguiente:

First app running behind the ingress controller

A continuación, agregue la ruta de acceso /hello-world-two a la dirección IP, como EXTERNAL_IP/hello-world-two. Se muestra la segunda aplicación de demostración con el título personalizado:

Second app running behind the ingress controller

Prueba de una dirección IP interna

  1. Cree un pod de prueba y asóciele una sesión de terminal.

    kubectl run -it --rm aks-ingress-test --image=mcr.microsoft.com/dotnet/runtime-deps:6.0 --namespace ingress-basic
    
  2. Instale curl en el pod mediante apt-get.

    apt-get update && apt-get install -y curl
    
  3. Acceda al controlador de ingreso de Kubernetes con curl, como http://10.224.0.42. Proporcione su propia dirección IP interna, que especificó al implementar el controlador de entrada.

    curl -L http://10.224.0.42
    

    No se proporcionó ninguna ruta de acceso con la dirección, por lo que el controlador de entrada se establece de manera predeterminada en la ruta /. Se devuelve la primera aplicación de demostración, tal como se muestra en la siguiente salida de ejemplo reducido:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>Welcome to Azure Kubernetes Service (AKS)</title>
    [...]
    
  4. Agregue la ruta de acceso /hello-world-two a la dirección, como http://10.224.0.42/hello-world-two.

    curl -L -k http://10.224.0.42/hello-world-two
    

    Se devuelve la segunda aplicación de demostración con el título personalizado, tal como se muestra en la siguiente salida de ejemplo reducido:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>AKS Ingress Demo</title>
    [...]
    

Limpieza de recursos

En este artículo, se usa Helm para instalar los componentes de entrada 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

Para eliminar el espacio de nombres de ejemplo completo, use el comando kubectl delete y especifique el nombre del espacio de nombres. Todos los recursos del espacio de nombres se eliminan.

kubectl delete namespace ingress-basic

Eliminación de recursos individualmente

Como alternativa, un enfoque más pormenorizado consiste en eliminar los recursos individuales creados.

  1. Despliegue una lista de las versiones de Helm con el comando helm list.

    helm list --namespace ingress-basic
    

    Busque los gráficos denominados ingress-nginx y aks-helloworld, tal y como se muestra en la salida del ejemplo siguiente:

    NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART                   APP VERSION
    ingress-nginx           ingress-basic   1               2020-01-06 19:55:46.358275 -0600 CST    deployed        nginx-ingress-1.27.1    0.26.1  
    
  2. Desinstale las versiones con el comando helm uninstall.

    helm uninstall ingress-nginx --namespace ingress-basic
    
  3. 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
    
  4. Elimine la ruta de entrada que dirige el tráfico a las aplicaciones de ejemplo.

    kubectl delete -f hello-world-ingress.yaml
    
  5. Para eliminar el espacio de nombres, use el comando kubectl delete y especifique el nombre.

    kubectl delete namespace ingress-basic
    

Pasos siguientes

Para configurar TLS con los componentes de entrada existentes, consulte Uso de TLS con un controlador de entrada en Azure Kubernetes Service (AKS).

Para configurar el clúster de AKS para que use el enrutamiento de aplicaciones HTTP, consulte Enrutamiento de aplicación HTTP.

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: