AKS Cluster privado de ponta a ponta

This post has been republished via RSS; it originally appeared at: Microsoft Tech Community - Latest Blogs - .

AKS Cluster privado de ponta a ponta

 

O requisito de segurança é muito comum em arquiteturas corporativas, mas é difícil determinar se uma aplicação está segura ou qual é o mínimo necessário. É mais uma jornada do que uma ação específica. Para começar a nossa jornada, vamos criar nosso AKS e ACR totalmente privados dentro de uma rede virtual do Azure.

 

Escrevi um artigo sobre o AKS, no qual eu falo sobre os conceitos principais e mostro como criar um cluster com um node pool Windows. A ideia foi explorar um cenário comum para aplicações legadas. Se você é novo no AKS, vale a pena conferir.

É muito comum utilizar redes virtuais privadas (VNET) restringindo o acesso à internet. Esse tipo de arquitetura é muito mais segura e desejado pela maioria dos projetos. Porém, para isso, precisamos entender claramente quais redes/sub-redes precisamos e onde cada recurso será criado.

Vamos entender a arquitetura, olhando para o desenho abaixo:

Arquitetura

Temos duas VNETs, uma que o próprio AKS criou quando escolhemos o modo de rede kubernet e a outra VNET que criamos manualmente para colocar a VM. Na VNET do AKS, criei uma subnet nova para o “private endpoint” do ACR.

Existem dois pontos de atenção:

  • Ao provisionar o AKS através do portal do Azure, o plugin de rede padrão é o “Kubenet”, o que significa que não é possível escolher uma Virtual Network (VNET) pré-existente. Se você precisa usar uma VNET pré-existente, precisará optar pelo modo de rede CNI no portal do Azure ou usar o Azure CLI para criar a instância do AKS. Com o Azure CLI, você poderá escolher o plugin “Kubenet” e também uma VNET pré-existente. saiba mais
  • O AKS cria seus recursos internos dentro de outro grupo de recursos, e é nele que está a VNET em questão, assim como outros recursos. Caso queira criar o AKS pelo CLI, dê uma olhada neste artigo: AKS com Windows — Microsoft Community Hub

 

Criando o AKS pelo portal do Azure

 

Para criar um cluster AKS pelo portal do Azure, no primeiro passo não é necessário selecionar nenhuma configuração especial para proteger o cluster. A configuração especial necessária para isso está na etapa quatro, na aba Network. Nesta seção, podemos escolher a opção de rede “Kubenet” ou “CNI”, conforme mencionado acima. Além disso, existe a opção “Enable private cluster” que deve ser marcada se desejarmos criar um cluster privado.

 

tela do Azure

Um cluster privado usa um endereço IP interno para garantir que o tráfego de rede entre o servidor API e os node pools permaneça apenas em uma rede privada. Saiba mais

Apenas para facilitar o processo, vamos até a aba “Integrations” e provisionamos o ACR, o único detalhe está na camada que precisa ser Premium para posteriormente configurarmos o acesso privado.

 

tela do Azure

Criação do ACR no momento da criação do AKS

Agora temos o AKS com a VNET criada, podemos confirmar no menu network e também podemos verificar que o cluster está privado.

 

tela do Azure

 

Configurando o ACR como privado

 

Após o ACR ser provisionado vamos no menu network e desabilitaremos o acesso público ao ACR conforme a imagem abaixo. Deixaremos os serviços do Azure liberados.

 

tela do Azure

 

Em seguida, na aba “Private Endpoint”, vamos criar um “Private Endpoint” para a subnet do ACR na VNET do AKS. Vale lembrar que estamos utilizando a VNET criada pelo AKS no RG MC_AKS_PRIVADO_AKSPRV01_eastus. Antes de prosseguir, é necessário criar a subnet manualmente na VNET.

Para criar a subnet, acesse a VNET no RG MC_AKS_PRIVADO_AKSPRV01_eastus e clique no menu Subnets para criar uma nova

 

