iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
Kubernetes

Kubernetes圖解筆記系列 第 29

Day-29 變數管理

  • 分享至 

  • xImage
  •  

設定在環境中的重要資訊 (⁎⁍̴̛ᴗ⁍̴̛⁎)


在 Serverless 架構中,常會面臨到應用程式變數應該如何配置的問題。尤其是像 Token、API Key、憑證等敏感資訊,更不能隨意存放,也不應該直接寫入程式碼中,必須採取安全的管理方式。

一般會將資訊儲存在幾種地方:

  • 環境變數 (Environment Variables)
    通常在會在部署時指定,並在服務啟動時透過程式碼存取

  • 外部儲存
    可能是資料庫或其他儲存服務,會在服務啟動或者需要時執行讀取

  • 配置管理服務
    雲平台供應商都會提供相對應的儲存方案

    • AWS:Systems Manager Parameter StoreSecrets Manager
    • Azure:Key Vault
    • GCP:Secret Manager

    這些工具提供了安全的儲存方式,並且確保應用程式可以動態且安全地讀取這些資訊。

  • Configuration Files
    某些情況下,變數可以透過部署工具的配置檔案進行管理。多半適用於雲平台,透過 yaml 設定檔將變數管理從程式碼中抽離出來,與工具做關聯,使服務在部署時能透過工具讀取變數,再注入到執行環境中。

這些方法提供了靈活性和安全性,確保 Serverless 應用程式能夠安全、動態地管理應用程式運行需要的敏感資訊。

而在 Kubernetes (K8s) 中,環境變數的配置由 SecretConfigMap 兩種資源來管理:

  • ConfigMap
    主要用於存儲非機密的資訊,如:環境變數、配置檔案或命令參數。
    資訊由 Cluster 中的所有 Pod 共享和重用。
  • Secret
    專門設計用來保存敏感資訊,例如密碼、API Key和憑證。
    這些訊息會以加密的方式存儲,避免在配置過程中暴露在不安全的環境中。

ConfigMap


集中管理 Pod 使用到的環境變數。
設定方式:

  • command
    kubectl create configmap \ 
    <config-name> --from-literal=<key1>=<value1> \
                  --from-literal=<key2>=<value2>
    # 範例
    kubectl create configmap \ 
    app-config  --from-literal=APP_ENV=prod \ 
                --from-literal=APP_COLOR=blue
    
  • yaml file
    apiVersion: v1 
    kind: ConfigMap 
    metadata: 
      name: app-config 
    data: 
      APP_ENV: prod 
      APP_COLOR: blue
    

這邊要特別留意,使用的是 data 而不是 spec

建立完成後,需將設定掛載進 Pod 中

有三種設定方式

  • 作為環境變數:envFrom
    apiVersion: v1
    kind: Pod
    metadata:
      name: webapp-color-pod
    spec:
      containers:
        - name: webapp-color
          image: webapp-color
          ports:
            - containerPort: 8080
          envFrom: 
            - configMapRef:
                name: app-config
    
  • 只取用部分設定值:env
    apiVersion: v1
    kind: Pod
    metadata:
      name: webapp-color-pod
    spec:
      containers:
        - name: webapp-color
          image: webapp-color
          ports:
            - containerPort: 8080
          env:
            - name: APP_COLOR
              valueFrom:
                configMapKeyRef:
                  name: app-config
                  key: APP_COLOR
    
  • 文件配置:volume
    apiVersion: v1
    kind: Pod
    metadata:
      name: webapp-color-pod
    spec:
      containers:
        - name: webapp-color
          image: webapp-color
          ports:
            - containerPort: 8080
          volumes:
          - name: app-config-volume
            configMap:
              name: app-config
    

透過 volumes 配置的 ConfigMap ,每一個 Key 都會被轉換為一個單獨的文件,文件名是 Key,文件的內容是 Value。讀取方式需要透過文件路徑,與另外兩種設定方式有所不同,需特別留意。

volumes 配置適用於 複雜的設定 或者 需要頻繁訪問和更新 的情境

