昨天我們已經安裝好 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!