tela do Azure

Utilize os pontos de extremidade privados para se conectar de forma privada a um serviço ou recurso. É importante lembrar que o ponto de extremidade privado deve estar na mesma região da sua rede virtual, mas pode estar em uma região diferente do recurso ao qual você está se conectando por meio do link privado. Saiba mais

 

Dê uma olhada no Resource Group criado pelo AKS MC_AKS_PRIVADO_AKSPRV01_eastus nele temos a VNET e vários outros recursos importantes como NSGs, DNS etc.

 

tela do Azure

CSV com os recursos do Resource Group

 

"08e2c034-1768-463f-8444-1122ee88c2ff","Public IP address","East US"  
"aks-agentpool-17649214-nsg","Network security group","East US"  
"aks-agentpool-17649214-routetable","Route table","East US"  
"aks-agentpool-45541675-vmss","Virtual machine scale set","East US"  
"aks-VNET-17649214","Virtual network","East US"  
"AKSPRV01-agentpool","Managed Identity","East US"  
"d6ce2cd6-9633-40f1-b530-9e27554dde80.privatelink.eastus.azmk8s.io","Private DNS zone","Global"  
"kube-apiserver","Private endpoint","East US"  
"kube-apiserver.nic.a93724b9-006b-4f14-8bbd-a0bb576abfd6","Network Interface","East US"  
"kubernetes","Load balancer","East US"  
"kubernetes-aafae011874a74f61a036d25d76ed247","Public IP address","East US"  
"omsagent-aksprv01","Managed Identity","East US"  
"privatelink.azurecr.io","Private DNS zone","Global"

 

Máquina Virtual com suporte a Nested Virtualization

 

Para testar a conectividade com o AKS e o ACR, vamos precisar de uma máquina JUMP, que é uma VM criada para acessar recursos protegidos por VNETs.

É importante escolher o tipo correto de VM, pois ela será utilizada para processos de conteinerização e é provável que seja necessário usar o Docker. Por isso, é recomendado escolher a família correta de máquinas virtuais. No meu caso, utilizei a máquina Standard D2s v3, com 2 vCPUs e 8 GiB de memória

Para entender melhor essa questão de nested virtualization dê uma olhada nesse artigo Saiba mais

 

tela do Azure

Configurando a Máquina Virtual

 

  1. Crie a VNET para a máquina virtual. Eu chamei de AKS_PRIVADO-VNET mas recomendo dar um nome melhor
  2. Crie uma subnet VM
  3. Crie a máquina virtual Windows (Windows 11 Enterprise) Standard D2s v3 (2 VCPUS, 8 GiB memory) ou Linux se preferir
  4. Instale o docker desktop a partir daqui
  5. Instale a atualização do kernel linux daqui # no meu caso, baseado em x64;

Devemos instalar uma distribuição Linux no WSL. Para isto podemos utilizar os seguintes comandos:

 

Comando Descrição
wsl -l -v Lista as distribuições instaladas no WSL
wsl –list –online Lista as distribuições disponíveis para instalação
wsl –install -d Ubuntu Instala uma distribuição no WSL
wsl –set-default-version 2 Define a versão padrão do WSL

 

OBS: Ao criar uma máquina virtual no Portal do Azure, é importante estar atento ao campo ‘Security Type’. O modo ‘Trusted’ pode gerar restrições de segurança que podem impedir a instalação do Docker Desktop. Recomenda-se avaliar cuidadosamente as configurações de segurança antes de prosseguir com a criação da VM, a fim de garantir uma instalação sem problemas.

 

Comparação campos Security Type

 

Instalar o Azure CLI

 

Primeiro instale a CLI do Azure clicando Instalar a CLI do Azure para Windows | Microsoft Learn

Utilizarei diversos comandos da CLI do Azure, inclusive para instalar a CLI do AKS e para efetuar logon no Azure. Para isto utilize os seguintes comandos:

 

