Migrar a contenedores OCI

En esta página se describe la infraestructura de compilación necesaria para reproducir el proceso de compilación de Cloud Foundry al generar imágenes de aplicaciones compatibles con OCI. Si ya has completado la guía de migración de Spring Music, puedes usar este artículo para profundizar en configuraciones de migración específicas para tu aplicación.

Diagrama que describe cómo crear imágenes de OCI con herramientas modernas

Antes de empezar

  1. Asegúrate de haber configurado un nuevo proyecto para Cloud Run como se describe en la página Configuración de Cloud Run.
  2. Asegúrate de tener un REGISTRY_URI para almacenar contenedores. Cloud Run recomienda usar Artifact Registry. Docker se usa para crear imágenes intermedias con las que compilar el proyecto.

Configurar un proceso de compilación compatible con Cloud Foundry

Debes crear dos contenedores OCI base para admitir este nuevo proceso:

  • Una imagen de compilación que refleja el proceso de compilación de Cloud Foundry y que puede compilar el código fuente de la aplicación en droplets de Cloud Foundry.
  • Una imagen de tiempo de ejecución que refleja el tiempo de ejecución de la aplicación de Cloud Foundry.

Los administradores de la plataforma deben llevar a cabo este proceso al menos una vez. Una vez que se haya establecido el proceso, todas las aplicaciones de Cloud Foundry que necesiten migrar a Cloud Run podrán compartir las imágenes de compilación y de ejecución.

Crear la imagen de compilación

En esta sección se crea una imagen de compilación usando cflinux3 como imagen base. La imagen de compilación se usa como entorno de compilación para crear la imagen de la aplicación.

  1. Crea un directorio llamado build/ y cd en él:

    mkdir build && cd build
    
  2. En la carpeta build/, crea un archivo llamado Dockerfile y pega el siguiente código:

    ARG CF_LINUX_FS=cloudfoundry/cflinuxfs3
    
    FROM golang:1.20-bullseye AS builder_build
    WORKDIR /build
    RUN ["git", "clone", "--depth=1", "https://github.com/cloudfoundry/buildpackapplifecycle.git"]
    WORKDIR /build/buildpackapplifecycle
    RUN ["go", "mod", "init", "code.cloudfoundry.org/buildpackapplifecycle"]
    RUN ["go", "mod", "tidy"]
    RUN CGO_ENABLD=0 go build -o /builder ./builder/
    
    FROM $CF_LINUX_FS
    # Set up container tools related to building applications
    WORKDIR /lifecycle
    COPY --from=builder_build /builder /lifecycle/builder
    
    # Set up environment to match Cloud Foundry's build.
    # https://docs.cloudfoundry.org/devguide/deploy-apps/environment-variable.html#app-system-env
    WORKDIR /staging/app
    WORKDIR /tmp
    ENV CF_INSTANCE_ADDR=127.0.0.1:8080 \
    CF_INSTANCE_IP=127.0.0.1 \
    CF_INSTANCE_INTERNAL_IP=127.0.0.1 \
    VCAP_APP_HOST=127.0.0.1 \
    CF_INSTANCE_PORT=8080 \
    LANG=en_US.UTF-8 \
    INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \
    VCAP_APPLICATION={} \
    VCAP_SERVICES={} \
    CF_STACK=cflinuxfs3
    
  3. Usar Cloud Build para compilar y publicar la imagen builder

    gcloud builds \
        submit --tag "REGISTRY_URI/builder:stable"
    

    Sustituye REGISTRY_URI por la dirección de Artifact Registry en la que quieras publicar la imagen de compilación. Por ejemplo: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/builder:stable.

Crear la imagen de tiempo de ejecución

