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.
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 endpoint- GET,- /, que imprime "hello world" no console.
- loadgen: um script que envia tráfego para- server, 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 o- server:- python3 server/server.py- Na inicialização, o - serverexibe 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 - serverresponde:- 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 - loadgengera 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 - servergrava 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 - localhostpara enviar solicitações para- server.
- Para interromper - loadgene- server, insira- Ctrl-cem 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 basemanda 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 ENTRYPOINTdefine o comando usado para executar o contêiner. Nesse caso, o comando é quase igual ao que você usou para executar oserver.pya partir do código-fonte.
- O comando EXPOSEespecifica que oserverescute na porta8080. Esse comando não expõe nenhuma porta, mas serve como documentação necessária para abrir a porta8080ao executar o contêiner.
Preparar para colocar o aplicativo em um contêiner
- Defina as seguintes variáveis de ambiente. Substitua - PROJECT_IDpelo ID do seu projeto doGoogle Cloud .- export PROJECT_ID="PROJECT_ID" - export GCR_REPO="asm-ready" - Você usa o valor de - PROJECT_IDe- GCR_REPOpara incluir uma tag na imagem do Docker ao criar e enviá-la ao seu Container Registry particular.
- Defina o projeto 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 projetoGoogle Cloud . - gcloud services enable containerregistry.googleapis.com
Colocar o server em um contêiner
- Mude para o diretório em que o - serverde amostra está localizado:- cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/ 
- Crie a imagem usando o - Dockerfilee as variáveis de ambiente definidas anteriormente:- docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1 .- A sinalização - -trepresenta 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 - loadgende 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 - gcloudcria um cluster no projeto e na zonaGoogle 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 - kubectlpara que você possa usá-la para gerenciar o cluster:- gcloud container clusters get-credentials asm-ready
- Agora é possível usar - kubectlpara 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 - servere- loadgenno 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 - loadgene- server. Ao executar os serviços em uma VM do Cloud Shell, envie solicitações para o- serverusando o endereço- localhost: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. O- serverusa um- LoadBalancer, que expõe um endereço IP externo para que você possa acessar o- serverde 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
- kindindica o tipo de objeto.
- metadata.nameespecifica o nome da implantação.
- O primeiro campo speccontém uma descrição do estado desejado.
- spec.replicasespecifica o número de pods desejado.
- A seção spec.templatedefine 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 comando- EXPOSE 8080em- Dockerfilenão expõe portas. Você expõe a porta- 8080para alcançar o contêiner- serverfora do cluster. Nesse caso,- hellosvc.default.cluster.local:80(nome abreviado:- hellosvc) é mapeado para a porta- 8080do IP do pod- helloserver.
- 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 - serverde amostra está localizado:- cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/ 
- Abra - server.yamlem um editor de texto.
- Substitua o nome no campo - imagepelo nome da imagem do Docker.- image: gcr.io/PROJECT_ID/asm-ready/helloserver:v0.0.1 - Substitua - PROJECT_IDpelo Google Cloud ID do projeto.
- 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 - loadgenestá localizado.- cd ../loadgen
- Abra - loadgen.yamlem um editor de texto.
- Substitua o nome no campo - imagepelo nome da imagem do Docker.- image: gcr.io/PROJECT_ID/asm-ready/loadgen:v0.0.1 - Substitua - PROJECT_IDpelo Google Cloud ID do projeto.
- Salve e feche - loadgen.yamle 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. Substitua- POD_IDpelo 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. Substitua- EXTERNAL_IPpelo endereço IP externo do- hellosvc.- 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
loadgenenvia 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 serverleva 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 loadgene oserverdeHTTPsimples ou mTLS ?
O Cloud Service Mesh pode responder a essas perguntas. O Cloud Service Mesh é uma versão gerenciada pelo Google Clouddo 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 servereloadgentê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é denominadahttpporqueserverusa o protocolo de comunicaçãoHTTP. SeserviceusougRPC, 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.