Fazer login na conta do Azure

az login

Para instalar a CLI do AKS usamos o comando

az aks install-cli

Voce também pode baixar o exe diretamente dessa url Baixar apenas kubectl

 

VNET da VM Peering com a VNET do AKS

 

Como vamos realizar nossos testes a partir de uma VM que está em uma VNET diferente da VNET do AKS, é necessário configurar o Peering. Essa configuração permitirá que as sub-redes da VNET A, existentes antes do Peering, possam se comunicar com as sub-redes da VNET B. Saiba mais

 

tela do Azure

Meus Resource group AKS_PRIVADO

 

tela do Azure

Exportei o CSV com os recursos do RG

 

"acrprv01","Container registry","East US"  
"AKS_PRIVADO-VNET","Virtual network","East US"  
"AKSPRV01","Kubernetes service","East US"  
"jumpprv01","Virtual machine","East US"  
"jumpprv01-ip","Public IP address","East US"  
"jumpprv01-nsg","Network security group","East US"  
"jumpprv01950_z1","Network Interface","East US"  
"jumpprv01_OsDisk_1_7e010fb8246a4ea596830d75eb08f346","Disk","East US"  
"pe_aks_VNET","Private endpoint","East US"  
"pe_aks_VNET-nic","Network Interface","East US"

 

privatelink.azurecr.io

 

Para realizar nossos testes, usaremos DNS em vez de IPs. Por isso, é necessário associar as Zonas de DNS Privado criadas para resolver os nomes de domínio azurecr.io e azmk8s.io em IPs na VNET da VM.

Esses recursos foram criados automaticamente e já estão associados à VNET do AKS.

tela do Azure

 

Associação do Private Dns Zone azurecr.io com VNET do AKS e da VM

 

Para realizar a associação, basta acessar a Zona DNS Privada, selecionar o menu ‘Link de rede virtual’ e clicar em ‘Adicionar’. Em seguida, selecione a VNET da VM.

 

tela do Azure

d6ce2cd6–9633–40f1-b530–9e27554dde80.privatelink.eastus.azmk8s.io

tela do Azure Tela do Azure Private Dns Zone azmk8s.io

 

Associação do azmk8s.io com VNET do AKS e da VM

 

Para realizar a associação, basta acessar a Zona DNS Privada, selecionar o menu ‘Link de rede virtual’ e clicar em ‘Adicionar’. Em seguida, selecione a VNET da VM.

 

tela do Azure Tela do Azure Associação do azmk8s.io com VNET do AKS e da VM

 

Recapitulando pontos chaves da configuração do ambiente

  1. Definir que o Cluster de AKS será privado
  2. Contratar o ACR na tier premium
  3. Desabilitar o acesso público no ACR
  4. Criar um Private Endpoint no ACR para a VNET do AKS de preferência em uma subnet própria.
  5. Criar a VM com suporte a Nested Virtualization em um VNET separada e fazer a configuração dos CLIs
  6. Fazer o Peering entre as VMS
  7. Associar os private DNS zones com as VNETs envolvidas

Depois disso estamos com o Ambiente pronto e nosso próximo passo é fazer um deploy no AKS.

 

Deploy no AKS usando imagem compilada com Docker

 

Conectando no AKS

az aks get-credentials --resource-group AKS_PRIVADO --name AKSPRV01

Precisamos conseguir listar os nodes do AKS para saber que a comunicação com o AKS funcionou corretamente

kubectl get nodes

Vou subir uma aplicação .net core então será necessário ter o SDK do .net core instalada na máquina também essa aplicação tem esse dockerFile

# Stage 1  
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build  
WORKDIR /build  
COPY . .  
RUN dotnet restore  
RUN dotnet publish -c Release -o /app  
# Stage 2  
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS final  
WORKDIR /app  
COPY --from=build /app .  
ENTRYPOINT ["dotnet", "Sample.Api.dll"]