Secret


保存敏感資訊,例如密碼、API Key和憑證。
設定方式:

  • command
    可透過直接寫入 key-value 或從 file 引入
    # key-value
    kubectl create secret generic <secret-name> --from-literal=key=value 
    # from file
    kubectl create secret generic <secret-name> --from-file=<file-path>
    
  • yaml
    apiVersion: v1 
    kind: Secret 
    metadata: 
      name: app-secret 
    data: 
      DB_HOST: mysql
      DB_USER: root 
      DB_PASSWORD: password
    

建立後同樣需引入 Pod 設定中

(ConfigMap 說明過這邊就不再贅述)

apiVersion: v1
kind: Pod
metadata:
  name: webapp-color-pod
spec:
  containers:
    - name: webapp-color
      image: webapp-color
      ports:
        - containerPort: 8080
      # ===== envFrom =====
      envFrom:
        - secretRef:
              name: db-secret
      # ===== env =====
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: DB_PASSWORD
      # ===== volume =====
      volumes:
      - name: app-secret-volume
        secret:
          secretName: app-secret

通常介紹是這樣寫,但其實 Secret 一點都不 Secret

相關討論可搭配這篇文章:Shhhh... Kubernetes Secrets Are Not Really Secret!

事情是這樣的:Secret 在預設情況下根本就沒有加密。
它只是有經過 base64 編碼,雖然不是明目張膽的存明碼,但也說不上是加密資訊。
並且,透過 Secret 儲存的資訊是存在 ETCD 中,只要有 kube-apiserver 對應存取權ETCD存取權 的人或服務,都有權限可以讀取、修改 Secret 值。
就算透過 Namespace 做環境隔離,也無法阻擋同一個 Namespace 中的 Pod 進行 Secret 存取。

那怎麼辦!!!

視執行平台而定。

  • 如果是雲平台供應商,多半都已經有解決方案,可以直接使用 Secret Management 相關服務。
  • 如果是自行建置呢?
    可以使用 Kubernetes 的 CSI 機制。
    此方案是將機敏資訊儲存在其他服務中:如 Secret Manager (AWS、GCP),Key Vault(Azure)甚至是地端,透過將資訊 mount 進 Pod 中提供程式存取使用。
    https://ithelp.ithome.com.tw/upload/images/20240930/201684371Oa9AwNQCq.png

Secrets Store CSI DriverSecrets Store CSI Provider 是配套使用的插件,用來實現 Kubernetes 從外部讀取 Secrets 的機制。

  • Secrets Store CSI Driver:負責從指定的管理服務中提取 Secret,並將其掛載到 Pod 之中。
  • Secrets Store CSI Provider :與外部存儲系統的通訊橋樑

這個方式是在 Pod 啟動(或重新啟動)時執行,透過 CSI Driver 使用 gRPC 與 CSI Provider 進行通訊,從自訂外部資源中將擷取指定的內容寫入磁碟區(volume),最後再將該磁碟區掛載到 Pod 中。

一旦 Pod 資源消失,Secret 也會跟著消失。
不但保證了 Pod 使用時不需要直接讀取外部儲存區,也確保了 Secret 在 Cluster 中的安全隱密性。

能不能將資訊直接存入其他雲端服務中,再 Import 進 Secret 使用?

技術上可行,但不建議這樣做。
這只是避免了直接在 Secret 設定的 yaml 中直接出現機敏資訊,卻沒有解決 Secret 中的值本身安全性不足的問題。
相關安全基準可參考:CIS Benchmarks

Ref: 在GKE安全地使用帳密(GCP KMS)


小結

其實關於 Secret 的使用有不少相關討論,在不同的環境中也有不同的解決方案。同時兼顧安全性與實用性才能使系統運行更加穩定。
畢竟,沒人想看到為了做資訊的加解密而導致系統延遲或是效能不彰吧?


上一篇
Day-28 Metrics Server
下一篇
Day-30 Volumes
系列文
Kubernetes圖解筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言