Esempio di migrazione da Cloud Foundry a Cloud Run: Spring Music

Questa migrazione di esempio utilizza il progetto Spring Music per mostrare come un'applicazione Cloud Foundry può essere creata come immagine dell'applicazione conforme a OCI. Questo esempio utilizza la strategia di lift and shift, che utilizza componenti open source dell'ecosistema Cloud Foundry. Dopo aver creato l'immagine dell'applicazione, devi configurare l'applicazione per il deployment in Cloud Run.

Prima di iniziare

  • Assicurati di aver configurato un nuovo progetto per Cloud Run come descritto nella pagina di configurazione.
  • Assicurati di avere un REGISTRY_URI per l'archiviazione dei contenitori. Cloud Run consiglia di utilizzare Artifact Registry.
  • Se il tuo progetto è soggetto a un criterio dell'organizzazione che limita le invocazioni non autenticate, dovrai accedere al servizio di cui è stato eseguito il deployment come descritto in Testare i servizi privati.

  • Installa Docker sulla tua workstation. Docker viene utilizzato per creare immagini intermedie per compilare il progetto.

Autorizzazioni necessarie per il deployment

Per questa guida, devi disporre delle autorizzazioni per creare, archiviare l'immagine container creata e eseguire il deployment.

Devi disporre dei seguenti ruoli:

Struttura del progetto

Per questa guida ti consigliamo di creare una directory del progetto, ad esempio cr-spring-music/ e di creare sottodirectory man mano che avanzi nella guida.

cr-spring-music/
├── build
├── run
└── spring-music

Crea l'immagine di compilazione

Questa sezione crea un'immagine di compilazione utilizzando cflinux3 come immagine di base. L'immagine di compilazione viene utilizzata come ambiente di compilazione per creare l'immagine dell'applicazione.

  1. Crea una directory denominata build/ e cd al suo interno:

    mkdir build && cd build
    
  2. Nella cartella build/, crea un nuovo file denominato Dockerfile e incolla il seguente codice:

    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. Utilizza Cloud Build per creare e pubblicare l'immagine builder

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

    Sostituisci REGISTRY_URI con l'indirizzo di Artifact Registry in cui vuoi pubblicare l'immagine di compilazione. Ad esempio: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/builder:stable.

Crea l'immagine di runtime

Questa sezione crea un'immagine di esecuzione utilizzando cflinux3 come immagine di base. L'immagine di esecuzione viene utilizzata come immagine di base per creare l'immagine dell'applicazione finale.

  1. Crea una directory denominata run/ e cd al suo interno:

    mkdir run && cd run
    
  2. Nella cartella run/, crea un nuovo script shell denominato entrypoint.bash con il seguente codice:

    #!/usr/bin/env bash
    set -e
    
    if [[ "$@" == "" ]]; then
    exec /lifecycle/launcher "/home/vcap/app" "" ""
    else
    exec /lifecycle/launcher "/home/vcap/app" "$@" ""
    fi
    
  3. Nella cartella run/, crea un nuovo file denominato Dockerfile e incolla il seguente codice:

    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. Utilizza Cloud Build per creare e pubblicare l'immagine runtime:

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

    Sostituisci REGISTRY_URI con l'indirizzo di Artifact Registry in cui vuoi pubblicare l'immagine di compilazione. Ad esempio: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/runtime:stable.

Creare Spring Music per Cloud Foundry

Per clonare il progetto Spring Music e eseguire i comandi di compilazione come se stessimo eseguendo il deployment del progetto su Cloud Foundry:

  1. Clona il repository Spring Music:

    git clone https://github.com/cloudfoundry-samples/spring-music.git
    
  2. Ai fini di questa guida, utilizzeremo una versione precedente dell'applicazione Spring Music che utilizza Java 8 e Spring Boot 2. Per farlo, passeremo a una versione precedente del progetto Spring Music:

    git checkout 610ba471a643a20dee7a62d88a7879f13a21d6a3
    
  3. Vai al repository:

    cd spring-music
    
  4. Crea il file binario di Spring Music:

    ./gradlew clean assemble
    

Ora hai una cartella build/ con l'app Spring Music compilata pronta per essere eseguita in un'istanza Cloud Foundry.

Converti Spring Music in un'applicazione compatibile con Cloud Run

Devi prendere l'output del comando di compilazione per preparare l'elemento Spring Music per il deployment in Cloud Run.

  1. Crea una directory di staging cr-app e una sottodirectory src al suo interno:

    mkdir -p cr-app/src
    
  2. Simula cf push estraendo i contenuti del file JAR compilato nella directory src:

    unzip build/libs/spring-music-1.0.jar -d cr-app/src
    
  3. Cambia la directory in cr-app/:

    cd cr-app/
    
  4. Crea un nuovo file denominato Dockerfile. Questo Dockerfile utilizzerà l'immagine di compilazione e l'immagine di runtime create nei passaggi precedenti per creare l'immagine dell'applicazione eseguibile per Spring Music, utilizzando il buildpack Java.

  5. Incolla il seguente codice in Dockerfile:

    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
    

Creare Spring Music come immagine conforme a OCI

In questo passaggio, indichi a Cloud Build come creare un'immagine conforme a OCI utilizzando l'immagine di compilazione, l'immagine di runtime e il Dockerfile dell'applicazione creati nei passaggi precedenti.

Per creare l'immagine conforme a OCI:

  1. Crea un file denominato cloudbuild.yaml. Si tratta di una configurazione di compilazione che indica a Cloud Build come compilare l'applicazione.

  2. Incolla la seguente configurazione in cloudbuild.yaml:

    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: REGISTRY_URI/builder:stable
      _RUN_IMAGE:  REGISTRY_URI/runtime:stable
      _BUILDPACKS: https://github.com/cloudfoundry/java-buildpack
      _TAG: REGISTRY_URI/spring-music:latest
    
    • Sostituisci REGISTRY_URI con l'URI del registro dei container in cui hai pubblicato il builder e il runner.
  3. Crea l'immagine dell'applicazione utilizzando Cloud Build:

    gcloud builds submit .
    

    Al termine della compilazione, prendi nota dell'URI immagine risultante. Ti servirà quando eseguirai il deployment dell'applicazione nei passaggi successivi. L'immagine risultante sarà un'immagine container conforme a OCI per l'esecuzione dell'app Spring Music, creata utilizzando componenti Cloud Foundry open source.

Esegui il deployment in Cloud Run

Devi creare un file di definizione del servizio da utilizzare in Cloud Run:

  1. Crea un account di servizio per la tua applicazione:

    gcloud iam service-accounts create spring-music
    
  2. Crea un file service.yaml con il seguente codice:

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: "spring-music"
      # Set this to be the project number of the project you're deploying to.
      namespace: "PROJECT_NUMBER"
      labels:
        cloud.googleapis.com/location: us-central1
        migrated-from: cloud-foundry
      annotations:
        run.googleapis.com/ingress: all
    spec:
      template:
        metadata:
          annotations:
            autoscaling.knative.dev/minScale: '1'
            autoscaling.knative.dev/maxScale: '1'
            run.googleapis.com/cpu-throttling: 'true'
            run.googleapis.com/startup-cpu-boost: 'true'
            run.googleapis.com/sessionAffinity: 'false'
        spec:
          containerConcurrency: 1000
          timeoutSeconds: 900
          serviceAccountName: spring-music@PROJECT_NUMBER.iam.gserviceaccount.com
          containers:
          - name: user-container
            # Set the following value to either:
            # - The image you built for your application in the last section of the guide.
            image: SPRING_IMAGE_URI
            ports:
            - name: http1
              containerPort: 8080
            env:
            - name: VCAP_APPLICATION
              value: |-
                    {
                        "application_id": "00000000-0000-0000-0000-000000000000",
                        "application_name": "spring-music",
                        "application_uris": [],
                        "limits": {
                        "disk": 0,
                        "mem": 1024
                        },
                        "name": "spring-music",
                        "process_id": "00000000-0000-0000-0000-000000000000",
                        "process_type": "web",
                        "space_name": "none",
                        "uris": []
                    }
            - name: MEMORY_LIMIT
              value: '1024M'
            resources:
              limits:
                memory: 1024Mi
                cpu: "1"
            startupProbe:
              httpGet:
                path: /
                port: 8080
              timeoutSeconds: 1
              failureThreshold: 30
              successThreshold: 1
              periodSeconds: 2
            livenessProbe:
              httpGet:
                path: /
                port: 8080
              timeoutSeconds: 1
              failureThreshold: 1
              successThreshold: 1
              periodSeconds: 30
      traffic:
      - percent: 100
        latestRevision: true
    
  3. Esegui il deployment del servizio in Cloud Run:

    gcloud run services replace service.yaml
    

    Una volta completato il deployment, potrai visitare l'applicazione SpringMusic in esecuzione all'URL di cui è stato eseguito il deployment.

Passaggi successivi