앱 현대화 워크샵

1. 소개

최종 업데이트: 2024년 11월 1일

이전 PHP 애플리케이션을 Google Cloud로 현대화하려면 어떻게 해야 하나요?

(📽️ 이 Codelab에 대한 7분 길이의 소개 동영상 시청)

현대화해야 하는 기존 애플리케이션이 온프레미스에서 실행되는 경우가 많습니다. 즉, 다양한 환경에서 확장 가능하고 안전하며 배포할 수 있어야 합니다.

이 워크샵에서는 다음을 수행합니다.

  1. PHP 애플리케이션을 컨테이너화합니다.
  2. 관리형 데이터베이스 서비스 ( Cloud SQL)로 이전합니다.
  3. Cloud Run에 배포합니다 (GKE/Kubernetes의 제로 운영 대안).
  4. Identity and Access Management (IAM) 및 Secret Manager로 애플리케이션을 보호합니다.
  5. Cloud Build를 통해 CI/CD 파이프라인을 정의합니다. Cloud Build는 GitHub 또는 GitLab과 같이 널리 사용되는 Git 제공업체에서 호스팅되는 Git 저장소와 연결할 수 있으며, 예를 들어 메인으로 푸시할 때 트리거될 수 있습니다.
  6. Cloud Storage에 애플리케이션 사진을 호스팅합니다. 이는 마운트를 통해 이루어지며, 앱을 변경하는 데 코드가 필요하지 않습니다.
  7. Cloud Functions (서버리스)를 통해 조정된 Gemini를 통해 생성형 AI 기능을 도입합니다.
  8. SLOs 및 새로 업데이트된 앱 운영에 관해 알아봅니다.

이 단계를 따르면 PHP 애플리케이션을 점진적으로 현대화하여 확장성, 보안, 배포 유연성을 개선할 수 있습니다. 또한 Google Cloud로 이전하면 강력한 인프라와 서비스를 활용하여 클라우드 네이티브 환경에서 애플리케이션이 원활하게 실행되도록 할 수 있습니다.

이러한 간단한 단계에 따라 학습한 내용은 언어/스택과 사용 사례가 다른 자체 애플리케이션 및 조직에 적용할 수 있습니다.

앱 정보

포크할 애플리케이션(MIT 라이선스코드)은 MySQL 인증이 포함된 기본 PHP 5.7 애플리케이션입니다. 이 앱의 기본 아이디어는 사용자가 사진을 업로드하고 관리자가 부적절한 이미지에 태그를 지정할 수 있는 플랫폼을 제공하는 것입니다. 애플리케이션에는 두 개의 테이블이 있습니다.

  • 사용자. 관리자와 함께 사전 컴파일되어 제공됩니다. 신규 사용자가 등록할 수 있습니다.
  • Images에 저장 몇 가지 샘플 이미지가 포함되어 있습니다. 로그인한 사용자는 새 사진을 업로드할 수 있습니다. 여기에 약간의 마법을 추가합니다.

내 목표

Google Cloud에 이전 애플리케이션을 통합하기 위해 애플리케이션을 현대화하고자 합니다. Google은 이러한 도구와 서비스를 활용하여 확장성을 개선하고, 보안을 강화하고, 인프라 관리를 자동화하고, Cloud SQL, Cloud Run, Cloud Build, Secret Manager 등의 서비스를 사용하여 이미지 처리, 모니터링, 데이터 저장소와 같은 고급 기능을 통합할 것입니다.

445f7a9ae37e9b4d.png

무엇보다도 단계별로 진행하여 각 단계의 사고 과정을 학습할 수 있도록 하고자 합니다. 일반적으로 각 단계는 다음 단계의 새로운 가능성을 열어줍니다(예: 모듈 2 -> 3, 6 -> 7).

아직 결정하지 않으셨나요? YouTube에서 7분 길이의 동영상을 확인하세요.

필요한 항목

  • 인터넷에 연결되어 있으며 브라우저가 설치되어 있는 컴퓨터
  • 일부 GCP 크레딧 현지 Google 애호가에게 물어보세요 ;)
  • gcloud 명령어가 작동하는 모습
  • 로컬에서 작업 중이신가요? 여기에서 다운로드하세요. 또한 멋진 편집기 (예: vscode 또는 intellij)도 필요합니다.
  • '클라우드'에서 모든 작업을 하고 싶으신가요? 그런 다음 Cloud Shell을 사용할 수 있습니다.
  • GitHub 사용자입니다. 자체 Git 저장소로 원본 코드 🧑🏻‍💻 gdgpescara/app-mod-workshop를 브랜치하려면 이 명령어가 필요합니다. 자체 CI/CD 파이프라인 (자동 커밋 -> 빌드 -> 배포)을 사용하려면 이 작업이 필요합니다.

샘플 솔루션은 다음에서 확인할 수 있습니다.

이 워크샵은 로컬 컴퓨터에서 이용하거나 브라우저에서 전체적으로 진행할 수 있습니다.

2. 크레딧 설정 및 포크

6dafc658860c0ce5.png

GCP 크레딧을 사용하고 GCP 환경을 설정합니다[선택사항].

이 워크숍을 실행하려면 크레딧이 있는 결제 계정이 필요합니다. 이미 자체 결제 시스템을 사용하고 있다면 이 단계를 건너뛰어도 됩니다.

새 Google Gmail 계정을 만드세요 (*). GCP 크레딧에 연결할 수 있습니다. GCP 크레딧을 사용할 수 있는 링크를 강사에게 요청하거나 여기(bit.ly/PHP-Amarcord-credits)에서 크레딧을 사용하세요 .

새로 만든 계정으로 로그인하고 안내를 따릅니다.

ff739240dbd84a30.png

(

) 새 Gmail 계정이 필요한 이유는 무엇인가요?*

이전에 GCP에 노출된 적이 있고 조직 정책에 따라 Codelab을 완료할 수 없는 계정(특히 직장 또는 학생 이메일)을 사용하는 사용자가 Codelab을 완료하지 못하는 경우가 있었습니다. 새 Gmail 계정을 만들거나 이전에 GCP를 사용한 적이 없는 기존 Gmail 계정 (gmail.com)을 사용하는 것이 좋습니다.

크레딧을 사용하려면 버튼을 클릭하세요.

331658dc50213403.png

다음 양식에 이름과 성명을 입력하고 이용약관에 동의합니다.

https://console.cloud.google.com/billing에서 결제 계정이 표시되기까지 몇 초 정도 기다려야 할 수 있습니다.

완료되면 Google Cloud 콘솔을 열고 왼쪽 상단 드롭다운 메뉴에 있는 프로젝트 선택기를 클릭하여 '조직 없음'이 표시된 새 프로젝트를 만듭니다. 아래 참조

bd7548f78689db0b.png

아래 스크린샷과 같이 프로젝트가 없으면 새 프로젝트를 만듭니다. 오른쪽 상단에 '새 프로젝트' 옵션이 있습니다.

6c82aebcb9f5cd47.png

다음과 같이 새 프로젝트를 GCP 체험판 결제 계정에 연결해야 합니다.

f202527d254893fb.png

이제 Google Cloud Platform을 사용할 수 있습니다. 초보자이거나 Cloud 환경에서 모든 작업을 수행하려는 경우 아래와 같이 왼쪽 상단의 다음 버튼을 통해 Cloud Shell 및 편집기에 액세스할 수 있습니다.

7d732d7bf0deb12e.png

왼쪽 상단에서 새 프로젝트가 선택되어 있는지 확인합니다.

선택되지 않음(잘못됨):

c2ffd36a781b276a.png

선택됨(좋음):

594563c158f4f590.png

GitHub에서 앱 포크

  1. 데모 앱으로 이동합니다. https://github.com/gdgpescara/app-mod-workshop
  2. 🍴 포크를 클릭합니다.
  3. GitHub 계정이 없는 경우 새 계정을 만들어야 합니다.
  4. 원하는 대로 수정합니다.

734e51bfc29ee5df.png

  1. git clone https://github.com/<YOUR-GITHUB-USER>/<YOUR-REPO-NAME>을 사용하여 앱 코드를 클론합니다.
  1. 원하는 편집기로 클론된 프로젝트 폴더를 엽니다. Cloud Shell을 선택한 경우 아래와 같이 '편집기 열기'를 클릭하면 됩니다.

40f5977ea4c1d1cb.png

다음 그림과 같이 Google Cloud Shell 편집기에 필요한 모든 것을 갖추었습니다.

a4e5ffb3e9a35e84.png

3. 모듈 1: SQL 인스턴스 만들기

645902e511a432a6.png

Google Cloud SQL 인스턴스 만들기

