iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
Cloud Native

EKS in Practice:IaC × GitOps 實戰 30 天系列 第 12

[Day 12] Cross Cluster GitOps:Argo CD Repo/Cluster Secret 的安全實作

  • 分享至 

  • xImage
  •  

前言

昨天我們已經安裝好 ArgoCD,但要讓它「真正」開始工作,還需要一件關鍵設定:Secret

ArgoCD 必須要能夠存取 Git repository,才有辦法讀取 desired state,也就是我們所希望的 cluster 配置。而這個存取的方式,會需要 ArgoCD 透過 ssh 向 git server 發出請求,才有辦法被授權允許存取 manifests。本篇的前半段會先以 GitLab 為例,介紹該如何在 GitLab 上設定這個 repo secret,並且讓 ArgoCD 可以正確存取他。

此外,雖然在安裝 ArgoCD 的時候,helm chart 中已經包含了 ArgoCD 所要被安裝到的 cluster 中的所有權限;而這些權限都是使用 pod 所在的 service account 來存取 in-cluster API。但當今天我們希望 ArgoCD 可以做到跨 cluster 的 application 管理時(如下圖),就必須要將 target cluster 的 cluster secret 記錄在 ArgoCD 所運行的 cluster 中。因此,本篇的下半段會介紹 cluster secret 儲存的方式。

https://ithelp.ithome.com.tw/upload/images/20250912/20119667eMMDOlLIWL.png

Repo Secret

首先是 Repo Secret,這裡的用途是讓 Argo CD 可以存取 GitLab Repo。

流程如下:

  1. 建立 SSH Key,並把 public key 註冊到 repo 的 Deploy Keys。

    ssh-keygen -t rsa -C "argo-repo"
    cat ~/.ssh/argo-repo.pub
    
  2. private key 做 base64 encode,存放到 AWS Secrets Manager。

    cat ~/.ssh/argo-repo | base64
    
  3. 使用 ExternalSecret 從 AWS Secrets Manager 拉取這個 private key,並寫入到 K8s Secret:

    apiVersion: external-secrets.io/v1beta1
    kind: ExternalSecret
    metadata:
      name: argo-repo-secret-[project-name]
      namespace: argocd
    spec:
    	##### Key Point 1
      secretStoreRef:
        kind: ClusterSecretStore
        name: default
      target:
        name: argo-repo-secret-[project-name]
        ##### Key Point 2
        template:
          metadata:
            labels:
              "argocd.argoproj.io/secret-type": repo-creds
          data:
            type: git
            name: project-name
            project: project-name
            url: git@gitlab.com:our-group/sre/project-name.git
            ##### Key Point 3
            sshPrivateKey: '{{ .retrievedSshKey }}'
      data:
        - secretKey: retrievedSshKey
          remoteRef:
            key: argocd-repo-key
            property: project-name
            decodingStrategy: Base64
    
    • Key Point 1:我們會採用昨天在部署 ExternalSecret 時,順手佈建的 ClusterSecretStore 作為存取 AWS Secrets Manager 的來源。

    • Key Point 2:因為 Secret 需要符合 ArgoCD 指定的特定格式,才有辦法讓 ArgoCD 知道這個 Secret 所代表的是 Repo Secret。因此,我們必需要在 ExternalSecret 裡面指定他長出來的 K8s Secret 的格式、以及他所帶有的資料欄位(包含 spec.target.template.data 欄位下的 type / name / project / url / sshPrivateKey 等),都是向 git repo 連線時的必要資訊。

    • Key Point 3:這邊是 ExternalSecret 內部的 reference 方式。我們在 spec.data 可以指定要讀取 Secrets Manager 的哪個 Secret,以及要拿取這個 Secret 下、哪個 Key 的 Value。但是要注意,remoteRef.key 要填寫的是 Secrets Manager 的 Secret name,remoteRef.property 才是 Secret 中的 Key

      https://ithelp.ithome.com.tw/upload/images/20250912/20119667WH0MmsufXF.png

      注意:這邊每多一個需要 ArgoCD 讀取的 repo,就要多寫一個 ExternalSecret resource 哦!

這樣 Argo CD 就能透過這個 Secret 去拉取 repo 了。設定 ExternalSecret 之後,可以到 ArgoCD UI 上檢查是否有正確連接到 repo。路徑是 Settings > Repositories:
https://ithelp.ithome.com.tw/upload/images/20250913/20119667pjmfYmsXpM.png

