Hoje em dia é muito comum ouvirmos falar de kubernetes, essa tecnologia é uma resposta para a grande adoção de aplicações baseadas em containers com arquiteturas como micro serviço ou Service Oriented Architectures (SOA), no entanto a criação de um cluster de kubernetes não gerenciado dentro da nossa infraestrutura (on-premises) é uma tarefa bem complexa e demanda uma equipe experiente para manter tudo rodando. Assim o AKS (Serviço de Kubernetes do Azure) se torna uma excelente opção para implantação de um cluster de Kubernetes de forma gerenciada na nuvem Azure. Podemos usar o AKS para simplificar a implantação e o gerenciamento de aplicativos nativos de nuvem, arquiteturas de micro serviços ou mesmo aquelas aplicações mais antigas, o AKS simplifica o dimensionamento horizontal, a auto recuperação e o balanceamento de carga.
Nesse artigo vou focar nas aplicações que precisam de windows para rodar, como por exemplo as aplicações desenvolvidas no .NET Full Framework, mas antes de partir para a prática vamos pontuar alguns conceitos básicos do AKS.
Container
Podemos entender o container como um pacote, com todas as dependências necessárias para o software rodar (código, DLLs, configurações de ambientes etc.). Ele é um processo isolado, e não possui um sistema operacional completo, pois ele utiliza o compartilhamento do kernel do Sistema Operacional onde está sendo executado, tornando um container ainda mais leve.
Mas e o Docker?
Docker é um conjunto de produtos que usam virtualização para entregar software em pacotes chamados contêineres. Com o Docker podemos fazer testes em nosso ambiente de desenvolvimento de forma muito simples, pois não precisamos instalar nada diretamente na máquina de desenvolvimento, tudo fica isolado em um container, uma vez configurados, ambientes complexos podem ficar disponíveis em minutos.
Azure kuberntes service(AKS)
O Kubernetes é um sistema de orquestração de contêineres open-source que automatiza a implantação, o dimensionamento e a gestão de aplicações em contêineres. Ele foi originalmente projetado pelo Google e agora é mantido pela Cloud Native Computing Foundation. Porém, configurar e operar um cluster de kubernetes não é uma tarefa fácil, e por isso, temos o Azure Kubernetes Service, que é uma implementação do Kubernetes como um serviço gerenciado, onde você não precisa se preocupar em manter o seu cluster.
Vantagens AKS
- Orquestração de Containers
- Escalabilidade
- Deploy Ágil CI/CD
- Segurança
- Integração com Azure Devops e Visual Studio
- Pague apenas pelos Nodes e Armazenamento
Arquitetura básica
- Cluster : Conjunto de máquinas
- Node: VM
- Pod: menor unidade que o AKS gerencia. Os containers rodam dentro dos pods.
Node pools
Os nodes são as máquinas do cluster, ou seja, onde os pods serão executados. Os Node pools, por sua vez, são um agrupamento de máquinas com uma mesma configuração, representados por um VM Scale Set. Pools de diferentes tipos podem ser adicionados ao cluster para lidar com uma variedade de cargas de trabalho. Os pools existentes podem ser dimensionados e atualizados ou os pools que não são mais necessários podem ser excluídos.
Network
Existem dois plugins disponíveis para definir o comportamento da rede do AKS, o Kubenet e o Azure CNI.
Kubernetes networking (Basic)
Os recursos de rede normalmente são criados e configurados conforme o cluster AKS é implantado. Neste modelo, os nodes recebem um endereço de IP da sua subnet, enquanto os pods recebem um IP virtual, que não faz parte da subnet, utilizando NAT (Network address translation) para que os pods consigam se comunicar entre si e atingir outros recursos da Azure.
Azure Container Networking Interface (CNI)
No caso do Azure CNI, os pods adotam IPs reais da subnet. Isso implica que o cluster AKS está conectado a recursos e configurações de rede virtual existentes, eliminando a necessidade do NAT. Esta opção é obrigatória para utilizar Node Pools Windows.
CLI
Vou usar vários comandos de CLI, começando com a CLI do AKS que precisa ser instalada. Também será preciso logar na conta do Azure usando a CLI do Azure e para isso use os comandos abaixo.
# Fazer login na conta do Azure
az login
az account set --subscription <id>
# Baixar a CLI do AKS
az aks install-cli
Criando cluster via CLI
Para criar containers Windows, precisamos usar o plugin Azure CNI, com o parâmetro –network-plugin azure, mas existem outros detalhes como a necessidade de atrelar a uma subnet, e em um service principal. O node pool inicial vai ser criado em Linux mas poderemos adicionar um segundo node pool com windows sem problemas siga os comandos abaixo para criar subir uma aplicação .NET Full Framework 4.8 chamada POC_KUBE_KEYVAULT, você pode usar qualquer aplicação semelhante no lugar dela.
Primeiro passo vamos criar a VNET
$vnet = az network vnet create `
--name AKS_BLOG_MS_VNET `
--resource-group AKS_BLOG_MS `
--subnet-name default
Depois criar o service principal
$sp=$(az identity create --name aks03sp --resource-group AKS_BLOG_MS | ConvertFrom-Json)
az role assignment create `
--assignee $sp.clientId `
--resource-group AKS_BLOG_MS `
--role "Network Contributor"
Listar a subnet
Vamos obter o ID do recurso de sub-rede para a rede virtual existente na qual o cluster AKS será associado
$subnetId = az network vnet subnet list `
--resource-group AKS_BLOG_MS `
--vnet-name AKS_BLOG_MS_VNET `
--query "[0].id" --output tsv
Por fim criar o cluster com node pool principal
Aqui vamos criar a instancia do AKS com um node pool Linux, ele é obrigatório e só depois de criado a instancia é que vamos adicionar um node pool com windows, observe que já na criação da instancia definimos o plugin de rede Azure CNI.
az aks create `
--resource-group AKS_BLOG_MS `
--name aks03blog `
--network-plugin azure `
--vnet-subnet-id $subnetId `
--docker-bridge-address 172.17.0.1/16 `
--dns-service-ip 10.2.0.10 `
--service-cidr 10.2.0.0/24 `
--generate-ssh-keys `
--enable-managed-identity `
--assign-identity $sp.id `
--node-count 1
Finalmente criamos o node pool windows
az aks nodepool add `
--resource-group AKS_BLOG_MS `
--cluster-name aks03blog `
--os-type Windows `
--name npwin `
--node-count 1
Para saber mais clique aqui
É possível usar o Cloud Shell direto no portal do Azure Assim não precisamos instalar as CLI no nosso ambiente, mas eu prefiro usar local.
Vamos conectar no cluster
# Obter credenciais de acesso para um cluster Kubernetes gerenciado
az aks get-credentials --resource-group AKS_BLOG_MS --name aks03blog
Listar e limpar os contextos
# Lista quais contextos ja foram configurados
kubectl config get-contexts
# reseta todos os contextos
kubectl config unset contexts
Agora já podemos usar alguns comandos do "kubectl" como listar um determinado tipo de recurso, podemos utilizar o comando "kubectl" get e o tipo do recurso
kubectl get pods
kubectl get nodes
kubectl get deployments
kubectl get services
kubectl logs <nomedopod>
kubectl top nodes
O comando "kubectl" logs exibe os logs de um container que está dentro do pod selecionado. O "kubectl" top nodes, por sua vez, lista os nodes do cluster de acordo com o uso de CPU e Memória.
Docker File imagem Windows
Agora vamos empacotar nossa aplicação em uma imagem utilizando do docker, esse arquivo apenas pega uma imagem windows desse repositório mcr.microsoft.com e copia os arquivos já compilados para dentro da pasta inetpub/wwwroot
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019
WORKDIR /inetpub/wwwroot
COPY /POC_KUBE_KEYVAULT/bin/publish .
RUN DIR
EXPOSE 80:80
Eu não adicionei o passo para compilar a aplicação com o msbuild, por isso é preciso que você faça isso na mão e aponte para a pasta dos arquivos compilados.
Compilação do arquivo DockerFile
docker build -t poc_kube_keyvault:dev01 .
docker images
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
poc_kube_keyvault dev01 71489f0f1f38 12 minutes ago 8.79GB
mcr.microsoft.com/dotnet/framework/aspnet 4.8-windowsservercore-ltsc2019 828e8fa2b4fd 2 weeks ago 8.75GB
Azure Container Registry
O ACR é um Registry Privado para hospedar imagens de containers. Usando o ACR, é possível armazenar as suas imagens de forma segura, como se fosse um repositório de código, mas no lugar de código temos as imagens.
Criar instância do ACR
az acr create --resource-group AKS_BLOG_MS --name acr03blog --sku Basic
Login ACR
az acr login -n acr03blog.azurecr.io
Criar TAG
docker tag poc_kube_keyvault:dev01 acr03blog.azurecr.io/pockubekeyvault:latest
Subindo a Imagem no acr
docker push acr03blog.azurecr.io/pockubekeyvault:latest
Criar manifesto YAML para Deploy
Para criar a aplicação, vamos criar um deploy. O deploy é como uma abastração do pod. Com ele, é possível configurar o número de réplicas do pod e utilizar estratégias de deploy. Uma dica para criar os arquivos YAML facilmente, é utilizar a linha de comando, com o "kubectl" create deploy, com o parametro o –dry-run=client -o yaml para gerar o yaml base.
kubectl create deploy pocaks --image=acr03blog.azurecr.io/pockubekeyvault:latest --dry-run=client -o yaml > deployblog01.yaml
Manifesto gerado
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: pocaks
name: pocaks
spec:
replicas: 1
selector:
matchLabels:
app: pocaks
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: pocaks
spec:
containers:
- image: acr03blog.azurecr.io/pockubekeyvault:latest
name: pockubekeyvault
resources: {}
status: {}
Adicionar um node selector para o label do sistema operacional
kubectl get nodes
NAME STATUS ROLES AGE VERSION
aks-nodepool1-14817848-vmss000000 Ready agent 5h56m v1.24.6
aksnpwin000000 Ready agent 35m v1.24.6
kubectl describe node aksnpwin000000
Vamos usar o label kubernetes.io/os:windows
nodeSelector:
kubernetes.io/os: windows
Final
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: pocaks
name: pocaks
spec:
replicas: 1
selector:
matchLabels:
app: pocaks
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: pocaks
spec:
containers:
- image: acr03blog.azurecr.io/pockubekeyvault:latest
name: pockubekeyvault
resources: {}
nodeSelector:
kubernetes.io/os: windows
status: {}
Deploy no AKS
kubectl create -f deployblog01.yaml
Criar arquivo YAML para Serviço
Após criar o deployment, é necessário expor os nossos pods para que seja possível acessá-los publicamente. Para isso, vamos utilizar um load balancer com um ip público o Kubernet usa uma abstração chamada de Service para configurá-lo:
kubectl expose -f deployblog01.yaml --name=pocsvc --type=LoadBalancer --port=80 --target-port=80 --dry-run=client -o yaml > svcblog01.yaml
Manifesto do serviço gerado
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: pocaks
name: pocsvc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: pocaks
type: LoadBalancer
status:
loadBalancer: {}
Deploy do serviço no AKS
kubectl create -f svcblog01.yaml
O segredo do AKS são os arquivos de yaml, eles vão ser a principal interface de configuração do AKS, nesse momento perceba que existe uma relação entre o arquivo da Aplicação e o Arquivo de Serviço, o primeiro yaml criar uma deploy de uma imagem especifica e chama isso de pocaks o segundo arquivo cria uma forma de acessar essa aplicação e aponta para ela usando o mesmo label pocaks.
Vamos ver qual o IP público
kubectl get services
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 18h
pocsvc LoadBalancer 10.0.198.13 20.237.239.202 80:31401/TCP 17h
Tentei acessar usando o ip externo acima do serviço pocsvc, mas a aplicação ainda não estava respondendo, então comecei a dar uma olhada no cluster usando os comandos de CLI.
kubectl get pods
NAME READY STATUS RESTARTS AGE
pocaks-859797885f-lnmsp 0/1 ImagePullBackOff 0 3m47s
Vamos ver os logs
kubectl get event --sort-by='.metadata.creationTimestamp' -A
kubectl describe pod pocaksapi-59c9b558ff-gf4zl
kubectl describe deployment pocaks
Encontrei essa entrada no log de eventos do AKS, e pelo que parece o que está faltando e atachar o ACR no AKS de forma que ele possa acessá-lo.
default 3m39s Warning Failed pod/pocaks-859797885f-j4tgb Failed to pull image “keyvaultaks.azurecr.io/pockubekeyvault:latest”: rpc error: code = Unknown desc = failed to pull and unpack image “keyvaultaks.azurecr.io/pockubekeyvault:latest”: failed to resolve reference “keyvaultaks.azurecr.io/pockubekeyvault:latest”: failed to authorize: failed to fetch anonymous token: unexpected status: 401 Unauthorized
az aks update -n aks03blog -g AKS_BLOG_MS --attach-acr acr03blog
Integrate Azure Container Registry with Azure Kubernetes Service - Azure Kubernetes Service
kubectl get pods
NAME READY STATUS RESTARTS AGE
pocaks-b87d78d46-wdts5 1/1 Running 0 30m
Demorou um pouco, mas deu certo!
az aks check-acr --name aks03blog --resource-group AKS_BLOG_MS --acr acr03blog.azurecr.io