透過 YAML 在 Google Cloud 中使用 Pulumi

1. 總覽

本研究室將說明如何使用 Pulumi,這項工具可將基礎架構視為程式碼,用於佈建及管理 Google Cloud 資源。

學習目標

本實驗室將說明如何執行下列工作:

  • 安裝及設定 Pulumi
  • 編寫 YAML 程式,在 Google Cloud 上建立基礎架構模型
  • 使用 Pulumi 佈建及管理雲端資源
  • 使用 pulumi convert 將 YAML 程式轉換為 Python 程式

2. 設定和需求

自修環境設定

  1. 登入 Google Cloud 控制台,然後建立新專案或重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • 「專案名稱」是這項專案參與者的顯示名稱。這是 Google API 未使用的字元字串。您隨時可以更新。
  • 專案 ID 在所有 Google Cloud 專案中都是不重複的值,且無法變更 (設定後即無法變更)。Cloud 控制台會產生不重複的字串,通常不是在乎。在大部分的程式碼研究室中,您必須參照專案 ID (專案 ID 通常會顯示為 PROJECT_ID)。如果您不喜歡產生的 ID,可以產生其他隨機字串。或者,您也可以自行嘗試,看看是否可用。這項設定在這個步驟後即無法變更,並會在專案期間維持不變。
  • 提醒您,有些 API 會使用第三個值,也就是「專案編號」。如要進一步瞭解這三個值,請參閱說明文件
  1. 接下來,您需要在 Cloud 控制台中啟用帳單功能,才能使用 Cloud 資源/API。執行本程式碼研究室時,費用應該不會太高,甚至可能不收費。如要關閉資源,以免系統產生本教學課程結束後產生的費用,您可以刪除自己建立的資源,或刪除整個專案。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

檢查堆疊設定,您應該會看到鍵 gcp:project,其中的值為您的專案 ID

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

更新 Pulumi.yaml 專案檔案,指向 Python 程式。請注意,執行階段和主要項目已變更

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

runtime: python
main: py-repo/
EOT

嘗試重新部署資料結構,然後選取「是」

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. 恭喜!

恭喜,您完成了研究室!