iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
Kubernetes

異世界生存戰記:30天煉成GKE大師系列 第 17

Day17 GKE 秘密封印:External Secret Manager & Reloader

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20241001/20169017u3DK8garMj.png

前言

K8s 的 Secret 是儲存應用程式敏感資訊的組件,但是如何管理以及傳遞敏感資訊到 K8s Secret 中是一個重要課題。

在本文中,我們將使用 External Secrets Operator 結合 GCP Secret Manager 和 GKE Secrets,可以安全且方便地使用 GCP 的 Secret Manager 服務來管理 GKE 的環境變數。此外,還將介紹在更新K8s Secret 物件時的痛點,每當我們更新 K8s 內部作為環境變數傳遞的 Secret 時,我們都需要重新啟動 pod 才能吃到新的環境變數,因此我們安裝 Reloader 來解決此問題。

GCP Secret Manager 介紹

Google Cloud Secret Manager 是一項安全且易於使用的服務,用於儲存和管理 API 金鑰、密碼和其他敏感資料。它讓開發人員可以集中儲存和輪替祕密,而無需在應用程式程式碼中直接管理它們。Secret Manager 提供版本控制、審核日誌和存取權限控制等功能,確保祕密的安全性與合規性。透過 Secret Manager,您可以保護敏感資訊,簡化祕密管理程序,並降低安全性漏洞的風險。

External Secrets Operator 介紹

Kubernetes External Secrets Operator 解決了將敏感資料(例如密碼、憑證)安全儲存在 Kubernetes 叢集中的難題。它能讓你將這些機密資訊儲存在外部金鑰管理系統,例如 HashiCorp Vault、AWS Secrets Manager 或 Google Secret Manager,並將其安全地掛載到你的應用程式中。External Secrets Operator 會自動同步外部金鑰管理系統和 Kubernetes Secrets,確保你的應用程式始终使用最新的憑證,而無需將敏感資料直接儲存在叢集中。

K8s Reloader 介紹

Kubernetes Reloader 是一種 Kubernetes 工具,可幫助您在容器化應用程式更新時自動執行容器更新。它會監控組態變更,例如 ConfigMaps 和 Secrets,並在偵測到變更時觸發部署或 Pod 的滾動更新。這可讓開發人員無需手動重新啟動 Pod 或重新部署應用程式,即可輕鬆地更新設定、機密資訊和其他應用程式相依性,從而簡化部署程序並減少停機時間。

在 GKE 內安裝 External Secrets Operator

$ helm repo add external-secrets https://charts.external-secrets.io
$ helm pull external-secrets/external-secrets  
$ helm install external-secrets \
   external-secrets/external-secrets \
    -n external-secrets \
    --create-namespace \
    --set installCRDs=true

啟用 GCP Secret Manager API

https://ithelp.ithome.com.tw/upload/images/20241001/20169017Oc7eJYBSCJ.png

建立 ClusterSecretStore.yaml

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: gcp-secret-manager
  namespace: external-secrets
  labels:
	  # 打標籤方便分類
    environment: ithome-202409-demo-2
spec:
  provider:
    gcpsm:
    # 改成GCP Secret Manager專案ID
      projectID: ithome-202409-demo-2
      auth:
        workloadIdentity:
          # name of the cluster region
          clusterLocation: us-central1
          # name of the GKE cluster
          clusterName: demo2-cluster
          # reference the sa from above
          serviceAccountRef:
            name: external-secrets
            namespace: external-secrets

https://ithelp.ithome.com.tw/upload/images/20241001/20169017DBzCf1bAGL.png

到 GCP Secret Manager 頁面,建立 httpbin-eso 密鑰

https://ithelp.ithome.com.tw/upload/images/20241001/20169017T8SprNMiFK.png

加入兩個 Secret,要使用 JSON 格式

{
  "eso-name": "httpbin-eso",
  "ping": "pong"
}

創建 ExternalSecret httpbin-config.yaml

# test-deployment.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: httpbin-config
  namespace: httpd
spec:
  # 這將每1分鐘刷新一次金鑰。可以根據自己的要求保留時間。
  refreshInterval: 1m
  secretStoreRef:
    name: gcp-secret-manager
    kind: ClusterSecretStore
  target:
  # 輸入剛剛創建的GCP External Secret名稱 httpbin-eso
    name: httpbin-eso
    creationPolicy: Owner
  dataFrom:
    - extract:
        key: httpbin-eso

這時會發現 K8s 的 Secret 物件已經從 GCP 的 Secret Manager 引入 httpbin-eso 然後創建出來了。

$ kubectl get secrets -n httpd         

NAME             TYPE        DATA   AGE
httpbin-eso      Opaque      2      1m

https://ithelp.ithome.com.tw/upload/images/20241001/20169017V0nM0Vf3vH.png

創建 test-deployment.yaml,在 envFrom 添加 secretRef.name: httpbin-eso,從 K8s Secret 物件注入環境變數

# test-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  namespace: httpd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
  template:
    metadata:
      labels:
        app: httpbin
    spec:
      containers:
        - image: specialyang/go-httpbin:v3
          args:
            - "--port=8090"
            - "--version=v1"
          imagePullPolicy: Always
          name: go-httpbin
          ports:
            - containerPort: 8090
# 在這裡添加環境變數來源
          envFrom:
            - secretRef:
                name: httpbin-eso

安裝 K8s Reloader

$ helm repo add stakater https://stakater.github.io/stakater-charts
$ helm repo update
$ helm install stakater/reloader
$ helm install reloader stakater/reloader -n reloader --create-namespace

預設情況下,reloader會偵測所有namespace的資源,如果要針對單一 Namespace 可使用 --set reloader.watchGlobally 為 false,以下範例為安裝在 reloader Namespace 並只偵測 foo Namespace 底下的資源

$ helm install reloader stakater/reloader -n reloader --set reloader.watchGlobally=false --namespace foo

將上面的 test-deployment.yaml 中的 metadata.annotations 新增 reloader.stakater.com/auto: "true"

metadata:
  annotations:
    reloader.stakater.com/auto: "true"

更新 GCP External Secret httpbin-eso,多一個 "version": "v1"

{
  "eso-name": "httpbin-eso",
  "ping": "pong",
  "version": "v1"
}

等待 1 分鐘左右,可以看到 test-deployment 自動開始重啟,出現新的 Pod 了

$ kubectl get pod -n httpd
                    
NAME                          READY   STATUS    RESTARTS   AGE
httpbin-c66bfd5b6-ml5jk       1/1     Running   0          29s

進入 httpbin Pod 執行指令,印出 version 環境變數,確認環境變數有被 Pod 吃進去

$ exec kubectl exec -i -t -n httpd httpbin-c66bfd5b6-ml5jk -c go-httpbin -- sh

$ echo $version
v1

總結

本文介紹了如何使用 GCP Secret Manager 和 K8s External Secrets 來安全管理和部署應用密鑰,並結合 K8s Reloader 實現自動更新。

首先,我們深入探討了將敏感信息存儲在 K8s Secret 中的風險,並引入了 GCP Secret Manager 作為更安全的替代方案。 接著,我們詳細介紹了如何利用 External Secrets Operator 將存儲在 GCP Secret Manager 中的密鑰同步到 GKE 集群中,從而實現應用程序對密鑰的安全訪問。

最後,我們展示了如何配置 K8s Reloader 來自動檢測 Secret 更新,並觸發 Deployment 重啟,從而確保應用程序始終使用最新的配置和密鑰。

通過這種方法,我們可以提高 GKE 應用程序的安全性,並簡化密鑰管理流程,實現更加安全、高效的雲原生應用部署。

參考文件


上一篇
Day16 Kubernetes 安全遠程操控術(三):Teleport 結合 Lens 的複合魔法
下一篇
Day18 GKE 共享的魔法卷軸(一):GKE NFS FileStore
系列文
異世界生存戰記:30天煉成GKE大師30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言