Crear un despliegue optimizado para contenedores

En este ejemplo completo se describe cómo crear una implementación con una máquina virtual que usa una imagen optimizada para contenedores. Para obtener más información sobre el uso de contenedores con Compute Engine, consulta Imágenes de Compute Engine optimizadas para contenedores.

En esta guía se describe cómo hacer lo siguiente:

  1. Crea un manifiesto de contenedor sencillo.
  2. Crea una configuración y una plantilla que usen una imagen de contenedor.
  3. Despliega tus recursos y comprueba que el despliegue se ha realizado correctamente.

Crear un manifiesto de contenedor

Para usar contenedores, debes definir un manifiesto de contenedor. El manifiesto describe propiedades como la imagen del contenedor, los contenedores que se van a iniciar, los comandos que se van a ejecutar al arrancar y los puertos que se van a habilitar.

Crea un archivo llamado container_manifest.yaml con el siguiente contenido:

# Copyright 2016 Google Inc. All rights reserved.
#
# 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.

# This is a container manifest, as described here:
#   https://cloud.google.com/compute/docs/containers/container_vms
apiVersion: v1
kind: Pod
metadata:
  name: simple-echo
spec:
  containers:
    - name: simple-echo
      image: gcr.io/google-samples/hello-app:2.0
      imagePullPolicy: Always
      ports:
        - containerPort: 8080
          hostPort: 8080

Este manifiesto crea un contenedor llamado simple-echo que usa la imagen de contenedor Hello Application e inicia un servidor echo que escucha en el puerto 8080.

Crear una plantilla y una configuración

A continuación, cree una plantilla que inicie una instancia de máquina virtual con una imagen optimizada para contenedores. Crea un archivo llamado container_vm.[jinja|py] con el siguiente contenido:

Jinja



{% set COMPUTE_URL_BASE = 'https://www.googleapis.com/compute/v1/' %}
{% set BASE_NAME = env['deployment'] + '-' + env['name'] %}

{% macro GlobalComputeUrl(project, collection, name) -%}
{{ COMPUTE_URL_BASE }}projects/{{ project }}/global/{{ collection }}/{{ name }}
{%- endmacro %}

{% macro ZonalComputeUrl(project, zone, collection, name) -%}
{{ COMPUTE_URL_BASE }}projects/{{ project }}/zones/{{ zone }}/{{ collection }}/{{ name }}
{%- endmacro %}

resources:
- name: {{ BASE_NAME }}
  type: compute.v1.instance
  properties:
    zone: {{ properties['zone'] }}
    machineType: {{ ZonalComputeUrl(env['project'], properties['zone'], 'machineTypes', 'n1-standard-1') }}
    metadata:
      items:
        - key: gce-container-declaration
          value: |
            {{ imports[properties['containerManifest']]|indent(12) }}
    disks:
      - deviceName: boot
        type: PERSISTENT
        autoDelete: true
        boot: true
        initializeParams:
          diskName: {{ BASE_NAME }}-disk
          sourceImage: {{ GlobalComputeUrl('cos-cloud', 'images', properties['containerImage']) }}
    networkInterfaces:
      - accessConfigs:
          - name: external-nat
            type: ONE_TO_ONE_NAT
        network: {{ GlobalComputeUrl(env['project'],  'networks', 'default') }}
    serviceAccounts:
      - email: default
        scopes:
        - https://www.googleapis.com/auth/logging.write
        - https://www.googleapis.com/auth/monitoring.write

Python

# Copyright 2016 Google Inc. All rights reserved.
#
# 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.

"""Creates a Container VM with the provided Container manifest."""


COMPUTE_URL_BASE = 'https://www.googleapis.com/compute/v1/'


def GlobalComputeUrl(project, collection, name):
  return ''.join([COMPUTE_URL_BASE, 'projects/', project,
                  '/global/', collection, '/', name])


def ZonalComputeUrl(project, zone, collection, name):
  return ''.join([COMPUTE_URL_BASE, 'projects/', project,
                  '/zones/', zone, '/', collection, '/', name])


def GenerateConfig(context):
  """Generate configuration."""

  res = []
  base_name = (context.env['deployment'] + '-' +
               context.env['name'])

  # Properties for the container-based instance.
  instance = {
      'zone': context.properties['zone'],
      'machineType': ZonalComputeUrl(context.env['project'],
                                     context.properties['zone'],
                                     'machineTypes',
                                     'n1-standard-1'),
      'metadata': {
          'items': [{
              'key': 'gce-container-declaration',
              'value': context.imports[
                  context.properties['containerManifest']],
              }]
      },
      'disks': [{
          'deviceName': 'boot',
          'type': 'PERSISTENT',
          'autoDelete': True,
          'boot': True,
          'initializeParams': {
              'diskName': base_name + '-disk',
              'sourceImage': GlobalComputeUrl('cos-cloud',
                                              'images',
                                              context.properties[
                                                  'containerImage'])
              },
      }],
      'networkInterfaces': [{
          'accessConfigs': [{
              'name': 'external-nat',
              'type': 'ONE_TO_ONE_NAT'
              }],
          'network': GlobalComputeUrl(context.env['project'],
                                      'networks',
                                      'default')
      }],
      'serviceAccounts': [{
          'email': 'default',
          'scopes': [
            "https://www.googleapis.com/auth/logging.write",
            "https://www.googleapis.com/auth/monitoring.write"
          ]
      }]
  }
  res.append({
      'name': base_name,
      'type': 'compute.v1.instance',
      'properties': instance
  })
  # Resources to return.
  resources = {
      'resources': res,
  }

  return resources

Crea el archivo de esquema correspondiente, que aplica la estructura de la plantilla:

Jinja

# Copyright 2016 Google Inc. All rights reserved.
#
# 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.

info:
  title: Container VM
  author: Google Inc.
  description: Creates a Container VM with the provided Container manifest.

required:
  - zone
  - containerImage
  - containerManifest

properties:
  zone:
    description: Zone in which this VM will run
    type: string
  containerImage:
    description: Name of the Google Cloud Container VM Image
    type: string
  containerManifest:
    description: String containing the Container Manifest in YAML
    type: string

Python

# Copyright 2016 Google Inc. All rights reserved.
#
# 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.

info:
  title: Container VM
  author: Google Inc.
  description: Creates a Container VM with the provided Container manifest.

required:
  - zone
  - containerImage
  - containerManifest

properties:
  zone:
    description: Zone in which this VM will run
    type: string
  containerImage:
    description: Name of the Google Cloud Container VM Image
    type: string
  containerManifest:
    description: String containing the Container Manifest in YAML
    type: string

Ten en cuenta que en esta plantilla se definen varios parámetros, entre los que se incluyen los siguientes:

  • Las variables de entorno deployment, name y project. Deployment Manager rellena automáticamente esas variables sin que tengas que hacer nada más.
  • Las propiedades zone, containerImage y containerManifest, que se definirán en la configuración.

Crea un archivo de configuración llamado container_vm.yaml que tenga el siguiente aspecto:

Jinja

# Copyright 2016 Google Inc. All rights reserved.
#
# 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.

imports:
- path: ../../common/container_manifest.yaml
  name: container_manifest
- path: container_vm.jinja

resources:
  - name: my-container-vm
    type: container_vm.jinja
    properties:
      zone: ZONE_TO_RUN
      containerImage: family/cos-stable
      containerManifest: container_manifest

Python

# Copyright 2016 Google Inc. All rights reserved.
#
# 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.

imports:
- path: ../../common/container_manifest.yaml
  name: container_manifest
- path: container_vm.py

resources:
  - name: my-container-vm
    type: container_vm.py
    properties:
      zone: ZONE_TO_RUN
      containerImage: family/cos-stable
      containerManifest: container_manifest

Sustituye ZONE_TO_RUN por la zona que quieras para tu máquina virtual. Ten en cuenta que el archivo también ha definido la imagen de contenedor que se va a usar y el manifiesto de contenedor que creaste anteriormente.

Desplegar la instancia de máquina virtual

Por último, despliega tu instancia de máquina virtual con la CLI de Google Cloud:

gcloud deployment-manager deployments create my-container-deployment \
  --config container_vm.yaml

Una vez que se haya creado el despliegue, podrás ver sus detalles. Por ejemplo:

$ gcloud deployment-manager deployments describe my-container-deployment
creationTimestamp: '2015-04-02T12:24:31.645-07:00'
fingerprint: ''
id: '8602410885927938432'
manifest: https://www.googleapis.com/deploymentmanager/v2/projects/myproject/global/deployments/my-container-deployment/manifests/manifest-1428002671645
name: my-container-deployment
state: DEPLOYED
resources:
NAME                                     TYPE                 ID                   UPDATE_STATE  ERRORS
my-container-deployment-my-container-vm  compute.v1.instance  3775082612632070557  COMPLETED     -

Verificar que la instancia se está ejecutando

Para comprobar que la instancia del contenedor se ha iniciado, visita la dirección IP externa de la máquina virtual en tu navegador. Debería mostrarse lo siguiente:hello world

  1. Añade una regla de cortafuegos de Compute Engine para poder consultar el tráfico de la máquina virtual a través del puerto 8080:

    gcloud compute firewall-rules create allow-8080 --allow tcp:8080
    
  2. Obtén la dirección IP externa de tu instancia:

    $ gcloud compute instances describe my-container-deployment-my-container-vm
    ...
    name: my-container-vm-my-container-deployment
    networkInterfaces:
    - accessConfigs:
      - kind: compute#accessConfig
        name: external-nat
        natIP: 104.197.8.138
        type: ONE_TO_ONE_NAT
      name: nic0
      network: https://www.googleapis.com/compute/v1/projects/myproject/global/networks/default
      networkIP: 10.240.97.220
    scheduling:
      automaticRestart: true
      onHostMaintenance: MIGRATE
    selfLink: https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/my-container-deployment-my-container-vm
    status: RUNNING
    tags:
      fingerprint: 42WmSpB8rSM=
    zone: https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a
    ...

    En este caso, la IP externa es 104.197.8.138.

  3. En una ventana del navegador, introduce la IP externa y el puerto 8080 en la barra de direcciones. Por ejemplo, 104.197.8.138:8080.

    Si se realiza correctamente, debería ver un mensaje hello world.

(Opcional) Eliminar la implementación

Si quieres ahorrar costes y ya no quieres o necesitas tu implementación, elimínala.

gcloud deployment-manager deployments delete my-container-deployment

Siguientes pasos

Consulta más información sobre Deployment Manager en las guías de usuario completas o a través de la API.

Prueba otros tutoriales: