העברה לדוגמה מ-Cloud Foundry ל-Cloud Run: Spring Music

בדוגמה הזו להעברה נעשה שימוש בפרויקט Spring Music כדי להראות איך אפשר ליצור אפליקציה תואמת OCI מתוך אפליקציית Cloud Foundry. בדוגמה הזו נעשה שימוש באסטרטגיית Lift and Shift, שמתבססת על רכיבי קוד פתוח מהסביבה העסקית של Cloud Foundry. אחרי שיוצרים את קובץ האימג' של האפליקציה, צריך להגדיר את האפליקציה לפריסה ב-Cloud Run.

לפני שמתחילים

  • מוודאים שהגדרתם פרויקט חדש ל-Cloud Run כמו שמתואר בדף ההגדרה.
  • מוודאים שיש לכם REGISTRY_URI לאחסון קונטיינרים. מומלץ להשתמש ב-Artifact Registry ב-Cloud Run.
  • אם אתם כפופים למדיניות ארגונית של הגבלת דומיין שמגבילה הפעלות לא מאומתות של הפרויקט, תצטרכו לגשת לשירות הפרוס שלכם כמו שמתואר בקטע בדיקת שירותים פרטיים.

  • מתקינים את Docker בתחנת העבודה. ‫Docker משמש ליצירת קובצי אימג' ביניים כדי ליצור את הפרויקט.

ההרשאות שנדרשות לפריסה

כדי לבצע את הפעולות במדריך הזה, צריך הרשאות לבנייה, לאחסון של קובץ האימג' של הקונטיינר ולפריסה.

אתם צריכים להיות בעלי התפקידים הבאים:

מבנה הפרויקט

במדריך הזה אנחנו מציעים ליצור ספריית פרויקט, למשל cr-spring-music/ ולצור ספריות משנה תוך כדי קריאת המדריך.

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

יצירת תמונת ה-build

בקטע הזה נוצר קובץ אימג' של build באמצעות cflinux3 כקובץ האימג' הבסיסי. קובץ האימג' ל-build משמש כסביבת ה-build ליצירת קובץ האימג' של האפליקציה.

  1. יוצרים ספרייה בשם build/ ומעבירים אליה את cd:

    mkdir build && cd build
    
  2. בתיקייה build/, יוצרים קובץ חדש בשם Dockerfile ומדביקים בו את הקוד הבא:

    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. שימוש ב-Cloud Build כדי ליצור ולפרסם את קובץ האימג' builder

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

    מחליפים את REGISTRY_URI בכתובת של Artifact Registry שבה רוצים לפרסם את אימג' הבנייה. לדוגמה: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/builder:stable.

יצירת תמונה נטענת לאפקט

בקטע הזה נוצרת תמונה של ריצה באמצעות cflinux3 כתמונת הבסיס. תמונת ההרצה משמשת כתמונת הבסיס כשיוצרים את תמונת האפליקציה הסופית.

  1. יוצרים ספרייה בשם run/ ומעבירים אליה את cd:

    mkdir run && cd run
    
  2. בתיקייה run/, יוצרים סקריפט מעטפת חדש בשם entrypoint.bash עם הקוד הבא:

    #!/usr/bin/env bash
    set -e
    
    if [[ "$@" == "" ]]; then
    exec /lifecycle/launcher "/home/vcap/app" "" ""
    else
    exec /lifecycle/launcher "/home/vcap/app" "$@" ""
    fi
    
  3. בתיקייה run/, יוצרים קובץ חדש בשם Dockerfile ומדביקים בו את הקוד הבא:

    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. משתמשים ב-Cloud Build כדי ליצור ולפרסם את קובץ האימג' runtime:

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

    מחליפים את REGISTRY_URI בכתובת של Artifact Registry שבה רוצים לפרסם את אימג' ה-build. לדוגמה: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/runtime:stable.

פיתוח Spring Music ל-Cloud Foundry

כדי לשכפל את הפרויקט Spring Music ולהריץ את פקודות ה-build כאילו אנחנו פורסים את הפרויקט ב-Cloud Foundry:

  1. משכפלים את מאגר Spring Music:

    git clone https://github.com/cloudfoundry-samples/spring-music.git
    
  2. לצורך המדריך הזה, נשתמש בגרסה ישנה יותר של אפליקציית Spring Music שמשתמשת ב-Java 8 וב-Spring Boot 2. כדי לעשות את זה, נעבור לגרסה קודמת של פרויקט Spring Music:

    git checkout 610ba471a643a20dee7a62d88a7879f13a21d6a3
    
  3. עוברים למאגר:

    cd spring-music
    
  4. יוצרים את הקובץ הבינארי של Spring Music:

    ./gradlew clean assemble
    

עכשיו יש לכם תיקייה של build/ עם אפליקציית Spring Music שעברה קומפילציה ומוכנה להעברה למופע של Cloud Foundry.

המרת Spring Music לאפליקציה שתואמת ל-Cloud Run

צריך להשתמש בפלט של פקודת ה-build כדי להכין את ארטיפקט Spring Music לפריסה ב-Cloud Run.

  1. יוצרים ספריית ביניים cr-app ותיקיית משנה src בתוכה:

    mkdir -p cr-app/src
    
  2. מחקים את cf push על ידי חילוץ התוכן של קובץ ה-JAR המהודר אל הספרייה src:

    unzip build/libs/spring-music-1.0.jar -d cr-app/src
    
  3. שינוי הספרייה ל-cr-app/:

    cd cr-app/
    
  4. יוצרים קובץ חדש בשם Dockerfile. הפקודה Dockerfile תשתמש בקובץ האימג' של ה-build ובקובץ האימג' של זמן הריצה שנוצרו בשלבים הקודמים כדי ליצור את קובץ האימג' של האפליקציה שאפשר להריץ עבור Spring Music, באמצעות Java buildpack.

  5. מדביקים את הקוד הבא ב-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
    

יצירת Spring Music כתמונה שתואמת ל-OCI

בשלב הזה, נותנים ל-Cloud Build הוראות איך ליצור תמונה שתואמת ל-OCI באמצעות תמונת ה-build, תמונת זמן הריצה וקובץ ה-Dockerfile של האפליקציה שנוצרו בשלבים הקודמים.

כדי ליצור את האימג' שתואם ל-OCI:

  1. יוצרים קובץ בשם cloudbuild.yaml. זהו קובץ הגדרות של build שמכיל הוראות ל-Cloud Build לגבי אופן יצירת האפליקציה.

  2. מדביקים את ההגדרה הבאה ב-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
    
    • מחליפים את REGISTRY_URI במזהה המשאבים האחיד (URI) של מאגר הקונטיינרים שבו פרסמתם את ה-builder ואת ה-runner.
  3. יוצרים את קובץ האימג' של האפליקציה באמצעות Cloud Build:

    gcloud builds submit .
    

    בסיום ה-build, רושמים את ה-URI של קובץ האימג' שנוצר. תצטרכו אותו כשפורסים את האפליקציה בשלבים הבאים. קובץ האימג' שיתקבל יהיה קובץ אימג' של קונטיינר שתואם ל-OCI להרצת אפליקציית Spring Music, שנוצר באמצעות רכיבי Cloud Foundry בקוד פתוח.

פריסה ב-Cloud Run

כדי להשתמש ב-Cloud Run, צריך ליצור קובץ הגדרת שירות:

  1. יוצרים חשבון שירות לאפליקציה:

    gcloud iam service-accounts create spring-music
    
  2. יוצרים קובץ service.yaml עם הקוד הבא:

    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. פורסים את השירות ב-Cloud Run:

    gcloud run services replace service.yaml
    

    אחרי שהפריסה תסתיים, תוכלו להיכנס לאפליקציית Spring Music הפועלת בכתובת ה-URL שנפרסה.

המאמרים הבאים