Implantar o app ASP.NET Core no Google Kubernetes Engine com o Istio (parte 1)

1. Visão geral

O ASP.NET Core é um framework de código aberto e multiplataforma para criação de aplicativos modernos baseados em nuvem e conectados à Internet usando a linguagem de programação C#.

O Kubernetes é um sistema de código aberto para automatizar a implantação, o escalonamento e o gerenciamento de aplicativos em contêineres. O Istio é um framework aberto para conectar, proteger, gerenciar e monitorar serviços.

Nesta primeira parte do laboratório, você vai implantar um app ASP.NET Core simples no Kubernetes executado no Google Kubernetes Engine (GKE) e configurá-lo para ser gerenciado pelo Istio.

Na segunda parte do laboratório, você vai conhecer melhor os recursos do Istio, como métricas, rastreamento, gerenciamento dinâmico de tráfego, injeção de falhas e muito mais.

O que você vai aprender

  • Como criar e empacotar um app simples do ASP.NET Core em um contêiner do Docker.
  • Como criar um cluster do Kubernetes com o Google Kubernetes Engine (GKE).
  • Como instalar o Istio em um cluster do Kubernetes no GKE.
  • Como implantar o app ASP.NET Core e configurar o tráfego dele para ser gerenciado pelo Istio.

O que é necessário

Como você usará este tutorial?

Apenas leitura Leitura e exercícios

Como você classificaria sua experiência com o Google Cloud Platform?

Iniciante Intermediário Proficiente

2. Configuração e requisitos

Configuração de ambiente autoguiada

  1. Faça login no console do Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID.

  1. Em seguida, será necessário ativar o faturamento no Console do Cloud para usar os recursos do Google Cloud.

A execução deste codelab não será muito cara, se for o caso. Siga todas as instruções na seção "Limpeza", que orienta você sobre como encerrar recursos para não incorrer em cobranças além deste tutorial. Novos usuários do Google Cloud estão qualificados para o programa de US$300 de avaliação sem custos.

Inicie o Cloud Shell

Embora o Google Cloud possa ser operado remotamente em seu laptop, neste codelab você vai usar o Google Cloud Shell, um ambiente de linha de comando executado no Google Cloud.

Ativar o Cloud Shell

  1. No Console do Cloud, clique em Ativar o Cloud Shell4292cbf4971c9786.png.

bce75f34b2c53987.png

Se você nunca iniciou o Cloud Shell, vai ver uma tela intermediária abaixo da dobra com a descrição dele. Se esse for o caso, clique em Continuar e você não a verá novamente. Esta é a aparência dessa tela única:

70f315d7b402b476.png

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

fbe3a0674c982259.png

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Praticamente todo o seu trabalho neste codelab pode ser feito em um navegador ou no seu Chromebook.

Depois de se conectar ao Cloud Shell, você já estará autenticado e o projeto já estará configurado com seu ID do projeto.

  1. Execute o seguinte comando no Cloud Shell para confirmar que você está autenticado:
gcloud auth list

Resposta ao comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Execute o comando a seguir no Cloud Shell para confirmar se o comando gcloud sabe sobre seu projeto:
gcloud config list project

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, configure-o usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

3. Crie um aplicativo do ASP.NET Core no Cloud Shell

No prompt do Cloud Shell, verifique se a ferramenta de linha de comando dotnet já está instalada conferindo a versão dela. Isso vai imprimir a versão da ferramenta de linha de comando dotnet instalada:

dotnet --version

Em seguida, crie uma estrutura para um app da Web ASP.NET Core.

dotnet new mvc -o HelloWorldAspNetCore

Esse comando cria um projeto e restaura as dependências dele. Você verá uma mensagem semelhante ao exemplo abaixo.

Restore completed in 11.44 sec for HelloWorldAspNetCore.csproj.

Restore succeeded.

4. Execute o aplicativo do ASP.NET Core

Quase tudo pronto para executar o app. Navegue até a pasta do app.

cd HelloWorldAspNetCore

Por fim, execute o app.

dotnet run --urls=http://localhost:8080

O aplicativo começará a ouvir na porta 8080.

Hosting environment: Production
Content root path: /home/atameldev/HelloWorldAspNetCore
Now listening on: http://[::]:8080
Application started. Press Ctrl+C to shut down.

Para confirmar que o app está em execução, clique no botão "Visualização da Web", no canto superior direito, e selecione "Visualizar na porta 8080".

Capture.PNG

A página da Web padrão do ASP.NET Core vai aparecer:

f579a9baedc108a9.png

Depois de verificar que o app está em execução, pressione Ctrl+C para desligá-lo.

5. Empacote o aplicativo do ASP.NET Core em um contêiner do Docker

Em seguida, prepare o app para ser executado como um contêiner. O primeiro passo é definir o contêiner e o conteúdo dele.

No diretório base do app, crie um Dockerfile para definir a imagem Docker.

touch Dockerfile

Adicione o código abaixo a Dockerfile usando seu editor preferido (vim, nano,emacs ou o editor de código do Cloud Shell).

# Use Microsoft's official build .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-sdk/
FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build
WORKDIR /app

# Install production dependencies.
# Copy csproj and restore as distinct layers.
COPY *.csproj ./
RUN dotnet restore

# Copy local code to the container image.
COPY . ./
WORKDIR /app

# Build a release artifact.
RUN dotnet publish -c Release -o out

# Use Microsoft's official runtime .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine AS runtime
WORKDIR /app
COPY --from=build /app/out ./

# Make sure the app binds to port 8080
ENV ASPNETCORE_URLS http://*:8080

# Run the web service on container startup.
ENTRYPOINT ["dotnet", "HelloWorldAspNetCore.dll"]

Uma importante configuração incluída no seu Dockerfile é a porta em que o aplicativo escuta o tráfego de entrada (8080). Isso é feito configurando a variável de ambiente ASPNETCORE_URLS, que os apps do ASP.NET Core usam para determinar em qual porta escutar.

Salve este Dockerfile. Agora, vamos criar a imagem:

docker build -t gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1 .

Quando isso for concluído (o download e a extração levam algum tempo), você verá que a imagem foi criada e salva localmente:

docker images

REPOSITORY                             TAG   
gcr.io/yourproject-XXXX/hello-dotnet   v1            

Teste a imagem localmente com o comando a seguir, que executa um contêiner do Docker localmente na porta 8080 na imagem de contêiner que você criou:

docker run -p 8080:8080 gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1

E aproveite novamente o recurso de visualização da Web do Cloud Shell :

Screenshot from 2015-11-03 17:20:22.png

A página da Web padrão do ASP.NET Core vai aparecer em uma nova guia.

f579a9baedc108a9.png

Depois de verificar que o app está sendo executado localmente em um contêiner do Docker, você pode parar o contêiner em execução com Ctrl-> C.

Agora que a imagem funciona como esperado, envie-a para o Google Container Registry. Ele é um repositório privado para imagens do Docker que todos os projetos do Google Cloud podem acessar, além de estar disponível também fora do Google Cloud Platform.

docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1

Se tudo der certo, depois de um tempo, a imagem do contêiner vai aparecer na seção Container Registry. Agora você tem uma imagem Docker disponível para todo o projeto que pode ser acessada e orquestrada pelo Kubernetes, como você verá em alguns minutos.

73558f3a54ce1c0c.png

Se você quiser, navegue pelas imagens do contêiner, já que estão armazenadas no Google Cloud Storage, neste link: https://console.cloud.google.com/storage/browser/. O link resultante completo deve ter este formato: https://console.cloud.google.com/project/PROJECT_ID/storage/browser/.

6. Criar um cluster do GKE com o Istio

Primeiro, verifique se a API Kubernetes Engine está ativada:

gcloud services enable container.googleapis.com

Criar um cluster do Kubernetes Se quiser, mude a região para um local próximo a você:

gcloud container clusters create hello-istio \
  --cluster-version=latest \
  --machine-type=n1-standard-2 \
  --num-nodes=4 \
  --region europe-west1

Aguarde até que o cluster esteja configurado. Ele vai aparecer na seção do Kubernetes Engine no console do Google Cloud Platform.

e46fd9c6ee82bcc4.png

