Alef Carlos
Bee Lab Academy
Published in
4 min readDec 10, 2019

--

Uma jornada gRPC+ k8s

Bom dia. Boa tarde. Boa noite

Contarei aqui a minha jornada ao tentar escrever um serviço gRPC até a publicação em ambiente produtivo no Kubernetes.

Tecnologias adotadas

  • ASP.NET Core
  • Helm
  • Digital Ocean Kubernetes
  • Azure Pipelines

Desenvolvimento

A fase de desenvolvimento é a mais tranquila, pois a maneira de desenvolvermos não muda quase nada, a diferença é: criamos serviços com base em contratos do protobuf.

Ao criar um projeto com o template padrão de gRPC do dotnet toda a estrutura e configurações são feitas. Serviço de exemplo também é disponibilizado.

Primeira dúvida — Posso usar juntamente com meus antigos endpoints?

Minha primeira alternativa foi manter meus endpoints REST + gRPC no mesmo serviço, porém foi quando tomei as primeiras dores.

O gRPC foi construído utilizando o HTTP/2, fazendo com que os endpoints que respondiam HTTP/1 retornassem 405 — method not allowed.

Então, comecei a pesquisar sobre como manter os dois em portas separadas, mas percebi que era desnecessário. Resolvi então separar em projetos distintos.

Mas pra quem quiser ver a solução o link é este — David Fowler quem escreveu

Testando

Quando falamos em testar api REST o que nos vem a cabeça é o Postman, será que criaram também um “Postman” pra gRPC ?

O BloomRPC é uma ótima ferramenta, onde você importa o arquivo proto e realiza as chamadas. — isso também pode ser feito utilizando a grpc_cli, mas sem UI.

Então eu o utilizado para meus testes.

Compartilhamento do arquivo proto

Enquanto o consumo do contrato estava tudo na mesma solution foi fácil manter o arquivo .proto, o problema apareceu quando precisei consumir esse proto em outro projeto. Tinha 2 alternativas:

  • Manter o arquivo proto nos 2 repositórios
  • Pesquisar como a comunidade estava gerenciando isso

Comecei a pesquisar as maneiras e encontrei o seguinte artigo CREATING GRPC .NET CORE CLIENT LIBRARIES do Steve Gordon — a serie dele sobre gRPC + .NET Core é imprescindível pra quem está galgando nesse reino.

Então para cada gRPC server eu tenho uma biblioteca cliente abstraindo todo o gerenciamento desse arquivo — sim, tenho depois pipelines: um para o pacote nuget e outro para o deploy do server.

Adotei como padrão nos meus repositórios.

Um exemplo da implementação dessa ideia pode ser encontrada aqui.

Depois de desenvolvido e testado, agora vamos para a publicação.

Publicação

Publicação do serviço

Todos os serviços seguem o mesmo template de pipeline.

Criei os pipelines utilizando AzureDevops Pipelines Yaml. A do servido contém 2 estágios: build e deploy.

O estágio de build realiza:

  1. GitVersion, uso para definir a TAG da imagem
  2. dotnet publish do csproj desejado
  3. Docker login
  4. Docker build e push, utilizando o Canister — repos privados grátis!

E o estágio de deploy:

  1. helm upgrade do meu pacote no cluster

Publicação do pacote NuGet interno

Para as libs de clientes gRPC eu subo no Artifacts do AzureDevops, com somente um estágio:

  1. GitVersion
  2. dotnet pack
  3. dotnet push

Liveness/Readness probes

Aqui veio o primeiro grande problema em ambiente produtivo: os probes do k8s.

Pesquisando descobri que o k8s não suporta grpc nativamente — mas os services mesh sim — , então tomei um balde de água fria, até pensei em dar rollback e usar api REST para aplicações internas — mas meu objetivo era aprender e validar a solução.

Até que encontrei também no blog do mestre Steve Gordon uma implementação do protocolo de heathcheks do gRPC, a próxima etapa era utilizar isso no k8s — esse healthcheck é compatível com o da Microsoft.

É necessário configurar deployment utlizando o exec, encontrei um cli da comunidade específica para isso: grpc_health_probe, o uso é muito simples:

spec:
containers:
- name: server
image: "[YOUR-DOCKER-IMAGE]"
ports:
- containerPort: 5000
readinessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:[PORT_NUMBER]"]
initialDelaySeconds: 5
livenessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:[PORT_NUMBER]"]
initialDelaySeconds: 10

Só é necessário disponibilizar o binário no container. No seu dockerfile basta adicionar:

## Health prob
RUN apt-get update -y && apt-get install wget -y && \GRPC_HEALTH_PROBE_VERSION=v0.3.1 && \wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64
RUN chmod +x /bin/grpc_health_probe

Feito isso, o binário está disponível para ser utilizado e totalmente funcional.

Para não precisar adicionar em todo Dockerfile, eu criei uma imagem base, mais a frente falarei sobre

Debug

Após ter concluído com sucesso, eu precisava fazer alguns troubleshooting realizando um port-forward do container pra minha máquina. Eu queria listar todos os serviços disponíveis e não conseguia, fui então pesquisar novamente.

Encontrei a cli grpc_cli que consegue realizar as operações que eu queria, então fui realizei alguns testes. Tomei pau, pois é necessário implementar o protocolo Server Reflection.

Por padrão o template do .NET não implementa o Server Reflector, então implementei utilizando o pacote Grpc.AspNetCore.Server.Reflection que tem essa funcionalidade já feita.

A partir de agora, tenho tudo que é necessário para ter uma vida tranquila com o processo em troubleshooting em produção.

Grpc.WebServer

Para facilitar o processo de desenvolvimento criei uma lib que implementa todos esses conceitos que comentei durante o artigo: healthchecks e Server Reflection. NuGet: PlusUltra.Grpc.

Um exemplo do startup utilizando a classe abstrata GrpcServerStartup

Imagens Docker

Criei também imagens base a partir das imagens 3.0 do aspnet com as ferramentas necessárias para fazer probe e troubleshooting.

Contém 2 tags:

  1. 3.0, contém somente a cli de probe
  2. 3.0-cli, contém a lib de prob + grpc_cli
Um exemplo de uso de uma das imagens base

Essas são as dores que compartilho que tive nessas últimas semanas com ASP.NET + gRPC + k8s

Lembrando que as cli que foram mencionadas funcionam em qualquer tecnologia, não somente em .NET

--

--

Alef Carlos
Bee Lab Academy

Desenvolvedor por paixão, arquiteto de software por profissão.