Usar TLS com um controlador de entrada no Serviço Kubernetes do Azure (AKS)

O protocolo TLS (Transport Layer Security) usa certificados para fornecer segurança para comunicação, criptografia, autenticação e integridade. Usar TLS com um controlador de entrada no AKS permite que você proteja a comunicação entre seus aplicativos e experimente os benefícios de um controlador de entrada.

Você pode trazer seus próprios certificados e integrá-los com o driver CSI da Secrets Store. Como alternativa, você pode usar o cert-manager, que gera e configura automaticamente os certificados Let's Encrypt . Duas aplicações são executadas no cluster AKS, cada uma das quais é acessível através de um único endereço IP.

Importante

O complemento de roteamento de aplicativos é recomendado para entrada no AKS. Para obter mais informações, consulte Managed nginx Ingress with the application routing add-on.

Importante

A Microsoft não gerencia nem oferece suporte ao cert-manager e a quaisquer problemas decorrentes de seu uso. Para problemas com o cert-manager, consulte a documentação de solução de problemas do cert-manager.

Existem dois controladores de entrada de código aberto para Kubernetes baseados em Nginx: um é mantido pela comunidade Kubernetes (kubernetes/ingress-nginx), e um é mantido pela NGINX, Inc. Este artigo usa o controlador de entrada da comunidade Kubernetes.

Antes de começar

  • Este artigo pressupõe que você tenha um controlador de entrada e aplicativos configurados. Se você precisar de um controlador de entrada ou aplicativos de exemplo, consulte Criar um controlador de entrada.

  • Este artigo usa o Helm 3 para instalar o controlador de entrada NGINX em uma versão suportada do Kubernetes. Certifique-se de que está a utilizar a versão mais recente do Helm e tenha acesso aos ingress-nginx repositórios e jetstack Helm. As etapas descritas neste artigo podem não ser compatíveis com versões anteriores do gráfico Helm, controlador de entrada NGINX ou Kubernetes.

  • Este artigo pressupõe que você tenha um cluster AKS existente com um Registro de Contêiner do Azure (ACR) integrado. Para obter mais informações sobre como criar um cluster AKS com um ACR integrado, consulte Autenticar com ACR do AKS.

  • Se você estiver usando a CLI do Azure, este artigo requer que você esteja executando a CLI do Azure versão 2.0.64 ou posterior. Executar az --version para localizar a versão. Se precisar de instalar ou atualizar, veja Install Azure CLI (Instalar o Azure CLI).

  • Se você estiver usando o Azure PowerShell, este artigo requer que você esteja executando o 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).

Use TLS com seus próprios certificados com o Secrets Store CSI Driver

Para usar o TLS com seus próprios certificados com o Driver CSI do Secrets Store, você precisa de um cluster AKS com o Driver CSI do Secrets Store configurado e uma instância do Azure Key Vault.

Para obter mais informações, consulte Configurar o driver CSI do Secrets Store para habilitar o NGINX Ingress Controller com TLS.

Usar TLS com certificados Let's Encrypt

Para usar o TLS com certificados Let's Encrypt , você implantará o cert-manager, que gera e configura automaticamente os certificados Let's Encrypt.

Importe as imagens do cert-manager usadas pelo gráfico Helm para o ACR

  • Use 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

Você também pode importar gráficos Helm para seu ACR. Para obter mais informações, consulte Enviar e puxar gráficos de leme para um ACR.

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

Você pode configurar seu controlador de entrada NGINX usando 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, tem de adicionar um registo A à sua zona DNS. Se você não estiver usando um domínio personalizado, poderá configurar um FQDN (nome de domínio totalmente qualificado) para o endereço IP do controlador de ingresso.

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

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

Você pode configurar seu controlador de entrada com um endereço IP público estático. O endereço IP público estático permanecerá se você excluir seu controlador de entrada. O endereço IP não permanece se você excluir seu cluster AKS.

Ao atualizar seu controlador de entrada, você deve passar um parâmetro para a liberação do Helm para garantir que o serviço do controlador de entrada esteja ciente do balanceador de carga que será alocado a ele. Para que os certificados HTTPS funcionem corretamente, use um rótulo DNS para configurar um FQDN para o endereço IP do controlador de entrada.

  1. Obtenha o nome do grupo de recursos do cluster 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ática usando o az network public-ip create comando. O exemplo a seguir cria um endereço IP público chamado myAKSPublicIP no grupo de recursos de cluster AKS obtido na etapa 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, você pode criar um endereço IP em um grupo de recursos diferente, que pode ser gerenciado separadamente do cluster AKS. Se você criar um endereço IP em um grupo de recursos diferente, verifique se o seguinte é verdadeiro:

  • A identidade do cluster usada pelo cluster AKS delegou permissões ao grupo de recursos, como Colaborador 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. O rótulo DNS pode ser definido quando o controlador de entrada é implantado pela primeira vez ou pode ser configurado posteriormente.

  2. Adicione o --set controller.service.loadBalancerIP="<STATIC_IP>" parâmetro. Especifique seu próprio endereço IP público que foi criado na etapa 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, consulte Usar um endereço IP público estático e um rótulo DNS com o balanceador de carga AKS.

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

Um endereço IP público do Azure é criado para seu controlador de entrada após a criação. O endereço IP público é estático durante a vida útil do seu controlador de entrada. O endereço IP público não permanece se você excluir seu controlador de entrada. Se você criar um novo controlador de entrada, ele receberá um novo endereço IP público. Sua saída deve ser semelhante à saída de exemplo a seguir.

  • Use o kubectl get service comando para obter o endereço IP público para seu 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 à sua zona DNS

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

  • Adicione um registro A à sua zona DNS com o endereço IP externo do serviço NGINX usando az network dns record-set a add-recordo .

    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 seu controlador de entrada