Neste codelab, vamos fazer o download e instalar o Istio em istio.io. Há outras opções de instalação, incluindo o complemento do Istio para GKE e o Anthos Service Mesh. As etapas do aplicativo após esta vão funcionar em qualquer instalação do Istio.

Primeiro, faça o download do cliente e das amostras do Istio. A página de lançamento do Istio oferece artefatos de download para vários sistemas operacionais. No nosso caso, podemos usar um comando conveniente para fazer o download e extrair a versão mais recente para nossa plataforma atual:

curl -L https://istio.io/downloadIstio | sh -

O script vai informar a versão do Istio que foi baixada:

Istio has been successfully downloaded into the istio-1.8.1 folder on your system.

O diretório de instalação contém aplicativos de amostra e o binário do cliente istioctl. Mude para esse diretório:

cd istio-1.8.1

Copie e cole o comando fornecido para adicionar o diretório bin ao seu PATH, assim você poderá usar istioctl:

export PATH="$PATH:/home/<YOURHOMEID>/istio-1.8.1/bin"

Verifique se istioctl está disponível conferindo se o cluster está pronto para o Istio:

istioctl x precheck

Você vai receber uma mensagem dizendo Install Pre-Check passed! The cluster is ready for Istio installation.

Instale o Istio com o perfil de demonstração:

istioctl install --set profile=demo

O Istio agora está instalado no cluster.

Injeção automática de sidecar

Para começar a usar o Istio, não é necessário fazer mudanças no aplicativo. Quando você configura e executa os serviços, sidecars do Envoy são injetados automaticamente em cada pod do serviço.

Para isso funcionar, é necessário ativar a injeção de sidecar no namespace ("default") usado para os microsserviços. Para isso, aplique um marcador:

kubectl label namespace default istio-injection=enabled

Para verificar se o rótulo foi aplicado, execute o seguinte comando:

kubectl get namespace -L istio-injection

A saída confirma que a injeção de sidecar está ativada para o namespace padrão:

NAME              STATUS   AGE    ISTIO-INJECTION
default           Active   3m     enabled
istio-system      Active   63s    disabled
...

7. Verifique a instalação

O Istio vem com três serviços: o plano de controle istiod e os gateways de entrada e saída (que podem ser considerados "proxies sidecar para o restante da Internet"), chamados istio-ingressgateway e istio-egressgateway, respectivamente.

kubectl get svc -n istio-system

A saída será parecida com esta:

NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP                                                                     AGE
istio-egressgateway    ClusterIP      10.55.252.182   <none>
istio-ingressgateway   LoadBalancer   10.55.250.185   35.233.118.42
istiod                 ClusterIP      10.55.253.217   <none>

O gateway de entrada tem um tipo LoadBalancer, então ele pode ser acessado pela Internet. Os outros só precisam ser acessíveis de dentro do cluster.

Em seguida, execute o código a seguir para verificar se os pods correspondentes do Kubernetes foram implantados e se todos os contêineres estão ativos:

kubectl get pods -n istio-system

Quando todos os pods estiverem em execução, você poderá continuar.

NAME                                    READY   STATUS
istio-egressgateway-674988f895-m6tk4    1/1     Running
istio-ingressgateway-6996f7dcc8-7lvm2   1/1     Running
istiod-6bf5fc8b64-j79hj                 1/1     Running
  • istiod: o plano de controle do Istio. Gerencia a configuração e a programação dos sidecars de proxy, a descoberta de serviços, a distribuição de certificados e a injeção de sidecar.
  • ingress gateway: atende às solicitações de fora do cluster.
  • egress gateway:processa solicitações de saída para endpoints fora do cluster.

8. Implantar o aplicativo

Agora que você verificou se o Istio está instalado e em execução, é possível implantar o app ASP.NET Core.

Implantação e serviço

Primeiro, crie um arquivo aspnetcore.yaml usando seu editor favorito (vim, nano,emacs ou o editor de código do Cloud Shell) e defina a implantação e o serviço do Kubernetes para o app:

apiVersion: v1
kind: Service
metadata:
  name: aspnetcore-service
  labels:
    app: aspnetcore
