Guía de inicio rápido: Implementa una app de lenguaje específico

En esta página, se muestra cómo hacer lo siguiente:

  1. Crear una app de Hello World
  2. Empaquetar la app en una imagen de contenedor con Cloud Build
  3. Crear un clúster en Google Kubernetes Engine (GKE)
  4. Implementar la imagen de contenedor en tu clúster.

El ejemplo se muestra en varios lenguajes, pero ten en cuenta que puedes usar otros lenguajes además de los que se muestran.

Antes de comenzar

  1. Accede a tu Cuenta de Google.

    Si todavía no tienes una cuenta, regístrate para obtener una nueva.

  2. Selecciona o crea un proyecto de GCP.

    Ir a la página Administrar recursos

  3. Comprueba que la facturación esté habilitada en tu proyecto.

    Descubre cómo puedes habilitar la facturación

  4. Habilita las Cloud Build and Google Kubernetes Engine API necesarias.

    Habilita las API

  5. Realiza la instalación y la inicialización del SDK de Cloud.
  6. kubectl se usa para administrar Kubernetes, el sistema de organización de clúster que usa GKE. Puedes instalar kubectl con gcloud:
    gcloud components install kubectl

Escribe la app de muestra

Si quieres obtener instrucciones para crear una app de Hello World que se ejecute en GKE, haz clic en tu lenguaje:

Go

  1. Crea un directorio nuevo llamado helloworld-gke y usa el comando de cambio de directorio en él:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crea un módulo nuevo llamado example.com/helloworld:

    go mod init example.com/helloworld
    
  3. Crea un archivo nuevo llamado helloworld.go y pega el código siguiente en él:

    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)
    }
    

    Con este código, se crea un servidor web que recibe datos en el puerto definido por la variable de entorno PORT.

Tu app está lista para empaquetarse en un contenedor de Docker y, luego, subirse a Container Registry.

Node.js

  1. Crea un directorio nuevo llamado helloworld-gke y usa el comando de cambio de directorio en él:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crea un archivo package.json con el contenido siguiente:

    {
      "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. En el mismo directorio, crea un archivo index.js y copia las líneas siguientes en él:

    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);
    });
    

    Con este código, se crea un servidor web que recibe datos en el puerto definido por la variable de entorno PORT.

Tu app está lista para empaquetarse en un contenedor de Docker y subirse a Container Registry.

Python

  1. Crea un directorio nuevo llamado helloworld-gke y usa el comando de cambio de directorio en él:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crea un archivo llamado app.py y pega el código siguiente en él:

    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

Crea una app de Spring Boot.

  1. Instala Java SE 8 o un JDK y cURL superior. Solo se requieren Java SE y cURL para crear el proyecto web nuevo en el paso siguiente. Dockerfile, que se describe más adelante, carga todas las dependencias en el contenedor.

  2. Desde tu terminal, crea un proyecto web vacío nuevo:

    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
    

    Ahora tienes un proyecto de Spring Boot nuevo en helloworld-gke.

  3. En el archivo src/main/java/com/example/helloworld/HelloworldApplication.java, actualiza la clase HelloworldApplication mediante un @RestController para controlar la asignación /.

    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);
    	}
    }
    

    Con este código, se crea un servidor web que recibe datos en el puerto definido por la variable de entorno PORT.

Tu app está lista para empaquetarse en un contenedor de Docker y, luego, subirse a Container Registry.

C#

  1. Instala .NET Core SDK 2.2. Solo se requiere SDK de .NET Core para crear el proyecto web nuevo en el siguiente paso. Dockerfile, que se describe más adelante, carga todas las dependencias en el contenedor.

  2. Desde tu terminal, crea un proyecto web vacío nuevo:

    dotnet new web -o helloworld-gke
    
  3. Cambia el directorio a helloworld-gke.

  4. Si deseas actualizar la definición CreateWebHostBuilder en Program.cs especifica la URL del puerto para .UseUrls() a fin de definir el puerto de entrega. En el ejemplo, se muestra el puerto 8080, pero puedes usar otros puertos. Tu servidor debe detectar cualquier puerto que especifiques aquí:

    // 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;
            }
        }
    }
    

Tu app está lista para empaquetarse en un contenedor de Docker y, luego, subirse a Container Registry.

PHP

  1. Crea un directorio nuevo llamado helloworld-gke y usa el comando de cambio de directorio en él:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crea un archivo llamado index.php y pega el código siguiente en él:

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

Tu app está lista para empaquetarse en un contenedor de Docker y, luego, subirse a Container Registry.

Ruby

  1. Crea un directorio nuevo llamado helloworld-gke y usa el comando de cambio de directorio en él:

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Crea un archivo llamado app.rb y pega el código siguiente en él:

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

    Con este código, se crea un servidor web que recibe datos en el puerto definido por la variable de entorno PORT.

  3. Crea un archivo llamado Gemfile y copia la información siguiente en él:

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

Crea contenedores para la app con Cloud Build

  1. Si quieres crear contenedores para la app de muestra, crea un archivo nuevo llamado Dockerfile en el mismo directorio que los archivos de origen y copia el siguiente contenido:

    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" ]
    

    Agrega otro archivo .dockerignore para asegurarte de que los archivos locales no afecten el proceso de compilación del contenedor:

    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
    

    Agrega un archivo .dockerignore para asegurarte de que los archivos locales no afecten el proceso de compilación del contenedor:

    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"]
    

    Agrega un archivo .dockerignore para asegurarte de que los archivos locales no afecten el proceso de compilación del contenedor:

    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"
    

    Agrega un archivo .dockerignore para asegurarte de que los archivos locales no afecten el proceso de compilación del contenedor:

    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. Obtén tu ID del proyecto de GCP:

    gcloud config get-value project
    

    Compila tu imagen de contenedor con Cloud Build , que es similar a ejecutar docker build y docker push, pero se realiza en Google Cloud Platform (GCP). Reemplaza PROJECT_ID por tu ID de GCP:

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

    La imagen se almacena en Container Registry.

Crea un clúster de Kubernetes Engine

Un clúster de GKE es un conjunto administrado de máquinas virtuales de Compute Engine que operan como un solo clúster de GKE. En este instructivo, se usa un solo nodo.

  1. Crea el clúster. Reemplaza YOUR_GCP_ZONE por la zona de GCP en la que quieres alojarlo. Para obtener una lista completa, consulta Geografía y regiones.

    gcloud container clusters create helloworld-gke \
       --num-nodes 1 \
       --enable-basic-auth \
       --issue-client-certificate \
       --zone YOUR_GCP_ZONE
    
  2. Verifica si tienes acceso al clúster. Con el comando siguiente, se enumeran los nodos de tu clúster de contenedores que están en funcionamiento y que indican que tiene acceso a él.

    kubectl get nodes
    

    Si detectas errores, consulta la Guía de solución de problemas de Kubernetes

Implementación en GKE

Si quieres implementar tu app en el clúster de GKE que creaste, necesitas dos objetos de Kubernetes.

  1. Una Implementación para definir tu app.
  2. Un servicio para definir cómo acceder a tu app.

Implementa una app

La app tiene un servidor frontend que controla las solicitudes web. Define los recursos del clúster necesarios para ejecutar el frontend en un archivo nuevo llamado deployment.yaml. Estos recursos se describen como una implementación. Debes usar implementaciones para crear y actualizar un ReplicaSet y sus pods asociados.

  1. Crea el archivo deployment.yaml en el mismo directorio que tus otros archivos y copia el contenido siguiente, y reemplaza $GCLOUD_PROJECT por tu ID del proyecto de 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. Implementa el recurso en el clúster:

    kubectl apply -f deployment.yaml
    
  3. Haz un seguimiento del estado de la implementación.

    kubectl get deployments
    

    Después de que la implementación tenga la misma cantidad de pods AVAILABLE que los pods DESIRED, se completará la implementación.

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

    Si la implementación falla, vuelve a ejecutar kubectl apply -f deployment.yaml para actualizarla con los cambios.

  4. Cuando la implementación finalice, podrás ver los pods que creó.

    kubectl get pods
    

Implementa el servicio:

Los servicios proporcionan un solo punto de acceso a un conjunto de pods. Si bien es posible acceder a un solo pod, los pods son efímeros y solo se puede acceder de manera confiable mediante una dirección del servicio. En tu app de Hello World, el servicio “hello” define un balanceador de cargas para acceder a los hello-app pods desde una sola dirección IP. Este servicio se define en el archivo service.yaml.

  1. Crea el archivo service.yaml en el mismo directorio que tus otros archivos de origen con el contenido siguiente:

    # 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
    

    Los pods se definen por separado desde el servicio que usa los pods. Kubernetes usa etiquetas para seleccionar los pods a los que se dirige un servicio. Gracias a las etiquetas, puedes tener un servicio que se dirija a los pods desde conjuntos de réplicas diferentes y tener varios servicios que apunten a un pod en particular.

  2. Crea el servicio Hello World:

    kubectl apply -f service.yaml
    
  3. Obtén la dirección IP externa del servicio:

    kubectl get services
    

    Puede tardar hasta 60 segundos asignar la dirección IP. La dirección IP externa aparecerá en la columna EXTERNAL-IP para el servicio 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
    

Visualiza una app implementada

Ya implementaste todos los recursos necesarios para ejecutar la app de Hello World en GKE. Usa la dirección IP externa del paso anterior para cargar la app en tu navegador web y visualiza tu app en ejecución.

# 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!

Realiza una limpieza

Para evitar que se generen cargos en tu cuenta de GCP por los recursos que usaste en esta guía de inicio rápido, sigue estos pasos:

Se cobra por las instancias de Compute Engine que se ejecutan en tu clúster y por la imagen de contenedor en Container Registry.

Borra el proyecto

Si borras tu proyecto de GCP, se dejan de facturar todos los recursos que usaste en ese proyecto.

  1. En la GCP Console, dirígete a la página Proyectos.

    Ir a la página Proyectos

  2. En la lista de proyectos, selecciona el proyecto que deseas borrar y haz clic en Borrar.
  3. En el cuadro de diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Borra tu clúster y contenedor

Si deseas conservar tu proyecto, pero solo borrar los recursos que usaste en este instructivo, borra tu clúster y la imagen.

Para borrar un clúster con la herramienta de línea de comandos de gcloud, ejecuta el comando siguiente:

gcloud container clusters delete helloworld-gke

Si deseas borrar una imagen de uno de tus repositorios de Container Registry, ejecuta el comando siguiente:

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

Pasos siguientes

Para obtener más información sobre Kubernetes, consulta los vínculos siguientes:

Para obtener más información sobre la implementación en GKE, consulta los vínculos siguientes:

Para obtener más información sobre la implementación en GKE directo desde tu IDE con Cloud Code, consulta los vínculos siguientes:

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Documentación de Kubernetes Engine