PHP 앱이 MySQL 데이터베이스에 연결되므로 원활한 마이그레이션을 위해 Google Cloud에 복제해야 합니다. Cloud SQL은 클라우드에서 완전 관리형 MySQL 데이터베이스를 실행할 수 있다는 점에서 완벽한 제품입니다. 다음 단계를 따르세요.

  1. Cloud SQL 페이지(https://console.cloud.google.com/sql/instances)로 이동합니다.
  2. '인스턴스 만들기'를 클릭합니다.
  3. 필요한 경우 API를 사용 설정합니다. 이 작업은 몇 초 정도 걸릴 수 있습니다.
  4. MySQL을 선택합니다.
  5. (더 오래 지속되는 가장 저렴한 버전을 제공하기 위해 노력하고 있습니다.)
  • 버전: Enterprise
  • 사전 설정: 개발 (샌드박스를 사용해 봤지만 효과가 없음)
  • Mysql 버전: 5.7 (와우, 과거의 추억이 새록새록!)
  1. 인스턴스 ID: appmod-phpapp를 선택합니다. 이 값을 변경하는 경우 향후 스크립트와 솔루션도 적절하게 변경해야 합니다.
  2. 비밀번호: 원하는 대로 저장하되 CLOUDSQL_INSTANCE_PASSWORD
  3. 리전: 앱의 나머지 부분에서 선택한 것과 동일하게 유지합니다 (예: Milan = europe-west8).
  4. 영역 어베일: 단일 영역 (데모 비용 절감 중)

Create Instance(인스턴스 만들기) 버튼을 클릭하여 Cloud SQL 데이터베이스를 배포합니다. ⌛ 완료하는 데 약 10분 정도 걸립니다.⌛ 그동안 문서를 계속 읽어보세요. DB 연결을 수정할 때까지는 첫 번째 부분의 이 모듈에 종속 항목이 없으므로 다음 모듈('PHP 앱 컨테이너화')을 풀기 시작해도 됩니다.

참고: 이 인스턴스의 비용은 하루에 약 7달러입니다. 워크숍이 끝난 후 반드시 가동해야 합니다.

Cloud SQL에서 image_catalog DB 및 사용자 만들기

앱 프로젝트에는 다음 두 개의 SQL 파일이 포함된 db/ 폴더가 있습니다.

  1. 01_schema.sql : 사용자 및 이미지 데이터가 포함된 두 개의 테이블을 만드는 SQL 코드가 포함되어 있습니다.
  2. 02_seed.sql: 이전에 만든 테이블에 데이터를 시드하는 SQL 코드가 포함되어 있습니다.

이러한 파일은 나중에 image_catalog 데이터베이스가 생성된 후에 사용됩니다. 다음 단계를 따르면 됩니다.

  1. 인스턴스를 열고 데이터베이스 탭을 클릭합니다.
  2. '데이터베이스 만들기'를 클릭합니다.
  3. image_catalog라고 합니다 (PHP 앱 구성과 마찬가지로).

997ef853e5ebd857.png

그런 다음 데이터베이스 사용자를 만듭니다. 이를 통해 image_catalog 데이터베이스에 인증할 수 있습니다.

  1. 이제 사용자 탭을 클릭합니다.
  2. '사용자 계정 추가'를 클릭합니다.
  3. 사용자: 하나 만들어 보겠습니다.
  • 사용자 이름: appmod-phpapp-user
  • 비밀번호: 기억하기 쉬운 비밀번호를 선택하거나 '생성'을 클릭합니다.
  • '모든 호스트 허용 (%)'을 유지합니다.
  1. '추가'를 클릭합니다.

DB를 잘 알려진 IP에 엽니다.

Cloud SQL의 모든 DB는 '격리된' 상태로 시작됩니다. 액세스할 수 있는 네트워크를 명시적으로 설정해야 합니다.

  1. 인스턴스를 클릭합니다.
  2. 메뉴 '연결'을 엽니다.
  3. '네트워킹' 탭을 클릭합니다.
  4. '승인된 네트워크'를 클릭합니다. 이제 서브넷을 추가합니다.
  • 지금은 앱이 작동하도록 INSECURE로 설정하겠습니다.
  • 이름: '전 세계 모든 사람 - 안전하지 않음'(이 저렴한 솔루션도 안전하지 않음)
  • 네트워크: '0.0.0.0/0'(참고: 안전하지 않음)

저장을 클릭합니다.

다음과 같은 결과를 확인할 수 있습니다.

5ccb9062a7071964.png

참고: 이 솔루션은 워크숍을 O(시간) 내에 완료하기에 좋은 절충안입니다. 하지만 프로덕션용으로 솔루션을 보호하려면 보안 문서를 참고하세요.

DB 연결을 테스트할 시간입니다.

이전에 만든 image_catalog 사용자가 작동하는지 확인해 보겠습니다. 인스턴스 내에서 Cloud SQL Studio에 액세스하고 아래와 같이 인증할 데이터베이스, 사용자, 비밀번호를 입력합니다.

d56765c6154c11a4.png

이제 SQL 편집기를 열고 다음 섹션으로 진행할 수 있습니다.

코드베이스에서 데이터베이스 가져오기

SQL 편집기를 사용하여 데이터가 포함된 image_catalog 테이블을 가져옵니다. 저장소의 sql 파일에서 SQL 코드를 가져와 순차적으로 하나씩 실행합니다. 01_schema.sql02_seed.sql을 차례로 실행합니다.

그러면 image_catalog에 아래와 같이 usersimages라는 두 개의 테이블이 생성됩니다.

65ba01e4c6c2dac0.png

편집기에서 다음을 실행하여 테스트할 수 있습니다. select * from images;

나중에 필요하므로 공개 IP 주소도 기록해 둡니다.

4. 모듈 2: PHP 앱 컨테이너화

e7f0e9979d8805f5.png

클라우드용으로 이 앱을 빌드하려고 합니다.

즉, 클라우드에서 코드를 실행하는 데 필요한 모든 정보가 포함된 일종의 ZIP 파일로 코드를 패키징합니다.

이를 패키징하는 몇 가지 방법이 있습니다.

  • Docker 매우 인기가 있지만 올바르게 설정하기에는 매우 복잡합니다.
  • Buildpacks 덜 인기가 있지만 빌드할 항목과 실행할 항목을 '자동 추측'하는 경향이 있습니다. 대부분은 자동으로 작동합니다.

이 워크숍에서는 Docker를 사용한다고 가정합니다.

Docker

직접 관리하려는 경우 이 솔루션이 적합합니다. 이는 특정 라이브러리를 구성하고 특정 명시적이지 않은 동작 (업로드의 chmod, 앱의 비표준 실행 파일 등)을 삽입해야 하는 경우에 적합합니다.

궁극적으로 컨테이너화된 애플리케이션을 Cloud Run에 배포할 예정이므로 다음 문서를 확인하고 빈칸을 채워 보세요. 지금으로서는 일을 쉽게 하기 위해 꼭 필요한 것만 제공합니다. 최종 Dockerfile은 다음과 유사합니다.

# Use an official PHP image with Apache
# Pull a suitable php image
FROM __________# Define the env variable for the Apache listening port 8080
ENV __________

# Set working directory inside the container
WORKDIR __________

# Install required PHP extensions: PDO, MySQL, and other dependencies
RUN __________

# Copy all application files into the container
COPY __________

# Configure Apache to listen on port 8080. Use ‘sed' command to change the default listening port.
RUN __________

# When in doubt, always expose to port 8080
EXPOSE __________

# Start Apache in the foreground
CMD __________

또한 애플리케이션을 로컬에서 테스트하려면 PHP 앱이 Google CloudSQL에서 사용 가능한 MySQL db에 연결되도록 config.php 파일을 변경해야 합니다. 이전에 설정한 내용을 바탕으로 빈칸을 채워보세요.

  • DBM_host는 Cloud SQL 공개 IP 주소이며 콘솔에서 확인할 수 있습니다.

bd27071bf450a8d0.png

  • Db_name은 변경되지 않아야 합니다. image_catalog
  • Db_user는 appmod-phpapp-user여야 합니다.
  • DBM_pass를 선택하면 됩니다. 작은따옴표로 설정하고 필요에 따라 이스케이프 처리합니다.
<?php
// Database configuration
$db_host = '____________';
$db_name = '____________';
$db_user = '____________';
$db_pass = '____________';

try {
    $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Errore di connessione: " . $e->getMessage());
}

session_start();
?>

또한 Gemini의 도움을 받아 이탈리아어로 된 몇 가지 콘텐츠를 영어로 번역해 보세요.

이제 Dockerfile이 생성되었고 DB에 연결하도록 PHP 앱을 구성했으므로 이를 사용해 보겠습니다.

아직 Docker가 설치되어 있지 않다면 설치합니다 ( 링크). Cloud Shell을 사용하는 경우에는 이 방법이 필요하지 않습니다. 정말 멋지죠?

이제 적절한 docker build 및 run 명령어를 사용하여 컨테이너화된 PHP 앱을 빌드하고 실행해 보세요.

  • docker build -t <IMAGE_TAG_NAME> .
  • docker run -it -p <CONTAINER PORT>:<LOCAL MACHINE PORT> <IMAGE_TAG_NAME>

모든 것이 제대로 작동하는 경우 로컬 호스트에 연결하면 다음 웹페이지가 표시됩니다.

Cloud Shell을 사용하는 경우 다음과 같이 로컬 포트 (예: 8080)를 브라우저로 내보낼 수도 있습니다.

docker build -t my-php-app-docker app-mod-workshop/ -f Dockerfile

docker run -it -p 8080:8080 my-php-app-docker

이제 앱이 포트 8080에서 실행 중임을 알 수 있습니다. '웹 미리보기' 아이콘(눈이 있는 브라우저)을 클릭한 다음 포트 8080에서 미리보기(또는 다른 포트의 경우 '포트 변경')를 클릭합니다.

33a24673f4550454.png

브라우저에서 결과 테스트하기

이제 애플리케이션이 다음과 같이 표시됩니다.

2718ece96b1f18b6.png

Admin/admin123으로 로그인하면 다음과 같은 내용이 표시됩니다.

68b62048c2e86aea.png

좋습니다. 작동 중 🎉🎉🎉

도커화가 잘 되었지만 DB 사용자 인증 정보가 잘못된 경우 다음과 같은 오류가 발생할 수 있습니다.

e22f45b79bab86e1.png

다시 시도해 보세요. 거의 맞았습니다.

빌드팩[선택사항]

빌드팩을 사용하면 앱이 자동으로 빌드됩니다. 안타깝게도 전체를 제어할 수 없으므로 예상치 못한 구성이 될 수 있습니다.

로컬 환경에 새 Docker 이미지가 있어야 합니다. 컨테이너를 실행해 볼 수 있지만 이미지가 빌드된 방식을 완전히 제어할 수 없으므로 앱이 작동하지 않을 수 있습니다. 어떤 경우든 실험해 보고 성공하면 의견을 공유해 주세요. 감사합니다.

Artifact Registry에 저장[선택사항]

이제 클라우드에 배포할 수 있는 컨테이너화된 PHP 애플리케이션이 작동해야 합니다. 다음으로, Docker 이미지를 저장하고 Cloud Run과 같은 Google Cloud 서비스에 배포할 수 있도록 액세스할 수 있는 클라우드 공간이 필요합니다. 이 스토리지 솔루션은 Docker 컨테이너 이미지, Maven 패키지, npm 모듈 등을 비롯한 애플리케이션 아티팩트를 저장하도록 설계된 완전 관리형 Google Cloud 서비스인 Artifact Registry라고 합니다.

적절한 버튼을 사용하여 Google Cloud Artifact Registry에 저장소를 만들어 보겠습니다.

e1123f0c924022e6.png

아티팩트를 저장하는 데 적합한 유효한 이름, 형식, 리전을 선택합니다.

4e516ed209c470ee.png

로컬 개발 환경 태그로 돌아가서 방금 만든 Artifact Registry 저장소에 앱 컨테이너 이미지를 푸시합니다. 다음 명령어를 실행하여 수행합니다.

  • Docker 태그 SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
  • docker push TARGET_IMAGE[:TAG]

결과는 다음 스크린샷과 같습니다.

1e498feb4e88be9f.png

축하합니다. 🎉🎉🎉 다음 단계로 이동할 수 있습니다.

메모를 탭합니다. /upload.php 엔드포인트를 사용해 보고 사진을 업로드해 보세요. '권한 거부됨' 오류가 표시될 수 있습니다. 이 경우 Dockerfile에서 chmod/chown 수정이 필요합니다.

5. 모듈 3: Cloud Run에 앱 배포

9ffca42774f6c5d1.png

Cloud Run을 선택해야 하는 이유

좋은 질문입니다. 몇 년 전만 해도 여러분은 Google App Engine을 선택했을 것입니다.

간단히 말해, 현재 Cloud Run은 최신 기술 스택을 사용하고 있으며, 배포가 더 쉽고, 비용이 더 저렴하며, 사용하지 않을 때는 0으로 확장됩니다. 스테이트리스 컨테이너를 유연하게 실행하고 다양한 Google Cloud 서비스와 통합할 수 있으므로 최소한의 오버헤드와 최대의 효율로 마이크로서비스와 최신 애플리케이션을 배포하는 데 적합합니다.

구체적으로 Cloud Run은 서버리스 환경에서 스테이트리스 컨테이너화된 애플리케이션을 실행할 수 있는 Google Cloud의 완전 관리형 플랫폼입니다. Cloud Run은 모든 인프라를 자동으로 처리하여 수신 트래픽에 맞게 0에서 확장하고 유휴 상태일 때는 축소하므로 비용 효율적이고 효율적입니다. Cloud Run은 컨테이너에 패키징되는 한 모든 언어 또는 라이브러리를 지원하므로 개발의 유연성을 크게 높일 수 있습니다. Cloud Functions는 다른 Google Cloud 서비스와 잘 통합되며 서버 인프라를 관리할 필요 없이 마이크로서비스, API, 웹사이트, 이벤트 기반 애플리케이션을 빌드하는 데 적합합니다.

기본 요건

이 작업을 완료하려면 로컬 머신에 gcloud가 설치되어 있어야 합니다. 여기의 안내를 참조하세요. Google Cloud Shell을 사용하는 경우 취해야 할 조치는 없습니다.

배포하기 전에

로컬 환경에서 작업하는 경우 다음과 같이 Google Cloud에 인증합니다.

  • $ gcloud auth login –update-adc # not needed in Cloud Shell

이렇게 하면 브라우저에서 OAuth 로그인을 통해 인증됩니다. 결제가 사용 설정된 상태로 Google Cloud에 로그인한 것과 동일한 사용자 (예: vattelapesca@gmail.com)로 Chrome을 통해 로그인해야 합니다.

다음 명령어로 Cloud Run API 사용 설정

  • $ gcloud services enable run.googleapis.com

이제 Cloud Run에 배포할 준비가 되었습니다.

gcloud를 통해 Cloud Run에 앱 배포

Cloud Run에 앱을 배포할 수 있는 명령어는 gcloud run deploy입니다. 목표를 달성하기 위해 설정할 수 있는 옵션은 여러 가지가 있습니다. 최소 집합은 다음과 같습니다.

  1. 앱에 배포하려는 Cloud Run 서비스의 이름입니다. Cloud Run 서비스는 앱에 엔드포인트를 제공하는 URL을 반환합니다.
  2. 앱이 실행될 Google Cloud 리전입니다.
  3. 앱을 래핑하는 컨테이너 이미지
  4. 앱이 실행 중에 사용해야 하는 환경 변수입니다.
  5. 모든 사용자가 추가 인증 없이 앱에 액세스할 수 있도록 허용하는 Allow-Unauthenticated 플래그

이 옵션을 명령어에 적용하는 방법은 문서를 참고하세요. 배포하는 데 몇 분 정도 걸립니다. 모든 것이 올바르다면 Google Cloud 콘솔에 다음과 같은 화면이 표시됩니다.

ef1029fb62f8de81.png

f7191d579c21ca3e.png

Cloud Run에서 제공한 URL을 클릭하고 애플리케이션을 테스트합니다. 인증되면 다음과 같이 표시됩니다.

d571a90cd5a373f9.png

'질문 없음'으로 'gcloud run deploy'

gcloud run deploy가 적절한 질문을 하고 사용자가 남긴 빈칸을 채우는 것을 확인했을 수 있습니다. 정말 멋져요.

하지만 몇몇 모듈에서는 질문을 받을 수 없으므로 이 명령어를 Cloud Build 트리거에 추가할 예정입니다. 명령어의 모든 옵션을 입력해야 합니다. 따라서 금색 gcloud run deploy --option1 blah --foo bar --region your-fav-region를 제작하려고 합니다. 어떻게 하시나요?

  1. gcloud가 질문하기를 중지할 때까지 2-3-4단계를 반복합니다.
  2. [루프] 지금까지 찾은 옵션이 포함된 gcloud run deploy
  3. [LOOP] 시스템에서 옵션 X를 요청함
  4. [LOOP] --my-option [my-value] 옵션을 추가하여 CLI에서 X를 설정하는 방법을 공개 문서에서 검색합니다.
  5. gcloud가 추가 질문 없이 완료되지 않는 한 지금 2단계로 돌아갑니다.
  6. 이 gcloud run deploy BLAH BLAH BLAH가 최고입니다. 명령어를 어딘가에 저장합니다. 나중에 Cloud Build 단계에서 필요합니다.

해결 방법은 여기에서 확인하실 수 있습니다.

축하합니다 🎉🎉🎉 Google Cloud에 앱을 배포하여 현대화의 첫 번째 단계를 완료했습니다.

6. 모듈 4: Secret Manager로 비밀번호 삭제

95cd57b03b4e3c73.png

이전 단계에서 Cloud Run에 앱을 배포하고 실행했습니다. 하지만 일부 비밀을 일반 텍스트로 제공하는 보안 악습관을 사용했습니다.

첫 번째 반복: ENV를 사용하도록 config.php 업데이트

DB 비밀번호를 config.php 파일의 코드에 바로 입력하는 것을 눈치채셨을 수도 있습니다. 테스트 목적으로 앱이 작동하는지 확인하는 데는 문제가 없습니다. 그러나 프로덕션 환경에서는 이러한 코드를 커밋하거나 사용할 수 없습니다. 비밀번호(및 기타 DB 연결 매개변수)는 동적으로 읽고 런타임에 앱에 제공해야 합니다. ENV 변수에서 db 매개변수를 읽도록 config.php 파일을 변경합니다. 실패하면 기본값을 설정하는 것이 좋습니다. 이는 ENV를 로드하지 못할 경우 유용합니다. 그러면 페이지 출력에서 기본값을 사용하고 있는지 알 수 있습니다. 공백을 채우고 config.php의 코드를 바꿉니다.

<?php
// Database configuration with ENV variables. Set default values as well 
$db_host = getenv('DB_HOST') ?: _______;
$db_name = getenv('DB_NAME') ?: 'image_catalog';
$db_user = getenv('DB_USER') ?: 'appmod-phpapp-user';
$db_pass = getenv('DB_PASS') ?: _______;
// Note getenv() is PHP 5.3 compatible
try {
    $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Errore di connessione: " . $e->getMessage());
}

session_start();
?>

앱이 컨테이너화되어 있으므로 앱에 ENV 변수를 제공하는 방법을 제공해야 합니다. 다음과 같은 몇 가지 방법으로 이를 수행할 수 있습니다.

  • Dockerfile의 빌드 시 이전 Dockerfile에 ENV DB_VAR=ENV_VAR_VALUE 문법을 사용하여 4개의 매개변수를 추가합니다. 이렇게 하면 런타임에 재정의할 수 있는 기본값이 설정됩니다. 예를 들어 'DB_NAME' 및 'DB_USER'는 여기에서만 설정할 수 있습니다.
  • 실행CLI 또는 UI에서 Cloud Run에 이러한 변수를 설정할 수 있습니다. Dockerfile에 설정된 기본값을 유지하려는 경우가 아니라면 4개의 변수를 모두 여기에 배치하는 것이 좋습니다.

localhost에서는 ENV 변수를 .env 파일에 배치하는 것이 좋습니다 (해결 방법 폴더 참고).

또한 .env가 .gitignore에 추가되어 있는지 확인합니다. 보안 비밀을 GitHub에 푸시하지 않아야 합니다.

echo .env >> .gitignore

그런 다음 로컬에서 인스턴스를 테스트할 수 있습니다.

docker run -it -p 8080:8080 --env-file .env my-php-app-docker

이제 다음 작업을 완료했습니다.

  1. 앱이 ENV에서 변수를 동적으로 읽습니다.
  2. 코드에서 DB 비밀번호를 삭제하여 보안이 강화되었습니다.)