En esta sección se crea una imagen de ejecución usando cflinux3 como imagen base. La imagen de ejecución se usa como imagen base al crear la imagen de aplicación final.

  1. Crea un directorio llamado run/ y cd en él:

    mkdir run && cd run
    
  2. En la carpeta run/, crea una secuencia de comandos shell llamada entrypoint.bash con el siguiente código:

    #!/usr/bin/env bash
    set -e
    
    if [[ "$@" == "" ]]; then
    exec /lifecycle/launcher "/home/vcap/app" "" ""
    else
    exec /lifecycle/launcher "/home/vcap/app" "$@" ""
    fi
    
  3. En la carpeta run/, crea un archivo llamado Dockerfile y pega el siguiente código:

    ARG CF_LINUX_FS=cloudfoundry/cflinuxfs3
    
    FROM golang:1.20-bullseye AS launcher_build
    WORKDIR /build
    RUN ["git", "clone", "--depth=1", "https://github.com/cloudfoundry/buildpackapplifecycle.git"]
    WORKDIR /build/buildpackapplifecycle
    RUN ["go", "mod", "init", "code.cloudfoundry.org/buildpackapplifecycle"]
    RUN ["go", "mod", "tidy"]
    RUN CGO_ENABLD=0 go build -o /launcher ./launcher/
    
    FROM $CF_LINUX_FS
    # Set up container tools related to launching the application
    WORKDIR /lifecycle
    COPY entrypoint.bash /lifecycle/entrypoint.bash
    RUN ["chmod", "+rx", "/lifecycle/entrypoint.bash"]
    COPY --from=launcher_build /launcher /lifecycle/launcher
    
    # Set up environment to match Cloud Foundry
    WORKDIR /home/vcap
    USER vcap:vcap
    ENTRYPOINT ["/lifecycle/entrypoint.bash"]
    
    # Expose 8080 to allow app to be run on Cloud Foundry,
    # and PORT so the container can be run locally.
    # These do nothing on Cloud Run.
    EXPOSE 8080/tcp
    # Set up environment variables similar to Cloud Foundry.
    ENV CF_INSTANCE_ADDR=127.0.0.1:8080 \
    CF_INSTANCE_IP=127.0.0.1 \
    INSTANCE_IP=127.0.0.1 \
    CF_INSTANCE_INTERNAL_IP=127.0.0.1 \
    VCAP_APP_HOST=127.0.0.1 \
    CF_INSTANCE_PORT=80 \
    LANG=en_US.UTF-8 \
    CF_INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \
    INSTANCE_GUID=00000000-0000-0000-0000-000000000000 \
    CF_INSTANCE_INDEX=0 \
    INSTANCE_INDEX=0 \
    PORT=8080 \
    VCAP_APP_PORT=8080 \
    VCAP_APPLICATION={} \
    VCAP_SERVICES={}
    
  4. Usa Cloud Build para compilar y publicar la imagen runtime:

    gcloud builds submit \
        --tag "REGISTRY_URI/runtime:stable"
    

    Sustituye REGISTRY_URI por la dirección de Artifact Registry en la que quieras publicar la imagen de compilación. Por ejemplo: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/runtime:stable.

Crear aplicaciones de Cloud Foundry como imágenes OCI

Cada aplicación migrada a Cloud Run necesita su propio archivo Dockerfile que coincida con la forma en que Cloud Foundry ejecuta las aplicaciones. El Dockerfile hace lo siguiente:

  • Carga la imagen del creador.
  • Ejecuta el ciclo de vida del paquete de compilación de la versión 2 para crear una droplet.
  • Extrae el contenido de la droplet.
  • Carga el contenido del droplet en la imagen de ejecución para crear la imagen de aplicación ejecutable.

La imagen de la aplicación final es compatible con Cloud Foundry y Cloud Run, por lo que puedes hacer pruebas A/B de tu migración para depurar cualquier comportamiento inesperado.

El equipo de la aplicación debe llevar a cabo este proceso con cada aplicación que se quiera migrar.

Recoger información de compilación de una aplicación de Cloud Foundry desplegada

  1. Consulta la pila de aplicaciones. La pila se proporciona a través de la marca -s en cf push o del campo stack del archivo de manifiesto de la aplicación.

    1. Si la pila es Windows, es probable que la aplicación no sea compatible con Cloud Run. Debes migrar la aplicación a Linux antes de continuar.
    2. Si la pila está en blanco, cflinuxfs3 o cflinuxfs4, la aplicación se puede migrar a Cloud Run.
  2. Recopila la lista de los paquetes de compilación de la aplicación. Los buildpacks se proporcionan a través de la marca -b en cf push, el campo buildpack en el archivo de manifiesto de la aplicación o el campo buildpacks del archivo de manifiesto de la aplicación.

    1. Si no se especifica ningún paquete de compilación, significa que se detectan automáticamente. Consulta la lista de paquetes de compilación detectados en la implementación de aplicaciones más reciente en Cloud Foundry o especifícalos explícitamente si conoces las rutas.
    2. Si los buildpacks son URLs, anote las URLs y vaya al siguiente paso.
    3. En el caso de los buildpacks que usen un nombre corto, consulta la siguiente tabla para asociarlos a URLs:

      Nombre abreviado URL
      staticfile_buildpack https://github.com/cloudfoundry/staticfile-buildpack
      java_buildpack https://github.com/cloudfoundry/java-buildpack
      ruby_buildpack https://github.com/cloudfoundry/ruby-buildpack
      dotnet_core_buildpack https://github.com/cloudfoundry/dotnet-core-buildpack
      nodejs_buildpack https://github.com/cloudfoundry/nodejs-buildpack
      go_buildpack https://github.com/cloudfoundry/go-buildpack
      python_buildpack https://github.com/cloudfoundry/python-buildpack
      php_buildpack https://github.com/cloudfoundry/php-buildpack
      binary_buildpack https://github.com/cloudfoundry/binary-buildpack
      nginx_buildpack https://github.com/cloudfoundry/nginx-buildpack

      El código fuente de los buildpacks menos comunes se puede encontrar en la organización de GitHub de Cloud Foundry.

  3. Recopila la ubicación del código fuente de la imagen. La fuente se proporciona mediante el atributo path del manifiesto de la aplicación o la marca -p del comando cf push. Si la fuente no está definida, se refiere al directorio actual.

  4. Determina si hay un archivo .cfignore en el directorio del código fuente. Si está ahí, muévelo a un archivo llamado .gcloudignore..

Compilar la aplicación de Cloud Foundry

En este paso, debes organizar los elementos de compilación en la siguiente estructura de carpetas:

.
├── cloudbuild.yaml
├── Dockerfile
├── .gcloudignore
└── src
    ├── go.mod
    └── main.go
  • cloudbuild.yaml proporciona a Cloud Build instrucciones de compilación específicas
  • Dockerfile usará las imágenes de compilación y ejecución de los pasos anteriores para crear la imagen de la aplicación.
  • src/ contiene el código fuente de tu aplicación
  1. Crea un archivo llamado Dockerfile en el directorio con el siguiente contenido:

    ARG BUILD_IMAGE
    ARG RUN_IMAGE
    FROM $BUILD_IMAGE as build
    
    COPY src /staging/app
    COPY src /tmp/app
    
    ARG BUILDPACKS
    RUN /lifecycle/builder \
    -buildArtifactsCacheDir=/tmp/cache \
    -buildDir=/tmp/app \
    -buildpacksDir=/tmp/buildpacks \
    -outputBuildArtifactsCache=/tmp/output-cache \
    -outputDroplet=/tmp/droplet \
    -outputMetadata=/tmp/result.json \
    "-buildpackOrder=${BUILDPACKS}" \
    "-skipDetect=true"
    
    FROM $RUN_IMAGE
    COPY --from=build /tmp/droplet droplet
    RUN tar -xzf droplet && rm droplet
    
  2. Crea un archivo llamado cloudbuild.yaml en el directorio con el siguiente contenido:

    steps:
    - name: gcr.io/cloud-builders/docker
      args:
      - 'build'
      - '--network'
      - 'cloudbuild'
      - '--tag'
      - '${_TAG}'
      - '--build-arg'
      - 'BUILD_IMAGE=${_BUILD_IMAGE}'
      - '--build-arg'
      - 'RUN_IMAGE=${_RUN_IMAGE}'
      - '--build-arg'
      - 'BUILDPACKS=${_BUILDPACKS}'
      - '.'
    images:
    - "${_TAG}"
    options:
      # Substitute build environment variables as an array of KEY=VALUE formatted strings here.
      env: []
    substitutions:
      _BUILD_IMAGE: BUILD_IMAGE_URI
      _RUN_IMAGE:  RUN_IMAGE_URI
      _BUILDPACKS: BUILDPACK_URL
      _TAG: APP_ARTIFACT_REGISTRY/APP_NAME:latest
    
    • Sustituye BUILD_IMAGE_URI por el URI de la imagen de compilación que has creado en los pasos anteriores.
    • Sustituye RUN_IMAGE_URI por el URI de la imagen de ejecución creada en los pasos anteriores.
    • Sustituye BUILDPACK_URL por las URLs de los buildpacks que usa tu aplicación. Puede ser una lista separada por comas con varios paquetes de compilación.
  3. Si tienes un archivo .cfignore, cópialo en el directorio con el nombre .gcloudignore.

  4. Crea un directorio llamado src en el directorio.

  5. Copia el contenido de tu solicitud en src:

    1. Si la fuente es un archivo ZIP (incluidos los archivos .jar), descomprime el contenido en src.
    2. Si el código fuente es un directorio, copia el contenido en src.
  6. Ejecuta gcloud builds submit . para compilar tu aplicación.

Incompatibilidades conocidas

  • Los paquetes de compilación que dependen de variables de entorno insertadas por Cloud Foundry, como VCAP_SERVICES, no funcionarán. En su lugar, debes declarar explícitamente una dependencia de lo que inyectan mediante el sistema de gestión de tu lenguaje.
  • Para parchear las imágenes producidas de esta forma, debes volver a compilar la imagen con una versión más reciente de la compilación y ejecutar la imagen. Las imágenes de aplicaciones no se parchearán automáticamente al actualizar las stemcells de BOSH si las ejecutas en Cloud Foundry.
  • Las compilaciones se realizarán en un entorno de red diferente al de tu clúster de Cloud Foundry, por lo que es posible que tengas que configurar grupos de Cloud Build personalizados con acceso a tus réplicas internas de paquetes.

Siguientes pasos