Cloud Foundry에서 Cloud Run으로 샘플 마이그레이션: Spring Music

이 샘플 마이그레이션에서는 Spring Music 프로젝트를 사용하여 Cloud Foundry 애플리케이션을 OCI 호환 애플리케이션 이미지로 빌드하는 방법을 보여줍니다. 이 샘플은 Cloud Foundry 생태계의 오픈소스 구성요소를 사용하는 리프트 앤 시프트 전략을 사용합니다. 애플리케이션 이미지를 만든 후 Cloud Run에 배포할 애플리케이션을 구성해야 합니다.

시작하기 전에

  • 설정 페이지에 설명된 대로 Cloud Run용 새 프로젝트를 설정했는지 확인합니다.
  • 컨테이너를 저장하기 위한 REGISTRY_URI가 있는지 확인합니다. Cloud Run에서는 Artifact Registry를 사용하는 것이 좋습니다.
  • 프로젝트에서 인증되지 않은 호출을 제한하는 도메인 제한 조직 정책이 적용되는 경우 비공개 서비스 테스트의 설명대로 배포된 서비스에 액세스해야 합니다.

  • 워크스테이션에 Docker를 설치합니다. Docker는 프로젝트를 빌드하기 위한 중간 이미지를 만드는 데 사용됩니다.

배포 시 필요한 권한

이 가이드에서는 빌드, 빌드된 컨테이너 이미지를 저장하고 배포하기 위한 권한이 필요합니다.

다음 역할이 있어야 합니다.

프로젝트 구조

이 가이드에서는 가이드를 진행하면서 프로젝트 디렉터리(예: cr-spring-music/)를 만들고 하위 디렉터리를 만드는 것이 좋습니다.

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

빌드 이미지 만들기

이 섹션에서는 cflinux3을 기본 이미지로 사용하여 빌드 이미지를 만듭니다. 빌드 이미지는 애플리케이션 이미지를 만들기 위한 빌드 환경으로 사용됩니다.

  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의 주소로 바꿉니다. 예를 들면 REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/runtime:stable.입니다.

Cloud Foundry용 Spring Music 빌드

Spring Music 프로젝트를 클론하고 Cloud Foundry에 프로젝트를 배포하는 것처럼 빌드 명령어를 실행하려면 다음 안내를 따르세요.

  1. Spring Music 저장소를 클론합니다.

    git clone https://github.com/cloudfoundry-samples/spring-music.git
    
  2. 이 가이드에서는 자바 8 및 Spring Boot 2를 사용하는 이전 버전의 Spring Music 애플리케이션을 사용합니다. 이를 위해 Spring Music 프로젝트의 이전 버전으로 이동합니다.

    git checkout 610ba471a643a20dee7a62d88a7879f13a21d6a3
    
  3. 저장소로 이동합니다.

    cd spring-music
    
  4. Spring Music 바이너리를 빌드합니다.

    ./gradlew clean assemble
    

이제 Cloud Foundry 인스턴스에 푸시할 준비가 된 컴파일된 Spring Music 앱이 포함된 build/ 폴더가 만들어졌습니다.

Spring Music을 Cloud Run 호환 애플리케이션으로 변환

빌드 명령어의 출력을 가져와 Cloud Run에 배포할 Spring Music 아티팩트를 준비해야 합니다.

  1. 스테이징 디렉터리 cr-app과 그 안에 src 하위 디렉터리를 만듭니다.

    mkdir -p cr-app/src
    
  2. 컴파일된 JAR의 콘텐츠를 src 디렉터리에 추출하여 cf push를 모방합니다.

    unzip build/libs/spring-music-1.0.jar -d cr-app/src
    
  3. 디렉터리를 cr-app/으로 변경합니다.

    cd cr-app/
    
  4. Dockerfile라는 새 파일을 만듭니다. 이 Dockerfile은 이전 단계에서 만든 빌드 이미지 및 런타임 이미지를 사용하여 자바 빌드팩을 사용하여 Spring Music에서 실행 가능한 애플리케이션 이미지를 만듭니다.

  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 호환 이미지로 빌드

이 단계에서는 이전 단계에서 만든 빌드 이미지, 런타임 이미지, 애플리케이션 Dockerfile을 사용하여 OCI 호환 이미지를 구성하는 방법을 Cloud Build에 지시합니다.

OCI 호환 이미지를 만들려면 다음 안내를 따르세요.

  1. cloudbuild.yaml라는 파일을 만듭니다. 이는 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를 빌더와 실행기를 게시한 Container Registry의 URI로 바꿉니다.
  3. Cloud Build를 사용하여 애플리케이션 이미지를 빌드합니다.

    gcloud builds submit .
    

    빌드가 완료되면 결과 이미지 URI를 기록해 둡니다. 다음 단계에서 애플리케이션을 배포할 때 필요합니다. 그러면 오픈소스 Cloud Foundry 구성요소를 사용하여 빌드된 Spring Music 앱을 실행할 수 있는 OCI 호환 컨테이너 이미지가 생성됩니다.

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
    

    배포가 완료되면 배포된 URL에서 실행 중인 Spring Music 애플리케이션으로 이동할 수 있습니다.

다음 단계