이제 Cloud Run에 새 버전을 배포할 수 있습니다. UI로 이동하여 환경 변수를 수동으로 설정해 보겠습니다.

  • https://console.cloud.google.com/run으로 이동합니다.
  • 앱을 클릭합니다.
  • '새 버전 수정 및 배포'를 클릭합니다.
  • 첫 번째 탭인 '컨테이너'에서 하단 탭인 '변수 및 보안 비밀'을 클릭합니다.
  • '+ 변수 추가'를 클릭하고 필요한 변수를 모두 추가합니다. 다음과 같이 표시됩니다.

7a5fbfa448544d3.png

f2780c35585388ca.png

좋을까요? 아니요. 대부분의 운영자에게는 여전히 PASS가 표시됩니다. Google Cloud Secret Manager를 사용하면 이러한 문제를 완화할 수 있습니다.

두 번째 반복: Secret Manager

코드에서 비밀번호가 사라졌습니다. 성공입니다. 하지만 잠깐만요, 우리는 안전한가요?

Google Cloud 콘솔에 액세스할 수 있는 모든 사용자는 비밀번호를 계속 볼 수 있습니다. 실제로 Cloud Run YAML 배포 파일에 액세스하면 가져올 수 있습니다. 또는 새 Cloud Run 버전을 수정하거나 배포하려고 하면 아래 스크린샷과 같이 변수 및 보안 비밀 섹션에 비밀번호가 표시됩니다.

Google Cloud Secret Manager는 API 키, 비밀번호, 인증서, 기타 보안 비밀과 같은 민감한 정보를 관리하기 위한 안전하고 중앙 집중식 서비스입니다.

이를 통해 세분화된 권한과 강력한 암호화를 사용하여 보안 비밀을 저장, 관리, 액세스할 수 있습니다. Secret Manager는 Google Cloud의 Identity and Access Management (IAM)와 통합되어 특정 비밀에 액세스할 수 있는 사용자를 제어하여 데이터 보안과 규정 준수를 보장합니다.

또한 자동 보안 비밀 순환 및 버전 관리를 지원하여 Google Cloud 서비스 전반에서 보안 비밀 수명 주기 관리를 간소화하고 애플리케이션의 보안을 강화합니다.

Secret Manager에 액세스하려면 햄버거 메뉴에서 보안 서비스로 이동한 다음 아래 스크린샷과 같이 데이터 보호 섹션에서 찾습니다.

6df83a1c3cb757f6.png

그런 다음 다음 이미지에 따라 Secret Manager API를 사용 설정합니다.

a96c312e2c098db1.png

  • 이제 '보안 비밀 만들기'를 클릭합니다. 합리적으로 이름을 지정하겠습니다.
  • 이름: php-amarcord-db-pass
  • 보안 비밀 값: 'DB 비밀번호'('파일 업로드' 부분은 무시)
  • 이 보안 비밀 링크에 주석을 추가할 때는 projects/123456789012/secrets/php-amarcord-db-pass과 같은 형식이어야 합니다. 보안 비밀에 대한 고유한 포인터입니다 (Terraform, Cloud Run 등). 이 번호는 고유한 프로젝트 번호입니다.

도움말: 왼쪽에서 오른쪽으로 전문화하여 보안 비밀에 일관된 이름 지정 규칙을 사용해 보세요(예: cloud-devrel-phpamarcord-dbpass).

  • 조직 (회사 포함)
  • 팀 (조직 내)
  • 신청 (팀 내)
  • 변수 이름(앱 내)

이렇게 하면 간단한 정규식으로 단일 앱의 모든 비밀을 찾을 수 있습니다.

새 Cloud Run 버전 만들기

이제 새 보안 비밀이 있으므로 DB_PASS ENV 변수를 삭제하고 새 보안 비밀로 대체해야 합니다. 따라서 다음과 같은 전략을 구사하세요.

  • Google Cloud 콘솔을 사용하여 Cloud Run에 액세스
  • 앱을 선택합니다.
  • '새 버전 수정 및 배포'를 클릭합니다.
  • 'Variables & Secrets(변수 및 보안 비밀)' 탭을 찾습니다.
  • '+ 보안 비밀 참조' 버튼을 사용하여 DB_PASS ENV 변수를 재설정합니다.
  • 참조된 보안 비밀에 동일한 'DB_PASS'를 사용하고 최신 버전을 사용합니다.

9ed4e35be7654dcb.png

완료되면 다음과 같은 오류가 표시됩니다.

da0ccd7af39b04ed.png

해결 방법을 찾아보십시오. 이 문제를 해결하려면 IAM 및 관리자 섹션에 액세스하여 권한 부여를 변경해야 합니다. 즐겁게 디버깅하세요.

문제를 파악한 후 Cloud Run으로 돌아가 새 버전을 다시 배포합니다. 다음과 같은 결과가 표시됩니다.

e89f9ca780169b6b.png

도움말: 개발자 콘솔(UI)은 권한 문제를 파악하는 데 유용합니다. Cloud 항목의 모든 링크를 둘러보세요.

7. 모듈 5: Cloud Build로 CI/CD 설정

ba49b033c11be94c.png

CI/CD 파이프라인을 사용해야 하는 이유

이제 gcloud run deploy를 몇 번 입력했을 겁니다. 같은 질문에 계속 답변했을 수도 있습니다.

gcloud run deploy로 앱을 수동으로 배포하는 데 지치셨나요? Git 저장소에 새 변경사항을 푸시할 때마다 앱이 자동으로 배포되면 얼마나 좋을까요?

CI/CD 파이프라인을 사용하려면 다음 두 가지가 필요합니다.

  1. 개인 Git 저장소: 다행히 2단계에서 이미 워크숍 저장소를 GitHub 계정으로 포크했을 것입니다. 완료되지 않았다면 해당 단계로 돌아가서 완료합니다. 포크된 저장소는 다음과 같이 표시됩니다. https://github.com/<YOUR_GITHUB_USER>/app-mod-workshop
  2. Cloud Build. 이 놀라운 저렴한 서비스를 사용하면 Terraform, 도커화된 앱 등 거의 모든 항목에 대한 빌드 자동화를 구성할 수 있습니다.

이 섹션에서는 Cloud Build 설정에 중점을 둡니다.

Cloud Build 시작

Cloud Build를 사용하여 다음을 실행합니다.

  • Dockerfile을 사용하여 소스를 빌드합니다. 빌드하고 실행하는 데 필요한 모든 항목('빌드 아티팩트')이 포함된 '큰 .zip 파일'이라고 생각하면 됩니다.
  • 이 아티팩트를 Artifact Registry (AR)로 푸시합니다.
  • 그런 다음 앱 'php-amarcord'의 AR에서 Cloud Run으로 배포를 실행합니다.
  • 이렇게 하면 기존 앱의 새 버전('버전')이 생성되며(새 코드가 포함된 레이어라고 생각해 보세요) 푸시가 성공하면 트래픽을 새 버전으로 전환하도록 구성됩니다.

다음은 php-amarcord 앱의 일부 빌드 예입니다.

f30f42d4571ad5e2.png

이 모든 작업은 어떻게 이루어질까요?

  1. 하나의 완벽한 YAML 파일을 작성하여 cloudbuild.yaml
  2. Cloud Build 트리거를 만듭니다.
  3. Cloud Build UI를 통해 GitHub 저장소에 연결합니다.

트리거 만들기 (및 저장소 연결)

  • https://console.cloud.google.com/cloud-build/triggers로 이동합니다.
  • '트리거 만들기'를 클릭합니다.
  • 컴파일:
  • 이름: on-git-commit-build-php-app와 같이 의미 있는 이름
  • 이벤트: 브랜치에 푸시
  • 소스: '새 저장소 연결' 대체 텍스트
  • 그러면 오른쪽에 '저장소 연결' 창이 열립니다.
  • 소스 제공업체: 'GitHub'(첫 번째)
  • "계속"
  • 인증을 클릭하면 GitHub에서 교차 인증할 수 있는 창이 열립니다. 안내에 따라 기다립니다. 저장소가 많은 경우 시간이 다소 걸릴 수 있습니다.
  • '저장소 선택' 계정/저장소를 선택하고 '확인' 부분에 체크표시합니다.
  • 오류가 발생한 경우: 저장소에 GitHub 앱이 설치되지 않았습니다. 'Google Cloud Build 설치'를 클릭하고 안내를 따르세요.
  • 23e0e0f1219afea3.png연결을 클릭하세요.
  • bafd904ec07122d2.png
  • 빙고! 이제 저장소가 연결되었습니다.
  • 트리거 부분으로 돌아갑니다.
  • 구성: 자동 감지됨 (*)
  • 고급: 서비스 계정 '[PROJECT_NUMBER]- compute@developer.gserviceaccount.com'을 선택합니다.
  • xxxxx는 프로젝트 ID입니다.
  • 기본 Compute 서비스 계정은 실험실 접근 방식에 적합합니다. 프로덕션에는 사용하지 마세요. ( 자세히 알아보기).
  • 나머지는 그대로 둡니다.
  • '만들기' 버튼을 클릭합니다.

(*) Dockerfile 또는 cloudbuild.yaml을 확인하므로 가장 간단한 방법입니다. 하지만 cloudbuild.yaml를 사용하면 어떤 단계에서 어떤 작업을 실행할지 결정할 수 있습니다.

전원이 공급되었습니다.

이제 Cloud Build 서비스 계정 (서비스 계정이란 무엇인가요? 작업을 대신하는 '로봇'의 이메일입니다(이 경우 Cloud에서 빌드 작업).

SA에게 권한을 부여하지 않으면 SA가 빌드 및 배포할 수 없습니다. 다행히 간단합니다.

  • 'Cloud Build' > '설정'으로 이동합니다.
  • '[PROJECT_NUMBER]- compute@developer.gserviceaccount.com' 서비스 계정
  • 다음 체크박스를 선택합니다.
  • Cloud Run
  • Secret Manager
  • 서비스 계정
  • Cloud Build
  • 또한 '선호하는 서비스 계정으로 설정'을 선택합니다.

8715acca72286a46.png

Cloud Build YAML은 어디에 있나요?

시간을 내어 자체 Cloud Build YAML을 만드는 것이 좋습니다.

시간이 없거나 시간을 내지 않으려는 경우 솔루션 폴더 .solutions에서 아이디어를 얻을 수 있습니다.

이제 변경사항을 github에 푸시하고 Cloud Build를 직접 관찰할 수 있습니다.

Cloud Build를 설정하는 것은 쉽지 않을 수 있습니다. 다음과 같은 답변이 오갈 수 있습니다.

  • https://console.cloud.google.com/cloud-build/builds;region=global에서 로그 확인
  • 오류 찾기
  • 코드에서 수정하고 git commit / git push를 다시 실행합니다.
  • 오류가 코드가 아닌 일부 구성에 있는 경우도 있습니다. 이 경우 UI에서 새 빌드를 발행할 수 있습니다 (Cloud Build > 'Triggers' > Run).

97acd16980a144ab.png

이 솔루션을 사용하는 경우 아직 할 일이 있습니다. 예를 들어 새로 만든 dev/prod 엔드포인트의 ENV 변수를 설정해야 합니다.

3da8723e4ff80c0a.png

여기에는 두 가지 방법이 있습니다.

  • UI를 통해 - ENV 변수를 다시 설정
  • CLI를 통해 '완벽한' 스크립트를 작성합니다. 예시는 gcloud-run-deploy.sh에서 확인할 수 있습니다 . 엔드포인트, 프로젝트 번호 등 몇 가지 사항을 조정해야 합니다. 프로젝트 번호는 Cloud 개요에서 찾을 수 있습니다.

GitHub에 코드를 커밋하려면 어떻게 해야 하나요?

git push를 GitHub에 푸시하는 가장 좋은 방법은 이 워크숍의 범위를 벗어납니다. Cloud Shell에서 문제가 발생한 경우 다음 두 가지 방법으로 문제를 해결할 수 있습니다.

  1. CLI 로컬에 ssh 키를 추가하고 git@github.com:YOUR_USER/app-mod-workshop.git (http 대신)으로 원격을 추가합니다.
  2. VSCode Cloud Shell 편집기를 사용하는 경우 소스 제어 (ctrl-shift-G) 탭을 사용하고 '변경사항 동기화'를 클릭한 다음 안내를 따릅니다. 이제 vscode에서 GitHub 계정을 인증할 수 있으며 여기에서 쉽게 가져오기/푸시할 수 있습니다.

f0d53f839c7fa3b6.png

다른 파일 중에서 git add clodubuild.yaml해야 하며, 그렇지 않으면 작동하지 않습니다.

심층적 'dev/prod 패리티'와 얕은 'dev/prod 패리티' 비교[선택사항]

여기에서 모델 버전을 복사한 경우 동일한 DEV 및 PROD 버전 2개가 생성됩니다. 이는 12팩터 앱의 규칙 10에 따른 바람직한 조치입니다.

그러나 앱이 동일한 데이터베이스를 가리키도록 하기 위해 두 가지 웹 엔드포인트를 사용하고 있습니다. 이 정도면 워크숍에서는 괜찮지만, 현실에서는 시간을 들여 적절한 프로덕션 환경을 만들어야 합니다. 즉, 두 개의 데이터베이스 (하나는 개발용, 하나는 프로덕션용)를 두고 재해 복구 / 고가용성을 위해 데이터베이스를 배치할 위치를 선택해야 합니다. 이 내용은 이 워크숍의 범위를 벗어나지만 한 번쯤 생각해 볼 만한 내용입니다.

'심층적인' 버전의 프로덕션을 진행할 시간이 있다면 다음과 같이 복제해야 하는 모든 리소스를 염두에 두세요.

  • Cloud SQL 데이터베이스 (일반적으로 SQL 인스턴스)
  • GCS 버킷
  • Cloud 함수
  • 개발 시에는 Gemini 1.5 Flash (더 저렴하고 빠름)를 모델로 사용하고 Gemini 1.5 Pro (더 강력함)를 사용할 수 있습니다.

일반적으로 앱에 관해 작업할 때마다 프로덕션에 동일한 값을 사용해야 하는지 비판적으로 생각해 보세요. 그렇지 않은 경우 작업을 반복합니다. 물론 Terraform을 사용하면 훨씬 더 쉽습니다. Terraform에서는 환경 (-dev, -prod)을 리소스의 접미사로 삽입할 수 있습니다.

8. 모듈 6: Google Cloud Storage로 이전

a680e0f287dd2dfb.png

스토리지

현재 앱은 상태를 Docker 컨테이너에 저장합니다. 머신이 다운되거나 앱이 비정상 종료되거나 새 버전을 푸시하면 스토리지를 재설정(=>비워짐)하여 새 버전이 예약됩니다. 🙈

해결 방법은 여러 가지가 있습니다.

  1. DB에 이미지를 저장합니다. 이전 PHP 앱에서 제가 한 작업이 바로 이 작업입니다. 복잡성을 추가하지 않으므로 가장 간단한 솔루션입니다. 하지만 DB에 지연 시간과 부하가 추가됩니다.
  2. Cloud Run 앱을 스토리지 친화적인 솔루션인 GCE + 영구 디스크로 마이그레이션하고 싶으신가요? GKE + 스토리지?
  3. GCS로 이동합니다. Google Cloud Storage는 Google Cloud 전체에 동급 최고의 스토리지를 제공하며 가장 Cloud에 적합한 솔루션입니다. 하지만 PHP 라이브러리를 사용해야 합니다. GCS용 PHP 5.7 라이브러리가 있나요? PHP 5.7Composer도 지원하나요 (Composer에서 지원하는 PHP 5.3.2가 가장 이른 버전인 것 같음)?
  4. docker sidecar를 사용해 보세요.
  5. 또는 GCS Cloud Run 볼륨 마운트를 사용할 수도 있습니다. 정말 멋진 기능이네요.

🤔 스토리지 이전 (개방형)

[해결 방법 없음] 이 연습에서는 어떤 방식으로든 유지되는 방식으로 이미지를 이동하는 솔루션을 찾으세요.

승인 테스트

해결 방법을 알려드리고 싶지 않지만 다음과 같이 진행되기를 바랍니다.

  1. newpic.jpg를 업로드합니다. 앱에 표시됩니다.
  2. 앱을 새 버전으로 업그레이드합니다.
  3. newpic.jpg님이 아직 남아 있으며 표시됩니다.

💡 해결 방법 (GCS Cloud Run 볼륨 마운트)

이는 코드를 전혀 건드리지 않고도 상태 저장 파일 업로드를 실현할 수 있는 매우 우아한 솔루션입니다 (이미지 설명을 표시하는 것 외에도 사소하지만 단지 눈의 만족을 위한 작업임).

이렇게 하면 Cloud Run에서 GCS로 폴더를 마운트할 수 있습니다.

  1. GCS에 대한 모든 업로드가 실제로 앱에 표시됩니다.
  2. 앱에 업로드된 모든 항목이 실제로 GCS에 업로드됩니다.
  3. GCS에 업로드된 객체에 마법이 실행됩니다 (7장).

참고: FUSE의 세부정보를 읽어보세요. 성능에 문제가 있는 경우에는 허용되지 않습니다.

GCS 버킷 만들기

GCS는 Google Cloud의 모든 위치에 있는 스토리지 서비스입니다. 철저한 테스트를 거쳤으며 스토리지가 필요한 모든 GCP 서비스에서 사용됩니다.

Cloud Shell에서 PROJECT_ID를 GOOGLE_CLOUD_PROJECT로 내보냅니다.

$ export PROJECT_ID=$GOOGLE_CLOUD_PROJECT

#!/bin/bash

set -euo pipefail

# Your Cloud Run Service Name, eg php-amarcord-dev
SERVICE_NAME='php-amarcord-dev'
BUCKET="${PROJECT_ID}-public-images"
GS_BUCKET="gs://${BUCKET}"

# Create bucket
gsutil mb -l "$GCP_REGION" -p "$PROJECT_ID" "$GS_BUCKET/"

# Copy original pictures there - better if you add an image of YOURS before.
gsutil cp ./uploads/*.png "$GS_BUCKET/"

/uploads/ 폴더에 버킷을 마운트하도록 Cloud Run 구성

이제 멋진 부분을 살펴보겠습니다. 볼륨 php_uploads를 만들고 Cloud Run에 MOUNT_PATH(/var/www/html/uploads/와 유사)에 FUSE 마운트를 실행하도록 지시합니다.

#!/bin/bash

set -euo pipefail

# .. keep variables from previous script..

# Uploads folder within your docker container.
# Tweak it for your app code.
MOUNT_PATH='/var/www/html/uploads/'

# Inject a volume mount to your GCS bucket in the right folder.
gcloud --project "$PROJECT_ID" beta run services update "$SERVICE_NAME" \
    --region $GCP_REGION \
    --execution-environment gen2 \
    --add-volume=name=php_uploads,type=cloud-storage,bucket="$BUCKET"  \
    --add-volume-mount=volume=php_uploads,mount-path="$MOUNT_PATH"

이제 Cloud Storage를 가리키려는 모든 엔드포인트에 대해 이 단계를 반복합니다.

UI에서도 동일한 작업을 실행할 수 있습니다.

  1. '볼륨' 탭에서 버킷을 가리키는 'Cloud Storage 버킷' 유형의 볼륨 마운트를 만듭니다(예: 이름이 'php_uploads').
  2. 컨테이너 > 볼륨 마운트에서 방금 만든 볼륨을 앱에서 요청한 볼륨 지점에 마운트합니다. Dockerfile에 따라 다르지만 var/www/html/uploads/처럼 보일 수 있습니다 .

어떤 경우든 새 Cloud Run 버전을 수정하면 다음과 같이 표시됩니다.

6c2bb98fc1b0e077.png

이제 /upload.php 엔드포인트에 새 이미지를 하나 업로드하는 새 애플리케이션을 테스트합니다.

PHP를 한 줄도 작성하지 않고도 이미지가 GCS에서 원활하게 흐르게 됩니다.

70032b216afee2d7.png

방금 어떤 문제가 발생했나요?

아주 마법 같은 일이 일어났어요.

이전 코드가 있는 기존 애플리케이션이 여전히 제 역할을 하고 있습니다. 새로운 현대화된 스택을 사용하면 앱의 모든 이미지/사진을 상태ful Cloud 버킷에 편안하게 보관할 수 있습니다. 이제 한계는 없습니다.

  • '위험' 또는 '누드' 이미지가 포함된 이미지가 들어올 때마다 이메일을 보내고 싶으신가요? PHP 코드를 건드리지 않고도 할 수 있습니다.
  • 이미지가 들어올 때마다 Gemini 멀티모달 모델을 사용하여 이미지를 설명하고 설명과 함께 DB를 업로드하고 싶으신가요? PHP 코드를 변경하지 않고도 이 작업을 수행할 수 있습니다. 믿지 않나요? 7장에서 계속 읽어보세요.

이제 큰 기회가 열렸습니다.

9. 모듈 7: Google Gemini로 앱 강화

c00425f0ad83b32c.png

이제 클라우드 스토리지를 사용하는 멋진 최신 PHP 앱 (예: 2024 Fiat 126)을 사용할 수 있습니다.

필드로 할 수 있는 작업

기본 요건

이전 장에서는 모델 솔루션을 사용하여 GCS에 /uploads/ 이미지를 마운트하여 사실상 앱 로직을 이미지 저장소에서 분리할 수 있었습니다.

이 연습에서는 다음을 수행해야 합니다.

  • 6장 (저장소)의 연습문제를 완료했습니다.
  • 사용자가 앱에 사진을 업로드하고 사진이 버킷으로 전송되는 이미지 업로드가 포함된 GCS 버킷이 있습니다.

Cloud 함수 설정(Python)

이벤트 기반 애플리케이션을 구현하는 방법을 궁금하게 생각해 보신 적이 있나요? 다음과 같은 형식입니다.

  • <event> 발생 => 이메일 보내기
  • <event> 발생 => <condition>이 true이면 데이터베이스를 업데이트합니다.

이벤트는 BigQuery에서 사용할 수 있는 새 레코드, GCS의 폴더에서 변경된 새 객체, Pub/Sub의 대기열에서 대기 중인 새 메시지 등 무엇이든 될 수 있습니다.

Google Cloud는 이를 위해 다양한 패러다임을 지원합니다. 특히 다음 항목에 주의해야 합니다.

이 연습에서는 Cloud Functions를 자세히 살펴보고 멋진 결과를 얻어 보겠습니다. 선택적으로 연습문제를 제공해 드립니다.

샘플 코드는 .solutions/에 있습니다.

Cloud 함수 설정 (🐍 python)

Google은 매우 야심찬 GCF를 만들기 위해 노력하고 있습니다.

  1. GCS에서 새 이미지가 생성되면 다음과 같은 작업이 실행됩니다. (누군가 앱에 업로드했기 때문일 수 있지만 그 외에도 다른 이유가 있을 수 있음)
  2. .. Gemini를 호출하여 이미지를 설명하고 이미지에 대한 텍스트 설명을 받습니다. (MIME를 확인하고 이미지가 PDF, MP3, 텍스트가 아닌 이미지인지 확인하는 것이 좋습니다.)
  3. .. 이 설명으로 DB를 업데이트합니다. (이 경우 images 테이블에 description 열을 추가하기 위해 DB를 패치해야 할 수 있습니다.)

DB를 패치하여 description이미지에 추가합니다.

  1. Cloud SQL Studio를 엽니다.

b92b07c4cba658ef.png

  1. 이미지 DB의 사용자 및 비밀번호를 입력합니다.
  2. 이미지 설명을 위한 열을 추가하는 다음 SQL을 삽입합니다.

ALTER TABLE images ADD COLUMN description TEXT;

3691aced78a6389.png

빙고! 이제 작동하는지 확인해 보세요.

SELECT * FROM images;

새 설명 열이 표시됩니다.

bed69d6ad0263114.png

Gemini f(x)를 작성합니다.

참고: 이 함수는 실제로 Gemini Code Assist의 도움을 받아 만들어졌습니다.

참고: 이 함수를 만들면 IAM 권한 오류가 발생할 수 있습니다. 일부 오류는 아래의 '가능한 오류' 단락에 설명되어 있습니다.

  1. API 사용 설정
  2. https://console.cloud.google.com/functions/list로 이동합니다.
  3. '함수 만들기'를 클릭합니다.
  4. API 마법사에서 API 사용 설정:

d22b82658cfd4c48.png

UI 또는 명령줄에서 GCF를 만들 수 있습니다. 여기서는 명령줄을 사용합니다.

사용 가능한 코드는 .solutions/에서 찾을 수 있습니다.

  1. 코드를 호스팅할 폴더(예: 'gcf/')를 만듭니다. 폴더를 입력합니다.
  2. requirements.txt 파일을 만듭니다.
google-cloud-storage
google-cloud-aiplatform
pymysql
  1. Python 함수를 만듭니다. 샘플 코드(gcf/main.py)
#!/usr/bin/env python

"""Complete this"""

from google.cloud import storage
from google.cloud import aiplatform
import vertexai
from vertexai.generative_models import GenerativeModel, Part
import os
import pymysql
import pymysql.cursors

# Replace with your project ID
PROJECT_ID = "your-project-id"
GEMINI_MODEL = "gemini-1.5-pro-002"
DEFAULT_PROMPT = "Generate a caption for this image: "

def gemini_describe_image_from_gcs(gcs_url, image_prompt=DEFAULT_PROMPT):
    pass

def update_db_with_description(image_filename, caption, db_user, db_pass, db_host, db_name):
    pass

def generate_caption(event, context):
    """
    Cloud Function triggered by a GCS event.
    Args:
        event (dict): The dictionary with data specific to this type of event.
        context (google.cloud.functions.Context): The context parameter contains
                                                event metadata such as event ID
                                                and timestamp.
    """
    pass
  1. 함수를 푸시합니다. gcf/push-to-gcf.sh와 유사한 스크립트를 사용할 수 있습니다.

참고 1 올바른 값으로 ENV를 소싱하거나 맨 위에 추가합니다 (GS_BUCKET=blah, ..).

참고 2 이렇게 하면 모든 로컬 코드(.)가 푸시되므로 코드를 특정 폴더로 묶고 대규모 라이브러리를 푸시하지 않도록 전문가처럼 .gcloudignore를 사용하세요. ( )

#!/bin/bash

set -euo pipefail

# add your logic here, for instance:
source .env || exit 2 

echo "Pushing ☁️ f(x)☁ to 🪣 $GS_BUCKET, along with DB config.. (DB_PASS=$DB_PASS)"

gcloud --project "$PROJECT_ID" functions deploy php_amarcord_generate_caption \
    --runtime python310 \
    --region "$GCP_REGION" \
    --trigger-event google.cloud.storage.object.v1.finalized \
    --trigger-resource "$BUCKET" \
    --set-env-vars "DB_HOST=$DB_HOST,DB_NAME=$DB_NAME,DB_PASS=$DB_PASS,DB_USER=$DB_USER" \
    --source . \
    --entry-point generate_caption \
    --gen2

참고: 이 예시에서 generate_caption는 호출된 메서드가 되고 Cloud Function은 GCS 이벤트를 모든 관련 정보(버킷 이름, 객체 이름 등)와 함께 전달합니다. 이벤트 Python 사전을 디버그하는 데 잠시 시간을 내세요.

함수 테스트

단위 테스트

함수에는 움직이는 부분이 많습니다. 모든 단일 API를 테스트하는 것이 좋습니다.

예는 gcf/test.py에 있습니다.

Cloud Functions UI

또한 UI에서 함수를 살펴보세요. 모든 탭을 살펴볼 가치가 있지만 특히 Source(제 최애 탭), Variables, Trigger, Logs을 살펴보세요. Logs에서는 오류를 해결하는 데 많은 시간을 보낼 것입니다(이 페이지 하단의 가능한 오류도 참고하세요). Permissions도 확인해야 합니다.

cf3ded30d532a2c7.png

E2E 테스트

이제 함수를 수동으로 테스트해 보겠습니다.

  1. 앱으로 이동하여 로그인합니다.
  2. 사진을 업로드합니다 (너무 크지 않게 하세요. 큰 이미지의 경우 문제가 발생한 적이 있습니다).
  3. UI에서 사진이 업로드되었는지 확인합니다.
  4. Cloud SQL 스튜디오에서 설명이 업데이트되었는지 확인합니다. 로그인하고 SELECT * FROM images 쿼리를 실행합니다.

43a680b12dbbdda0.png

그 효과는 매우 뛰어났습니다. 이 설명을 표시하도록 프런트엔드를 업데이트하는 것도 좋습니다.

표시되도록 PHP 업데이트[선택사항]

앱이 작동하는 것으로 확인되었습니다. 하지만 사용자가 이 설명을 볼 수 있으면 좋겠습니다.

PHP 전문가가 아니어도 index.php에 설명을 추가할 수 있습니다. 이 코드는 다음을 실행해야 합니다(예, Gemini가 대신 작성해 주었습니다).

<?php if (!empty($image['description'])): ?>
    <p class="font-bold">Gemini Caption:</p>
    <p class="italic"><?php echo $image['description']; ?></p>
<?php endif; ?>

이 코드를 원하는 대로 foreach 내부에 배치합니다.

다음 단계에서는 Gemini Code Assist 덕분에 더 멋진 UI 버전도 확인할 수 있습니다. 예쁜 버전은 다음과 같습니다.

fdc12de0c88c4464.png

결론

GCS에 도착하는 새 객체에 대해 트리거되는 Cloud Functions가 있습니다. 이 Cloud Functions는 사람이 할 수 있는 것처럼 이미지 콘텐츠에 주석을 달고 DB를 자동으로 업데이트할 수 있습니다. 와우!

다음 단계 동일한 추론을 사용하여 두 가지 멋진 기능을 실행할 수 있습니다.

[선택사항] Cloud Functions 추가[개방형]

몇 가지 추가 기능이 떠오릅니다.

📩 이메일 트리거

누군가 사진을 보낼 때마다 이메일을 보내는 이메일 트리거입니다.

  • 너무 자주? 추가 제약 조건을 추가합니다. 큰 사진 또는 Gemini 콘텐츠에 '과도한 노출/과도한 노출/폭력'이라는 단어가 포함된 사진
  • EventArc에서 이를 확인해 보세요.

🚫 부적절한 사진 자동 검토

현재 관리자가 이미지를 '부적절한' 것으로 신고하고 있습니다. Gemini가 스페이스를 관리하고 중재하도록 해보세요. 이전 함수에서 배운 대로 테스트를 추가하여 부적절한 트리거 콘텐츠를 신고하고 DB를 업데이트합니다. 즉, 기본적으로 이전 함수를 가져와서 프롬프트를 변경하고 답변에 따라 DB를 업데이트합니다.

주의사항 생성형 AI의 출력은 예측할 수 없습니다. Gemini의 '광고 소재 출력'이 '정상적으로' 실행되는지 확인합니다. 0~1의 신뢰도 점수, JSON과 같은 결정론적 답변을 요청할 수 있습니다. 이를 실행하는 방법에는 여러 가지가 있습니다. 예를 들면 * Python 라이브러리 pydantic, langchain 사용 * Gemini 구조화된 출력 사용

도움말 다음과 같이 여러 함수를 사용하거나 JSON 답변을 적용하는 단일 프롬프트를 사용할 수 있습니다 (위에서 강조 표시된 'Gemini 구조화된 출력'과 함께 작동).

이를 생성하려면 어떤 프롬프트가 되어야 할까요?

{
    "description": "This is the picture of an arrosticino",
    "suitable": TRUE
}

프롬프트에 추가 필드를 추가하여 '좋았던 점은 무엇인가요?'와 같은 유용한 정보를 얻을 수 있습니다. 나쁜가요? 장소를 알아보시겠어요? 텍스트가 있나요(OCR이 그 어느 때보다 쉬워졌습니다)?

  • goods: '맛있어 보입니다'
  • bads: '건강에 좋지 않은 음식처럼 보입니다'
  • OCR: 'Da consumare preferibilmente prima del 10 Novembre 2024'
  • location: '페스카라, 룽고마레'

일반적으로 N 결과에 N 함수를 사용하는 것이 좋지만 10가지 작업을 하는 함수를 사용하는 것이 훨씬 좋습니다. 방법은 리카르도님의 도움말을 참고하세요.

가능한 오류 (대부분 IAM / 권한)

이 솔루션을 가장 먼저 개발하면서 몇 가지 IAM 권한 문제가 발생했습니다. 공감과 해결 방법에 대한 아이디어를 제공하기 위해 여기에 추가하겠습니다.

오류: 서비스 계정에 권한이 충분하지 않음

  1. GCS 버킷을 리슨하는 GCF 함수를 배포하려면 그림과 같이 작업에 사용 중인 서비스 계정에 적절한 권한을 설정해야 합니다.

22f51012fa6b4a24.png

EventArc API도 사용 설정해야 할 수도 있습니다. 이 API가 완전히 사용 가능해지기까지 몇 분은 걸릴 수 있습니다.

오류: Cloud Run 호출자 누락

  1. GCF 권한 설정에 관한 UI의 다른 의견은 다음과 같습니다 ( Cloud Run 호출자 역할).

be72e17294f2d3f3.png

이 오류는 이미지에서 fix-permissions.sh와 유사한 명령어를 실행하여 수정할 수 있습니다.

이 문제는 https://cloud.google.com/functions/docs/securing/authenticating에 설명되어 있습니다.

오류: 메모리 한도 초과

처음 실행했을 때 로그에 '메모리 한도 244MiB를 초과했습니다(사용량 270MiB). 메모리 한도를 늘리는 것이 좋습니다. https://cloud.google.com/functions/docs/configuring/memory를 참고하세요.' GCF에 RAM을 다시 추가합니다. UI에서 간단하게 할 수 있습니다. 다음과 같은 문제가 발생할 수 있습니다.

bed69d6ad0263114.png

또는 Cloud Run 배포 스크립트를 수정하여 MEM/CPU를 올릴 수도 있습니다. 시간이 조금 더 걸립니다.

오류: PubSub 게시됨

GCF v1으로 트리거를 만들 때 한 번 다음 오류가 발생했습니다.

e5c338ee35ad4c24.png

이 문제는 IAM으로 이동하여 서비스 계정에 'Pub/Sub 게시자' 역할을 부여하면 쉽게 해결할 수 있습니다.

오류: Vertex AI가 사용되지 않았습니다.

이 오류가 표시되는 경우:

권한 거부됨: 403 Vertex AI API가 이전에 YOUR_PROJECT 프로젝트에 사용된 적이 없거나 사용 중지되었습니다. https://console.developers.google.com/apis/api/aiplatform.googleapis.com/overview?project=YOR_PROJECT에서 사용 설정합니다.

Vertex AI API를 사용 설정하기만 하면 됩니다. 필요한 모든 API를 사용 설정하는 가장 쉬운 방법은 다음과 같습니다.

  1. https://console.cloud.google.com/vertex-ai
  2. '모든 권장 API 사용 설정'을 클릭합니다.

492f05ac377f3630.png

오류: EventArc 트리거를 찾을 수 없습니다.

오류가 발생하면 함수를 다시 배포하세요.

8ec4fc11833d7420.png

오류: 400개의 서비스 에이전트가 프로비저닝 중입니다.

400개의 서비스 에이전트가 프로비저닝되고 있습니다( https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents ). 제공된 Cloud Storage 파일을 읽으려면 서비스 에이전트가 필요합니다. 잠시 후 다시 시도해 주세요.

이 경우 잠시 기다리거나 Google 직원에게 문의하세요.

10. 모듈 8: 가용성 SLO 만들기

이 장에서는 다음을 달성하려고 합니다.

  1. SLI 만들기
  2. SLI를 기반으로 SLO 만들기
  3. SLO를 기반으로 알림 만들기

f63426182c052123.png

리치아르도는 Google Cloud의 SRE / DevOps 영역에서 근무하고 있으므로 이 주제는 저자에게 매우 소중합니다.

(개방형) 이 앱의 SLI 및 SLO 만들기

앱이 다운되었는지 알 수 없는 앱은 얼마나 좋은 앱일까요?

SLO란 무엇인가요?

이런, Google에서 SLO를 만들었습니다. 자세한 내용은 다음을 참고하세요.

1단계: 가용성 SLI/SLO 만들기

가용성 SLO부터 시작해 보겠습니다. 가용성 SLO는 측정하기 가장 쉽고 가장 중요한 항목일 수 있습니다.

다행히 Cloud Run에는 Istio 덕분에 사전 빌드된 SLO 지원이 포함되어 있습니다.

Cloud Run에서 앱을 실행하면 아주 간단하게 달성할 수 있습니다. 30초면 완료됩니다.

  • Cloud Run 페이지로 이동합니다.
  • 앱을 클릭/선택합니다.
  • SLOs 탭을 선택합니다.
  • '+ SLO 만들기'를 클릭합니다.
  • 사용 가능 여부(요청 기반)
  • 계속
  • 캘린더 월/99%
  • 'SLO 만들기'를 클릭합니다.

e471c7ebdc56cdf6.png

2단계: 이 SLO에 대한 알림 설정하기

다음과 같이 2개의 알림을 만드는 것이 좋습니다.

  1. 이메일을 통해 알림을 보내는 소모 속도가 느린 티켓('Slowburn', 낮은 우선순위 티켓을 시뮬레이션함)
  2. SMS를 통해 알림을 제공하는 높은 소모율('빠른 소모')의 티켓(높은 우선순위 티켓/무선 호출기 시뮬레이션)

이전의 SLO tab(으)로 이동합니다.

두 번 실행합니다.

314bfd6b9ef0a260.png

  • 'SLO 알림 만들기' (오른쪽에 더하기가 있는 🔔 버튼)를 클릭합니다.
  • 전환 확인 기간, 소진율 기준:
  • [빠름] 처음: 60분 / 10
  • [느림]. 초: 720분/2x
  • 알림 채널: 알림 채널 관리를 클릭합니다.
  • 먼저 '이메일' -> 새 항목 추가 -> ..
  • 두 번째로 'SMS' -> '새 항목 추가' -> '휴대전화에서 인증'을 선택합니다.
  • 도움말: 이름에 이모티콘을 사용하고 싶습니다. 데모용으로 좋습니다.
  • 완료되면 오른쪽 상단의 큰 X를 클릭합니다.
  • 먼저 전화(빠름)를 선택한 다음 이메일(느림)을 선택합니다.
  • 다음과 같은 샘플 문서를 추가합니다.
  • [PHP Amarcord] Riccardo told me to type sudo reboot or to check documentation in http://example.com/playbooks/1.php but I guess he was joking.

빙고!

최종 결과

실제로 작동하는 SLO 1개와 가용성에 대한 알림 2배가 확보되고 이메일과 휴대폰으로 알림이 전송되면 이 연습이 완료된 것으로 간주할 수 있습니다.

원하는 경우 지연 시간을 추가하거나 더 복잡한 것을 추가할 수 있습니다. 가능하면 추가하는 것이 좋습니다. 지연 시간의 경우 적절하다고 생각되는 지연 시간을 선택합니다. 확실하지 않은 경우 200ms를 선택합니다.

11. 다음 단계

모든 단계를 완료했는데 무엇이 누락되었나요?

다음 사항을 고려해 보세요.

Gemini로 플레이하기

Gemini는 두 가지 버전으로 사용할 수 있습니다.

  1. Vertex AI GCP와 긴밀하게 연결된 '엔터프라이즈 방식'으로, 7장(GCF+Gemini)에서 살펴봤습니다. 모든 인증이 자동으로 작동하고 서비스가 서로 원활하게 연결됩니다.
  2. Google AI '소비자 방식' 여기에서 Gemini API 키를 받아 이미 보유한 모든 워크로드 (독점 작업, 기타 클라우드, 로컬 호스트 등)에 연결할 수 있는 간단한 스크립트를 빌드하세요. API 키를 대체하기만 하면 코드가 마법처럼 작동하기 시작합니다.

자신의 반려동물 프로젝트로 (2)를 살펴보세요.

UI 리프팅

UI는 잘 모르겠어요. 하지만 Gemini는 지원됩니다. 단일 PHP 페이지를 사용하여 다음과 같이 작성할 수 있습니다.

I have a VERY old PHP application. I want to touch it as little as possible. Can you help me:

1. add some nice CSS to it, a single static include for tailwind or similar, whatever you prefer
2. Transform the image print with description into cards, which fit 4 per line in the canvas?

Here's the code:

-----------------------------------
[Paste your PHP page, for instance index.php - mind the token limit!]

Cloud Build 하나로 5분 이내에 쉽게 설정할 수 있습니다. :)

Gemini의 대답이 완벽했습니다 (즉, 아무것도 변경할 필요가 없었습니다).

8a3d5fe37ec40bf8.png

다음은 작성자의 개인 앱의 새로운 레이아웃입니다.

81620eb90ae3229a.png

참고: 코드를 가져가라는 것이 아니라 여러분의 창의적인 UI/프런트엔드 제약 조건을 사용하여 Gemini가 코드를 작성하도록 하기 위해 코드가 이미지로 붙여넣어집니다. 믿어 주시겠어요? 나중에 아주 사소한 변경사항만 남게 됩니다.

보안

이 앱을 적절하게 보호하는 것은 이 4시간 워크숍의 목표가 아닙니다.

아이디어를 얻으려면 SECURITY doc를 참고하세요.

12. 축하합니다.

축하합니다. 🎉🎉🎉 Google Cloud로 기존 PHP 애플리케이션을 성공적으로 현대화했습니다.

24cb9a39b1841fbd.png

이 Codelab에서는 다음을 알아봤습니다.

  • Google Cloud SQL에 MySQL 데이터베이스를 배포하는 방법과 기존 데이터베이스를 Google Cloud SQL로 마이그레이션하는 방법을 알아봅니다.
  • Docker 및 Buildpack으로 PHP 애플리케이션을 컨테이너화하고 이미지를 Google Cloud Artifact Registry에 저장하는 방법
  • 컨테이너화된 앱을 Cloud Run에 배포하고 Cloud SQL로 실행하는 방법
  • Google Secret Manager를 사용하여 민감한 구성 매개변수(예: DB 비밀번호)를 비밀리에 저장/사용하는 방법
  • GitHub 저장소에 코드를 푸시할 때마다 PHP 앱을 자동으로 빌드하고 배포하도록 Google Cloud Build로 CI/CD 파이프라인을 설정하는 방법
  • Cloud Storage를 사용하여 앱 리소스를 '클라우드화'하는 방법
  • 서버리스 기술을 활용하여 앱 코드를 건드리지 않고도 Google Cloud를 기반으로 멋진 워크플로를 빌드하는 방법
  • 적절한 사용 사례에 Gemini 멀티모달 기능을 사용합니다.

이제 Google Cloud를 통한 애플리케이션 현대화 여정을 시작해 보세요.

🔁 의견

이 워크숍에 대한 경험을 공유하고 싶다면 이 의견 양식을 제출해 주세요.

여러분의 의견과 코드에 관한 PR을 보내 주세요.

🙏 감사합니다

저자는 솔루션 작성 및 테스트에 도움을 준 Datatonic의 Mirko Gilioli와 Maurizio Ipsale에게 감사의 인사를 전합니다.