Este exemplo avançado demonstra como criar uma app de registo que usa o node.js para o respetivo frontend e o MySQL para o respetivo backend. O modelo também cria e liga um balanceador de carga HTTP que equilibra a carga em duas zonas, e um escalador automático para dimensionar automaticamente a app.
Este exemplo pressupõe que conhece os contentores Docker, bem como os recursos do Compute Engine, particularmente o balanceamento de carga HTTP, a escala automática, os grupos de instâncias geridas e os modelos de instâncias.
Para ver mais tutoriais introdutórios, consulte o guia de introdução ou o guia passo a passo.
Antes de começar
- Se quiser usar os exemplos de linhas de comando neste guia, instale a ferramenta de linhas de comando`gcloud`.
- Se quiser usar os exemplos de API neste guia, configure o acesso à API.
- Familiarizado com o balanceamento de carga HTTP do Compute Engine.
- Ter conhecimentos sobre contentores Docker.
Criar os seus modelos
Este exemplo inicia uma implementação com vários tipos de recursos. Para começar, vai criar modelos reutilizáveis que definem estes recursos separadamente. Mais tarde, vai usar estes modelos na configuração final.
No final deste exemplo, terá uma implementação que contém estes recursos:
- Uma única instância do Compute Engine para a máquina virtual MySQL de back-end.
- Um modelo de instância que usa uma imagem do Docker.
- Dois grupos de instâncias geridos com escalamento automático em duas zonas diferentes, a executar o serviço node.js de front-end.
- Outro grupo de instâncias gerido com escala automática que serve dados estáticos.
- Uma verificação de estado e um balanceador de carga HTTP para distribuir o tráfego pelos respetivos grupos de instâncias geridas.
Criar os modelos de back-end
O back-end desta app é uma única instância do Compute Engine que executa um contentor do Docker do MySQL. Crie um modelo que defina uma instância do Compute Engine que use uma imagem otimizada para contentores. Atribua o nome container_vm.[py|jinja]
ao ficheiro:
Jinja
Python
O modelo define várias variáveis, como containerImage
e manifest
, que são preenchidas quando define a sua configuração. Este modelo sozinho apenas cria uma instância de máquina virtual (VM).
Quando usa imagens de contentores em instâncias do Compute Engine, também tem de fornecer um ficheiro de manifesto (diferente de um manifesto do Deployment Manager) para descrever ao Compute Engine que imagem de contentor usar. Crie um método auxiliar denominado container_helper.[py|jinja]
para definir dinamicamente o manifesto do contentor:
Jinja
Python
Criar os modelos de front-end
O frontend desta app é executado no Node.js e permite que os utilizadores publiquem mensagens na página Web. Existem dois grupos de instâncias geridas que contêm duas instâncias cada: um grupo de instâncias geridas principal e um grupo de instâncias geridas secundário para o equilíbrio de carga.
Para criar estes modelos de front-end, use as seguintes instruções.
Crie um modelo de instância.
Precisa de um recurso de modelo de instância para criar um grupo de instâncias geridas, que é um grupo de instâncias de VMs idênticas geridas centralmente. Este exemplo cria um grupo de instâncias gerido para as instâncias do Node.js de front-end, mas primeiro tem de criar o modelo de instância.
Defina um ficheiro com o nome
container_instance_template.[py|jinja]
:Jinja
Python
Crie um grupo de instâncias gerido com escalamento automático.
Agora que tem um modelo de instância, pode definir um modelo que use o modelo de instância para criar um grupo de instâncias geridas com escalamento automático. Crie um novo ficheiro denominado
autoscaled_group.[py|jinja]
com o seguinte conteúdo:Jinja
Python
Crie o ficheiro de esquema correspondente:
Jinja
Python
Crie recursos com estes modelos.
Até este ponto, definiu modelos base que determinam as propriedades dos seus recursos. Com estes modelos, defina a configuração do seu front-end. Crie um novo ficheiro denominado
service.[py|jinja]
com o seguinte conteúdo:Jinja
Python
Crie o ficheiro de esquema correspondente:
Jinja
Python
Vamos analisar o que este modelo está a criar:
Dois grupos de instâncias geridas, um principal e um secundário.
O modelo usa o modelo
autoscaled_group.[py|jinja]
para criar um grupo de instâncias gerido com escalamento automático primário e secundário.Em seguida, o modelo cria um serviço de back-end e um verificador de funcionamento. É necessário um serviço de back-end para o balanceamento de carga HTTP, e este define a capacidade de publicação dos grupos de instâncias nesse serviço de back-end. Neste caso, os grupos de instâncias geridas principais e secundários fazem parte deste back-end, e as propriedades predefinidas do serviço de back-end aplicam-se.
Por predefinição, um serviço de back-end realiza o equilíbrio de carga com base na utilização da CPU dos grupos de instâncias associados, mas também pode fazer o equilíbrio de carga com base em pedidos por segundo (RPS).
Nota: uma verificação de funcionamento é sempre necessária quando cria um serviço de back-end.
Criar um modelo unificador
Por último, crie um modelo unificador que combine os modelos de back-end e front-end. Crie um novo ficheiro com o nome application.[py|jinja]
:
Jinja
Python
Crie um ficheiro 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 geridas primários e secundários. Este serviço estático disponibiliza uma página Web localizada no caminho
/static
na sua app.Um recurso de mapa de URL. O balanceamento de carga HTTP requer um mapa de URLs para mapear os diferentes URLs para os caminhos corretos. Neste caso, o caminho predefinido, indicado pela propriedade
defaultService
, é o serviço de back-end que criou anteriormente. Se um utilizador navegar para/static
, o mapa de URLs mapeia esse caminho para o serviço estático, conforme definido na secçãopathMatchers
.Uma regra de encaminhamento global e um proxy HTTP de destino. Uma vez que a app está a ser balanceada em duas zonas separadas, precisa de uma regra de encaminhamento global que publique um único endereço IP externo. Além disso, é necessário um proxy HTTP de destino para a configuração do balanceamento de carga HTTP.
Uma regra de firewall que permite o tráfego através da porta 8080.
A criar a sua configuração
Agora que tem os modelos e os esquemas relacionados prontos, pode criar uma configuração que implemente estes recursos. Crie um ficheiro de configuração denominado
application.yaml
com o seguinte conteúdo e substitua ZONE_TO_RUN
e
SECONDARY_ZONE_TO_RUN
pelas zonas primárias e secundárias da sua escolha.
Jinja
Python
Implementar a configuração
Agora, vamos implementar os seus recursos. Usando a CLI Google Cloud, execute o comando seguinte, escolhendo opcionalmente substituir advanced-configuration-l7
por um nome de implementação à sua escolha. Tenha em atenção que o nome da implementação
vai ser usado automaticamente para dar nome aos recursos.
Neste exemplo, o nome da implementação é advanced-configuration-l7
. Se optar por alterar o nome da implementação, certifique-se de que usa esse nome da implementação em todos os exemplos seguintes.
gcloud deployment-manager deployments create advanced-configuration-l7 --config application.yaml
A resposta deve ter um aspeto semelhante aos 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 []
Adicionar etiquetas de serviço
Em seguida, especifique as etiquetas de serviço adequadas para os seus grupos de instâncias geridos. As etiquetas de serviço são metadados usados pelo serviço de equilíbrio de carga para agrupar recursos.
Para adicionar etiquetas de serviço, execute os seguintes comandos, fazendo corresponder as zonas primárias e secundárias às zonas que selecionou no ficheiro de configuração da implementaçã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]
Testar a configuração
Para testar a sua configuração, obtenha o endereço IP externo que está a publicar 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
.
Num navegador, visite o endereço IP externo na porta 8080. Por exemplo, se o seu IP externo for 107.178.249.126
, o URL seria:
http://107.178.249.126:8080
Deve ver uma página em branco, o que é esperado. Em seguida, publique uma mensagem na página. Aceda ao seguinte URL:
http://107.178.249.126:8080?msg=hello_world!
É apresentada uma confirmação de que a mensagem foi adicionada. Regresse ao URL principal e, agora, a página deve ter a mensagem:
hello_world!
Também pode visitar a página estática que criou ou verificar o estado da sua app através dos seguintes URLs:
# Static web page
http://107.178.249.126:8080/static
# Health check
http://107.178.249.126:8080/_ah/health
Parabéns! Implementou a sua configuração com êxito.
(Opcional) Criar imagens de Docker
O Docker permite-lhe automatizar e executar software em contentores. Os contentores permitem-lhe isolar diferentes serviços em contentores que podem ser executados numa única instância do Linux.
Este exemplo usou algumas imagens do Docker existentes, mas também pode criar as suas próprias versões destas imagens do Docker. Pode encontrar as instruções para criar as imagens de back-end do MySQL e as imagens de front-end do Node.js na secção Criar os modelos de recursos.
Para criar a imagem do Docker que publica a página Web estática:
Crie uma nova instância de VM com uma imagem otimizada para contentores:
gcloud compute instances create docker-playground \ --image-family container-vm \ --image-project google-containers \ --zone us-central1-a \ --machine-type f1-micro
Associe-se à instância:
gcloud compute ssh --zone us-central1-a docker-playground
Crie um ficheiro denominado
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 ficheiro denominado
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 utilizador do Docker Hub. Se não tiver um nome de utilizador do Docker Hub, crie um primeiro antes de criar a imagem do Docker.sudo docker build --no-cache -t username/nodejsservicestatic .
Envie as imagens para o repositório Docker:
sudo docker push username/nodejsservicestatic
Agora, tem as imagens Docker para executar o Node.js e o MySQL. Pode ver estas imagens no repositório pesquisando os nomes das imagens. Para experimentar as imagens, pode substituir todas as instâncias de
gcr.io/deployment-manager-examples/mysql
e
gcr.io/deployment-manager-examples/nodejsservice
pelas suas respetivas imagens.
Passos seguintes
Depois de concluir este exemplo, pode:
- Continue a desenvolver este exemplo criando uma página Web mais robusta ou adicionando mais serviços ao servidor Web.
- Leia mais sobre as configurações ou as implementações.
- Experimente criar as suas próprias configurações.