Tem uma cópia da API nesse git, clone esse projeto vá até a pasta dele e rode o comando abaixo para gerar uma imagem

docker build -t sampleapi:dev01 .

Depois vamos gerar uma tag

docker tag sampleapi:dev01 acrprv01.azurecr.io/sampleapi:latest

Precisamos fazer o Login no ACR

az acr login -n acrprv01.azurecr.io

E agora podemos subir a imagem no ACR

docker push acrprv01.azurecr.io/sampleapi:latest

Feito isso já podemos gerar nossos arquivos de manifestos para fazer o deploy no AKS vou usar um comando que gerar o arquivo pronto apontando para a imagem.

kubectl create deploy sampleapi --image=acrprv01.azurecr.io/sampleapi:latest --dry-run=client -o yaml > sampleapi.yaml

Aplica o Deploy

kubectl create -f .\\sampleapi.yaml

Gerar arquivo de manifesto para o serviço por enquanto vou usar um ip público mas isso não é o final

kubectl expose -f sampleapi.yaml --name=sampleapisvc --type=LoadBalancer --port=80 --target-port=80 --dry-run=client -o yaml > svcsampleapi.yaml

aplica o Deploy

kubectl create -f .\\svcsampleapi.yaml

Se tudo deu certo você precisa ver os pods rodando e o serviço criado com o IP externo que você vai usar para acessar a aplicação

ao rodar o comando baixo

kubectl get pods

precisamos ver algo com isso

NAME                     READY   STATUS    RESTARTS   AGE  
sampleapi-b87d78d46-wdts5   1/1     Running   0          30m

e para descobrir o IP público usamos

kubectl get services

e precisamos de algo como isso

NAME         TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)        AGE  
kubernetes   ClusterIP      10.0.0.1      <none>           443/TCP        18h  
sampleapisvc LoadBalancer   10.0.68.139   20.232.252.49   80:32246/TCP   26m  

 

Por fim, conseguimos acessar a aplicação pelo IP público. No entanto, é importante lembrar que isso não é ideal. O recomendado é criar uma camada adicional de segurança em frente ao AKS e mantê-lo sem acesso público. Para isso, podemos utilizar, por exemplo, o Application Gateway. Ele terá um IP público, mas também estará em uma VNET que pode se comunicar com a VNET do AKS, mantendo tudo seguro.

 

tela do swagger

 

Compilar com o ACR

 

Caso você não queira instalar o Docker em sua máquina de JUMP, é possível usar o próprio ACR para compilar suas imagens. Para isso, será necessário configurar um agente e utilizá-lo para a compilação das imagens.

 

Configurando um Agent

 

Começamos pegando o id da subnet

$subnetId= az network vnet subnet list --resource-group AKS_PRIVADO --vnet-name AKS_PRIVADO-VNET --query "[0].id" --output tsv

Depois criando o agent

az acr agentpool create --registry acrprv01 --name myagentpool --tier S1 --subnet-id "/subscriptions/60701f8d-0759-4bb3-8d6b-1f1810aef353/resourceGroups/AKS_PRIVADO/providers/Microsoft.Network/virtualNetworks/AKS_PRIVADO-VNET/subnets/default"

E agora rodando ACR buid com o agent criado

az acr build -t sampleapiacr --agent-pool myagentpool --registry acrprv01 .

Podemos ver o agentes criados pelo portal do Azure

 

tela do swagger

Podemos listar as imagens do ACR

 

az acr repository list -n acrprv01

[  
  "sampleapi",  
  "sampleapiacr"  
]

 

AGIC (Application Gateway Ingress Controller)

 

