Utilizar o TLS com um controlador de entrada no Azure Kubernetes Service (AKS)

O protocolo TLS (Transport Layer Security) utiliza certificados para fornecer segurança para comunicação, encriptação, autenticação e integridade. Utilizar o TLS com um controlador de entrada no AKS permite-lhe proteger a comunicação entre as suas aplicações e experimentar os benefícios de um controlador de entrada.

Pode trazer os seus próprios certificados e integrá-los com o controlador CSI do Arquivo de Segredos. Em alternativa, pode utilizar o cert-manager, que gera e configura automaticamente certificados Let's Encrypt . Duas aplicações são executadas no cluster do AKS, cada uma delas acessível através de um único endereço IP.

Nota

Existem dois controladores de entrada open source para o Kubernetes baseados no Nginx: um é mantido pela comunidade do Kubernetes (kubernetes/ingress-nginx) e um é mantido pela NGINX, Inc. (nginxinc/kubernetes-ingress). Este artigo utiliza o controlador de entrada da comunidade do Kubernetes.

Antes de começar

  • Este artigo pressupõe que tem um controlador de entrada e aplicações configurados. Se precisar de um controlador de entrada ou aplicações de exemplo, veja Criar um controlador de entrada.

  • Este artigo utiliza o Helm 3 para instalar o controlador de entrada NGINX numa versão suportada do Kubernetes. Certifique-se de que está a utilizar a versão mais recente do Helm e tem acesso aos ingress-nginx repositórios helm e e jetstack . Os passos descritos neste artigo podem não ser compatíveis com versões anteriores do gráfico Helm, do controlador de entrada NGINX ou do Kubernetes.

  • Este artigo pressupõe que tem um cluster do AKS existente com um Azure Container Registry integrado (ACR). Para obter mais informações sobre como criar um cluster do AKS com um ACR integrado, veja Authenticate with ACR from AKS (Autenticar com o ACR a partir do AKS).

  • Se estiver a utilizar a CLI do Azure, este artigo requer a execução da versão 2.0.64 ou posterior da CLI do Azure. Executar az --version para localizar a versão. Se precisar de instalar ou atualizar, veja Install Azure CLI (Instalar o Azure CLI).

  • Se estiver a utilizar Azure PowerShell, este artigo requer que execute Azure PowerShell versão 5.9.0 ou posterior. Executar Get-InstalledModule -Name Az para localizar a versão. Se precisar de instalar ou atualizar, veja Install Azure PowerShell(Instalar o Azure PowerShell).

Utilizar o TLS com os seus próprios certificados com o Controlador CSI do Arquivo de Segredos

Para utilizar o TLS com os seus próprios certificados com o Controlador CSI do Arquivo de Segredos, precisa de um cluster do AKS com o Controlador CSI do Arquivo de Segredos configurado e uma instância do Azure Key Vault.

Para obter mais informações, veja Configurar o Controlador CSI do Arquivo de Segredos para ativar o Controlador de Entradas NGINX com o TLS.

Utilizar o TLS com certificados Let's Encrypt

Para utilizar o TLS com certificados Let's Encrypt , irá implementar o cert-manager, que gera e configura automaticamente certificados Let's Encrypt.

Importar as imagens do cert-manager utilizadas pelo gráfico Helm para o ACR

  • Utilize az acr import para importar as seguintes imagens para o seu 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

Também pode importar gráficos Helm para o seu ACR. Para obter mais informações, veja Emitir e solicitar gráficos Helm para um ACR.

Opções de configuração do controlador de entrada

Pode configurar o controlador de entrada NGINX com um endereço IP público estático ou um endereço IP público dinâmico. Se estiver a utilizar um domínio personalizado, terá de adicionar um registo A à sua zona DNS. Se não estiver a utilizar um domínio personalizado, pode configurar um nome de domínio completamente qualificado (FQDN) para o endereço IP do controlador de entrada.

Criar um endereço IP público estático ou dinâmico

Utilizar um endereço IP público estático

Pode configurar o controlador de entrada com um endereço IP público estático. O endereço IP público estático permanece se eliminar o controlador de entrada. O endereço IP não permanece se eliminar o cluster do AKS.

Ao atualizar o controlador de entrada, tem de transmitir um parâmetro para a versão do Helm para garantir que o serviço do controlador de entrada tem conhecimento do balanceador de carga que lhe será atribuído. Para que os certificados HTTPS funcionem corretamente, utilize uma etiqueta DNS para configurar um FQDN para o endereço IP do controlador de entrada.

  1. Obtenha o nome do grupo de recursos do cluster do AKS com o az aks show comando .

    az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
    
  2. Crie um endereço IP público com o método de alocação estático com o az network public-ip create comando . O exemplo seguinte cria um endereço IP público com o nome myAKSPublicIP no grupo de recursos do cluster do AKS obtido no passo 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

