4 min read

GCP GKE 掛載 cloud storage

以下操作將會使用到 GCP IAM 服務帳戶, Cloud Stroage 這兩個服務

大致上分為以下幾個步驟

  1. 創建IAM 服務帳戶
  2. 創建 cloud storage bucket 及給予權限
  3. 返回第一步驟,並配置關鍵的GKE SA帳號(請注意格式!)

目前會有以下有可能的風險,以及要注意的事項

  1. 容器內給予chmod chown 無效
  2. 在瞬間寫入大量文件時,速度比較慢


1.創建服務帳戶

IAM -> 服務帳戶 -> +建立服務帳戶 創建一組給 cloud storage專用的帳號 ,名稱可以自定義,主要是服務帳戶ID(右圖)稍後會用到,權限具備存取權的主體預設配置即可。

2.創建 cloud storage bucket

選擇授予存取權 -> 新增主體

  1. 主體 -> 上方創建的IAM服務帳戶email。
  2. 角色 -> 儲存空間物件管理員。

3.返回IAM服務帳戶

接下來要到最關鍵的環節,配置具備存取權的主體要填入給GKE使用的SA帳號。

格式為 {project_id}.svc.id.goog[{gke_namespace}/{sa_name}]

example:

  1. GCP 帳號ID為 wooo1314
  2. GKE namespace prod
  3. GKE service Account php

則填入 woo1314.svc.id.goog[prod/php]


最後

以下是使用的範例

apiVersion: v1
kind: ServiceAccount
metadata:
  name: storage-sa
  namespace: prod
  annotations:
    iam.gke.io/gcp-service-account: [email protected]
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php
  namespace: prod
spec:
  selector:
    matchLabels:
      app: php
  template:
    metadata:
      labels:
        app: php
      annotations:
        gke-gcsfuse/volumes: "true"
        gke-gcsfuse/ephemeral-storage-limit: "5Gi" # 建議開啟
        gke-gcsfuse/cpu-limit: "500m" # 建議加上 CPU 限制
        gke-gcsfuse/memory-limit: "1Gi" # 建議加上記憶體限制
    spec:
      serviceAccountName: storage-sa
      containers:
      - name: php
        image: asia-east1-docker.pkg.dev/1234/5678/php
        ports:
        - containerPort: 80
          name: http
        readinessProbe:
          httpGet:
            path: /api/app/version
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 15
        imagePullPolicy: Always
        workingDir: /app
        resources:
          limits:
            cpu: "1000m"
            memory: "2096Mi"
          requests:
            cpu: "500m"
            memory: "200Mi"
        volumeMounts:
        - name: gcs-fuse
          mountPath: /app/http/static
      volumes:
      - name: gcs-fuse
        csi:
          driver: gcsfuse.csi.storage.gke.io
          volumeAttributes:
            bucketName: test-1230-v2 # 輸入創建的bucketName
            mountOptions: "implicit-dirs,http-client-timeout=10s,stat-cache-ttl=1m"

透過glcoud 一鍵快捷

#!/bin/bash
set -e # 遇到錯誤立即停止

# ==========================================
# 1. 設定您的變數 (請修改這裡)
# ==========================================
PROJECT_ID="xxx-xxx"      # 您的 GCP Project ID
CLUSTER_NAME="test-1"               # GKE 集群名稱
REGION="asia-east1"                 # GKE 集群區域
NAMESPACE="prod"                    # K8s Namespace
BUCKET_NAME="test-bucket"           # 要創建/使用的 Bucket 名稱
GSA_NAME="test-storage"        # GCP Service Account 名稱
KSA_NAME="test-storage"        # K8s Service Account 名稱

# ==========================================
# 2. 開始執行 GCP 設定
# ==========================================
echo "=== 正在切換專案到 $PROJECT_ID ==="
gcloud config set project $PROJECT_ID

echo "=== 正在啟用必要的 API ==="
gcloud services enable container.googleapis.com storage.googleapis.com iam.googleapis.com

echo "=== 正在檢查/創建 Bucket: gs://$BUCKET_NAME ==="
if ! gcloud storage buckets describe gs://$BUCKET_NAME > /dev/null 2>&1; then
    gcloud storage buckets create gs://$BUCKET_NAME --location=$REGION
    echo "Bucket 已創建。"
else
    echo "Bucket 已存在,跳過創建。"
fi

echo "=== 正在創建 GCP Service Account: $GSA_NAME ==="
if ! gcloud iam service-accounts describe $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com > /dev/null 2>&1; then
    gcloud iam service-accounts create $GSA_NAME --display-name="GCS FUSE Access for GKE"
    echo "SA 創建請求已發送,正在等待權限傳播 (30秒)..."
    sleep 30  # <--- 加入這行等待
else
    echo "SA 已存在,跳過創建。"
fi

echo "=== 正在賦予 Bucket 權限 (Storage Object Admin) ==="
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_NAME \
    --member "serviceAccount:$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
    --role "roles/storage.objectAdmin"

echo "=== 正在綁定 Workload Identity (允許 K8s SA 扮演 GCP SA) ==="
gcloud iam service-accounts add-iam-policy-binding $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]"