Configure o Driver de CSI de armazenamento de segredos para habilitar o controlador de entrada NGINX com TLS
Este artigo orienta você pelo processo de proteção de um controlador de entrada NGINX com TLS com um cluster AKS (Serviço de Kubernetes do Azure) e uma instância de Azure Key Vault (AKV). Para obter mais informações, confira TLS no Kubernetes.
Você pode importar o certificado TLS de entrada para o cluster usando um dos seguintes métodos:
- Aplicativo: o manifesto de implantação do aplicativo declara e monta o volume do provedor. Somente quando você implanta o aplicativo o certificado é disponibilizado no cluster. Quando você remove o aplicativo, o segredo também é removido. Esse cenário se encaixa em equipes de desenvolvimento responsáveis pela infraestrutura de segurança do aplicativo e sua integração com o cluster.
- Controlador de entrada: a implantação de entrada é modificada para declarar e montar o volume do provedor. O segredo é importado quando os pods de entrada são criados. O pods do aplicativo não tem acesso ao certificado TLS. Esse cenário se ajusta a cenários em que uma equipe (por exemplo, a de TI) gerencia e cria componentes de rede e infraestrutura (incluindo certificados TLS HTTPS) e outras equipes gerenciam o ciclo de vida do aplicativo.
Pré-requisitos
- Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.
- Antes de começar, verifique se a sua versão da CLI do Azure é > =
2.30.0
ou instale a versão mais recente. - Um cluster do AKS com o Driver de CSI de armazenamento de segredos configurado.
- Uma instância do Azure Key Vault.
Gerar um certificado TLS
Gere um certificado TLS usando o comando a seguir.
export CERT_NAME=aks-ingress-cert openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -out aks-ingress-tls.crt \ -keyout aks-ingress-tls.key \ -subj "/CN=demo.azure.com/O=aks-ingress-tls"
Importar o certificado para AKV
Exporte o certificado para um arquivo PFX usando o comando a seguir.
export AKV_NAME="[YOUR AKV NAME]" openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key -out $CERT_NAME.pfx # skip Password prompt
Importe o certificado usando o comando
az keyvault certificate import
.az keyvault certificate import --vault-name $AKV_NAME --name $CERT_NAME --file $CERT_NAME.pfx
Implantar um SecretProviderClass
Exporte um novo namespace usando o comando a seguir.
export NAMESPACE=ingress-basic
Crie o namespace usando o comando
kubectl create namespace
.kubectl create namespace $NAMESPACE
Selecione um método para fornecer uma identidade de acesso e configure seu YAML de acordo com SecretProviderClass.
- Use
objectType=secret
, pois essa é a única maneira de obter a chave privada e o certificado do AKV. - Defina
kubernetes.io/tls
comotype
em sua seçãosecretObjects
.
Confira o exemplo a seguir de como pode ser a aparência de seu SecretProviderClass:
apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: azure-tls spec: provider: azure secretObjects: # secretObjects defines the desired state of synced K8s secret objects - secretName: ingress-tls-csi type: kubernetes.io/tls data: - objectName: $CERT_NAME key: tls.key - objectName: $CERT_NAME key: tls.crt parameters: usePodIdentity: "false" useVMManagedIdentity: "true" userAssignedIdentityID: <client id> keyvaultName: $AKV_NAME # the name of the AKV instance objects: | array: - | objectName: $CERT_NAME objectType: secret tenantId: $TENANT_ID # the tenant ID of the AKV instance
- Use
Aplique SecretProviderClass ao cluster do Kubernetes usando o comando
kubectl apply
.kubectl apply -f secretProviderClass.yaml -n $NAMESPACE
Implantar o controlador de entrada
Adicionar o repositório de gráfico de entrada oficial
Adicione o repositório oficial do gráfico de entrada usando os comandos
helm
a seguir.helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update
Configurar e implantar a entrada do NGINX
Dependendo do seu cenário, você pode optar por associar o certificado ao aplicativo ou ao controlador de entrada. Siga as instruções abaixo de acordo com sua seleção:
Associar certificado ao aplicativo
Associe o certificado ao aplicativo usando o comando
helm install
. A implantação do aplicativo faz referência ao provedor do Azure Key Vault do Driver de CSI do Repositório de Segredos.helm install ingress-nginx/ingress-nginx --generate-name \ --namespace $NAMESPACE \ --set controller.replicaCount=2 \ --set controller.nodeSelector."kubernetes\.io/os"=linux \ --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \ --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux
Associar certificado ao controlador de entrada
Associe o certificado ao controlador de entrada usando o comando
helm install
. A implantação do controlador de entrada faz referência ao provedor do Azure Key Vault do Driver CSI Repositório de Segredos.Observação
Se não estiver usando a identidade gerenciada por pod do Microsoft Entra como seu método de acesso, remova a linha com
--set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME
.Além disso, é necessário associar o SecretProviderClass a um pod para que o Driver CSI do Repositório de Segredos o monte e gere o segredo do Kubernetes. Consulte Sincronizar conteúdo montado com um segredo do Kubernetes.
helm install ingress-nginx/ingress-nginx --generate-name \ --namespace $NAMESPACE \ --set controller.replicaCount=2 \ --set controller.nodeSelector."kubernetes\.io/os"=linux \ --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \ --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \ --set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME \ -f - <<EOF controller: extraVolumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" extraVolumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true EOF
Verifique se o segredo do Kubernetes foi criado usando o comando
kubectl get secret
.kubectl get secret -n $NAMESPACE NAME TYPE DATA AGE ingress-tls-csi kubernetes.io/tls 2 1m34s
Implantar o aplicativo
Novamente, as instruções mudam ligeiramente dependendo do seu cenário. Siga as instruções correspondentes ao cenário selecionado.
Implantar o aplicativo usando uma referência de aplicativo
Crie um arquivo chamado
aks-helloworld-one.yaml
com o conteúdo a seguir.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)" volumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true volumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-one spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-one
Crie um arquivo chamado
aks-helloworld-two.yaml
com o conteúdo a seguir.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" volumeMounts: - name: secrets-store-inline mountPath: "/mnt/secrets-store" readOnly: true volumes: - name: secrets-store-inline csi: driver: secrets-store.csi.k8s.io readOnly: true volumeAttributes: secretProviderClass: "azure-tls" --- apiVersion: v1 kind: Service metadata: name: aks-helloworld-two spec: type: ClusterIP ports: - port: 80 selector: app: aks-helloworld-two
Aplique os arquivos YAML ao cluster usando o comando
kubectl apply
.kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
Verifique se o segredo do Kubernetes foi criado usando o comando
kubectl get secret
.kubectl get secret -n $NAMESPACE NAME TYPE DATA AGE ingress-tls-csi kubernetes.io/tls 2 1m34s
Implantar o aplicativo usando uma referência de controlador de entrada
Crie um arquivo chamado
aks-helloworld-one.yaml
com o conteúdo a seguir.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
Crie um arquivo chamado
aks-helloworld-two.yaml
com o conteúdo a seguir.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
Aplique os arquivos YAML ao cluster usando o comando
kubectl apply
.kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
Implantar um recurso de entrada referenciando o segredo
Agora podemos implantar um recurso de entrada do Kubernetes referenciando o segredo.
Crie um arquivo chamado
hello-world-ingress.yaml
com o conteúdo a seguir.apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-tls annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx tls: - hosts: - demo.azure.com secretName: ingress-tls-csi rules: - host: demo.azure.com 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
Anote a seção
tls
que faz referência ao segredo que criamos anteriormente e aplique o arquivo ao cluster usando o comandokubectl apply
.kubectl apply -f hello-world-ingress.yaml -n $NAMESPACE
Obter o endereço IP externo do controlador de entrada
Obtenha o endereço IP externo para o controlador de entrada usando o comando
kubectl get service
.kubectl get service --namespace $NAMESPACE --selector app.kubernetes.io/name=ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-1588032400-controller LoadBalancer 10.0.255.157 EXTERNAL_IP 80:31293/TCP,443:31265/TCP 19m nginx-ingress-1588032400-default-backend ClusterIP 10.0.223.214 <none> 80/TCP 19m
Testar a entrada protegida com TLS
Verifique se a entrada está configurada corretamente com o TLS usando o comando
curl
a seguir. Use o IP externo da etapa anterior.curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com
Como nenhum outro caminho foi fornecido com o endereço, o controlador de entrada aceita o padrão da rota /. O primeiro aplicativo de demonstração é retornado, conforme mostrado na saída de exemplo condensada a seguir:
[...] <!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> [...]
O parâmetro -v no comando
curl
gera informações detalhadas, incluindo o certificado TLS recebido. Na metade da saída de curvas, você pode verificar se seu próprio certificado TLS foi usado. O parâmetro -k continua carregando a página, embora estejamos usando um certificado autoassinado. O exemplo a seguir mostra que o certificado emissor: CN=demo.azure.com; S = aks-entrada-tls foi usado:[...] * Server certificate: * subject: CN=demo.azure.com; O=aks-ingress-tls * start date: Oct 22 22:13:54 2021 GMT * expire date: Oct 22 22:13:54 2022 GMT * issuer: CN=demo.azure.com; O=aks-ingress-tls * SSL certificate verify result: self signed certificate (18), continuing anyway. [...]
Adicione o caminho /hello-world-two ao endereço, como
https://demo.azure.com/hello-world-two
, e verifique se o segundo aplicativo de demonstração está configurado corretamente.curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com/hello-world-two
O segundo aplicativo de demonstração com um título personalizado é retornado, conforme mostrado na saída de exemplo condensada a seguir:
[...] <!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> [...]
Azure Kubernetes Service