Em alternativa, pode criar um endereço IP num grupo de recursos diferente, que pode gerir separadamente do cluster do AKS. Se criar um endereço IP num grupo de recursos diferente, certifique-se de que o seguinte é verdadeiro:

  • A identidade do cluster utilizada pelo cluster do AKS tem permissões delegadas para o grupo de recursos, como Contribuidor de Rede.
  • Adicione o --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-resource-group"="<RESOURCE_GROUP>" parâmetro . Substitua <RESOURCE_GROUP> pelo nome do grupo de recursos onde reside o endereço IP.
  1. Adicione o --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name"="<DNS_LABEL>" parâmetro . A etiqueta DNS pode ser definida quando o controlador de entrada é implementado pela primeira vez ou pode ser configurado mais tarde.

  2. Adicione o --set controller.service.loadBalancerIP="<STATIC_IP>" parâmetro . Especifique o seu próprio endereço IP público que foi criado no passo 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 obter mais informações, veja Utilizar um endereço IP público estático e uma etiqueta DNS com o balanceador de carga do AKS.

Utilizar um endereço IP público dinâmico

É criado um endereço IP público do Azure para o controlador de entrada após a criação. O endereço IP público é estático durante o tempo de vida do controlador de entrada. O endereço IP público não permanece se eliminar o controlador de entrada. Se criar um novo controlador de entrada, será atribuído um novo endereço IP público. O resultado deverá ter um aspeto semelhante ao seguinte resultado de exemplo.

  • Utilize o kubectl get service comando para obter o endereço IP público para o 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
    

Adicionar um registo A à zona DNS

Se estiver a utilizar um domínio personalizado, terá de adicionar um registo A à sua zona DNS. Se não estiver a utilizar um domínio personalizado, pode configurar o endereço IP público com um FQDN.

  • Adicione um registo A à zona DNS com o endereço IP externo do serviço NGINX com 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 um FQDN para o controlador de entrada

Opcionalmente, pode configurar um FQDN para o endereço IP do controlador de entrada em vez de um domínio personalizado ao definir uma etiqueta DNS. O FQDN deve seguir este formulário: <CUSTOM DNS LABEL>.<AZURE REGION NAME>.cloudapp.azure.com.

Importante

A etiqueta DNS tem de ser exclusiva na respetiva localização do Azure.

Pode configurar o FQDN com um dos seguintes métodos:

  • Defina a etiqueta DNS com a CLI do Azure ou Azure PowerShell.
  • Defina a etiqueta DNS com as definições do gráfico Helm.

Para obter mais informações, veja Etiquetas de nome DNS do endereço IP público.

Definir a etiqueta DNS com a CLI do Azure ou Azure PowerShell

Certifique-se de que substitui <DNS_LABEL> pela sua etiqueta DNS exclusiva.

# 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

Definir a etiqueta DNS com as definições do gráfico Helm

Pode transmitir uma definição de anotação para a configuração do gráfico Helm com o --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name" parâmetro . Este parâmetro pode ser definido quando o controlador de entrada é implementado pela primeira vez ou pode ser configurado mais tarde.

O exemplo seguinte mostra como atualizar esta definição após a implementação do controlador. Certifique-se de que substitui <DNS_LABEL> pela sua etiqueta DNS exclusiva.

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 o cert-manager

O controlador de entrada do NGINX suporta a terminação de TLS. Existem várias formas de obter e configurar certificados para HTTPS. Este artigo utiliza o cert-manager, que fornece funcionalidades automáticas de gestão e geração de certificados Lets Encrypt .

Para instalar o controlador cert-manager, utilize os seguintes comandos.

# 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 obter mais informações sobre a configuração do cert-manager, veja o projeto cert-manager.

Criar um emissor de clusters de AC

Antes de os certificados poderem ser emitidos, o cert-manager requer um dos seguintes emissores:

  • Um Emissor, que funciona num único espaço de nomes.
  • Um recurso ClusterIssuer , que funciona em todos os espaços de nomes.

Para obter mais informações, veja a documentação do emissor do cert-manager .

  1. Crie um emissor de clusters, como cluster-issuer.yaml, com o seguinte manifesto de exemplo. Substitua MY_EMAIL_ADDRESS por um endereço válido da sua organização.

    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 o emissor com o kubectl apply comando .

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

Atualizar as rotas de entrada

