Configurar o driver CSI do Secrets Store para habilitar o NGINX Ingress Controller com TLS
Este artigo orienta você pelo processo de proteção de um Controlador de Ingresso NGINX com TLS com um cluster do Serviço Kubernetes do Azure (AKS) e uma instância do Azure Key Vault (AKV). Para obter mais informações, consulte 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 é que o certificado é disponibilizado no cluster. Quando você remove o aplicativo, o segredo também é removido. Esse cenário se encaixa nas equipes de desenvolvimento responsáveis pela infraestrutura de segurança do aplicativo e sua integração com o cluster.
- Ingress Controller: A implantação de ingresso é modificada para declarar e montar o volume do provedor. O segredo é importado quando os pods de entrada são criados. Os pods do aplicativo não têm acesso ao certificado TLS. Esse cenário se encaixa em cenários em que uma equipe (por exemplo, TI) gerencia e cria componentes de infraestrutura e rede (incluindo certificados HTTPS TLS) e outras equipes gerenciam o ciclo de vida do aplicativo.
Pré-requisitos
- Se não tiver uma subscrição do Azure, crie uma conta gratuita antes de começar.
- Antes de começar, verifique se a versão da CLI do Azure é >=
2.30.0
ou instale a versão mais recente. - Um cluster AKS com o driver CSI do Secrets Store configurado.
- Uma instância do Azure Key Vault.
Gerar um certificado TLS
Gere um certificado TLS usando o seguinte comando.
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 seguinte comando.
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
az keyvault certificate import
comando.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
kubectl create namespace
comando.kubectl create namespace $NAMESPACE
Selecione um método para fornecer uma identidade de acesso e configure seu YAML SecretProviderClass de acordo.
- Certifique-se de usar
objectType=secret
, que é a única maneira de obter a chave privada e o certificado da AKV. - Defina
kubernetes.io/tls
como otype
na suasecretObjects
seção.
Veja o exemplo a seguir de como seu SecretProviderClass pode parecer:
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
- Certifique-se de usar
Aplique o SecretProviderClass ao cluster do Kubernetes usando o
kubectl apply
comando.kubectl apply -f secretProviderClass.yaml -n $NAMESPACE
Implantar o controlador de ingresso
Adicione o repositório oficial do gráfico de entrada
Adicione o repositório oficial do gráfico de entrada usando os seguintes
helm
comandos.helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update
Configurar e implantar a entrada NGINX
Dependendo do cenário, você pode optar por vincular o certificado ao aplicativo ou ao controlador de entrada. Siga as instruções abaixo de acordo com a sua seleção:
Vincular certificado ao aplicativo
Vincule o certificado ao aplicativo usando o
helm install
comando. A implantação do aplicativo faz referência ao provedor do Azure Key Vault do Driver CSI do Secrets Store.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
Vincular certificado ao controlador de ingresso
Vincule o certificado ao controlador de entrada usando o
helm install
comando. A implantação do controlador de ingresso faz referência ao provedor do Azure Key Vault do Driver CSI do Secrets Store.Nota
Se não estiver usando a identidade gerenciada pelo 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, vincular o SecretProviderClass a um pod é necessário para que o driver CSI do Secrets Store 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
kubectl get secret
comando.kubectl get secret -n $NAMESPACE NAME TYPE DATA AGE ingress-tls-csi kubernetes.io/tls 2 1m34s
Implementar a aplicação
Mais uma vez, 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 nomeado
aks-helloworld-one.yaml
com o seguinte conteúdo.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 nomeado
aks-helloworld-two.yaml
com o seguinte conteúdo.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
kubectl apply
comando.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
kubectl get secret
comando.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 nomeado
aks-helloworld-one.yaml
com o seguinte conteúdo.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 nomeado
aks-helloworld-two.yaml
com o seguinte conteúdo.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
kubectl apply
comando.kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
Implantar um recurso de entrada fazendo referência ao segredo
Agora podemos implantar um recurso de ingresso do Kubernetes fazendo referência ao segredo.
Crie um nome
hello-world-ingress.yaml
de arquivo com o seguinte conteúdo.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
tls
seção que faz referência ao segredo criado anteriormente e aplique o arquivo ao cluster usando okubectl apply
comando.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
kubectl get service
comando.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
Ingresso de teste protegido com TLS
Verifique se sua entrada está configurada corretamente com TLS usando o comando a seguir
curl
. Certifique-se de usar o IP externo da etapa anterior.curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com
Como outro caminho não foi fornecido com o endereço, o controlador de entrada assume como padrão a / rota. O primeiro aplicativo de demonstração é retornado, como mostrado na seguinte saída de exemplo condensado:
[...] <!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
curl
comando produz informações detalhadas, incluindo o certificado TLS recebido. Na metade da saída de ondulação, você pode verificar se seu próprio certificado TLS foi usado. O parâmetro -k continua carregando a página mesmo que estejamos usando um certificado autoassinado. O exemplo a seguir mostra o emissor: CN=demo.azure.com; O=aks-ingress-tls foi utilizado certificado:[...] * 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 o título personalizado é retornado, conforme mostrado na seguinte saída de exemplo condensado:
[...] <!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