使用 AWS SSM Parameter Store 實現集中式設定管理,解決多專案 CI/CD 變數分散問題
前言
過去在前幾份工作經驗中,大型專案 / 大型公司在管理變數時,常會遇到幾個問題:
- 有 global 的變數需全公司共用
- 部門內也會有多個 Project 需共用變數
- 單個 Project 也有不同 environment 的變數
如果是用那種各 Project 各自設定 variables 的作法,不管是設在 project 內的 config,還是設在 GitHub/Gitlab 的 variables 中,同個變數都有可能在多個不同專案中被重複設定
如果這些專案都只有一個人管理或許沒事,但如果未來共同維護的 RD 越來越多,組別拆分越來越細,一旦要更新 value,有任何一個組別 / Project 沒通知到要改,一上線就會大爆炸了 🚬
過去我也曾經為了上述的問題花費不少維護時間,所以我決定開個 side project 進一步研究,陸續做一些嘗試後,最終收斂出一個可行的解決方案 → 使用雲端參數集中管理服務!
什麼是 AWS SSM Parameter Store
雲端參數集中管理服務有很多種,可以看你用哪一家的雲來做選擇,這裡我使用的是 AWS 的 SSM Parameter Store
SSM Parameter Store 是一個由 AWS 提供的「參數管理服務」,可以用來集中儲存和管理 Application 的 variables 和 secrets
使用它有以下幾個好處:
- 可集中管理變數,不會四散在各地
- 可供多 Project 共用
- 支援 AWS KMS 加密,安全性更高
- 可透過 IAM 限制參數存取的權限(哪個專案可以存取哪些變數)
- 有版本控制,每次變更都會有更改紀錄可以追蹤,要 rollback 也很方便
- 費用便宜,如果只是使用 Standard 參數的話甚至是免費的(Advanced 才要收費,採用 1 個參數每個月多少錢的計算方式)
接下來會簡單展示一下創建的方式,並沿途做一些知識補充與探討,以及最後也會提供 GitHub Action yaml 給大家使用
開始~~~~~!
Create Parameter Store (AWS Console)
有好幾種方式(CLI、Terraform、AWS Console)可以創建 Parameter Store
這裡我用 AWS Console 示範
搜尋 Systems Manager
我的參數 > 建立參數
名稱
可以用斜線做多層的結構,方便之後需限制權限時可以分層管控
( ex: /a-team/a-project/prod/xxurl )
方案
根據自身的使用情境選擇
| Standard ( 標準 ) | Advanced ( 高級 ) | |
| 數量上限 (每個 AWS account / 每個 region) | 10,000 | 100,000 |
| 單筆容量 | 4 KB | 8 KB |
| 可用 Parameter Policy | ❌ | ✅ |
| 可與其他 AWS 帳戶分享 | ❌ | ✅ |
| 定價 | Free | 每個 Advanced 參數 每月 0.05 USD |
費用可能會隨時間異動,最新金額以官方公告為主:集中式營運中心 – AWS Systems Manager 定價 – Amazon Web Services
類型
String:
儲存非敏感的純文字資訊,無加密,沒有 KMS 保護StringList:
他會儲存像是這樣的資料結構 → value1,value2,value3
需要多個值的時候使用SecureString:
儲存敏感資訊,會使用 KMS 加密
KMS 金鑰 ID 可以使用他預設的
KMS 金鑰來源
顧名思義,看你的 Key 是放在目前帳戶還是放在其他帳戶,根據自身情況選擇
KMS 金鑰 ID
指定「用哪一把 Key 來加解密資料」,不一定要更改它,可以用 AWS 預設的
更多 AWS KMS Key 詳情可參考:AWS KMS keys - AWS Key Management Service
值
就 Value,如果類型選擇 SecureString,KMS 會自動對這個內容進行加密
標籤
如果你有想要為變數分組方便日後管理或設置權限,可以添加標籤,結構是 key / value
填好後創建即可 👍
Parameter Store 介紹 (AWS Console)
新增完的變數可以在列表看到
點擊參數本身,可以進到詳情頁
如果是 SecureString,他的值 Default 會是隱藏的
如果你有權限查看,就可以在這裡打開來確認 Value 的內容
歷程紀錄中則可以看到每次變更的 Value、更改時間、更改的 User 是誰
值得注意的是,歷程記錄中的標籤欄位,並不等於參數的標籤喔!
他是 版本的別名(alias)
每次異動變數時,AWS 都會新增一個版本,其中版本號是流水號,只會一直累加,如果需要用一個有意義的名稱來指向特定版本,並藉此用來快速切換 & rollback,就可以使用標籤功能
(ex: 程式碼那邊讀取變數時是吃 current,目前線上使用的是最新的版本 2,他被添加了一個標籤「current」,如果我要退版,我只要移除版本 2 的標籤,在版本 1 添加標籤「current」即可,程式碼就不用動)
更多詳情可參考官方:Working with parameter labels in Parameter Store - AWS Systems Manager
如果你有新增參數的標籤,就可以在標籤分頁看到
Parameter Store / Secrets Manager 抉擇
AWS 除了 Parameter Store 可以用來儲存參數以外,還有另一個選擇:Secrets Manager
所以這裡我想比較一下這 2 個服務的差異
Secrets Manager 是 AWS「專門」提供用來存放敏感資訊的服務
更多詳情可參考官方文件:什麼是 AWS Secrets Manager? - AWS Secrets Manager
看到這裡很多人會產生一個疑惑❓
一般非敏感資訊存 Parameter store 沒問題,但敏感資訊應該存哪裏比較正確?
(1) Parameter store 的 SecureString
(2) Secrets Manager
過去在技術論壇中常會看到有人在討論這個議題,其中蠻多人會選擇 (2),原因在於跟 Parameter Store 相比,Secrets Manager 還多了跨帳號共享和Auto Rotation功能,並且它的容量更大,能存放更多變數,以功能定位來說用來存放敏感資訊也極為合理
but …. Secrets Manager 最大的缺點就是他比較貴 🤢
然而~隨著時代的變化,Parameter Store 缺乏跨帳號共享和Auto Rotation的問題也已經不是問題了!
Parameter Store 從 2024 年 2 月起開始允許分享(Advanced)參數
接著,這裡簡單討論一下Auto Rotation的問題
Secrets Manager 它底層是透過呼叫 Lambda function 來做 Auto Rotation
只要有支援 rotation 的 AWS 服務(ex:RDS),AWS 就會自動幫我們建立對應的 Lambda function,不用自己撰寫 Lambda 邏輯
而 Parameter Store 因為預設沒有 Auto Rotation 功能
所以如果要做到 Auto Rotation,就要另外自行開發 Lambda Function,用 EventBridge 去 trigger 定期更改 RDS 的密碼,以及更新 Parameter Store 的值
這裡再放個表格整理一下他們的差異細節
| Secrets Manager | Parameter Store (Advanced) | |
| 定位 | 專門管理「機密資料」 | 通用的資料存放服務,可存放一般資料、機密資料 |
| 加密 | 預設強制 KMS 加密 | SecureString 才可用 KMS 加密 |
| Rotation ( 定期更換機密資料 ) | ✅ | ❌ (但可自己實作) |
| 跨帳號共享 | ✅ | ✅ |
| 版本管理 | ✅ 內建「版本狀態機制」,AWS 幫你管理 current / previous / pending | ✅ 只有「版本流水號」,狀態(current / previous / pending)要自己用 label 管 |
| 單筆容量 | 64 KB | 8 KB |
| 數量上限 (每個 AWS account / 每個 region) | 500,000 個 secrets | 100,000 個 Advanced |
| 定價 | 每個 Secrets 參數 每月 0.40 USD 每 10,000 次 API 呼叫 0.05 USD | 每個 Advanced 參數 每月 0.05 USD |
溫馨提醒:以上關於容量、費用等數值會隨時間異動,此表僅供參考,最新資訊請以官方公告為主
從上面的表格中可以看到
他們主要是差異在容量、數量大小限制
大部分的功能沒差多少
即使 Parameter Store 沒有內建 Auto Rotation 功能,也依然可以自己架出差不多的自動化架構
若你使用量沒有那麼大,使用 Parameter Store (Advanced) 是相對比較經濟實惠的選擇
那就看你們公司的現有條件適合哪一種囉~
在 GitHub Actions 存取 Parameter Store
要讓 GitHub Actions 能存取 AWS 服務的話,需要先做身分驗證以取得存取的權限(Create Access Key 或使用 OIDC),這裡主要著重在變數管理,我就不補充存取權限的部分了,不知道的夥伴們再自行爬文,以下假設你已經做好權限的處理~
這裡我把它包成一個 GitHub Actions composite action,方便重複使用
.github/actions/get-ssm-parameters/action.yml
🟠 input
這個 composite action 接受一個 input 參數 ssm_param_path
這裡要輸入你 Parameter Store 創建的路徑
(ex:/budget-sentinel/prod)
🟠 variables 存取方式
yaml 中會去逐一取出這個路徑底下的所有 Parameter Store,並取路徑的最後一段作為變數名稱
(ex:/budget-sentinel/prod/TEST_URL 只取 TEST_URL)
使用 GitHub Actions 的 ::add-mask:: workflow command,避免敏感資訊列印在 GitHub Actions Log,加了這個設定後他在 Log 就會被打碼,變成 *******,但不會影響他真正的 value
更多 workflow command 說明可參考:GitHub Actions 的工作流命令 - GitHub 文档
🟠 output
接著他會將所有參數以逗號串聯,輸出成 $GITHUB_OUTPUT
(ex:"TEST_URL": "***","TEST_URL_2": "***")
使用端 yml
使用端就可以新增一個 step(Get SSM Parameters),呼叫 composite action 以取得逗號分隔的變數們
為此 step 設置 id,讓其他 step 可以用 steps.<id>.outputs.<output名稱> 存取它的輸出值
其他 step 就取 ${{ steps.get-ssm.outputs.env_vars }} 自行加工使用
這個 yaml 以取某一個路徑底下的所有變數為範例,大家可以根據需求自行微調
因為所有變數都統一集中在 AWS SSM Parameter Store
所以只要有存取權限的 Project 都可以使用那些變數
未來要改某個變數值,只要改一個地方,所有有用到它的 Project 都可以吃到最新的,提高可維護性~
END











