Creación de un controlador de entrada HTTPS en Azure Kubernetes Service (AKS)
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. Mediante reglas de entrada y un controlador 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). El proyecto cert-manager se usa para generar y configurar automáticamente certificados Let's Encrypt. Por último, en el clúster de AKS se ejecutan dos aplicaciones, a las que se puede acceder con una sola dirección IP.
También puede:
- Creación de un controlador de entrada básico con conectividad de red externa
- Habilitación del complemento de enrutamiento de aplicación HTTP
- Creación de un controlador de entrada que use una red privada interna y una dirección IP
- Crear un controlador de entrada que usa sus propios certificados TLS
- Crear un controlador de entrada que usa Let's Encrypt para generar automáticamente certificados TLS con una dirección IP pública estática
Antes de empezar
En este artículo se supone que ya tiene un clúster de AKS. Si necesita un clúster de AKS, consulte el inicio rápido de AKS mediante la CLI de Azure o mediante Azure Portal.
En este artículo se supone que tiene un dominio personalizado con una zona DNS en el mismo grupo de recursos que el clúster de AKS.
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.
Para obtener más información sobre cómo configurar y usar Helm, consulte Instalación de aplicaciones con Helm en Azure Kubernetes Service (AKS). Para obtener instrucciones de actualización, vea la documentación de instalación de Helm.
En este artículo también se requiere que ejecute la versión 2.0.64 de la CLI de Azure o una versión posterior. Ejecute az --version para encontrar la versión. Si necesita instalarla o actualizarla, vea Instalación de la CLI de Azure.
Además, en este artículo se da por supuesto que tiene un clúster de AKS existente con un ACR integrado. Para obtener más información sobre cómo crear un clúster de AKS con un ACR integrado, consulte Autenticación con Azure Container Registry desde Azure Kubernetes Service.
Importación de las imágenes usadas por el gráfico de Helm en el ACR
En este artículo se usa el gráfico de Helm del controlador de entrada de NGINX, que 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=k8s.gcr.io
CONTROLLER_IMAGE=ingress-nginx/controller
CONTROLLER_TAG=v1.0.4
PATCH_IMAGE=ingress-nginx/kube-webhook-certgen
PATCH_TAG=v1.1.1
DEFAULTBACKEND_IMAGE=defaultbackend-amd64
DEFAULTBACKEND_TAG=1.5
CERT_MANAGER_REGISTRY=quay.io
CERT_MANAGER_TAG=v1.5.4
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 $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
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
Además de importar imágenes de contenedor en el ACR, también puede importar gráficos de Helm en el ACR. Para obtener 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 el comando helm para instalar nginx-ingress. 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.
El controlador de entrada también debe programarse en un nodo de 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.
Sugerencia
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.
Sugerencia
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 paso a través de TLS no funciona.
# Add the ingress-nginx repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# Set variable for ACR location to use for pulling images
ACR_URL=<REGISTRY_URL>
# Use Helm to deploy an NGINX ingress controller
helm install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress-basic --create-namespace \
--set controller.replicaCount=2 \
--set controller.nodeSelector."kubernetes\.io/os"=linux \
--set controller.image.registry=$ACR_URL \
--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.admissionWebhooks.patch.image.registry=$ACR_URL \
--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_URL \
--set defaultBackend.image.image=$DEFAULTBACKEND_IMAGE \
--set defaultBackend.image.tag=$DEFAULTBACKEND_TAG \
--set defaultBackend.image.digest=""
Durante la instalación se crea una dirección IP pública de Azure para el controlador de entrada. Esta dirección IP pública es estática durante el período de vida del controlador de entrada. Si elimina el controlador de entrada, se pierde la asignación de dirección IP pública. Si después crea un controlador de entrada adicional, se asigna una dirección IP pública nueva. Si quiere conservar el uso de la dirección IP pública, en su lugar puede crear un controlador de entrada con una dirección IP pública estática.
Para obtener la dirección IP pública, use el comando kubectl get service. La asignación de la dirección IP al servicio puede tardar hasta un minuto.
$ kubectl --namespace ingress-basic get services -o wide -w nginx-ingress-ingress-nginx-controller
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
Todavía no se creó ninguna regla de entrada. Si navega a la dirección IP pública, se muestra la página 404 predeterminada del controlador de entrada NGINX.
Adición de un registro A a la zona DNS
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
Configuración de 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. Este FQDN tendrá el formato <CUSTOM LABEL>.<AZURE REGION NAME>.cloudapp.azure.com.
Existen dos métodos para realizar esta configuración, los cuales se describen a continuación.
Método 1: Establecimiento de la etiqueta DNS mediante la CLI de Azure
Tenga en cuenta que este ejemplo es para un shell de Bash.
# Public IP address of your ingress controller
IP="MY_EXTERNAL_IP"
# Name to associate with public IP address
DNSNAME="demo-aks-ingress"
# 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 $DNSNAME
# Display the FQDN
az network public-ip show --ids $PUBLICIPID --query "[dnsSettings.fqdn]" --output tsv
Método 2: Establecimiento de 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". Esto 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.
DNS_LABEL="demo-aks-ingress"
NAMESPACE="nginx-basic"
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--namespace $NAMESPACE \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"=$DNS_LABEL
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 muestra cómo utilizar cert manager, que proporciona la generación automática de certificados Lets Encrypt y la funcionalidad de administración.
Para instalar el controlador cert-manager:
# 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
Para poder emitir certificados, cert-manager requiere un recurso Issuer o ClusterIssuer. La funcionalidad de los recursos de Kubernetes es idéntica, pero Issuer funciona en un espacio de nombres único, mientras que ClusterIssuer funciona en todos los espacios de nombres. Para obtener más información, consulte la documentación de cert-manager issuer.
Cree un emisor de clúster, como cluster-issuer.yaml, con el manifiesto de ejemplo siguiente. Actualice la dirección de correo electrónico con 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
Para crear el emisor, use el comando kubectl apply.
kubectl apply -f cluster-issuer.yaml
Ejecución de aplicaciones de demostración
Se deben haber configurado una solución de administración de certificados y un controlador de entrada. Ahora vamos a ejecutar dos aplicaciones de demostración en el clúster de AKS. En este ejemplo, Helm se usa para implementar dos instancias de una aplicación Hola mundo sencilla.
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.
Cree un 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
Cree un 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
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. Sin embargo, están configuradas con un servicio de tipo ClusterIP y no son accesibles desde Internet. Para que estén disponibles de manera pública, 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 hello-world-ingress.MY_CUSTOM_DOMAIN se enruta al servicio aks-helloworld-one. El tráfico a la dirección 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 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.
Cree un archivo denominado hello-world-ingress.yaml mediante el ejemplo de YAML siguiente. Actualice los hosts y el host al nombre DNS que creó en un paso anterior.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world-ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/use-regex: "true"
cert-manager.io/cluster-issuer: letsencrypt
spec:
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:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /static/$2
nginx.ingress.kubernetes.io/use-regex: "true"
cert-manager.io/cluster-issuer: letsencrypt
spec:
tls:
- hosts:
- hello-world-ingress.MY_CUSTOM_DOMAIN
secretName: tls-secret
rules:
- host: hello-world-ingress.MY_CUSTOM_DOMAIN
http:
paths:
- path:
pathType: Prefix
backend:
service:
name: aks-helloworld-one
port:
number: 80
path: /static(/|$)(.*)
Cree 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. Es probable que el elemento cert-manager haya creado 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, lo que puede tardar varios minutos.
$ kubectl get certificate --namespace ingress-basic
NAME READY SECRET AGE
tls-secret True tls-secret 11m
Prueba de la configuración de entrada
Abra un explorador web a la dirección hello-world-ingress.MY_CUSTOM_DOMAIN del controlador de entrada de Kubernetes. Tenga en cuenta que se le redirige a usar HTTPS, que el certificado es de confianza y la aplicación de demostración se muestra en el explorador web. Agregue la ruta de acceso /hello-world-two y observe 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 algunos 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. En primer lugar, quite los recursos del emisor del clúster:
kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
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
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
Luego, 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
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
Por último, puede eliminar 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:
- Creación de un controlador de entrada básico con conectividad de red externa
- Habilitación del complemento de enrutamiento de aplicación HTTP
- Creación de un controlador de entrada que use una red privada interna y una dirección IP
- Crear un controlador de entrada que usa sus propios certificados TLS
- Crear un controlador de entrada que usa Let's Encrypt para generar automáticamente certificados TLS con una dirección IP pública estática