Este exemplo avançado demonstra como criar um aplicativo de registro de ocorrências que usa node.js para o front-end e MySQL para o back-end. O modelo também cria e conecta um balanceador de carga HTTP, que faz o balanceamento de carga entre duas zonas, e um autoescalador, para fazer o escalonamento automático do aplicativo.
Este exemplo pressupõe que você tenha familiaridade com contêineres Docker e recursos do Compute Engine, especialmente balanceamento de carga HTTP, escalonamento automático, grupos de instâncias gerenciadas e modelos de instância.
Para mais tutoriais introdutórios, consulte o Guia de primeiros passos ou o Guia passo a passo.
Antes de começar
- Para usar os exemplos de linha de comando deste guia, instale a ferramenta de linha de comando "gcloud".
- Para usar os exemplos de API deste guia, configure o acesso de API.
- Familiarize-se com o balanceamento de carga HTTP do Compute Engine.
- Familiarize-se com os contêineres Docker.
Como criar modelos
Neste exemplo, iniciamos inicia uma implantação com diversos tipos de recursos. Para começar, você criará modelos reutilizáveis que definem esses recursos separadamente. Posteriormente, você os usará na configuração final.
Ao final deste exemplo, você terá uma implantação com os seguintes recursos:
- uma única instância do Compute Engine para a máquina virtual MySQL back-end
- um modelo de instância que usa uma imagem Docker
- dois grupos de instâncias gerenciadas em escalonamento automático em duas zonas diferentes, executando o serviço node.js front-end
- outros dois grupos de instâncias gerenciadas em escalonamento automático que fornecem dados estáticos
- uma verificação de integridade e um balanceador de carga HTTP para tráfego distribuído em todos os respectivos grupos de instâncias gerenciadas
Como criar os modelos de back-end
O back-end desse aplicativo é uma única instância do Compute Engine que executa um contêiner Docker
com o MySQL. Crie um modelo que defina uma instância do Compute Engine que use uma imagem otimizada para contêiner. Coloque o nome de container_vm.[py|jinja]
no arquivo:
Jinja
Python
O modelo define um número de variáveis, como containerImage
e
manifest
, que serão preenchidas quando você definir sua
configuração. Sozinho, este modelo apenas cria uma
única instância de máquina virtual (VM).
Quando você usa imagens de contêiner em instâncias do Compute Engine, também é necessário
fornecer um arquivo de manifesto para descrever qual imagem usar.
Esse manifesto é diferente do utilizado pelo Deployment Manager. Crie um método
auxiliar chamado container_helper.[py|jinja]
para definir dinamicamente o manifesto do
contêiner:
Jinja
Python
Como criar os modelos de front-end
O front-end deste aplicativo executa o Node.js e permite que os usuários postem mensagens na página da Web. Haverá dois grupos de instâncias gerenciadas contendo duas instâncias cada: um grupo de instâncias gerenciadas principal e um grupo de instâncias gerenciadas secundário para o balanceamento de carga.
Para criar modelos de front-end, use as instruções a seguir.
Crie um modelo de instância.
Você precisa de um recurso de modelo de instância para criar um grupo de instâncias gerenciadas, que é um grupo de instâncias de VM idênticas gerenciadas centralmente. Este exemplo cria um grupo de instâncias gerenciadas para as instâncias node.js front-end, mas antes é preciso criar o modelo de instância.
Defina um arquivo chamado
container_instance_template.[py|jinja]
:Jinja
Python
Crie um grupo de instâncias gerenciadas com escalonamento automático.
Agora que você tem um modelo de instância, defina um modelo que use o modelo de instância para criar um grupo de instâncias gerenciadas de escalonamento automático. Crie um novo arquivo chamado
autoscaled_group.[py|jinja]
com o seguinte conteúdo:Jinja
Python
Crie o arquivo de esquema correspondente:
Jinja
Python
Crie recursos usando esses modelos.
Até este ponto, você definiu modelos base que determinam as propriedades dos recursos. Use esses modelos para definir a configuração do front-end. Crie um novo arquivo chamado
service.[py|jinja]
com o seguinte conteúdo:Jinja
Python
Crie o arquivo de esquema correspondente:
Jinja
Python
Detalhemos o que esse modelo está criando:
Dois grupos de instâncias gerenciadas, um principal e outro secundário.
O modelo usa o modelo
autoscaled_group.[py|jinja]
para criar um grupo de instâncias gerenciado, com escalonamento automático principal e secundário.Em seguida, o modelo cria um serviço back-end e um verificador de integridade. Um serviço back-end é necessário para o balanceamento de carga HTTP e define a capacidade de distribuição dos grupos de instâncias nesse serviço back-end. Nesse caso, os grupos de instâncias gerenciadas principal e secundário fazem parte desse back-end, e as propriedades padrão do serviço back-end são aplicáveis.
Por padrão, um serviço de back-end realiza o balanceamento de carga com base na utilização da CPU dos grupos de instâncias associadas, mas você também pode equilibrar a carga com base em solicitações por segundo (RPS, na sigla em inglês).
Observação: uma verificação de integridade sempre é obrigatória durante a criação de um serviço de back-end.
Como criar um modelo unificado
Por fim, crie um modelo unificador que combine os modelos back-end e front-end. Crie um novo arquivo denominado application.[py|jinja]
:
Jinja
Python
Crie um arquivo de esquema correspondente:
Jinja
Python
Além do front-end e do back-end, o modelo também define alguns recursos adicionais:
Um serviço estático com grupos de instâncias gerenciadas principal e secundário. Esse serviço estático exibe uma página da Web, localizada no caminho
/static
do seu aplicativo.Um recurso de mapa URL. O balanceamento de carga HTTP exige um mapa URL para mapear os URLs diferentes para os caminhos corretos. Nesse caso, o caminho padrão, indicado pela propriedade
defaultService
, é o serviço de back-end que você criou anteriormente. Se um usuário navegar para/static
, o mapa de URLs mapeará esse caminho para o serviço estático, conforme definido na seçãopathMatchers
.Uma regra de encaminhamento global e um proxy HTTP de destino. Como a carga do aplicativo está sendo balanceada entre duas zonas separadas, você precisará de uma regra de encaminhamento global que ofereça um único endereço IP externo. Além disso, um proxy HTTP de destino é obrigatório para a configuração do balanceamento de carga HTTP.
Uma regra de firewall que permita o tráfego pela porta 8080.
Como criar a configuração
Agora que tem os modelos e os esquemas relacionados prontos, crie uma configuração que implante esses recursos. Crie um arquivo de configuração chamado
application.yaml
com o conteúdo a seguir e substitua ZONE_TO_RUN
e
SECONDARY_ZONE_TO_RUN
pelas zonas primária e secundária que você preferir.
Jinja
Python
Como implantar a configuração
Agora, faremos a implantação dos recursos. Usando a Google Cloud CLI, execute o
comando a seguir, optando por substituir advanced-configuration-l7
por um nome de implantação de sua escolha. Lembre-se de que o nome da implantação
será usado automaticamente para identificar os recursos.
Neste exemplo, o nome da implantação é advanced-configuration-l7
. Caso você opte por alterar o nome da implantação, não se esqueça de usá-lo em todos os exemplos a seguir.
gcloud deployment-manager deployments create advanced-configuration-l7 --config application.yaml
A resposta deve ser semelhante à resposta dos seguintes recursos:
Waiting for create operation-1469468950934-5387966d431f0-49b11bc4-1421b2f0...done. Create operation operation-1469468950934-5387966d431f0-49b11bc4-1421b2f0 completed successfully. NAME TYPE STATE ERRORS advanced-configuration-l7-application-fw compute.v1.firewall COMPLETED [] advanced-configuration-l7-application-l7lb compute.v1.globalForwardingRule COMPLETED [] advanced-configuration-l7-application-targetproxy compute.v1.targetHttpProxy COMPLETED [] advanced-configuration-l7-application-urlmap compute.v1.urlMap COMPLETED [] advanced-configuration-l7-backend compute.v1.instance COMPLETED [] advanced-configuration-l7-frontend-bes compute.v1.backendService COMPLETED [] advanced-configuration-l7-frontend-hc compute.v1.httpHealthCheck COMPLETED [] advanced-configuration-l7-frontend-it compute.v1.instanceTemplate COMPLETED [] advanced-configuration-l7-frontend-pri-as compute.v1.autoscaler COMPLETED [] advanced-configuration-l7-frontend-pri-igm compute.v1.instanceGroupManager COMPLETED [] advanced-configuration-l7-frontend-sec-as compute.v1.autoscaler COMPLETED [] advanced-configuration-l7-frontend-sec-igm compute.v1.instanceGroupManager COMPLETED [] advanced-configuration-l7-static-service-bes compute.v1.backendService COMPLETED [] advanced-configuration-l7-static-service-hc compute.v1.httpHealthCheck COMPLETED [] advanced-configuration-l7-static-service-it compute.v1.instanceTemplate COMPLETED [] advanced-configuration-l7-static-service-pri-as compute.v1.autoscaler COMPLETED [] advanced-configuration-l7-static-service-pri-igm compute.v1.instanceGroupManager COMPLETED [] advanced-configuration-l7-static-service-sec-as compute.v1.autoscaler COMPLETED [] advanced-configuration-l7-static-service-sec-igm compute.v1.instanceGroupManager COMPLETED []
Como adicionar rótulos de serviço
Em seguida, especifique os rótulos de serviço para os grupos de instâncias gerenciadas. Esses rótulos são metadados usados pelo serviço de balanceamento de carga para agrupar recursos.
Para adicionar rótulos de serviço, execute os seguintes comandos, comparando as zonas primária e secundária com as zonas selecionadas no arquivo de configuração da implantação:
gcloud compute instance-groups unmanaged set-named-ports advanced-configuration-l7-frontend-pri-igm \
--named-ports http:8080,httpstatic:8080 \
--zone [PRIMARY_ZONE]
gcloud compute instance-groups unmanaged set-named-ports advanced-configuration-l7-frontend-sec-igm \
--named-ports http:8080,httpstatic:8080 \
--zone [SECONDARY_ZONE]
Como testar a configuração
Para testar a configuração, veja o endereço IP externo que exibe o tráfego consultando a regra de encaminhamento:
gcloud compute forwarding-rules list | grep advanced-configuration-l7-l7lb advanced-configuration-l7-l7lb 107.178.249.126 TCP advanced-configuration-l7-targetproxy
Neste caso, o IP externo é 107.178.249.126
.
Em um navegador, visite o endereço IP externo na porta 8080. Por exemplo, se o IP externo for 107.178.249.126
, o URL será:
http://107.178.249.126:8080
Aparecerá uma página em branco, o que é esperado. Em seguida, poste uma mensagem na página. Acesse o seguinte URL:
http://107.178.249.126:8080?msg=hello_world!
Você verá uma confirmação de que a mensagem foi adicionada. Volte ao URL principal, e agora a página terá a mensagem:
hello_world!
Também é possível visitar a página estática criada por você ou verificar a integridade do aplicativo nos seguintes URLs:
# Static web page
http://107.178.249.126:8080/static
# Health check
http://107.178.249.126:8080/_ah/health
Parabéns, configuração implantada com sucesso.
(Opcional) Como criar imagens do Docker
O Docker permite automatizar e executar software em contêineres. Os contêineres permitem isolar serviços diferentes dentro de contêineres que podem ser todos executados em uma única instância do Linux.
Neste exemplo, algumas imagens do Docker foram usadas, mas você pode criar as próprias versões delas. Veja as instruções para criar as imagens de back-end MySQL e a imagens de front-end do Node.js na seção Criar modelos de recurso.
Para criar a imagem Docker que exibe a página da Web estática:
Crie uma nova instância de VM com uma imagem otimizada para contêiner:
gcloud compute instances create docker-playground \ --image-family container-vm \ --image-project google-containers \ --zone us-central1-a \ --machine-type f1-micro
Conecte-se à instância:
gcloud compute ssh --zone us-central1-a docker-playground
Crie um arquivo chamado
Dockerfile
com o seguinte conteúdo:FROM node:latest RUN mkdir /var/www/ ADD service.js /var/www/service.js WORKDIR /var/www/ RUN npm install mysql CMD ["node", "service.js"]
Crie um arquivo chamado
service.js
com o seguinte conteúdo:var http = require('http'); var url = require('url'); console.log('Started static node server') http.createServer(function (req, res) { reqUrl = url.parse(req.url, true); res.useChunkedEncodingByDefault = false; res.writeHead(200, {'Content-Type': 'text/html'}); if (reqUrl.pathname == '/_ah/health') { res.end('ok'); } else if (reqUrl.pathname == '/exit') { process.exit(-1) } else { res.end('static server'); } }).listen(8080, '0.0.0.0'); console.log('Static server running at http://127.0.0.1:8080/');
Crie a imagem do Docker, substituindo
username
pelo seu nome de usuário do Docker Hub. Caso você não tenha um nome de usuário do Docker Hub, crie um antes de criar a imagem Docker.sudo docker build --no-cache -t username/nodejsservicestatic .
Envie as imagens para o repositório do Docker:
sudo docker push username/nodejsservicestatic
Agora você tem as imagens do Docker para executar Node.js e MySQL. Essas imagens
podem ser vistas realmente no
repositório,
basta pesquisar pelos respectivos nomes. Para testar as imagens, substitua todas as instâncias de
gcr.io/deployment-manager-examples/mysql
e
gcr.io/deployment-manager-examples/nodejsservice
pelas suas imagens.
Próximas etapas
Após concluir este exemplo, você poderá:
- Continuar a desenvolver a partir dele, criando uma página da Web mais robusta ou adicionando mais serviços ao servidor da Web.
- Leia mais sobre configurações ou implantações.
- tentar criar configurações próprias.