이 Codelab 정보
1. 개요
Cloud SQL Go 커넥터를 사용하면 Go 애플리케이션을 Cloud SQL 데이터베이스에 안전하게 연결할 수 있습니다. Cloud Run은 HTTP 요청을 통해 호출 가능한 스테이트리스(Stateless) 컨테이너를 실행하는 완전 관리형 서버리스 플랫폼입니다. 이 Codelab에서는 IAM 인증을 사용하여 서비스 계정으로 Cloud Run의 Go 애플리케이션을 PostgreSQL용 Cloud SQL 데이터베이스에 안전하게 연결하는 방법을 보여줍니다.
학습할 내용
이 실습에서는 다음 작업을 진행하는 방법을 학습합니다.
- PostgreSQL용 Cloud SQL 데이터베이스 만들기
- Cloud Run에 Go 애플리케이션 배포
- Go 커넥터를 사용하여 Cloud SQL에 애플리케이션 연결
기본 요건
- 이 실습에서는 Cloud 콘솔 및 Cloud Shell 환경에 익숙하다고 가정합니다.
2. 시작하기 전에
Cloud 프로젝트 설정
- Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Google 계정이 없다면 계정을 만들어야 합니다.
- 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
- 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔이 고유한 문자열을 자동으로 생성합니다. 보통은 그게 뭔지 상관하지 않습니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로
PROJECT_ID
로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 무작위로 다른 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다. - 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
- 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스를 삭제하거나 전체 프로젝트를 삭제하면 됩니다. Google Cloud 새 사용자에게는 미화 $300 상당의 무료 체험판 프로그램에 참여할 수 있는 자격이 부여됩니다.
환경 설정
검색창 오른쪽에 있는 아이콘을 클릭하여 Cloud Shell을 활성화합니다.
Cloud Shell에서 API를 사용 설정합니다.
gcloud services enable compute.googleapis.com sqladmin.googleapis.com \
run.googleapis.com artifactregistry.googleapis.com \
cloudbuild.googleapis.com servicenetworking.googleapis.com
승인하라는 메시지가 표시되면 '승인'을 클릭합니다. 계속하려면
이 명령어를 완료하는 데 몇 분 정도 걸릴 수 있지만 최종적으로 다음과 유사한 성공 메시지가 표시됩니다.
Operation "operations/acf.p2-327036483151-73d90d00-47ee-447a-b600-a6badf0eceae" finished successfully.
3. 서비스 계정 설정
Cloud SQL에 연결할 수 있는 올바른 권한을 갖도록 Cloud Run에서 사용할 Google Cloud 서비스 계정을 만들고 구성합니다.
- 다음과 같이
gcloud iam service-accounts create
명령어를 실행하여 새 서비스 계정을 만듭니다.gcloud iam service-accounts create quickstart-service-account \
--display-name="Quickstart Service Account" - 다음과 같이 gcloud projects add-iam-policy-binding 명령어를 실행하여 방금 만든 Google Cloud 서비스 계정에 Cloud SQL 클라이언트 역할을 추가합니다. Cloud Shell에서
${GOOGLE_CLOUD_PROJECT}
표현식은 프로젝트 이름으로 대체됩니다. 원하는 경우 직접 교체해도 됩니다.gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role="roles/cloudsql.client" - 다음과 같이 gcloud projects add-iam-policy-binding 명령어를 실행하여 방금 만든 Google Cloud 서비스 계정에 Cloud SQL 인스턴스 사용자 역할을 추가합니다.
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role="roles/cloudsql.instanceUser" - 다음과 같이 gcloud projects add-iam-policy-binding 명령어를 실행하여 방금 만든 Google Cloud 서비스 계정에 로그 작성자 역할을 추가합니다.
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
--member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--role="roles/logging.logWriter"
4. Cloud SQL 설정
gcloud sql instances create
명령어를 실행하여 Cloud SQL 인스턴스를 만듭니다.
- –database-version: 데이터베이스 엔진 유형 및 버전 지정하지 않으면 API 기본값이 사용됩니다. 사용 가능한 현재 버전을 보려면 gcloud 데이터베이스 버전 문서를 참조하세요.
- –cpu: 머신에서 필요한 코어 수입니다.
- –memory: 시스템에서 원하는 메모리의 양을 나타내는 정수 값입니다. 크기 단위 (예: 3072MB 또는 9GB)를 제공해야 합니다. 단위를 지정하지 않으면 GB로 간주됩니다.
- –region: 인스턴스의 리전 위치 (예: us-central1, asia-east1, us-east1)입니다.
- –database-flags: 플래그를 설정할 수 있습니다. 이 경우에는
cloudsql.iam_authentication
를 사용 설정하여 Cloud Run에서 이전에 만든 서비스 계정을 사용하여 Cloud SQL에 연결할 수 있도록 합니다.gcloud sql instances create quickstart-instance \
--database-version=POSTGRES_14 \
--cpu=1 \
--memory=4GB \
--region=us-central1 \
--database-flags=cloudsql.iam_authentication=on
이 명령어를 완료하는 데 몇 분 정도 걸릴 수 있습니다.
gcloud sql databases create
명령어를 실행하여 quickstart-instance
내에 Cloud SQL 데이터베이스를 만듭니다.
gcloud sql databases create quickstart_db \
--instance=quickstart-instance
이전에 만든 서비스 계정에 대해 PostgreSQL 데이터베이스 사용자를 만들어 데이터베이스에 액세스합니다.
gcloud sql users create quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam \
--instance=quickstart-instance \
--type=cloud_iam_service_account
5. 애플리케이션 준비
HTTP 요청에 응답하는 Go 애플리케이션을 준비합니다.
- Cloud Shell에서
helloworld
라는 새 디렉터리를 만든 후 해당 디렉터리로 변경합니다.mkdir helloworld
cd helloworld go mod init
를 실행하여 새 Go 애플리케이션을 초기화합니다.go mod init github.com/GoogleCloudPlatform/golang-samples/run/helloworld
- Cloud SQL Go Connector 종속 항목을 설치합니다.
go get cloud.google.com/go/cloudsqlconn
go get cloud.google.com/go/cloudsqlconn/postgres/pgxv4 - 애플리케이션 코드로
main.go
파일을 만듭니다. 이 코드로 수행할 수 있는 작업은 다음과 같습니다.- HTTP 요청 수락
- 데이터베이스에 연결
- 데이터베이스에 HTTP 요청 시간 저장
- 마지막 요청 5개의 시간을 반환합니다.
cat > main.go << "EOF"
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
"cloud.google.com/go/cloudsqlconn"
"cloud.google.com/go/cloudsqlconn/postgres/pgxv4"
)
// visitData is used to pass data to the HTML template.
type visitData struct {
RecentVisits []visit
}
// visit contains a single row from the visits table in the database.
// Each visit includes a timestamp.
type visit struct {
VisitTime time.Time
}
// getDB creates a connection to the database
// based on environment variables.
func getDB() (*sql.DB, func() error) {
cleanup, err := pgxv4.RegisterDriver("cloudsql-postgres", cloudsqlconn.WithIAMAuthN())
if err != nil {
log.Fatalf("Error on pgxv4.RegisterDriver: %v", err)
}
dsn := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=disable", os.Getenv("INSTANCE_CONNECTION_NAME"), os.Getenv("DB_USER"), os.Getenv("DB_NAME"))
db, err := sql.Open("cloudsql-postgres", dsn)
if err != nil {
log.Fatalf("Error on sql.Open: %v", err)
}
createVisits := `CREATE TABLE IF NOT EXISTS visits (
id SERIAL NOT NULL,
created_at timestamp NOT NULL,
PRIMARY KEY (id)
);`
_, err = db.Exec(createVisits)
if err != nil {
log.Fatalf("unable to create table: %s", err)
}
return db, cleanup
}
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("Listening on port %s", port)
db, cleanup := getDB()
defer cleanup()
http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
// Insert current visit
_, err := db.Exec("INSERT INTO visits(created_at) VALUES(NOW())")
if err != nil {
log.Fatalf("unable to save visit: %v", err)
}
// Get the last 5 visits
rows, err := db.Query("SELECT created_at FROM visits ORDER BY created_at DESC LIMIT 5")
if err != nil {
log.Fatalf("DB.Query: %v", err)
}
defer rows.Close()
var visits []visit
for rows.Next() {
var visitTime time.Time
err := rows.Scan(&visitTime)
if err != nil {
log.Fatalf("Rows.Scan: %v", err)
}
visits = append(visits, visit{VisitTime: visitTime})
}
response, err := json.Marshal(visitData{RecentVisits: visits})
if err != nil {
log.Fatalf("renderIndex: failed to parse totals with json.Marshal: %v", err)
}
w.Write(response)
})
if err := http.ListenAndServe(":"+port, nil); err != nil {
log.Fatal(err)
}
}
EOF
이 코드는 PORT 환경 변수로 정의한 포트를 리슨하는 기본 웹 서버를 생성합니다. 이제 애플리케이션을 배포할 준비가 되었습니다.
6. Cloud Run 애플리케이션 배포
아래 명령어를 실행하여 애플리케이션을 배포합니다.
- –region: 인스턴스의 리전 위치 (예: us-central1, asia-east1, us-east1)입니다.
- –source: 배포할 소스 코드입니다. 이 경우
.
는 현재 폴더helloworld
의 소스 코드를 참조합니다. - –set-env-vars: 애플리케이션이 애플리케이션을 Cloud SQL 데이터베이스로 보내는 데 사용하는 환경 변수를 설정합니다.
- –service-account: 이 Codelab의 시작 부분에서 생성된 Cloud SQL 데이터베이스에 연결할 권한이 있는 서비스 계정에 Cloud Run 배포를 연결합니다.
- –allow-unauthenticated: 인터넷에서 애플리케이션에 액세스할 수 있도록 인증되지 않은 요청을 허용합니다.
gcloud run deploy helloworld \
--region=us-central1 \
--source=. \
--set-env-vars INSTANCE_CONNECTION_NAME="${GOOGLE_CLOUD_PROJECT}:us-central1:quickstart-instance" \
--set-env-vars DB_NAME="quickstart_db" \
--set-env-vars DB_USER="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam" \
--service-account="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
--allow-unauthenticated
메시지가 표시되면 y
및 Enter
를 눌러 계속 진행할지 확인합니다.
Do you want to continue (Y/n)? y
몇 분 후 애플리케이션에 방문할 수 있는 URL이 제공됩니다.
URL로 이동하여 실제 애플리케이션을 확인합니다. URL을 방문하거나 페이지를 새로고침할 때마다 가장 최근의 방문 내역 5개가 JSON으로 반환됩니다.
7. 축하합니다
Cloud SQL에서 실행되는 PostgreSQL 데이터베이스에 연결할 수 있는 Go 애플리케이션을 Cloud Run에 배포했습니다.
학습한 내용
- PostgreSQL용 Cloud SQL 데이터베이스 만들기
- Cloud Run에 Go 애플리케이션 배포
- Go 커넥터를 사용하여 Cloud SQL에 애플리케이션 연결
삭제
이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요. 전체 프로젝트를 삭제하려면 다음을 실행합니다.
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}