Opcionalmente, você pode configurar um FQDN para o endereço IP do controlador de entrada em vez de um domínio personalizado definindo um rótulo DNS. O seu FQDN deve seguir este formulário: <CUSTOM DNS LABEL>.<AZURE REGION NAME>.cloudapp.azure.com.

Importante

Seu rótulo DNS deve ser exclusivo em seu local do Azure.

Você pode configurar seu FQDN usando um dos seguintes métodos:

  • Defina o rótulo DNS usando a CLI do Azure ou o Azure PowerShell.
  • Defina o rótulo DNS usando as configurações do gráfico Helm.

Para obter mais informações, consulte Rótulos de nome DNS de endereço IP público.

Definir o rótulo DNS usando a CLI do Azure ou o Azure PowerShell

Certifique-se de substituir <DNS_LABEL> por seu rótulo DNS exclusivo.

# 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 o rótulo DNS usando as configurações do gráfico Helm

Você pode passar uma configuração de anotação para a configuração do gráfico Helm usando o --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-dns-label-name" parâmetro. Esse parâmetro pode ser definido quando o controlador de entrada é implantado pela primeira vez ou pode ser configurado posteriormente.

O exemplo a seguir mostra como atualizar essa configuração após a implantação do controlador. Certifique-se de substituir <DNS_LABEL> por seu rótulo DNS exclusivo.

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 usa o cert-manager, que fornece a funcionalidade automática de geração e gerenciamento de certificados Lets Encrypt .

Para instalar o controlador cert-manager, use 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, consulte o projeto cert-manager.

Criar um emissor de cluster de CA

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

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

  1. Crie um emissor de cluster, como cluster-issuer.yaml, usando o manifesto de exemplo a seguir. 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 usando o kubectl apply comando.

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

Atualize suas rotas de entrada

Você precisa atualizar suas rotas de entrada para lidar com o tráfego para seu FQDN ou domínio personalizado.

No exemplo a seguir, o tráfego é roteado como tal:

  • Tráfego para hello-world-ingress. MY_CUSTOM_DOMAIN é roteado para o serviço aks-helloworld-one .
  • Tráfego para hello-world-ingress. MY_CUSTOM_DOMAIN/hello-world-two é roteado para o serviço aks-helloworld-two .
  • Tráfego para hello-world-ingress. MY_CUSTOM_DOMAIN/static é roteado para o serviço chamado aks-helloworld-one para ativos estáticos.

Nota

Se você configurou um FQDN para o endereço IP do controlador de entrada em vez de um domínio personalizado, use o FQDN em vez de hello-world-ingress. MY_CUSTOM_DOMAIN.

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

  1. Crie ou atualize o hello-world-ingress.yaml arquivo usando o seguinte exemplo de arquivo YAML. Atualize o spec.tls.hosts e spec.rules.host para o nome DNS que você criou em uma etapa 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 usando o kubectl apply comando.

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

Verificar se um objeto de certificado foi criado

Em seguida, um recurso de certificado deve ser criado. O recurso de certificado define o certificado X.509 desejado. Para obter mais informações, consulte certificados cert-manager.

O Cert-manager cria automaticamente um objeto de certificado para você usando ingress-shim, que é implantado automaticamente com o cert-manager desde a v0.2.2. Para obter mais informações, consulte a documentação do ingress-shim.

Para verificar se o certificado foi criado com êxito, use o kubectl get certificate --namespace ingress-basic comando e verifique se READY é True. Pode levar vários minutos para obter a saída.

kubectl get certificate --namespace ingress-basic

A saída a seguir mostra o status do certificado.

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

Testar a configuração de entrada

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

  • Você será redirecionado para usar HTTPS.
  • O certificado é confiável.
  • O aplicativo de demonstração é mostrado no navegador da web.
  • Adicione /hello-world-two ao final do domínio e certifique-se de que o segundo aplicativo de demonstração com o título personalizado seja mostrado.

Clean up resources (Limpar recursos)

Este artigo usou o Helm para instalar os componentes de entrada, certificados e aplicativos de exemplo. Quando você implanta um gráfico Helm, muitos recursos do Kubernetes são criados. Esses recursos incluem pods, implantações e serviços. Para limpar esses recursos, você pode excluir todo o namespace de exemplo ou os recursos individuais.

Excluir o namespace de exemplo e todos os recursos

A exclusão do namespace de exemplo também exclui todos os recursos no namespace.

  • Exclua todo o namespace de exemplo usando o comando e especificando o nome do kubectl delete namespace.

    kubectl delete namespace ingress-basic
    

Excluir recursos individualmente

Como alternativa, você pode excluir o recurso individualmente.

  1. Remova os recursos do emissor do cluster.

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

    $ 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 usando o helm uninstall comando. O exemplo a seguir desinstala as implantações NGINX ingress e cert-manager.

    $ helm uninstall cert-manager nginx --namespace ingress-basic
    
    release "cert-manager" uninstalled
    release "nginx" uninstalled
    
  4. Remova os dois aplicativos 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 os aplicativos de exemplo.

    kubectl delete -f hello-world-ingress.yaml --namespace ingress-basic
    
  6. Exclua o namespace próprio. Use o comando e especifique o nome do kubectl delete namespace.

    kubectl delete namespace ingress-basic
    

Próximos passos

Este artigo incluiu alguns componentes externos ao AKS. Para saber mais sobre esses componentes, consulte as seguintes páginas do projeto:

Também pode: