Guia de início rápido: como implantar um aplicativo em uma linguagem específica

Nesta página, você aprende a fazer o seguinte:

  1. Criar um aplicativo "Hello World".
  2. Empacotar o aplicativo em uma imagem de contêiner usando o Cloud Build.
  3. Criar um cluster no Google Kubernetes Engine (GKE).
  4. Implantar a imagem de contêiner no cluster.

A amostra é exibida em várias linguagens, mas é possível usar outras além destas.

Antes de começar

  1. Faça login na sua Conta do Google.

    Se você ainda não tiver uma, inscreva-se.

  2. Selecione ou crie um projeto do Google Cloud Platform.

    Acessar a página Gerenciar recursos

  3. Verifique se o faturamento foi ativado no projeto do Google Cloud Platform.

    Saiba como ativar o faturamento

  4. Ativar Cloud Build and Google Kubernetes Engine APIs.

    Ativar as APIs

  5. Instale e inicialize o SDK do Cloud.
  6. A kubectl é utilizado para gerenciar o Kubernetes, o sistema de orquestração de clusters do GKE. Use a gcloud para instalar a kubectl:
    gcloud components install kubectl

Como escrever o aplicativo de amostra

Para instruções sobre como criar um aplicativo "Hello World" que seja executado no GKE, clique na linguagem usada por você:

Go

  1. Crie um novo diretório chamado helloworld-gke e acesse-o:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crie um novo módulo chamado example.com/helloworld:

    go mod init example.com/helloworld
    
  3. Crie um novo arquivo chamado helloworld.go e cole o código a seguir nele:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"os"
    )
    
    func main() {
    	http.HandleFunc("/", handler)
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    	}
    	log.Printf("Listening on localhost:%s", port)
    	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
    	log.Print("Hello world received a request.")
    	target := os.Getenv("TARGET")
    	if target == "" {
    		target = "World"
    	}
    	fmt.Fprintf(w, "Hello %s!\n", target)
    }
    

    Com esse código, você cria um servidor da Web que realiza detecções na porta definida pela variável de ambiente PORT.

Você concluiu seu aplicativo. Ele está pronto para ser empacotado em um contêiner do Docker e enviado por upload ao Container Registry.

Node.js

  1. Crie um novo diretório chamado helloworld-gke e acesse-o:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crie um arquivo package.json com o conteúdo a seguir:

    {
      "name": "gke-helloworld",
      "version": "1.0.0",
      "description": "GKE hello world sample in Node",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "author": "",
      "license": "Apache-2.0",
      "dependencies": {
        "express": "^4.16.4"
      }
    }
    
  3. No mesmo diretório, crie um arquivo index.js e copie as linhas a seguir para ele:

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      console.log('Hello world received a request.');
    
      const target = process.env.TARGET || 'World';
      res.send(`Hello ${target}!`);
    });
    
    const port = process.env.PORT || 8080;
    app.listen(port, () => {
      console.log('Hello world listening on port', port);
    });
    

    Com esse código, você cria um servidor da Web que realiza detecções na porta definida pela variável de ambiente PORT.

Você concluiu seu aplicativo. Ele está pronto para ser empacotado em um contêiner do Docker e enviado por upload ao Container Registry.

Python

  1. Crie um novo diretório chamado helloworld-gke e acesse-o:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crie um arquivo chamado app.py e cole o código a seguir nele:

    import os
    
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        target = os.environ.get('TARGET', 'World')
        return 'Hello {}!\n'.format(target)
    
    if __name__ == "__main__":
        app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8080)))
    

Java

Crie um aplicativo Spring Boot.

  1. Instale o JDK Java SE 8 ou superior e também o cURL (páginas em inglês). Eles são necessários apenas para criar o novo projeto da Web na próxima etapa. O Dockerfile, descrito posteriormente, carrega todas as dependências no contêiner.

  2. No terminal, crie um novo projeto da Web vazio:

    curl https://start.spring.io/starter.zip \
        -d dependencies=web \
        -d javaVersion=1.8 \
        -d bootVersion=2.1.3.RELEASE \
        -d name=helloworld \
        -d artifactId=helloworld \
        -d baseDir=helloworld-gke \
        -o helloworld-gke.zip
    unzip helloworld-gke.zip
    cd helloworld-gke
    

    Agora você tem um novo projeto Spring Boot em helloworld-gke.

  3. No arquivo src/main/java/com/example/helloworld/HelloworldApplication.java, atualize a classe HelloworldApplication. Basta adicionar um @RestController para processar o mapeamento de /.

    package com.example.helloworld;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    public class HelloworldApplication {
    
    	@Value("${TARGET:World}")
    	String target;
    
    	@RestController
    	class HelloworldController {
    		@GetMapping("/")
    		String hello() {
    			return "Hello " + target + "!";
    		}
    	}
    
    	public static void main(String[] args) {
    		SpringApplication.run(HelloworldApplication.class, args);
    	}
    }
    

    Com esse código, você cria um servidor da Web que realiza detecções na porta definida pela variável de ambiente PORT.

Você concluiu seu aplicativo. Ele está pronto para ser empacotado em um contêiner do Docker e enviado por upload ao Container Registry.

C#

  1. Instale o SDK do .NET Core 2.2 (em inglês). Ele é necessário apenas para criar o novo projeto da Web na próxima etapa. O Dockerfile, descrito posteriormente, carrega todas as dependências no contêiner.

  2. No terminal, crie um novo projeto da Web vazio:

    dotnet new web -o helloworld-gke
    
  3. Acesse o diretório helloworld-gke.

  4. Atualize a definição CreateWebHostBuilder em Program.cs. Basta especificar o URL da porta em .UseUrls() para definir a porta de serviço. A amostra mostra a porta 8080, mas é possível usar outras. Seu servidor precisa fazer detecções na porta que você especificar a seguir:

    // Copyright (c) 2019 Google LLC.
    //
    // Licensed under the Apache License, Version 2.0 (the "License"); you may not
    // use this file except in compliance with the License. You may obtain a copy of
    // the License at
    //
    // http://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    // License for the specific language governing permissions and limitations under
    // the License.
    
    using System;
    using Microsoft.AspNetCore;
    using Microsoft.AspNetCore.Hosting;
    
    namespace HelloGKE
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateWebHostBuilder(args).Build().Run();
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>()
                    .UsePortEnvironmentVariable();
        }
    
        static class ProgramExtensions
        {
            // Google Cloud Run sets the PORT environment variable to tell this
            // process which port to listen to.
            public static IWebHostBuilder UsePortEnvironmentVariable(
                this IWebHostBuilder builder)
            {
                string port = Environment.GetEnvironmentVariable("PORT");
                if (!string.IsNullOrEmpty(port))
                {
                    builder.UseUrls($"http://0.0.0.0:{port}");
                }
                return builder;
            }
        }
    }
    

Você concluiu seu aplicativo. Ele está pronto para ser empacotado em um contêiner do Docker e enviado por upload ao Container Registry.

PHP

  1. Crie um novo diretório chamado helloworld-gke e acesse-o:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crie um arquivo chamado index.php e cole o código a seguir nele:

    <?php
    $target = getenv('TARGET', true) ?: 'World';
    echo sprintf("Hello %s!", $target);
    

Você concluiu seu aplicativo. Ele está pronto para ser empacotado em um contêiner do Docker e enviado por upload ao Container Registry.

Ruby

  1. Crie um novo diretório chamado helloworld-gke e acesse-o:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crie um arquivo chamado app.rb e cole o código a seguir nele:

    require 'sinatra'
    
    set :bind, '0.0.0.0'
    set :port, ENV['PORT'] || '8080'
    
    get '/' do
      target = ENV['TARGET'] || 'World'
      "Hello #{target}!\n"
    end
    

    Com esse código, você cria um servidor da Web que realiza detecções na porta definida pela variável de ambiente PORT.

  3. Crie um arquivo chamado Gemfile e copie o código a seguir para ele:

    source 'https://rubygems.org'
    
    gem 'sinatra'
    gem 'rack', '>= 2.0.6'
    

Como contentorizar um aplicativo com o Cloud Build

  1. Para contentorizar o aplicativo de amostra, crie um novo arquivo chamado Dockerfile no mesmo diretório dos arquivos de origem e copie o conteúdo a seguir:

    Go

    # Use the offical Golang image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    # https://hub.docker.com/_/golang
    FROM golang:1.12 as builder
    
    # Copy local code to the container image.
    WORKDIR /app
    COPY . .
    
    # Build the command inside the container.
    RUN CGO_ENABLED=0 GOOS=linux go build -v -o helloworld
    
    # Use a Docker multi-stage build to create a lean production image.
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM alpine
    RUN apk add --no-cache ca-certificates
    
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /app/helloworld /helloworld
    
    # Run the web service on container startup.
    CMD ["/helloworld"]
    

    Node.js

    # Use the official lightweight Node.js 10 image.
    # https://hub.docker.com/_/node
    FROM node:10-slim
    
    # Create and change to the app directory.
    WORKDIR /usr/src/app
    
    # Copy application dependency manifests to the container image.
    # A wildcard is used to ensure both package.json AND package-lock.json are copied.
    # Copying this separately prevents re-running npm install on every code change.
    COPY package*.json ./
    
    # Install production dependencies.
    RUN npm install --only=production
    
    # Copy local code to the container image.
    COPY . ./
    
    # Run the web service on container startup.
    CMD [ "npm", "start" ]
    

    Adicione outro arquivo .dockerignore para garantir que os arquivos locais não afetem o processo de criação do contêiner:

    Dockerfile
    README.md
    node_modules
    npm-debug.log
    

    Python

    # Use the official lightweight Python image.
    # https://hub.docker.com/_/python
    FROM python:3.7-slim
    
    # Copy local code to the container image.
    ENV APP_HOME /app
    WORKDIR $APP_HOME
    COPY . ./
    
    # Install production dependencies.
    RUN pip install Flask gunicorn
    
    # Run the web service on container startup. Here we use the gunicorn
    # webserver, with one worker process and 8 threads.
    # For environments with multiple CPU cores, increase the number of workers
    # to be equal to the cores available.
    CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 app:app
    

    Adicione um arquivo .dockerignore para garantir que os arquivos locais não afetem o processo de criação do contêiner:

    Dockerfile
    README.md
    *.pyc
    *.pyo
    *.pyd
    __pycache__
    

    Java

    # Use the official maven/Java 8 image to create a build artifact.
    # https://hub.docker.com/_/maven
    FROM maven:3.5-jdk-8-alpine as builder
    
    # Copy local code to the container image.
    WORKDIR /app
    COPY pom.xml ./
    COPY src ./src/
    
    # Build a release artifact.
    RUN mvn package -DskipTests
    
    # Use AdoptOpenJDK for base image.
    # It's important to use OpenJDK 8u191 or above that has container support enabled.
    # https://hub.docker.com/r/adoptopenjdk/openjdk8
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM adoptopenjdk/openjdk8:jdk8u202-b08-alpine-slim
    
    # Copy the jar to the production image from the builder stage.
    COPY --from=builder /app/target/helloworld-*.jar /helloworld.jar
    
    # Run the web service on container startup.
    CMD ["java","-Djava.security.egd=file:/dev/./urandom","-Dserver.port=${PORT}","-jar","/helloworld.jar"]
    

    C#

    # Use Microsoft's official lightweight .NET images.
    # https://hub.docker.com/r/microsoft/dotnet
    
    FROM mcr.microsoft.com/dotnet/core/sdk:2.2-alpine AS build
    WORKDIR /app
    
    # Install production dependencies.
    # Copy csproj and restore as distinct layers.
    COPY *.csproj ./
    RUN dotnet restore
    
    # Copy local code to the container image.
    COPY . ./
    
    # Build a release artifact.
    RUN dotnet publish -c Release -o out
    
    # Run the web service on container startup in a lean production image.
    FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-alpine
    WORKDIR /app
    
    COPY --from=build /app/out ./
    CMD ["dotnet", "HelloGKE.dll"]
    

    Adicione um arquivo .dockerignore para garantir que os arquivos locais não afetem o processo de criação do contêiner:

    Dockerfile
    README.md
    **/obj/
    **/bin/
    

    PHP

    # Use the official PHP 7.2 image.
    # https://hub.docker.com/_/php
    FROM php:7.2-apache
    
    # Copy local code to the container image.
    COPY index.php /var/www/html/
    
    # Use port 8080 in Apache configuration files.
    RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
    
    # Configure PHP for development.
    # Switch to the production php.ini for production operations.
    # RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
    # https://hub.docker.com/_/php#configuration
    RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
    

    Adicione um arquivo .dockerignore para garantir que os arquivos locais não afetem o processo de criação do contêiner:

    Dockerfile
    README.md
    vendor
    

    Ruby

    # Use the official lightweight Ruby image.
    # https://hub.docker.com/_/ruby
    FROM ruby:2.5-slim
    
    # Install production dependencies.
    WORKDIR /usr/src/app
    COPY Gemfile ./
    RUN bundle install
    
    # Copy local code to the container image.
    COPY . ./
    
    # Run the web service on container startup.
    CMD ["ruby", "./app.rb"]
    

  2. Consiga o ID do seu projeto do GCP:

    gcloud config get-value project
    

    Crie a imagem de contêiner usando o Cloud Build. Ele é semelhante à execução de docker build e docker push, mas é executado no Google Cloud Platform (GCP). Substitua PROJECT_ID pelo seu ID do GCP:

    gcloud builds submit --tag gcr.io/PROJECT_ID/helloworld-gke .
    

    A imagem é armazenada no Container Registry.

Como criar um cluster do Kubernetes Engine

O cluster do GKE é um conjunto gerenciado de máquinas virtuais do Compute Engine que é operado como uma única unidade. Neste tutorial, apenas um nó é usado.

  1. Crie o cluster. Substitua YOUR_GCP_ZONE pela zona do GCP em que você quer hospedar o cluster. Para uma lista completa, consulte Geografia e regiões.

    gcloud container clusters create helloworld-gke \
       --num-nodes 1 \
       --enable-basic-auth \
       --issue-client-certificate \
       --zone YOUR_GCP_ZONE
    
  2. Verifique se você tem acesso ao cluster. O comando a seguir lista os nós no cluster do contêiner que estão em execução e indica que você tem acesso a eles.

    kubectl get nodes
    

    Se ocorrer erros, consulte o Guia de solução de problemas do Kubernetes (em inglês).

Como fazer implantações no GKE

Para implantar o aplicativo no cluster do GKE que você criou, são necessários dois objetos do Kubernetes.

  1. O objeto Implantação para definir o aplicativo.
  2. O objeto Service para definir como acessar o aplicativo.

Implantar um aplicativo

O aplicativo tem um servidor de front-end que processa as solicitações da Web. Você define os recursos do cluster necessários para executar o front-end em um novo arquivo chamado deployment.yaml. Eles são conhecidos como Implantação. Use Implantações para criar e atualizar um ReplicaSet (em inglês) e os pods associados.

  1. Crie o arquivo deployment.yaml no mesmo diretório que os outros arquivos e copie o conteúdo a seguir, substituindo $GCLOUD_PROJECT pelo ID do projeto do GCP:

    # This file configures the hello-world app which serves public web traffic.
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: helloworld-gke
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: hello
      template:
        metadata:
          labels:
            app: hello
        spec:
          containers:
          - name: hello-app
            # Replace $GCLOUD_PROJECT with your project ID
            image: gcr.io/$GCLOUD_PROJECT/helloworld-gke:latest
            # This app listens on port 8080 for web traffic by default.
            ports:
            - containerPort: 8080
            env:
              - name: PORT
                value: "8080"
    
  2. Implante o recurso no cluster:

    kubectl apply -f deployment.yaml
    
  3. Acompanhe o status da implantação:

    kubectl get deployments
    

    Depois que o número de pods AVAILABLE for igual ao de DESIRED, a implantação estará concluída.

    NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    hello-deployment   1         1         1            1           20s
    

    Se ocorrer um erro na implantação, execute kubectl apply -f deployment.yaml novamente para atualizá-la com as alterações.

  4. Depois que a implantação for concluída, veja os pods criados por ela:

    kubectl get pods
    

Implantar um Service

O objeto Service fornece um único ponto de acesso a um conjunto de pods. É possível acessar um único pod, mas eles são efêmeros, e o acesso só é confiável quando feito usando um endereço de serviço. No aplicativo "Hello World", o Service "hello" define um balanceador de carga (em inglês) para acessar os pods hello-app de um único endereço IP. Esse Service é definido no arquivo service.yaml.

  1. Crie o arquivo service.yaml no mesmo diretório que os outros arquivos de origem com o conteúdo a seguir:

    # The hello service provides a load-balancing proxy over the hello-app
    # pods. By specifying the type as a 'LoadBalancer', Kubernetes Engine will
    # create an external HTTP load balancer.
    apiVersion: v1
    kind: Service
    metadata:
      name: hello
    spec:
      type: LoadBalancer
      selector:
        app: hello
      ports:
      - port: 80
        targetPort: 8080
    

    Os pods são definidos separadamente do Service que os usa. No Kubernetes, use rótulos para selecionar os pods atendidos por um Service. Com isso, você tem um Service que inclui pods de diferentes conjuntos de réplicas e vários Services que apontam para um pod específico.

  2. Crie o Service "Hello World":

    kubectl apply -f service.yaml
    
  3. Consiga o endereço IP externo do Service:

    kubectl get services
    

    Pode levar até 60 segundos para alocar o endereço IP. O endereço IP externo está listado na coluna EXTERNAL-IP do Service hello.

    NAME         TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
    hello        LoadBalancer   10.22.222.222   35.111.111.11   80:32341/TCP   1m
    kubernetes   ClusterIP      10.22.222.1     <none>          443/TCP        20m
    

Ver um aplicativo implantado

Agora você implantou todos os recursos necessários para executar o aplicativo "Hello World" no GKE. Use o endereço IP externo da etapa anterior para carregar o aplicativo no navegador da Web e executá-lo.

# Example cURL call to your running appication on GKE
$ kubectl get service hello \
    -o=custom-columns=NAME:.status.loadBalancer.ingress[*].ip --no-headers
35.111.111.11
$ curl 35.111.111.11
Hello World!

Limpar

Para evitar cobranças na sua conta do GCP pelo uso de recursos neste guia de início rápido:

Você é cobrado pelas instâncias do Compute Engine em execução no cluster, bem como pela imagem de contêiner do Container Registry.

Excluir o projeto

A exclusão do projeto do GCP interrompe o faturamento de todos os recursos usados nesse projeto.

  1. No Console do GCP, acesse a página Projetos.

    Acessar a página Projetos

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir delete.
  3. Na caixa de diálogo, digite o código do projeto e clique em Encerrar para excluí-lo.

Excluir o cluster e o contêiner

Se quiser manter o projeto, mas excluir apenas os recursos usados neste tutorial, remova o cluster e a imagem.

Para excluir um cluster usando a ferramenta de linha de comando gcloud, execute o comando a seguir:

gcloud container clusters delete helloworld-gke

Para excluir uma imagem de um dos repositórios do Container Registry, execute o comando a seguir:

gcloud container images delete gcr.io/[PROJECT-ID]/helloworld-gke

A seguir

Para mais informações sobre o Kubernetes, consulte:

Para mais informações sobre como fazer implantações no GKE, consulte:

Para mais informações sobre como fazer implantações no GKE diretamente do seu ambiente de desenvolvimento integrado com o Cloud Code, consulte:

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Kubernetes Engine