Tem de atualizar as rotas de entrada para processar o tráfego para o seu FQDN ou domínio personalizado.

No exemplo seguinte, o tráfego é encaminhado como tal:

  • Tráfego para hello-world-ingress. MY_CUSTOM_DOMAIN é encaminhado para o serviço aks-helloworld-one .
  • Tráfego para hello-world-ingress. MY_CUSTOM_DOMAIN/hello-world-two é encaminhado para o serviço aks-helloworld-two .
  • Tráfego para hello-world-ingress. MY_CUSTOM_DOMAIN/estático é encaminhado para o serviço com o nome aks-helloworld-one para recursos estáticos.

Nota

Se tiver configurado um FQDN para o endereço IP do controlador de entrada em vez de um domínio personalizado, utilize o FQDN em vez de hello-world-ingress. MY_CUSTOM_DOMAIN.

Por exemplo, se o FQDN for demo-aks-ingress.eastus.cloudapp.azure.com, substitua hello-world-ingress. MY_CUSTOM_DOMAIN com demo-aks-ingress.eastus.cloudapp.azure.com no hello-world-ingress.yaml.

  1. Crie ou atualize o hello-world-ingress.yaml ficheiro com o seguinte ficheiro YAML de exemplo. Atualize o spec.tls.hosts e spec.rules.host para o nome DNS que criou num passo 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. Atualize o recurso de entrada com o kubectl apply comando .

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

Verificar se foi criado um objeto de certificado

Em seguida, tem de ser criado um recurso de certificado. O recurso de certificado define o certificado X.509 pretendido. Para obter mais informações, veja Certificados do cert-manager.

O Cert-manager cria automaticamente um objeto de certificado para si através do ingress-shim, que é implementado automaticamente com o cert-manager desde v0.2.2. Para obter mais informações, veja a documentação ingress-shim.

Para verificar se o certificado foi criado com êxito, utilize o kubectl get certificate --namespace ingress-basic comando e verifique se READY é Verdadeiro. Poderá demorar vários minutos a obter a saída.

kubectl get certificate --namespace ingress-basic

O resultado seguinte mostra o estado do certificado.

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

Testar a configuração de entrada

Abra um browser para hello-world-ingress. MY_CUSTOM_DOMAIN ou o FQDN do controlador de entrada do Kubernetes. Certifique-se de que o seguinte é verdadeiro:

  • É redirecionado para utilizar HTTPS.
  • O certificado é fidedigno.
  • A aplicação de demonstração é apresentada no browser.
  • Adicione /hello-world-two ao fim do domínio e certifique-se de que é apresentada a segunda aplicação de demonstração com o título personalizado.

Limpar os recursos

Este artigo utilizou o Helm para instalar os componentes de entrada, certificados e aplicações de exemplo. Quando implementa um gráfico Helm, são criados muitos recursos do Kubernetes. Estes recursos incluem pods, implementações e serviços. Para limpar estes recursos, pode eliminar todo o espaço de nomes de exemplo ou os recursos individuais.

Eliminar o espaço de nomes de exemplo e todos os recursos

Eliminar o espaço de nomes de exemplo também elimina todos os recursos no espaço de nomes.

  • Elimine todo o espaço de nomes de exemplo com o kubectl delete comando e especifique o nome do espaço de nomes.

    kubectl delete namespace ingress-basic
    

Eliminar recursos individualmente

Em alternativa, pode eliminar o recurso individualmente.

  1. Remova os recursos do emissor de clusters.

    kubectl delete -f cluster-issuer.yaml --namespace ingress-basic
    
  2. Liste as versões do Helm com o helm list comando . Procure gráficos com o nome nginx e cert-manager, conforme mostrado na saída de exemplo seguinte.

    $ 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 as versões com o helm uninstall comando . O exemplo seguinte desinstala as implementações de entrada NGINX e cert-manager.

    $ helm uninstall cert-manager nginx --namespace ingress-basic
    
    release "cert-manager" uninstalled
    release "nginx" uninstalled
    
  4. Remova as duas aplicações de exemplo.

    kubectl delete -f aks-helloworld-one.yaml --namespace ingress-basic
    kubectl delete -f aks-helloworld-two.yaml --namespace ingress-basic
    
  5. Remova a rota de entrada que direcionou o tráfego para as aplicações de exemplo.

    kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
    
  6. Elimine o próprio espaço de nomes. Utilize o kubectl delete comando e especifique o nome do espaço de nomes.

    kubectl delete namespace ingress-basic
    

Passos seguintes

Este artigo incluía alguns componentes externos para o AKS. Para saber mais sobre estes componentes, veja as seguintes páginas do projeto:

Também pode: