【How-to Guides】GCP FinOps — 閒置資源清理任務 Part1

Kellen
17 min readFeb 14, 2024

--

當公司開始享受上雲的生活,代表著總算家裡接通了水、電、網路,只需要開啟開關,就能享受現代生活的便利。但是費用的水龍頭也正式被扭開,本篇將介紹 FinOps 新手村的罐頭任務,如何找到閒置資源,通常可從以下三種入門:

  • External IP 放著不用
  • 無人認領的 Orphaned and unused Disk 問題
  • 未依服務需求選擇經濟實惠的儲存方案

就 GCP FinOps 維度來說雖然在右下象限,不過持續累積的效果也是滿可觀

成本分析與 FinOps 建議

1️⃣ Delete unused reserved external IP addresses

在 Google Cloud 上,如果您保留了靜態 IP(Static IP 或稱外部 IP, External IP)位址,卻未將該位址指派給任一資源(例如 VM 執行個體或轉送規則),或是隨時間推移虛擬機器完成階段任務,但確沒有將之移除,這些「預留」的 IP,GCP 並不會幫你自動移除。而這些閒置 IP 的費率會高於使用中的靜態 IP,有點帶有逞罰計價的味道。這種浪費可能會隨時間推移變得非常顯著,特別是對於那些嚴重依賴靜態 IP 並且有大量使用的應用程式來說。

例如 GCE 黃框的部份可以直接預留一個 Static IP,或是在網路頁面亦可以執行預先保留作業

9.36 美元(0.013 x 24 x 30)是 Google 對未使用的靜態 IP 每月收取的費用(asia-east1),你可以找到多少的這類未使用的靜態 IP?

GCP 計價 — 在 Peemptible and Spot 這邊 GCP 表格感覺是有誤鍵($0.03),與註釋中的 $0.0025 對不起來,經驗上大概就是 Standard 的半價

👎 壞消息是靜態或臨時 IP(IPv4)計費在 20240201 漲價了,漲幅高達 25%;IP 正式從免費到計價,再到漲價年代

📰 20240201 — BillingNews
Static and ephemeral IP addresses in use on standard VM instances will go from $.004 to $.005.
Static and ephemeral IP addresses in use on preemptible VM instances will go from $.002 to
$.0025.

舊的計價模式,從 2020 年的免費到計價到漲價,放此讓雲端老街友懷念一下

2️⃣ Clean up unattached and orphaned persistent disks

永久性磁碟若在建立時未掛接到虛擬機,或者虛擬機具有多個磁碟,並且一個或多個磁碟已分離,則這些永久性磁碟就是未使用(orphaned)或孤立(unattached)的磁碟,這些磁碟佔用空間的費用也是滿嚇人。

磁碟定價

每個 VM 至少會連接一個磁碟,且每個磁碟都會產生費用,且計價上是包含所有已使用和未使用的空間,如果申請 200 GB 磁碟,系統會向您收取整個磁碟空間的費用,直到釋出磁碟空間為止。

例如以上為 GCE 在加掛磁碟定價的參考,若使用平衡型且 100GB 為一個單位,費用約為 $10 USD,但很多狀況是屬於閒置資源,你可以抓到幾個單位呢?

Persistent Disk 類型選擇

配置永久性磁碟時,您可以選擇以下磁碟類型(Storage options),從便宜至貴的介紹

標準型( pd-standard)💰

  • 以標準硬碟(HDD)作為支援,適用於主要使用 sequential I/Os 的大型資料處理工作負載

均衡型pd-balanced)💰💰

  • 效能(pd-ssd) 永久性磁碟的替代方案並以固態硬碟(SSD)作為支援
  • 性能與費用的平衡。對於大多數虛擬機器形式(非常大的磁碟類型除外),這些磁碟具有與 SSD 永久性磁碟相同的最大 IOPS,這種磁碟類型提供的效能適合大多數通用應用,價位介於標準永久性磁碟和效能(pd-ssd)永久性磁碟之間

效能SSDpd-ssd)💰💰💰

  • 以固態硬碟(SSD)作為支援,適用於需要比標準永久性磁碟更短延遲時間和更多 IOPS 的應用程式和高效能資料庫
  • 專為單數位毫秒延遲而設計

極端型( pd-extreme)💰💰💰💰

  • 以固態硬碟(SSD)作為支援,為隨機存取工作負載和批量吞吐量提供始終如一的優越效能
  • 專為高階資料庫工作負載而設計
  • 允許您預配目標 IOPS
  • 適用於有限數量的機器類型

磁碟快照

一般來說,這種快照的儲存費用較低,GCP 還可以使用標準(standard)、即時(instant)和封存(archive)快照來備份 Persistent Disk。封存檔和標準快照是遠端磁碟備份,即時快照則是本機磁碟備份。

而像是標準快照只會按照快照總大小產生費用。舉例來說,假設在 5 個 TiB 永久磁碟上只使用 2 TiB 的磁碟空間,系統會針對已使用的 2 TiB 壓縮儲存空間(而非已佈建的 5 TiB)產生的完整磁碟空間收取快照大小。

3️⃣ 遷移到更經濟實惠的儲存類別

當您在 Google Cloud Storage(GCS)中儲存大量的物件(例如文件、圖像、影片等),這些物件的存儲成本可能會成為一個考慮因素。Google Cloud 提供了一項功能,稱為「儲存物件生命週期規則」,這讓您可以自動管理這些物件的存儲位置,以最大程度地節省成本。

這些生命週期規則允許您根據一組條件(例如物件的建立日期或即時狀態)將物件自動移動到不同的儲存類別中。舉例來說,您可以設置規則,讓 GCS 自動將一段時間未被存取的物件從標準存儲類別(例如 Regional Storage)移動到較低成本的存儲類別(例如 Nearline Storage 或 Coldline Storage),以節省成本。

然而,這些生命週期規則僅根據物件的屬性來進行操作,這些規則無法確定相關物件是否已被存取過。因此,有時您可能會希望手動處理某些物件,即使它們仍符合生命週期規則的條件。例如,即使某些較新的物件已有一段時間未被存取,但基於特定需求,您仍希望將它們移至 Nearline 儲存空間以節省成本。很多情況,就需要手動操作或使用其他自動化方案來處理這些物件的移動。

先前也有使用過類似的技術,進行 Cloud SQL 的節費處理
📙【How-to Guides】GCP FinOps — 善用 Scheduler 有效降低 CloudSQL 高昂費用

1️⃣ Delete unused reserved external IP addresses 實作

前置作業:建立 Compute Engine 虛擬機器並掛載靜態外部 IP ,並設定一個單獨的「未使用」的靜態外部 IP,作為模擬殘留的靜態外部 IP

  • 制作 Cloud Functions 函數,以識別「未使用」的 IP
  • 建立一個 Cloud Scheduler 作業,並設計 HTTP trigger,驅動 Cloud Function 定期移除未使用的 IP 或將其資料拋出的的 FinOps 計畫
輔導案例:長期下來 rotate 不少 Compute Engine(配置有靜態 IP),會遺留下大量閒置資源 — 靜態 IP

以下是將提供的程式碼範例轉換為 Python 的版本,並添加了兩個功能:列印未使用的靜態 IP 地址並將其刪除。

❶ 單一專案(自行管理目的)
➋ 多專案且未引入組織層定義(常見的沙盒環境)
➌ 多專案且為組織層定義(公司環境或引入組織作為資安管理用途)

單一專案(自行管理目的)

(1) Web UI
最簡單就是到 Web UI > VPC 查看全部 IP 狀態,會看到 External IP 且使用者若有「⚠️無」的註記,表示未使用或清除掉的 IP 閒置資源

(2) gcloud 指令
使用 gcloud compute 這個也很方便,但要自動化還是稍嫌不夠

STATUS: RESERVED or IN_USE

實驗關係,我們只留下 35.224.233.24434.127.107.40 作為閒置資源

# 簡易輸出
$ gcloud compute addresses list
NAME: ooo
ADDRESS/RANGE: 35.224.233.244
TYPE: EXTERNAL
PURPOSE:
NETWORK:
REGION: us-central1
SUBNET:
STATUS: RESERVED

NAME: xxx
ADDRESS/RANGE: 34.127.107.40
TYPE: EXTERNAL
PURPOSE:
NETWORK:
REGION: us-west1
SUBNET:
STATUS: RESERVED

# 只取必要資訊出來
$ gcloud compute addresses list --filter="status=RESERVED" --format="table(name, address, region)"
# 格式如下
NAME: xxx
ADDRESS: 34.127.107.40
REGION: us-west1

# 再次整理成可以輸出至 CSV 上使用的格式
gcloud compute addresses list --filter="status=RESERVED" \
--format="csv(NAME, ADDRESS, REGION)" \
| awk 'NR==1 {print "NAME, ADDRESS, REGION"} NR>1 {print $0}'

NAME, ADDRESS, REGION, TYPE
ooo,35.224.233.244,us-central1, EXTERNAL
xxx,34.34.127.107.40,us-west1, EXTERNAL

使用 Google Cloud 的 gcloud 命令列工具列出所有的 Compute Engine 未使用的 IP:

  • --filter="status=RESERVED":篩選出顯示狀態為 "RESERVED" 的 IP 出來
  • --format="csv(NAME, ADDRESS, REGION, TYPE)":指定輸出格式為 CSV,並僅包含名稱、地址和地區與類別欄位
  • |:管道符號,將第一個指令的輸出導向到下一個指令的輸入
  • awk:文本處理工具,用於對輸入進行處理
  • NR==1 {print "NAME, ADDRESS, REGION"}:當第一行時輸出 "NAME, ADDRESS, REGION, TYPE" 欄位名稱
  • NR>1 {print $0}:當二行及之後的行時,輸出整行內容

(3) Cloud Function — Python🐍

基本款式的自動化,搭建一個 Cloud Function 後,可以在使用 Cloud Scheduler 來排程輸出相關資訊至指定 channel,作為定期排查閒置資源的資訊

  • project 將專案名稱置入至 Cloud Function 執行階段環境變數中
  • 處理 Cloud Logging 中只顯示了 DEBUG 級別的記錄,但不顯示 INFO 級別的記錄,因此加上 logging.getLogger().setLevel(logging.INFO)
  • compute_client.list 中的 list 是一個方法,它是 AddressesClient 類別的一部分,並使用至 google.cloud.compute_v1 模組
  • 這個 list 方法用於檢索指定區域內包含的地址列表。具體功能是根據提供的 ListAddressesRequest 對象來發送請求並返回地址的分頁結果

程式範例參考

使用 Google Cloud 的官方 Python 客戶端庫(google-cloud-compute

  • e.g., from google.cloud import compute_v1
  • 用途:這個客戶端庫專門針對 GCP 上的 Compute Engine 服務進行了高層次的封裝,提供更簡化的操作界面
  • 功能:提供了對 Compute Engine 相關資源(例如實例、磁盤、網路、地址等)的高層次抽象,開發者可以通過直觀的方法來執行各種操作
Github finops repository

說明

  • list()方法可以接受 ListAddressesRequest 物件與關鍵字參數形式
  • 可以建立一個名為ListAddressesRequest的物件並包含了您要執行操作所需的所有參數,例如專案名稱、區域等
  • 關鍵字參數也可以將專案名稱和區域作為關鍵字參數傳遞給list()方法
  • addresses是 GCP Client Package 用來處理清單分頁的類 <class ‘google.cloud.compute_v1.services.addresses.pagers.ListPager’>,需要遍歷它並從中提取每個 IP 位址的詳細資訊
  • 遍歷的每個 address 的型態為 <class ‘Address’>,表示 address 是一個Address 物件,可使用屬性來存取 Address物件中的各個欄位。例如,要取得位址的類型(address_type)或位址值(address
# 印出 address 裡面的內容
id: 6074783325493135069
kind: "compute#address"
name: "ooo"
creation_timestamp: "2024-02-17T23:56:34.318-08:00"
region: "https://www.googleapis.com/compute/v1/projects/esun-cncf/regions/us-central1"
label_fingerprint: "42WmSpB8rSM="
status: "RESERVED"
address_type: "EXTERNAL"
description: ""
self_link: "https://www.googleapis.com/compute/v1/projects/esun-cncf/regions/us-central1/addresses/ooo"
address: "34.173.122.84"
network_tier: "PREMIUM"
Github finops repository

並記得將 requirement.txt 加入套件依賴項

# Function dependencies, for example:
# package>=version
google-cloud-compute==1.16.1

執行結果如下,並照我們的 logging.info 印出每一個 IP 資訊

進階選項

⚠️ 這部份也看公司或個人使用的需求,如果發現有未使用的 IP 地址(狀態為 RESERVED),除將其資訊添加到列表外,可以再調用 delete_address 函數來刪除未使用的 IP 地址。

自訂義 delete_address function 係使用 compute_clientdelete method

def delete_address(compute_client, project_id, region, address_name):
# 刪除指定地區的 IP 地址
operation = compute_client.delete(project=project_id, region=region, address=address_name)
# 等待操作完成
operation.result()

多專案且未引入組織層定義(常見的沙盒環境)

一個專案還好,如果有數十個或上百個專案呢?另外,因為這個情境是沒有組織與 Folder 層級,就要思考擁有一組服務帳戶來存取多個專案層,作法如下:

  • 在 Project A 選單中 IAM & Admin 選擇 Service Accounts
  • 因為它將在跨專案中使用,請明確定義它,這邊我們提供該服務帳號Viewer 權限,您也可以向權限添加任何條件
  • 切換到 Project B IAM & Admin 選擇 ADD 👨 即 Add Principle to Project B,將先前 Service account ID 引入並建立帳戶,一樣給予 Viewer 權限

程式範例說明
註:初版雛型,驗證可行性使用,還有滿多如 print 及異常處理要調整

  • list_unused_static_ipsget_all_regions function 和 ❶ 單一專案用法一致
  • list_projects:作為主程式處理,紅框包括使用 resource manager 這個模組及藍框是在處理時有遇到不少專案未開啟 Compute Engine API,不加入此異常處理會直接報錯
my Github finops repository
  • is_compute_engine_api_enabled function:功用如 doc string 所示
my Github finops repository

執行結果畫面(1/3 Pages)

第一次在 Lab 執行上面的健檢 script 時,就掃出有高達 20 多個的 External IP 閒置在雲端燒錢!Σ(;゚д゚) 約莫每月燒個 20 ✖ $10 USD

紅框為閒置的 External IP;黃框為 Internal IP 對了帳單及 GCP 公告,雖不計價,但會造成管理上的困擾

多專案且為組織層定義(公司環境或引入組織作為資安管理用途)

實作細節參照上面資訊,需要留意的是要在組織層級設定權限,GCP 預定義角色roles/browser 可以滿足相關需求,若是要自訂角色應該會有以下的權限要考量

  • resourcemanager.projects.get
  • resourcemanager.project.list
  • resourcemanager.folders.get
  • resourcemanager.folders.list

總結

糟糕,過程滿多細節不少,造成篇幅過長,2️⃣ & 3️⃣ 有空再放入 Part2 中。

2️⃣ Clean up unattached and orphaned persistent disks
3️⃣ 遷移到更經濟實惠的儲存類別

重點就是建立一個自動化的系統,用於識別和減少雲端支出的浪費或作一些資訊上的揭露。

--

--

Kellen

Backend(Python)/K8s and Container eco-system/Technical&Product Manager/host Developer Experience/早期投入資料創新與 ETL 工作,近期堆疊 Cloud☁️ 解決方案並記錄實作與一些雲端概念💡