YAML로 Google Cloud에서 Pulumi 사용

1. 개요

이 실습에서는 코드형 인프라 도구인 Pulumi를 사용하여 Google Cloud 리소스를 프로비저닝하고 관리하는 방법을 알아봅니다.

학습할 내용

이 실습에서는 다음 작업을 진행하는 방법을 학습합니다.

  • Pulumi 설치 및 구성
  • Google Cloud에서 인프라를 모델링하는 YAML 프로그램 작성
  • Pulumi를 사용한 Cloud 리소스 프로비저닝 및 관리
  • pulumiconvert를 사용하여 YAML 프로그램을 Python 프로그램으로 변환합니다.

2. 설정 및 요구사항

자습형 환경 설정

  1. Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
  • 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔이 고유한 문자열을 자동으로 생성합니다. 보통은 그게 뭔지 상관하지 않습니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로 PROJECT_ID로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 무작위로 다른 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다.
  • 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
  1. 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스를 삭제하거나 전체 프로젝트를 삭제하면 됩니다. Google Cloud 새 사용자에게는 미화 $300 상당의 무료 체험판 프로그램에 참여할 수 있는 자격이 부여됩니다.

3. 인프라 설정

Pulumi 설치 및 구성

Cloud Shell에서 다음 명령어를 실행하여 Pulumi를 설치합니다.

curl -fsSL https://get.pulumi.com | sh

경로에 Pulumi를 추가하고 Pulumi의 도움말 메시지를 확인하세요

export PATH=${PATH}:~/.pulumi/bin
# view the help message to verify pulumi runs
pulumi -h

다음 명령어를 실행하여 프로젝트 ID를 설정하고 액세스를 승인합니다. 사용자는 이 명령어를 사용하여

export PROJECT_ID=$(gcloud config get-value project)
gcloud auth application-default login

Cloud Shell에서 GCS 버킷을 만들어 백엔드로 사용

gsutil mb gs://pulumi-${PROJECT_ID}
pulumi login gs://pulumi-${PROJECT_ID}

새 프로젝트 만들기

Cloud Shell에서 프로젝트 루트 디렉터리 만들기

mkdir pulumi-lab && cd pulumi-lab

프로젝트 파일 정의(Pulumi의 진입점)

cat <<EOT > Pulumi.yaml
name: pulumi-lab
description: Try Pulumi

runtime: yaml
main: yaml-repo/
EOT

YAML 리소스 정의

yaml 형식으로 클라우드 리소스 정의를 저장할 디렉터리 만들기

mkdir yaml-repo

다음 리소스 정의로 yaml-repo/Pulumi.yaml 파일을 만듭니다.

  1. 버킷
  2. IAM 바인딩
  3. 문자열 'Hello World!'가 있는 텍스트 객체
  4. 몇 가지 출력은
resources:
  # Create a GCP resource (Storage Bucket)
  my-bucket:
    type: gcp:storage:Bucket
    properties:
      location: US
      website:
        mainPageSuffix: index.html
      uniformBucketLevelAccess: true

  my-bucket-binding:
    type: gcp:storage:BucketIAMBinding
    properties:
      bucket: ${my-bucket.name}
      role: "roles/storage.objectViewer"
      members: ["allUsers"]

  index-object:
    type: gcp:storage:BucketObject
    properties:
      bucket: ${my-bucket}
      source:
        fn::stringAsset: Hello World!

outputs:
  bucketName: ${my-bucket.url}

리소스 배포

스택 초기화 및 구성

export PULUMI_CONFIG_PASSPHRASE=pulumi-lab
pulumi stack init dev
pulumi config set gcp:project $PROJECT_ID

스택 구성을 확인하면 프로젝트 ID가 값으로 포함된 gcp:project 키가 표시됩니다.

pulumi config

이 시점에서 디렉터리 구조는 다음과 같아야 합니다.

├── Pulumi.dev.yaml
├── Pulumi.yaml
└── yaml-repo
    └── Pulumi.yaml

스택 배포

pulumi up

이 명령어는 프로그램을 평가하고 수행할 리소스 업데이트를 결정합니다. 먼저, 명령어를 실행할 때 변경되는 사항을 간략히 설명하는 미리보기가 표시됩니다.

(출력)

Previewing update (dev):
Downloading plugin gcp v6.44.0: 45.69 MiB / 45.69 MiB [=============] 100.00% 1s
     Type                             Name               Plan
 +   pulumi:pulumi:Stack              pulumi-lab-dev     create
 +   ├─ gcp:storage:Bucket            my-bucket          create
 +   ├─ gcp:storage:BucketObject      index-object       create
 +   └─ gcp:storage:BucketIAMBinding  my-bucket-binding  create


Outputs:
    bucketName: output<string>

Resources:
    + 4 to create

Do you want to perform this update?  [Use arrows to move, type to filter]
  yes
> no
  details

를 선택하면 리소스가 프로비저닝됩니다. 다음과 같이 출력됩니다.

Do you want to perform this update? yes
Updating (dev):
     Type                             Name               Status
 +   pulumi:pulumi:Stack              pulumi-lab-dev     created (3s)
 +   ├─ gcp:storage:Bucket            my-bucket          created (1s)
 +   ├─ gcp:storage:BucketObject      index-object       created (0.78s)
 +   └─ gcp:storage:BucketIAMBinding  my-bucket-binding  created (5s)


Outputs:
    bucketName: "gs://my-bucket-874aa08"

Resources:
    + 4 created

Duration: 11s

다음 명령어를 실행하면 정의된 출력이 출력됩니다.

pulumi stack output

다음 명령어를 실행하여 변경사항을 확인합니다.

gsutil ls $(pulumi stack output bucketName)

다음과 같이 출력됩니다.

(출력)

gs://my-bucket-11a9046/index-object-77a5d80

4. YAML을 Python으로 변환

위의 예시를 Pulumi Python 프로그램으로 변환해 보겠습니다.

pulumi convert --language python --out ./py-repo

py-repo에서 생성된 코드 검사

cat py-repo/__main__.py

(출력)

import pulumi
import pulumi_gcp as gcp

my_bucket = gcp.storage.Bucket("my-bucket",
    location="US",
    website=gcp.storage.BucketWebsiteArgs(
        main_page_suffix="index.html",
    ),
    uniform_bucket_level_access=True)
my_bucket_binding = gcp.storage.BucketIAMBinding("my-bucket-binding",
    bucket=my_bucket.name,
    role="roles/storage.objectViewer",
    members=["allUsers"])
index_object = gcp.storage.BucketObject("index-object",
    bucket=my_bucket.id,
    source=pulumi.StringAsset("Hello World!"))
pulumi.export("bucketName", my_bucket.url)
.......

Python 가상 환경 활성화

source py-repo/bin/activate

Python 프로그램을 가리키도록 Pulumi.yaml 프로젝트 파일을 업데이트합니다. 런타임과 기본 항목이 변경된 것을 알 수 있습니다.

cat <<EOT > Pulumi.yaml
name: pulumi-lab
description: Try Pulumi

runtime: python
main: py-repo/
EOT

스택을 재배포하고 yes를 선택합니다.

pulumi up

변경사항이 없으며 출력은 다음과 같이 표시됩니다.

(출력)

Previewing update (dev):
     Type                 Name            Plan
     pulumi:pulumi:Stack  pulumi-lab-dev


Resources:
    4 unchanged

Do you want to perform this update? yes
Updating (dev):
     Type                 Name            Status
     pulumi:pulumi:Stack  pulumi-lab-dev


Outputs:
    bucketName: "gs://my-bucket-c2b49ad"

Resources:
    4 unchanged

Duration: 6s

5. 리소스 삭제

만든 리소스를 삭제합니다.

pulumi destroy

확인 내용은 다음과 같이 표시됩니다.

Previewing update (dev):
     Type                 Name            Plan
     pulumi:pulumi:Stack  pulumi-lab-dev


Resources:
    4 unchanged

Do you want to perform this update?  [Use arrows to move, type to filter]
  yes
> no
  details


Do you want to perform this destroy? yes
Destroying (dev):
     Type                             Name               Status
 -   pulumi:pulumi:Stack              pulumi-lab-dev     deleted
 -   ├─ gcp:storage:BucketIAMBinding  my-bucket-binding  deleted (5s)
 -   ├─ gcp:storage:BucketObject      index-object       deleted (1s)
 -   └─ gcp:storage:Bucket            my-bucket          deleted (0.73s)


Outputs:
  - bucketName: "gs://my-bucket-874aa08"

Resources:
    - 4 deleted

Duration: 10s

6. 축하합니다.

축하합니다. 실습을 완료하셨습니다.