spec:
  ports:
  - port: 8080
    name: http
  selector:
    app: aspnetcore
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aspnetcore-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aspnetcore
      version: v1
  template:
    metadata:
      labels:
        app: aspnetcore
        version: v1
    spec:
      containers:
      - name: aspnetcore
        image: gcr.io/YOUR-PROJECT-ID/hello-dotnet:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

O conteúdo do arquivo são implantações e serviços padrão para implantar o aplicativo e não contêm nada específico do Istio.

Implante os serviços no namespace padrão com kubectl:

kubectl apply -f aspnetcore.yaml
service "aspnetcore-service" created
deployment.extensions "aspnetcore-v1" created

Verifique se os pods estão em execução:

kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
aspnetcore-v1-6cf64748-mddb   2/2       Running   0          34s

Gateway e VirtualService

Para permitir que o tráfego de entrada chegue à malha, crie um gateway e um VirtualService.

Um gateway configura um balanceador de carga para tráfego HTTP/TCP, geralmente operando na borda da malha para ativar o tráfego de entrada de um aplicativo. Um VirtualService define as regras que controlam como as solicitações de um serviço são roteadas em uma malha de serviço do Istio.

Crie um arquivo aspnetcore-gateway.yaml para definir o gateway:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: aspnetcore-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

Crie um arquivo aspnetcore-virtualservice.yaml para definir o VirtualService:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - route:
    - destination:
        host: aspnetcore-service

Execute o comando kubectl para implantar o gateway com:

kubectl apply -f aspnetcore-gateway.yaml

O comando produz a seguinte saída:

gateway.networking.istio.io "aspnetcore-gateway" created

Em seguida, execute o comando a seguir para implantar o VirtualService:

kubectl apply -f aspnetcore-virtualservice.yaml

O comando produz a seguinte saída:

virtualservice.networking.istio.io "aspnetcore-virtualservice" created

Verifique se tudo está em execução:

kubectl get gateway
NAME                      AGE
aspnetcore-gateway   28s
kubectl get virtualservice
NAME                             AGE
aspnetcore-virtualservice   33s

Parabéns! Você acabou de implantar um aplicativo com o Istio ativado. Em seguida, você vai ver o aplicativo em uso.

9. Testar o aplicativo

Agora você pode ver o aplicativo em ação. É preciso ter o IP externo e a porta do gateway. Ele está listado em EXTERNAL-IP:

kubectl get svc istio-ingressgateway -n istio-system

Exporte o IP externo e a porta para uma variável GATEWAY_URL:

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')

export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

Use curl para testar o app. O serviço vai responder com um código de resposta 200:

curl -o /dev/null -s -w "%{http_code}\n" http://${GATEWAY_URL}/

Como alternativa, abra o navegador e acesse http://<gatewayurl> para ver o app:

f579a9baedc108a9.png

10. Parabéns!

Você acabou de implantar um app ASP.NET Core simples no Kubernetes executado no Google Kubernetes Engine (GKE) e o configurou para ser gerenciado pelo Istio.

Talvez você esteja se perguntando: "Qual é o benefício do Istio?". Essa é uma ótima pergunta. Até agora, não há vantagem em ter o Istio gerenciando esse app. Na segunda parte do laboratório, vamos conhecer melhor os recursos do Istio, como métricas, rastreamento, gerenciamento dinâmico de tráfego, visualização de serviços e injeção de falhas.

Próximas etapas

Licença

Este conteúdo está sob a licença Atribuição 2.0 Genérica da Creative Commons.

11. Limpeza

Se você não for continuar para a segunda parte do laboratório, exclua o app e desinstale o Istio ou simplesmente exclua o cluster do Kubernetes.

Excluir o app

Para excluir o aplicativo, siga estas etapas:

kubectl delete -f aspnetcore-gateway.yaml
Kubectl delete -f aspnetcore-virtualservice.yaml
kubectl delete -f aspnetcore.yaml

Para confirmar que o app foi removido:

kubectl get gateway 
kubectl get virtualservices 
kubectl get pods

Desinstalar o Istio

Para excluir o Istio:

kubectl delete -f install/kubernetes/istio-demo-auth.yaml

Para confirmar que o Istio foi removido:

kubectl get pods -n istio-system

Excluir o cluster do Kubernetes

gcloud container clusters delete hello-istio