Cluster Secret

Repo Secret 解決了「Argo CD 如何讀 repo」,但還要解決「Argo CD 如何寫進 cluster」。這部分需要設定 Cluster Secret

在這裡,我們不是手動準備好 kubeconfig / token 再用 ExternalSecret 生 Secret,而是把這件事直接寫在 被納管的 cluster Terraform module 裡面。換句話說:每當 Terraform 建立一個新 cluster,就會同時在那個 cluster 裡面部署一個 ExternalSecret,由它去 AWS Secrets Manager 取回對應的憑證,並且生成 ArgoCD 可讀取的 cluster secret。

🔑 注意:這些 cluster secret 會只存放在「專案帳號」自己的 AWS Secrets Manager,而不是 central Argo CD 所在的帳號。這樣做可以避免不同帳號之間的敏感資訊混用,也能讓專案團隊自行控管憑證的生命週期。

這樣的做法有幾個好處:

  • 自動化:cluster 一旦被建立,ArgoCD 就能立即管理它。
  • 一致性:每個 cluster 的 secret 都遵循相同的規範,不需要手動補充。
  • 安全性:敏感憑證仍然只存放在專案帳號的 AWS Secrets Manager,不會進到 Git repo,更不會集中到 central account。

以下是我們在 Terraform module 中會產生的範例 YAML:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: argo-repo-secret-${var.argo_config.source.repo_name}
  namespace: argocd
spec:
  secretStoreRef:
    kind: ClusterSecretStore
    ##### Key point: 專案帳號也會部署一個 ClusterSecretStore 作為 Secrets Manager 的中介
    name: ${local.cluster_secret_store_name}
  target:
    name: argo-repo-secret-${var.argo_config.source.repo_name}
    template:
	  ##### Key point: 如同 Repo Secret,Cluster Secret 也會需要符合特定格式
      metadata:
        labels:
          "argocd.argoproj.io/secret-type": cluster
      data:
        name: ${var.project_name}
        server: ${var.argo_config.cluster.endpoint}
        config: |
          {
            "bearerToken": "{{ .bearerToken }}",
            "tlsClientConfig": {
              "insecure": false,
              "caData": "{{ .caData }}"
            }
          }
  data:
  - secretKey: bearerToken
    remoteRef:
      key: argocd-cluster-key
      property: ${var.project_name}-bearer
      decodingStrategy: Base64
  - secretKey: caData
    remoteRef:
      key: argocd-cluster-key
      property: ${var.project_name}-ca
      decodingStrategy: Base64

只要這個 Secret 存在於 argocd namespace,Argo CD 就會自動識別並把它當成可用的 cluster 來管理。正確納管之後,可以到 ArgoCD 的介面上,點選 Settings > Clusters,就會有已被納管的 cluster 列表,如下圖:
https://ithelp.ithome.com.tw/upload/images/20250913/20119667YZUkHLEzAL.png

ExternalSecret 在這裡的角色

在 Day 11,我們已經先安裝 External Secrets Controller。今天在設定 Repo Secret 與 Cluster Secret 的時候,你會發現它正好派上用場:

  • 我們把敏感憑證(SSH Key、Bearer Token、CA Data)放在 AWS Secrets Manager;
  • ExternalSecret 自動把它們同步到 K8s Secret;
  • Argo CD 只需要讀取現成的 Secret,就能安全地連到 repo 與 cluster。

這樣的分工讓我們完全不需要在 Git repo 裡存放任何敏感資訊,安全性與可維護性都大幅提升。

結語

今天我們把 Argo CD 能「讀 repo」、「寫 cluster」的兩大 Secret 類型都設定好了,並且透過 ExternalSecret 將 AWS Secrets Manager 整合進來。

明天,我們就能正式進入 ArgoCD 實際部署單位:Application 的介紹,以及 App-of-Apps pattern,把多個應用一次性 deploy 上 cluster!


上一篇
[Day 11] GitOps & Argo CD 安裝
下一篇
[Day 13] 一次管好一堆應用:Argo CD App-of-Apps 實戰
系列文
EKS in Practice:IaC × GitOps 實戰 30 天14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言