Fiz uma alteração interessante: ao invés de utilizar o LoadBalancer e expor um IP público para acessar a aplicação no AKS, criei um Ingress Controller para o Application Gateway, deixando tudo privado de ponta a ponta e ganhando todas as funcionalidades de um Gateway de camada 7 como roteamento com base em atributos adicionais de uma solicitação HTTP, por exemplo, caminho de URI ou cabeçalhos de host. Dessa forma, podemos remover o serviço sampleapisvc usando o comando abaixo.

 

kubectl delete service sampleapisvc

 

Deletado o serviço vamos começar as configurações no AKS em Settings/network habilitando o Application gateway:

Portal do Azure AKS, menu Network Ingress Controller para o Application Gateway habilitado

Habilitar Ingress no APPGW

 

Para fazer um deploy de ingress privado devemos logo depois de integrar o AKS com o APGW criar um IP em Frontend IP configurations.

 

APGW com private IP

Ao clicar nesse item será necessário atribuir um IP manualmente marcando a opção Choose a specific private IP address.

 

Definindo o IP do Frontend do APPGW

Basicamente eu escolhi um IP da subnet do gateway que no meu caso foi essa rede 10.225.0.0/16 então botei o 10.225.0.10.

Para criar um ingress, é necessário associá-lo a um serviço do tipo ClusterIP. Essa associação pode ser realizada por meio da linha de comando (CLI)

 

kubectl expose deployment sampleapi --type=ClusterIP --port=80 --target-port=80

 

Vale ressaltar que ‘sample api’ refere-se ao deployment da aplicação que se deseja acessar.

 

kubectl get services
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.0.0.1       <none>        443/TCP   3h1m
sampleapi    ClusterIP   10.0.135.190   <none>        80/TCP    18m

 

Em seguida, criei o manifesto ‘deploymentingress.yaml’, apontando-o para o serviço do tipo ClusterIP ‘sampleapi’.

 

apiVersion: networking.k8s.io/v1  
kind: Ingress  
metadata:  
  name: sampleapi  
  annotations:  
    kubernetes.io/ingress.class: azure/application-gateway  
    appgw.ingress.kubernetes.io/use-private-ip: "true"  
spec:  
  rules:  
  - http:  
      paths:  
      - path: /  
        backend:  
          service:  
            name: sampleapi  
            port:  
              number: 80  
        pathType: Exact

 

aplicar o deploy

 

kubectl apply -f .\\deploymentingress.yaml

 

Observe que agora o ingress ficou atrelado ao ip privado do gateway

 

kubectl get ingress  
NAME          CLASS    HOSTS   ADDRESS       PORTS   AGE  
aspnetappv2   <none>   \*       10.225.0.15   80      42m

 

O serviço pode ser acessado de dentro da VNET ou de outras VNETs que possuam peering com a VNET do AKS. Para expor o serviço de forma segura, uma boa opção é utilizar um Azure API Management em uma VNET com peering na VNET do AKS, mantendo assim o AKS totalmente privado e protegido.

 

 

Conclusão

 

O uso de containers e orquestradores como o AKS pode melhorar significativamente a disponibilidade e a resiliência de nossas aplicações. No entanto, é fundamental considerar os requisitos de segurança desde o início do projeto. É importante notar que, para atingir nossos objetivos, novos componentes do Azure são necessários, como VNETs, SUBNETS, Application Gateway, Private DNS Zones, entre outros, como o APIM. É essencial compreender que dificilmente um único recurso do Azure atenderá a todos os requisitos de nosso negócio. Portanto, é imprescindível entender como diferentes componentes podem nos ajudar a projetar arquiteturas corporativas mais robustas e seguras.

 

Referências

  1. Criar um cluster privado do Serviço de Kubernetes do Azure
  2. Conectar-se de forma privada a um registro de contêiner do Azure usando o Link Privado do Azure
  3. Configurar ponto de extremidade privado com link privado — Azure Container Registry | Microsoft Learn
  4. Usar pool dedicado para executar uma tarefa — Tarefas — Azure Container Registry | Microsoft Learn

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.