O Cloud Service Mesh é uma ferramenta poderosa para gerenciar e monitorar aplicativos distribuídos. Para aproveitar ao máximo o Cloud Service Mesh, é importante entender as abstrações subjacentes, incluindo contêineres e Kubernetes. Neste tutorial, explicamos como preparar um aplicativo para o Cloud Service Mesh com o código-fonte para um contêiner em execução no GKE, até o momento antes de instalar o Cloud Service Mesh.
Se você já tiver familiaridade com os conceitos de Kubernetes e malha de serviço, pule este tutorial e acesse o guia de instalação do Cloud Service Mesh.
Objetivos
- Explorar um aplicativo "hello world" de vários serviços
- Executar o aplicativo a partir do código-fonte
- Colocar o aplicativo em um contêiner
- Criar um cluster do Kubernetes
- Implantar os contêineres no cluster
Antes de começar
Siga estas etapas para ativar a API Cloud Service Mesh:- Acesse a página do Kubernetes Engine no Console do Google Cloud.
- Crie ou selecione um projeto.
- Aguarde a ativação da API e dos serviços relacionados. Isso pode levar alguns minutos.
-
Make sure that billing is enabled for your Google Cloud project.
Neste tutorial, usamos o Cloud Shell, que provisiona uma máquina virtual (VM) g1-small do Compute Engine executando um sistema operacional Linux baseado em Debian.
Preparar o Cloud Shell
As vantagens de usar o Cloud Shell são:
- Os ambientes de desenvolvimento Python 2 e Python 3 (incluindo
virtualenv
) estão configurados. - As ferramentas de linha de comando
gcloud
,docker
,git
ekubectl
usadas neste tutorial já estão instaladas. É possível escolher os editores de texto:
Editor de código, que você acessa clicando em na parte superior da janela do Cloud Shell.
Emacs, Vim ou Nano, que você acessa na linha de comando do Cloud Shell.
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
Fazer o download do exemplo de código
Faça o download do código-fonte
helloserver
:git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
Mude para o diretório do código de amostra:
cd anthos-service-mesh-samples/docs/helloserver
Explorar o aplicativo multisserviço
O aplicativo de amostra é escrito em Python e tem dois componentes que se comunicam usando REST:
server
: um servidor simples com um endpointGET
,/
, que imprime "hello world" no console.loadgen
: um script que envia tráfego paraserver
, com um número configurável de solicitações por segundo (RPS, na sigla em inglês).
Executar o aplicativo a partir do código-fonte
Para se familiarizar com o aplicativo de amostra, execute-o no Cloud Shell.
No diretório
sample-apps/helloserver
, execute oserver
:python3 server/server.py
Na inicialização, o
server
exibe o seguinte:INFO:root:Starting server...
Abra outra janela de terminal para enviar solicitações ao
server
. Clique em para abrir outra sessão.Envie uma solicitação para
server
:curl http://localhost:8080
O
server
responde:Hello World!
No diretório em que você fez o download do código de amostra, mude para o diretório que contém
loadgen
:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/loadgen
Crie as variáveis de ambiente a seguir:
export SERVER_ADDR=http://localhost:8080 export REQUESTS_PER_SECOND=5
Inicialize
virtualenv
:virtualenv --python python3 env
Ative o ambiente virtual:
source env/bin/activate
Instale os requisitos para
loadgen
:pip3 install -r requirements.txt
Execute o
loadgen
:python3 loadgen.py
Na inicialização, o
loadgen
gera uma mensagem semelhante a esta:Starting loadgen: 2019-05-20 10:44:12.448415 5 request(s) complete to http://localhost:8080
Na outra janela do terminal, o
server
grava mensagens no console semelhante a esta:127.0.0.1 - - [21/Jun/2019 14:22:01] "GET / HTTP/1.1" 200 - INFO:root:GET request, Path: / Headers: Host: localhost:8080 User-Agent: python-requests/2.22.0 Accept-Encoding: gzip, deflate Accept: */*
Do ponto de vista da rede, todo o aplicativo está em execução no mesmo host. Por isso, use
localhost
para enviar solicitações paraserver
.Para interromper
loadgen
eserver
, insiraCtrl-c
em cada janela de terminal.Na janela de terminal
loadgen
, desative o ambiente virtual:deactivate
Colocar o aplicativo em um contêiner
Para executar o aplicativo no GKE, você precisa empacotar o aplicativo
de amostra, server
e loadgen
, em contêineres. Um
contêiner é uma forma de empacotar um aplicativo de modo que ele fique isolado
do ambiente subjacente.
Para colocar o aplicativo em um contêiner, você precisa de um Dockerfile
. Um Dockerfile
é um arquivo de texto
que define os comandos necessários para juntar o código-fonte do aplicativo
e as dependências em uma
imagem do Docker. Depois de criar a imagem,
faça o upload dela para um registro de contêiner, como o Docker Hub ou
o Container Registry.
A amostra vem com um Dockerfile
para o server
e o loadgen
com todos os comandos necessários para criar as imagens. Veja a seguir o
Dockerfile
para server
:
- O comando
FROM python:3-slim as base
manda o Docker usar a imagem mais recente do Python 3 como a imagem de base. - O comando
COPY . .
copia os arquivos de origem no diretório de trabalho atual (neste caso, apenasserver.py
) para o sistema de arquivos do contêiner. - O
ENTRYPOINT
define o comando usado para executar o contêiner. Nesse caso, o comando é quase igual ao que você usou para executar oserver.py
a partir do código-fonte. - O comando
EXPOSE
especifica que oserver
escute na porta8080
. Esse comando não expõe nenhuma porta, mas serve como documentação necessária para abrir a porta8080
ao executar o contêiner.
Preparar para colocar o aplicativo em um contêiner
Defina as seguintes variáveis de ambiente. Substitua
PROJECT_ID
pelo ID do projeto do Google Cloud.export PROJECT_ID="PROJECT_ID"
export GCR_REPO="asm-ready"
Você usa o valor de
PROJECT_ID
eGCR_REPO
para incluir uma tag na imagem do Docker ao criar e enviá-la ao seu Container Registry particular.Defina o projeto do Google Cloud padrão para a Google Cloud CLI.
gcloud config set project $PROJECT_ID
Defina a zona padrão da Google Cloud CLI.
gcloud config set compute/zone us-central1-b
Verifique se o serviço do Container Registry está ativado no seu projeto do Google Cloud.
gcloud services enable containerregistry.googleapis.com
Colocar o server
em um contêiner
Mude para o diretório em que o
server
de amostra está localizado:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/
Crie a imagem usando o
Dockerfile
e as variáveis de ambiente definidas anteriormente:docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1 .
A sinalização
-t
representa a tag do Docker. Esse é o nome da imagem que você usa ao implantar o contêiner.Enviar a imagem ao Container Registry
docker push gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1
Colocar o loadgen
em um contêiner
Mude para o diretório em que o
loadgen
de amostra está localizado:cd ../loadgen
Crie a imagem:
docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1 .
Enviar a imagem ao Container Registry
docker push gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1
Listar as imagens
Gere uma lista das imagens no repositório para confirmar se as imagens foram enviadas:
gcloud container images list --repository gcr.io/$PROJECT_ID/asm-ready
O comando responde com os nomes das imagens que você acabou de enviar:
NAME gcr.io/PROJECT_ID/asm-ready/helloserver gcr.io/PROJECT_ID/asm-ready/loadgen
Criar um cluster do GKE
É possível executar esses contêineres na VM do Cloud Shell usando o comando docker run
. Mas, na produção, você precisa
orquestrar contêineres de maneira mais unificada. Por exemplo, você precisa
de um sistema que garanta que os contêineres estejam sempre em execução e também precisa
de uma maneira de escalonar e iniciar instâncias extras de um contêiner para lidar
com aumentos de tráfego.
Use o GKE para executar aplicativos em contêineres. O GKE é uma plataforma de orquestração de contêineres que funciona ao conectar VMs cluster. Cada VM é chamada de nó. Os clusters do GKE são fornecidos pelo sistema de gerenciamento de clusters de código aberto Kubernetes. O Kubernetes contém os mecanismos necessários para interagir com o cluster.
Para criar um cluster do GKE:
Crie o cluster:
gcloud container clusters create asm-ready \ --cluster-version latest \ --machine-type=n1-standard-4 \ --num-nodes 4
O comando
gcloud
cria um cluster no projeto e na zona do Google Cloud definidos anteriormente. Para executar o Cloud Service Mesh, recomendamos pelo menos quatro nós e o tipo de máquina n1-standard-4.O comando para criar o cluster leva alguns minutos para ser concluído. Quando o cluster estiver pronto, o comando gerará uma mensagem semelhante a esta:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS asm-ready us-central1-b 1.13.5-gke.10 203.0.113.1 n1-standard-2 1.13.5-gke.10 4 RUNNING
Forneça credenciais à ferramenta de linha de comando
kubectl
para que você possa usá-la para gerenciar o cluster:gcloud container clusters get-credentials asm-ready
Agora é possível usar
kubectl
para se comunicar com o Kubernetes. Por exemplo, execute o comando a seguir para ver o status dos nós:kubectl get nodes
O comando responde com uma lista dos nós, semelhante à seguinte:
NAME STATUS ROLES AGE VERSION gke-asm-ready-default-pool-dbeb23dc-1vg0 Ready <none> 99s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-36z5 Ready <none> 100s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-fj7s Ready <none> 99s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-wbjw Ready <none> 99s v1.13.6-gke.13
Entender os principais conceitos do Kubernetes
O diagrama a seguir descreve o aplicativo em execução no GKE:
Antes de implantar os contêineres no GKE, convém analisar alguns dos principais conceitos do Kubernetes. No final deste tutorial, fornecemos links para que você possa saber mais sobre cada conceito.
Nós e clusters: no GKE, um nó é uma VM. Em outras plataformas do Kubernetes, um nó pode ser uma máquina física ou virtual. Um cluster é um conjunto de nós que podem ser tratados como uma única máquina, em que você implanta um aplicativo em contêiner.
Pods: no Kubernetes, os contêineres são executados em um pod. Um pod é a unidade atômica no Kubernetes. Um pod tem um ou mais contêineres. Implante os contêineres
server
eloadgen
no próprio pod. Quando um pod executa vários contêineres (por exemplo, um servidor de aplicativos e um servidor proxy), eles são gerenciados como uma única entidade e compartilham os recursos do pod.Implantações: uma implantação é um objeto do Kubernetes que representa um conjunto de pods idênticos. Uma implantação executa várias réplicas dos pods distribuídos entre os nós de um cluster. Uma implantação substitui automaticamente todos os pods com falha ou que não respondem.
Serviço do Kubernetes: a execução do código do aplicativo no GKE altera a rede entre
loadgen
eserver
. Ao executar os serviços em uma VM do Cloud Shell, envie solicitações para oserver
usando o endereçolocalhost:8080
. Depois que você implantar no GKE, os pods serão programados para execução nos nós disponíveis. Por padrão, não é possível controlar em que nó o pod está sendo executado. Portanto, os pods não têm endereços IP estáveis.Para receber um endereço IP para
server
, defina uma abstração de rede sobre os pods, chamado de Serviço do Kubernetes. Um Serviço do Kubernetes fornece um endpoint de rede estável para um conjunto de pods. Existem vários tipos de serviços. Oserver
usa umLoadBalancer
, que expõe um endereço IP externo para que você possa acessar oserver
de fora do cluster.O Kubernetes também tem um sistema DNS integrado, que atribui nomes DNS (por exemplo,
helloserver.default.cluster.local
) aos serviços. Isso permite que pods dentro do cluster alcancem outros pods no cluster com um endereço estável. Não é possível usar esse nome DNS fora do cluster, como no Cloud Shell.
Manifestos do Kubernetes
Ao executar o aplicativo a partir do código-fonte, você usou um comando
imperativo: python3 server.py
Imperativo significa que ele está orientado por verbos: "faça isso".
Por outro lado, o Kubernetes opera em um modelo declarativo. Isso significa que, em vez de dizer ao Kubernetes exatamente o que fazer, você informa ao Kubernetes o estado pretendido. Por exemplo, o Kubernetes inicia e encerra os pods conforme necessário para que o estado real do sistema corresponda ao estado desejado.
Especifique o estado pretendido em um conjunto de manifestos ou arquivos YAML. Um arquivo YAML contém a especificação para um ou mais objetos do Kubernetes.
A amostra contém um arquivo YAML para server
e loadgen
. Cada arquivo YAML
especifica o estado desejado para o objeto de implantação e o serviço
do Kubernetes.
Servidor
kind
indica o tipo de objeto.metadata.name
especifica o nome da implantação.- O primeiro campo
spec
contém uma descrição do estado desejado. spec.replicas
especifica o número de pods desejado.- A seção
spec.template
define um modelo de pod. Incluído na especificação para os pods está no campoimage
, que é o nome da imagem a ser extraída do Container Registry.
O serviço é definido assim:
LoadBalancer
: os clientes enviam solicitações para o endereço IP de um balanceador de carga de rede, que tem um endereço IP estável e pode ser acessado fora do cluster.targetPort
: lembre-se de que o comandoEXPOSE 8080
emDockerfile
não expõe portas. Você expõe a porta8080
para alcançar o contêinerserver
fora do cluster. Nesse caso,hellosvc.default.cluster.local:80
(nome abreviado:hellosvc
) é mapeado para a porta8080
do IP do podhelloserver
.port
: é o número da porta que outros serviços no cluster usam ao enviar solicitações.
Gerador de carga
O objeto de implantação em loadgen.yaml
é semelhante a server.yaml
. Uma diferença significativa
é que o objeto de implantação contém uma seção chamada env
. Esta
seção define as variáveis de ambiente exigidas por loadgen
, que você definiu
anteriormente quando executou o aplicativo a partir da origem.
Como loadgen
não aceita solicitações de entrada, o campo type
é definido
como ClusterIP
. Esse tipo fornece um endereço IP estável que os serviços no
cluster podem usar, mas o endereço IP não é exposto aos clientes externos.
Implantar os contêineres no GKE
Mude para o diretório em que o
server
de amostra está localizado:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/
Abra
server.yaml
em um editor de texto.Substitua o nome no campo
image
pelo nome da imagem do Docker.image: gcr.io/PROJECT_ID/asm-ready/helloserver:v0.0.1
Substitua
PROJECT_ID
pelo ID do projeto do Google Cloud.Salve e feche
server.yaml
.Implante o arquivo YAML no Kubernetes:
kubectl apply -f server.yaml
Se o procedimento for bem-sucedido, o comando responderá com o seguinte:
deployment.apps/helloserver created service/hellosvc created
Mude para o diretório em que
loadgen
está localizado.cd ../loadgen
Abra
loadgen.yaml
em um editor de texto.Substitua o nome no campo
image
pelo nome da imagem do Docker.image: gcr.io/PROJECT_ID/asm-ready/loadgen:v0.0.1
Substitua
PROJECT_ID
pelo ID do projeto do Google Cloud.Salve e feche
loadgen.yaml
e o editor de texto.Implante o arquivo YAML no Kubernetes:
kubectl apply -f loadgen.yaml
Se o procedimento for bem-sucedido, o comando responderá com o seguinte:
deployment.apps/loadgenerator created service/loadgensvc created
Verifique o status dos pods:
kubectl get pods
O comando responde com o status semelhante ao seguinte:
NAME READY STATUS RESTARTS AGE helloserver-69b9576d96-mwtcj 1/1 Running 0 58s loadgenerator-774dbc46fb-gpbrz 1/1 Running 0 57s
Encontre os registros do aplicativo do pod
loadgen
. SubstituaPOD_ID
pelo identificador da saída anterior.kubectl logs loadgenerator-POD_ID
Encontre os endereços IP externos de
hellosvc
:kubectl get service
O resultado do comando é semelhante ao seguinte:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hellosvc LoadBalancer 10.81.15.158 192.0.2.1 80:31127/TCP 33m kubernetes ClusterIP 10.81.0.1 <none> 443/TCP 93m loadgensvc ClusterIP 10.81.15.155 <none> 80/TCP 4m52s
Envie uma solicitação para
hellosvc
. SubstituaEXTERNAL_IP
pelo endereço IP externo dohellosvc
.curl http://EXTERNAL_IP
Preparação para o Cloud Service Mesh
Agora o aplicativo foi implantado no GKE. O loadgen
pode usar o DNS do Kubernetes (hellosvc:80
) para enviar solicitações para server
e
para server
com um endereço IP externo. Embora
o Kubernetes ofereça muitos recursos, algumas informações sobre os serviços
estão faltando:
- Como os serviços interagem? Qual é a relação entre
os serviços? Como o tráfego flui entre os serviços? Você sabe que
loadgen
envia solicitações paraserver
, mas imagine que não está familiarizado com o aplicativo. Não é possível responder a essas perguntas na lista de pods do GKE no GKE. - Métricas: quanto tempo o
server
leva para responder às solicitações recebidas? Quantas solicitações por segundo (RPS) são enviadas aoserver
? Há respostas de erro? - Informações de segurança: o tráfego entre
loadgen
e oserver
deHTTP
simples ou mTLS ?
O Cloud Service Mesh pode responder a essas perguntas. O Cloud Service Mesh é uma versão gerenciada pelo Google Cloud do projeto de código aberto do Istio. O Cloud Service Mesh coloca um
proxy sidecar do Envoy em cada pod. O proxy Envoy
intercepta todo o tráfego de entrada e saída para os contêineres de aplicativos. Isso
significa que server
e loadgen
recebem um proxy sidecar do Envoy e todo
o tráfego de loadgen
para server
é mediado pelos proxies do Envoy. As conexões entre esses proxies do Envoy formam a malha de serviço. Essa arquitetura de serviço
fornece uma camada de controle sobre o Kubernetes.
Como os proxies do Envoy são executados nos próprios contêineres, é possível instalar o Cloud Service Mesh sobre um cluster do GKE sem causar alterações significativas no código do aplicativo. No entanto, existem algumas maneiras principais de preparar o aplicativo para ser instrumentado com o Cloud Service Mesh:
- Serviços para todos os contêineres: as implantações
server
eloadgen
têm um serviço do Kubernetes anexado. Mesmo oloadgen
, que não recebe solicitações de entrada, tem um serviço. - As portas nos serviços precisam ser nomeadas: embora o GKE permita
definir portas de serviço sem nome, o Cloud Service Mesh exige o
nome de uma porta
que corresponda ao protocolo da porta. No arquivo YAML, a porta para
server
é denominadahttp
porqueserver
usa o protocolo de comunicaçãoHTTP
. Seservice
usougRPC
, você nomeia a portagrpc
. - As implantações são rotuladas: isso permite usar os recursos de gerenciamento de tráfego do Cloud Service Mesh, como dividir o tráfego entre as versões do mesmo serviço.
Instalar o Cloud Service Mesh
Acesse o guia de instalação do Cloud Service Mesh e siga as instruções para instalar o Cloud Service Mesh no cluster.
Limpar
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.
Para limpar, exclua o cluster do GKE. A exclusão do cluster exclui todos os recursos que compõem o cluster de contêiner, como instâncias de computação, discos e recursos de rede.
gcloud container clusters delete asm-ready
A seguir
Saiba mais sobre as tecnologias usadas neste tutorial:
Saiba mais sobre as ferramentas:
Saiba mais sobre os conceitos do Kubernetes: