Usar resúmenes de imágenes de contenedor en manifiestos de Kubernetes

Last reviewed 2023-07-21 UTC

En este tutorial se muestra a los desarrolladores y operadores que despliegan contenedores en Kubernetes cómo usar resúmenes de imágenes de contenedor para identificar imágenes de contenedor. Una síntesis de imagen de contenedor identifica de forma única e inmutable una imagen de contenedor.

Desplegar imágenes de contenedor mediante el digest de la imagen ofrece varias ventajas en comparación con el uso de etiquetas de imagen. Para obtener más información sobre los resúmenes de imágenes, consulta el documento complementario sobre cómo usar resúmenes de imágenes de contenedor antes de continuar con este tutorial.

El argumento image de los contenedores de una especificación de pod de Kubernetes acepta imágenes con resúmenes. Este argumento se aplica en cualquier lugar en el que uses una especificación de pod, como en la sección template de los recursos Deployment, StatefulSet, DaemonSet, ReplicaSet, CronJob y Job.

Para desplegar una imagen mediante el digest, usa el nombre de la imagen seguido de @sha256: y el valor del digest. A continuación, se muestra un ejemplo de un recurso Deployment que usa una imagen con un digest. Un Deployment es un objeto de la API de Kubernetes que te permite ejecutar varias réplicas de pods distribuidas entre los nodos de un clúster.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deployment
spec:
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echoserver
        image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
        ports:
        - containerPort: 8080

Una de las desventajas de usar resúmenes de imágenes es que no se conoce el valor del resumen hasta que se publica la imagen en un registro. A medida que creas nuevas imágenes, el valor del digest cambia y necesitas una forma de actualizar tus manifiestos de Kubernetes cada vez que implementas.

En este tutorial se muestra cómo puedes usar herramientas como Skaffold, kpt, digester, kustomize, gke-deploy, y ko para usar resúmenes de imágenes en tus manifiestos.

Recomendaciones

En este documento se presentan varias formas de usar resúmenes de imágenes en implementaciones de Kubernetes. Las herramientas que se describen en este documento son complementarias. Por ejemplo, puedes usar la salida de una función de kpt con kustomize para crear variantes de diferentes entornos. Skaffold puede compilar imágenes con ko y desplegar las imágenes en tus clústeres de Kubernetes con kubectl o kpt.

Las herramientas se complementan porque realizan ediciones estructuradas basadas en el modelo de recursos de Kubernetes (KRM). Este modelo permite conectar las herramientas y puedes desarrollar el uso que haces de ellas para crear procesos y flujos de trabajo que te ayuden a desplegar tus aplicaciones y servicios.

Para empezar, te recomendamos que elijas el enfoque que mejor se adapte a tus herramientas y procesos:

  • Skaffold puede añadir resúmenes a las referencias de imágenes. Puedes habilitar esta función con un pequeño cambio en la configuración. Adoptar Skaffold ofrece ventajas adicionales, como la abstracción de la forma en que las diferentes herramientas compilan e implementan imágenes de contenedor.

  • Si usas la herramienta de resumen como webhook de admisión mutante en tus clústeres de Kubernetes, puedes añadir resúmenes a todas tus implementaciones con un impacto mínimo en tus procesos actuales de compilación e implementación de imágenes de contenedor. El webhook de digest también simplifica la adopción de Autorización binaria, ya que solo requiere que se añada una etiqueta a un espacio de nombres.

  • kpt es una opción excelente si necesitas una herramienta flexible para manipular manifiestos de Kubernetes. La herramienta de resumen se puede usar como una función KRM del lado del cliente en una pipeline de kpt.

  • Si ya usas kustomize para gestionar los manifiestos de Kubernetes en diferentes entornos, te recomendamos que aproveches sus transformadores de imágenes para desplegar imágenes por digest.

  • ko es una forma estupenda de crear y publicar imágenes para aplicaciones Go, y la usan proyectos de software libre como Knative, Tekton y sigstore.

Si no usas ninguna de las herramientas descritas en este documento, te recomendamos que empieces con Skaffold y el webhook de digester. Skaffold es una herramienta habitual que usan tanto los desarrolladores como los equipos de lanzamiento, y se integra con las otras herramientas descritas en este tutorial. Puedes aprovechar estas opciones de integración a medida que evolucionen tus requisitos. El webhook de Kubernetes de digester complementa Skaffold al permitir despliegues basados en resúmenes para todo un clúster.

Objetivos

  • Usa Skaffold para compilar y enviar una imagen, así como para insertar el nombre y el digest de la imagen en un manifiesto de Kubernetes.
  • Usa la función del lado del cliente del digester y el webhook de admisión mutante para añadir resúmenes a las imágenes de los pods y las plantillas de pods de Kubernetes.
  • Usa setters de kpt para sustituir una etiqueta de imagen en un manifiesto de Kubernetes por un digest de imagen.
  • Usa kustomize para generar un manifiesto de Kubernetes con un digest de imagen.
  • Usa gke-deploy para resolver una etiqueta de imagen en un digest en un manifiesto de Kubernetes.
  • Usa ko para compilar y enviar una imagen, así como para insertar el nombre y el digest de la imagen en un manifiesto de Kubernetes.

Costes

En este documento, se utilizan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costes basada en el uso previsto, utiliza la calculadora de precios.

Los usuarios nuevos Google Cloud pueden disfrutar de una prueba gratuita.

Cuando termines las tareas que se describen en este documento, puedes evitar que se te siga facturando eliminando los recursos que has creado. Para obtener más información, consulta la sección Limpiar.

Antes de empezar

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. Enable the Artifact Registry API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  4. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  5. En Cloud Shell, define el proyecto predeterminado de Google Cloud CLI:

    gcloud config set project PROJECT_ID
    

    Sustituye PROJECT_ID por tu [ID de proyecto].

  6. Crea un repositorio de imágenes de contenedor en Artifact Registry:

    gcloud artifacts repositories create REPOSITORY \
        --location=LOCATION \
        --repository-format=docker
    

    Haz los cambios siguientes:

    • REPOSITORY: el nombre que quieras usar para tu repositorio, por ejemplo, digest-tutorial.
    • LOCATION: una ubicación de Artifact Registry, por ejemplo, us-central1.
  7. Configura la autenticación en la ubicación de Artifact Registry para las herramientas de la CLI que se usan en este tutorial:

    gcloud auth configure-docker LOCATION-docker.pkg.dev
    

    Usar Skaffold

    Skaffold es una herramienta de línea de comandos para el desarrollo y el despliegue continuos de aplicaciones en clústeres de Kubernetes.

    Usa Skaffold para compilar una imagen, transferirla a Artifact Registry y sustituir el valor de marcador de posición image en una plantilla de manifiesto de Kubernetes por el nombre, la etiqueta y el digest de la imagen transferida:

    1. En Cloud Shell, crea un directorio y ve a él para almacenar los archivos que crees en esta sección:

      mkdir -p ~/container-image-digests-tutorial/skaffold
      cd ~/container-image-digests-tutorial/skaffold
      
    2. Clona el repositorio de Git de Skaffold:

      git clone https://github.com/GoogleContainerTools/skaffold.git
      
    3. Ve al directorio del ejemplo getting-started:

      cd skaffold/examples/getting-started
      
    4. Consulta la etiqueta de Git que coincida con tu versión de Skaffold:

      git checkout $(skaffold version)
      
    5. Consulta el archivo de configuración skaffold.yaml:

      cat skaffold.yaml
      

      El archivo tiene un aspecto similar al siguiente:

      apiVersion: skaffold/v4beta6
      kind: Config
      build:
        artifacts:
        - image: skaffold-example
      manifests:
        rawYaml:
        - k8s-pod.yaml

      La sección build.artifacts contiene el nombre de una imagen de marcador de posición. Skaffold busca este marcador de posición en los archivos de manifiesto de entrada.

      La sección manifests indica a Skaffold que lea un manifiesto de entrada del directorio actual con el nombre k8s-pod.yaml.

      Para ver un resumen de todas las opciones disponibles, consulta la documentación de referencia de skaffold.yaml.

    6. Consulta la plantilla del archivo de manifiesto de Kubernetes:

      cat k8s-pod.yaml
      

      El archivo es el siguiente:

      apiVersion: v1
      kind: Pod
      metadata:
        name: getting-started
      spec:
        containers:
        - name: getting-started
          image: skaffold-example

      El valor del marcador de posición skaffold-example del campo image coincide con el valor del campo image del archivo skaffold.yaml. Skaffold sustituye este valor de marcador de posición por el nombre completo de la imagen y el digest en la salida renderizada.

    7. Crea la imagen y envíala a Artifact Registry:

      skaffold build \
          --default-repo=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY \
          --file-output=artifacts.json \
          --interactive=false \
          --push=true \
          --update-check=false
      

      Este comando usa las siguientes marcas:

      • La marca --file-output especifica el archivo en el que Skaffold guarda información sobre la imagen compilada, incluido el valor del digest.
      • La marca --push indica a Skaffold que envíe la imagen compilada al registro de imágenes de contenedor especificado por la marca --default-repo.
      • Las marcas --interactive y --update-check tienen el valor false. Define estas marcas como false en entornos no interactivos, como las pipelines de compilación, pero déjalas con sus valores predeterminados (true para ambas marcas) en el desarrollo local.

      Si usas Cloud Deploy para desplegar en GKE, usa el archivo de la marca --file-output como valor de la marca --build-artifacts cuando crees una versión.

    8. Renderiza el manifiesto de Kubernetes ampliado con el nombre, la etiqueta y el digest de la imagen de contenedor del paso anterior:

      skaffold render \
          --build-artifacts=artifacts.json \
          --digest-source=none \
          --interactive=false \
          --offline=true \
          --output=rendered.yaml \
          --update-check=false
      

      Este comando usa las siguientes marcas:

      • La marca --build-artifacts hace referencia al archivo de salida del comando skaffold build del paso anterior.
      • La marca --digest-source=none significa que Skaffold usa el valor del digest del archivo proporcionado en la marca --build-artifacts, en lugar de resolver el digest del registro de imágenes de contenedor.
      • La marca --offline=true significa que puedes ejecutar el comando sin necesidad de acceder a un clúster de Kubernetes.
      • La marca --output especifica el archivo de salida del manifiesto renderizado.
    9. Para ver el archivo de manifiesto renderizado, sigue estos pasos:

      cat rendered.yaml
      

      La salida es similar a la siguiente:

      apiVersion: v1
      kind: Pod
      metadata:
        name: getting-started
      spec:
        containers:
        - image: LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/skaffold-example:TAG@sha256:DIGEST
          name: getting-started

      En este resultado, verá los siguientes valores:

      • TAG: la etiqueta que Skaffold ha asignado a la imagen.
      • DIGEST: el valor del digest de la imagen

    Usar el digeridor

    Digester añade resúmenes a las imágenes de contenedores y de contenedores init en las especificaciones de Pod y PodTemplate de Kubernetes. El digestor sustituye las referencias de imágenes de contenedor que usan etiquetas:

    spec:
      containers:
      - image: gcr.io/google-containers/echoserver:1.10
    

    Con referencias que usan el digest de la imagen:

    spec:
      containers:
      - image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
    

    Digester se puede ejecutar como un webhook de admisión mutante en un clúster de Kubernetes o como una función KRM del lado del cliente con las herramientas de línea de comandos kpt o kustomize.

    Usar la función KRM de digester

    1. En Cloud Shell, crea un directorio y ve a él para almacenar los archivos que crees en esta sección:

      mkdir -p ~/container-image-digests-tutorial/digester-fn
      cd ~/container-image-digests-tutorial/digester-fn
      
    2. Descarga el archivo binario del digester:

      mkdir -p ${HOME}/bin
      export PATH=${HOME}/bin:${PATH}
      DIGESTER_VERSION=$(curl -sL https://api.github.com/repos/google/k8s-digester/releases/latest | jq -r .tag_name)
      curl -L "https://github.com/google/k8s-digester/releases/download/${DIGESTER_VERSION}/digester_$(uname -s)_$(uname -m)" --output ${HOME}/bin/digester
      chmod +x ${HOME}/bin/digester
      
    3. Crea un manifiesto de Pod de Kubernetes que haga referencia a la imagen gcr.io/google-containers/echoserver mediante la etiqueta 1.10:

      cat << EOF > pod.yaml
      apiVersion: v1
      kind: Pod
      metadata:
        name: echo
      spec:
        containers:
        - name: echoserver
          image: gcr.io/google-containers/echoserver:1.10
          ports:
          - containerPort: 8080
      EOF
      
    4. Ejecuta la función KRM de digester con kpt y los manifiestos del directorio actual (.):

      kpt fn eval . --exec digester
      

      Cuando ejecutas este comando, kpt realiza una actualización in situ de los manifiestos del directorio actual. Si quieres que kpt muestre el manifiesto actualizado en la consola y deje el archivo de manifiesto sin cambios, añade la marca --output unwrap.

    5. Consulta el archivo de manifiesto actualizado:

      cat pod.yaml
      

      El archivo es el siguiente:

      apiVersion: v1
      kind: Pod
      metadata:
        name: echo
      spec:
        containers:
          - name: echoserver
            image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
            ports:
              - containerPort: 8080

    Usar el webhook de admisión de digester

    1. En Cloud Shell, crea un directorio y ve a él para almacenar los archivos que crees en esta sección:

      mkdir -p ~/container-image-digests-tutorial/digester-webhook
      cd ~/container-image-digests-tutorial/digester-webhook
      
    2. Crea un clúster local de Kubernetes con kind:

      kind create cluster
      

      kind es una herramienta de línea de comandos para ejecutar clústeres de Kubernetes locales con Docker.

    3. Despliega el webhook del digester:

      DIGESTER_VERSION=$(curl -sL https://api.github.com/repos/google/k8s-digester/releases/latest | jq -r .tag_name)
      kustomize build "https://github.com/google/k8s-digester.git/manifests?ref=${DIGESTER_VERSION}" | kubectl apply -f -
      
    4. Crea un espacio de nombres de Kubernetes llamado digester-demo en el clúster de tipo:

      kubectl create namespace digester-demo
      
    5. Añade la etiqueta digest-resolution: enabled al espacio de nombres digester-demo:

      kubectl label namespace digester-demo digest-resolution=enabled
      

      El webhook del generador de resúmenes añade resúmenes a los pods de los espacios de nombres con esta etiqueta.

    6. Crea un manifiesto de Deployment de Kubernetes que haga referencia a la imagen gcr.io/google-containers/echoserver con la etiqueta 1.10:

      cat << EOF > deployment.yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echo-deployment
      spec:
        selector:
          matchLabels:
            app: echo
        template:
          metadata:
            labels:
              app: echo
          spec:
            containers:
            - name: echoserver
              image: gcr.io/google-containers/echoserver:1.10
              ports:
              - containerPort: 8080
      EOF
      
    7. Aplica el manifiesto en el espacio de nombres digester-demo:

      kubectl apply --filename deployment.yaml --namespace digester-demo \
          --output jsonpath='{.spec.template.spec.containers[].image}{"\n"}'
      

      La marca --output indica a kubectl que muestre el nombre de la imagen en la consola, seguido de un carácter de salto de línea. El resultado es el siguiente:

      gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229

      En este resultado se muestra que el webhook del digestor ha añadido el digest de la imagen a la especificación de la plantilla de Pod en el recurso Deployment.

    8. Elimina el clúster de Kind para liberar recursos en tu sesión de Cloud Shell:

      kind delete cluster
      

    Usar setters de kpt

    kpt es una herramienta de línea de comandos para gestionar, manipular, personalizar y aplicar manifiestos de recursos de Kubernetes.

    Puedes usar las funciones create-setters y apply-setters de KRM del catálogo de funciones de kpt para actualizar los resúmenes de imágenes en tus manifiestos de Kubernetes cuando compiles imágenes nuevas.

    1. En Cloud Shell, crea un directorio y ve a él para almacenar los archivos que crees en esta sección:

      mkdir -p ~/container-image-digests-tutorial/kpt
      cd ~/container-image-digests-tutorial/kpt
      
    2. Crea un paquete kpt en el directorio actual:

      kpt pkg init --description "Container image digest tutorial"
      
    3. Crea un manifiesto de Pod de Kubernetes que haga referencia a la imagen gcr.io/google-containers/echoserver mediante la etiqueta 1.10:

      cat << EOF > pod.yaml
      apiVersion: v1
      kind: Pod
      metadata:
        name: echo
      spec:
        containers:
        - name: echoserver
          image: gcr.io/google-containers/echoserver:1.10
          ports:
          - containerPort: 8080
      EOF
      
    4. Usa kpt para crear un setter llamado echoimage para el campo de manifiesto, donde el valor es gcr.io/google-containers/echoserver:1.10:

      kpt fn eval . \
          --image gcr.io/kpt-fn/create-setters@sha256:0220cc87f29ff9abfa3a3b5643aa50f18d355d5e9dc9e1f518119633ddc4895c \
          -- "echoimage=gcr.io/google-containers/echoserver:1.10"
      
    5. Para ver el archivo de manifiesto, haz lo siguiente:

      cat pod.yaml
      

      El archivo es el siguiente:

      apiVersion: v1
      kind: Pod
      metadata:
        name: echo
      spec:
        containers:
        - name: echoserver
          image: gcr.io/google-containers/echoserver:1.10 # kpt-set: ${echoimage}
          ports:
          - containerPort: 8080
    6. Obtén el valor de resumen de la imagen de contenedor:

      DIGEST=$(gcloud container images describe \
          gcr.io/google-containers/echoserver:1.10 \
          --format='value(image_summary.digest)')
      
    7. Defina el nuevo valor del campo:

      kpt fn eval . \
          --image gcr.io/kpt-fn/apply-setters@sha256:4d4295727183396f0c3c6a75d2560254c2f9041a39e95dc1e5beffeb49cc1a12 \
          -- "echoimage=gcr.io/google-containers/echoserver:1.10@$DIGEST"
      

      Cuando ejecutas este comando, kpt sustituye el valor del campo image en el manifiesto.

    8. Consulta el archivo de manifiesto actualizado:

      cat pod.yaml
      

      El archivo es el siguiente:

      apiVersion: v1
      kind: Pod
      metadata:
        name: echo
      spec:
        containers:
        - name: echoserver
          image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 # kpt-set: ${echoimage}
          ports:
          - containerPort: 8080

    Usar transformadores de imágenes de Kustomize

    kustomize es una herramienta de línea de comandos que te permite personalizar manifiestos de Kubernetes mediante superposiciones, parches y transformadores.

    Puedes usar el transformador de imágenes de kustomize para actualizar el nombre, la etiqueta y el digest de la imagen en tu manifiesto.

    En el siguiente fragmento de kustomization.yaml se muestra cómo configurar el transformador de imágenes para que use el valor digest del transformador en las imágenes en las que el valor image de la especificación del pod coincida con el valor name del transformador:

    images:
    - name: gcr.io/google-containers/echoserver
      digest: sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229

    Para usar un transformador de imágenes de Kustomize con un digest de imagen, haz lo siguiente:

    1. En Cloud Shell, crea un directorio y ve a él para almacenar los archivos que crees en esta sección:

      mkdir -p ~/container-image-digests-tutorial/kustomize
      cd ~/container-image-digests-tutorial/kustomize
      
    2. Crea un archivo kustomization.yaml:

      kustomize init
      
    3. Crea un manifiesto de Kubernetes con una especificación de Pod que haga referencia a la imagen gcr.io/google-containers/echoserver con la etiqueta 1.10:

      cat << EOF > pod.yaml
      apiVersion: v1
      kind: Pod
      metadata:
        name: echo
      spec:
        containers:
        - name: echoserver
          image: gcr.io/google-containers/echoserver:1.10
          ports:
          - containerPort: 8080
      EOF
      
    4. Añade el manifiesto como recurso en el archivo kustomization.yaml:

      kustomize edit add resource pod.yaml
      
    5. Usa un transformador de imágenes para actualizar el resumen de la imagen:

      kustomize edit set image \
          gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
      
    6. Consulta el transformador de imágenes en el archivo kustomization.yaml:

      cat kustomization.yaml
      

      El archivo es el siguiente:

      apiVersion: kustomize.config.k8s.io/v1beta1
      kind: Kustomization
      resources:
      - pod.yaml
      images:
      - digest: sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
        name: gcr.io/google-containers/echoserver
    7. Para ver el archivo de manifiesto resultante, sigue estos pasos:

      kustomize build .
      

      El resultado es el siguiente:

      apiVersion: v1
      kind: Pod
      metadata:
        name: echo
      spec:
        containers:
        - image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
          name: echoserver
          ports:
          - containerPort: 8080
    8. Para ejecutar el transformador de kustomize y aplicar el manifiesto resultante a un clúster de Kubernetes en un solo paso, puedes usar el comando kubectl apply con la marca --kustomize:

      kubectl apply --kustomize .
      

      Si quieres aplicar el resultado más adelante, puedes redirigir el resultado del comando kustomize build a un archivo.

    Estás usando gke-deploy

    gke-deploy es una herramienta de línea de comandos que se usa con Google Kubernetes Engine (GKE). gke-deploy envuelve la herramienta de línea de comandos kubectl y puede modificar los recursos que crees siguiendo las prácticas recomendadas de Google.

    Si usas los subcomandos gke-deployprepare o run, gke-deploy resuelve tus etiquetas de imagen en resúmenes y guarda los manifiestos expandidos con los resúmenes de imagen en el archivo output/expanded/aggregated-resources.yaml de forma predeterminada.

    Puedes usar gke-deploy run para sustituir la etiqueta de imagen por un digest y aplicar el manifiesto ampliado a tu clúster de GKE. Aunque este comando es práctico, tiene un inconveniente: la etiqueta de imagen se sustituye en el momento de la implementación. Es posible que la imagen asociada a la etiqueta haya cambiado entre el momento en que decidiste implementar y el momento en que lo hiciste, lo que ha provocado que se implementara una imagen inesperada. En el caso de las implementaciones de producción, te recomendamos que sigas pasos independientes para generar y aplicar manifiestos.

    Para sustituir una etiqueta de imagen en un manifiesto de implementación de Kubernetes por el digest de la imagen, haz lo siguiente:

    1. En Cloud Shell, crea un directorio y ve a él para almacenar los archivos que crees en esta sección:

      mkdir -p ~/container-image-digests-tutorial/gke-deploy
      cd ~/container-image-digests-tutorial/gke-deploy
      
    2. Instalar gke-deploy:

      go install github.com/GoogleCloudPlatform/cloud-builders/gke-deploy@latest
      
    3. Crea un manifiesto de Deployment de Kubernetes que haga referencia a la imagen gcr.io/google-containers/echoserver con la etiqueta 1.10:

      cat << EOF > deployment.yaml
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: echo-deployment
      spec:
        selector:
          matchLabels:
            app: echo
        template:
          metadata:
            labels:
              app: echo
          spec:
            containers:
            - name: echoserver
              image: gcr.io/google-containers/echoserver:1.10
              ports:
              - containerPort: 8080
      EOF
      
    4. Genera un archivo de manifiesto ampliado basado en el archivo de manifiesto deployment.yaml:

      gke-deploy prepare \
          --filename deployment.yaml \
          --image gcr.io/google-containers/echoserver:1.10 \
          --version 1.10
      
    5. Para ver el manifiesto ampliado, haz lo siguiente:

      cat output/expanded/aggregated-resources.yaml
      

      El resultado es el siguiente:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        labels:
          app.kubernetes.io/managed-by: gcp-cloud-build-deploy
          app.kubernetes.io/version: "1.10"
        name: echo-deployment
        namespace: default
      spec:
        selector:
          matchLabels:
            app: echo
        template:
          metadata:
            labels:
              app: echo
              app.kubernetes.io/managed-by: gcp-cloud-build-deploy
              app.kubernetes.io/version: "1.10"
          spec:
            containers:
            - image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
              name: echoserver
              ports:
              - containerPort: 8080

      En el manifiesto ampliado, la etiqueta de imagen se sustituye por el digest.

      El argumento --version que has usado con el comando gke-deploy define el valor de la etiqueta app.kubernetes.io/version en el manifiesto desplegado y en los metadatos de la plantilla de pod.

      Para saber cómo usar gke-deploy con Cloud Build, consulta la documentación de Cloud Build para gke-deploy.

    Estás usando ko

    ko es una herramienta de línea de comandos y una biblioteca para crear Go imágenes de contenedor y desplegarlas en clústeres de Kubernetes. ko compila imágenes sin usar el daemon de Docker, por lo que puedes usarlo en entornos en los que no puedes instalar Docker.

    El subcomando ko build compila imágenes y las publica en un registro de imágenes de contenedor o las carga en tu daemon de Docker local.

    El subcomando ko resolve hace lo siguiente:

    • Identifica las imágenes que se van a compilar buscando marcadores de posición en los campos image de los manifiestos de Kubernetes que proporciones mediante el argumento --filename.
    • Crea y publica tus imágenes.
    • Sustituye los marcadores de posición de valor image por los nombres y resúmenes de las imágenes que ha creado.
    • Imprime los manifiestos ampliados.

    Los subcomandos ko apply, create y run realizan los mismos pasos que resolve y, a continuación, ejecutan kubectl apply, create o run con los manifiestos ampliados.

    Para crear una imagen a partir de código fuente de Go y añadir el digest de la imagen a un manifiesto de implementación de Kubernetes, haz lo siguiente:

    1. En Cloud Shell, crea un directorio y ve a él para almacenar los archivos que crees en esta sección:

      mkdir -p ~/container-image-digests-tutorial/ko
      cd ~/container-image-digests-tutorial/ko
      
    2. Descarga ko y añádelo a PATH de la siguiente forma:

      mkdir -p ${HOME}/bin
      export PATH=${HOME}/bin:${PATH}
      KO_VERSION=$(curl -sL https://api.github.com/repos/ko-build/ko/releases/latest | jq -r .tag_name | cut -c2-)
      curl -L "https://github.com/ko-build/ko/releases/download/v${KO_VERSION}/ko_${KO_VERSION}_$(uname -s)_$(uname -m).tar.gz" | tar -zxC ${HOME}/bin ko
      
    3. Crea una aplicación de Go con el nombre de módulo example.com/hello-world en un directorio nuevo llamado app:

      mkdir -p app/cmd/ko-example
      
      cd app
      
      go mod init example.com/hello-world
      
      cat << EOF > cmd/ko-example/main.go
      package main
      
      import "fmt"
      
      func main() {
          fmt.Println("hello world")
      }
      EOF
      
    4. Define el repositorio de imágenes que usa ko para publicar imágenes:

      export KO_DOCKER_REPO=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY
      

      En este ejemplo se usa Artifact Registry, pero puedes usar ko con otro registro de imágenes de contenedor.

    5. Para compilar y publicar una imagen de tu aplicación, sigue uno de estos pasos:

      • Crea y publica una imagen de tu aplicación proporcionando la ruta de acceso a tu paquete principal de Go:

        ko build --base-import-paths ./cmd/ko-example
        

        El argumento opcional --base-import-paths significa que ko usa el nombre corto del directorio del paquete principal como nombre de la imagen.

        ko imprime el nombre y el digest de la imagen en stdout con el siguiente formato:

        LOCATION-docker.pkg.dev/PROJECT_ID/ko-example@sha256:DIGEST

        En este resultado, DIGEST es el valor del resumen de la imagen.

      • Usa ko para sustituir un marcador de posición de manifiesto por el nombre y el resumen de la imagen que crea y publica:

        1. Crea un manifiesto de Pod de Kubernetes. El manifiesto usa el marcador de posición ko://IMPORT_PATH_OF_YOUR_MAIN_PACKAGE como valor del campo image:

          cat << EOF > ko-pod.yaml
          apiVersion: v1
          kind: Pod
          metadata:
            name: ko-example
          spec:
            containers:
            - name: hello-world
              image: ko://example.com/hello-world/cmd/ko-example
          EOF
          
        2. Compila y publica una imagen de tu aplicación, y sustituye el marcador de posición del manifiesto por el nombre y el digest de la imagen:

          ko resolve --base-import-paths --filename ko-pod.yaml
          

          ko imprime el manifiesto con el nombre y el digest de la imagen en stdout:

          apiVersion: v1
          kind: Pod
          metadata:
            name: ko-example
          spec:
            containers:
            - name: hello-world
              image: LOCATION-docker.pkg.dev/PROJECT_ID/ko-example@sha256:DIGEST

          En este resultado, DIGEST es el valor del resumen de la imagen.

    Limpieza

    La forma más fácil de evitar que te cobren es eliminar el Google Cloud proyecto que has creado para el tutorial. También puedes eliminar los recursos de forma individual.

    Eliminar el proyecto

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    Eliminar los recursos

    Si quieres conservar el Google Cloud proyecto que has usado en este tutorial, elimina los recursos:

    1. En Cloud Shell, elimina los archivos que has creado en este tutorial:

      cd
      rm -rf ~/container-image-digests-tutorial
      
    2. Elimina el repositorio de imágenes de contenedor en Artifact Registry:

      gcloud artifacts repositories delete REPOSITORY \
          --location=LOCATION --async --quiet
      

    Siguientes pasos