Migrar para contêineres OCI

Nesta página, descrevemos a infraestrutura de compilação necessária para reproduzir o processo de compilação do Cloud Foundry e gerar imagens de aplicativos compatíveis com OCI. Se você já concluiu o guia de migração do Spring Music, pode usá-lo para se aprofundar nas configurações de migração específicas do seu aplicativo.

Diagrama que descreve como criar imagens OCI usando ferramentas
modernas

Antes de começar

  1. Verifique se você configurou um novo projeto para o Cloud Run conforme descrito na página de configuração do Cloud Run.
  2. Verifique se você tem um REGISTRY_URI para armazenar contêineres. O Cloud Run recomenda o uso do Artifact Registry. Ele é usado na criação de imagens intermediárias para o projeto.

Como configurar um processo de compilação compatível com o Cloud Foundry

É preciso criar dois contêineres OCI de base para aceitar esse novo processo:

  • Uma imagem do criador que espelha o processo de compilação do Cloud Foundry e é capaz de criar o código-fonte do aplicativo em gotas do Cloud Foundry.
  • Uma imagem de tempo de execução que espelha o ambiente de execução do aplicativo do Cloud Foundry.

Esse processo precisa ser feito pelo menos uma vez pelos administradores da plataforma. Depois que o processo é estabelecido, as imagens de build e execução podem ser compartilhadas por todos os aplicativos do Cloud Foundry que precisam migrar para o Cloud Run.

Criar a imagem do builder

Nesta seção, criamos uma imagem de build usando cflinux3 como a imagem de base. A imagem de build é usada como o ambiente de build para criar a imagem do aplicativo.

  1. Crie um diretório chamado build/ e cd nele:

    mkdir build && cd build
    
  2. Na pasta build/, crie um novo arquivo chamado Dockerfile e cole o seguinte 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 o Cloud Build para criar e publicar a imagem builder

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

    Substitua REGISTRY_URI pelo endereço do Artifact Registry em que você quer publicar a imagem do build. Por exemplo: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/builder:stable.

Criar a imagem do ambiente de execução

Nesta seção, criamos uma imagem de execução usando cflinux3 como a imagem de base. A imagem de execução é usada como a imagem de base quando você cria a imagem final do aplicativo.

  1. Crie um diretório chamado run/ e cd nele:

    mkdir run && cd run
    
  2. Na pasta run/, crie um novo script de shell chamado entrypoint.bash com o seguinte 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. Na pasta run/, crie um novo arquivo chamado Dockerfile e cole este 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. Use o Cloud Build para criar e publicar a imagem runtime:

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

    Substitua REGISTRY_URI pelo endereço do Artifact Registry em que você quer publicar a imagem do build. Por exemplo: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/runtime:stable.

Como criar aplicativos do Cloud Foundry como imagens OCI

Cada aplicativo migrado para o Cloud Run precisa de um Dockerfile próprio que corresponda à maneira como o Cloud Foundry executa aplicativos. O Dockerfile faz o seguinte:

  • Carrega a imagem do builder.
  • Executa o ciclo de vida do buildpack v2 para criar um droplet.
  • Extrai o conteúdo da gota.
  • Carrega o conteúdo do droplet na imagem de execução para criar a imagem do aplicativo executável.

A imagem do aplicativo final é compatível com o Cloud Foundry e o Cloud Run. Assim, é possível fazer testes A/B da migração para ajudar a depurar comportamentos inesperados.

Esse processo precisa ser feito pela equipe de aplicativos para cada aplicativo que precisa ser migrado.

Coletar informações de build de um aplicativo implantado do Cloud Foundry

  1. Observe a pilha de aplicativos. A pilha é fornecida pela sinalização -s em cf push ou no campo stack do manifesto do aplicativo.

    1. Se a pilha for do Windows, provavelmente o aplicativo será incompatível com o Cloud Run. É preciso portar o aplicativo para Linux antes de continuar.
    2. Se a pilha estiver em branco, cflinuxfs3 ou cflinuxfs4, o aplicativo poderá ser migrado para o Cloud Run.
  2. Reúna a lista dos buildpacks do aplicativo. Eles são fornecidos usando a sinalização -b em cf push, o campo buildpack no manifesto do aplicativo ou o campo buildpacks no manifesto do aplicativo.

    1. Se nenhum buildpack for especificado, isso significa que eles estão sendo detectados automaticamente. Consulte a lista de buildpack detectado na implantação mais recente de seu aplicativo no Cloud Foundry ou especifique-os explicitamente se você conhecer os caminhos.
    2. Se os pacotes de criação forem URLs, anote os URLs e prossiga para a próxima etapa.
    3. Para qualquer buildpack que use um nome curto, use a tabela a seguir para fazer o mapeamento deles para URLs:

      Apelido 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

      O código-fonte dos pacotes de criação menos comuns pode ser encontrado na organização do Cloud Foundry no GitHub (em inglês).

  3. Reunir o local do código-fonte para a imagem. A origem é fornecida pelo atributo path do manifesto do aplicativo ou pela sinalização -p do comando cf push. Se a origem for indefinida, ela se refere ao diretório atual.

  4. Determine se há um arquivo .cfignore no diretório do código-fonte. Se estiver lá, mova-o para um arquivo chamado .gcloudignore.

Criar o aplicativo do Cloud Foundry

Nesta etapa, você organiza os elementos de build na seguinte estrutura de pastas:

.
├── cloudbuild.yaml
├── Dockerfile
├── .gcloudignore
└── src
    ├── go.mod
    └── main.go
  • cloudbuild.yaml fornece instruções de build específicas ao Cloud Build
  • Dockerfile usará a versão de build e executará imagens das etapas anteriores para criar a imagem do aplicativo
  • src/ contém o código-fonte do seu aplicativo.
  1. Crie um arquivo chamado Dockerfile no diretório com o seguinte conteúdo:

    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. Crie um arquivo chamado cloudbuild.yaml no diretório com o seguinte conteúdo:

    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
    
    • Substitua BUILD_IMAGE_URI pelo URI da imagem de build criada nas etapas anteriores.
    • Substitua RUN_IMAGE_URI pelo URI da imagem de execução criada nas etapas anteriores.
    • Substitua BUILDPACK_URL pelos URLs dos pacotes de build usados pelo aplicativo. Pode ser uma lista separada por vírgulas com vários pacotes de criação.
  3. Se você tiver um arquivo .cfignore, copie-o para o diretório com o nome .gcloudignore.

  4. Crie um diretório chamado src nele.

  5. Copie o conteúdo do aplicativo para src:

    1. Se a origem for um arquivo ZIP (incluindo .jar), descompacte o conteúdo em src.
    2. Se o código-fonte for um diretório, copie o conteúdo para src.
  6. Execute gcloud builds submit . para criar seu aplicativo.

Incompatibilidades conhecidas

  • Buildpacks que dependem de variáveis de ambiente injetadas pelo Cloud Foundry, como VCAP_SERVICES, não funcionarão. Em vez disso, declare explicitamente uma dependência do que elas injetam usando o sistema de gerenciamento do seu idioma.
  • Para corrigir as imagens produzidas dessa maneira, é preciso recriá-la usando uma versão mais recente do build e executar a imagem. Se você executá-las no Cloud Foundry, as imagens de aplicativos não serão corrigidas automaticamente com a atualização das células-tronco BOSH.
  • As versões serão realizadas em um ambiente de rede diferente do cluster do Cloud Foundry. Talvez seja necessário configurar pools personalizados do Cloud Build com acesso aos espelhos do pacote interno.

Próximas etapas