昨天我們已經安裝好 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 儲存的方式。

首先是 Repo Secret,這裡的用途是讓 Argo CD 可以存取 GitLab Repo。
流程如下:
建立 SSH Key,並把 public key 註冊到 repo 的 Deploy Keys。
ssh-keygen -t rsa -C "argo-repo"
cat ~/.ssh/argo-repo.pub
把 private key 做 base64 encode,存放到 AWS Secrets Manager。
cat ~/.ssh/argo-repo | base64
使用 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

注意:這邊每多一個需要 ArgoCD 讀取的 repo,就要多寫一個 ExternalSecret resource 哦!
這樣 Argo CD 就能透過這個 Secret 去拉取 repo 了。設定 ExternalSecret 之後,可以到 ArgoCD UI 上檢查是否有正確連接到 repo。路徑是 Settings > Repositories:
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 所在的帳號。這樣做可以避免不同帳號之間的敏感資訊混用,也能讓專案團隊自行控管憑證的生命週期。
這樣的做法有幾個好處:
以下是我們在 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 列表,如下圖:
在 Day 11,我們已經先安裝 External Secrets Controller。今天在設定 Repo Secret 與 Cluster Secret 的時候,你會發現它正好派上用場:
這樣的分工讓我們完全不需要在 Git repo 裡存放任何敏感資訊,安全性與可維護性都大幅提升。
今天我們把 Argo CD 能「讀 repo」、「寫 cluster」的兩大 Secret 類型都設定好了,並且透過 ExternalSecret 將 AWS Secrets Manager 整合進來。
明天,我們就能正式進入 ArgoCD 實際部署單位:Application 的介紹,以及 App-of-Apps pattern,把多個應用一次性 deploy 上 cluster!