Argo CD のデプロイ結果を Slack へ通知させる方法
クラウドエース 北野です。
Argo CD の結果を Slack に通知する方法を紹介します。
概要
Argo CD の結果を Slack に通知するには、以下を実施します。
- Slack アプリと通知先チャンネルの作成
- Configmap
argocd-notifications-cm
に通知方法の定義 - Application への通知設定
metadata.annotations
の定義
Configmap argocd-notifications-cm
の内容は次のとおりです。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
service.slack: |
token: $slack-token
context: |
argocdUrl: <Argo CD URL>
template.app-sync-succeeded: |
slack:
attachments: |
[{
"color": "#36a64f",
"blocks": [{
"type": "header",
"text": {
"type": "plain_text",
"text": "【SUCCESS】 Argo CD {{.app.metadata.name}} Application Manifest Sync"
}
}]
}]
deliveryPolicy: Post
groupingKey: ""
notifyBroadcast: false
trigger.on-sync-succeeded: |
- description: Application syncing has succeeded
send:
- app-sync-succeeded
when: app.status.operationState != nil and app.status.operationState.phase in ['Succeeded']
Application の metadata.annotations
は次のとおりです。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: <APPLICATION NAME>
namespace: argocd
annotations:
notifications.argoproj.io/subscribe.<TRIGGER NAME>.slack: <CHANNEL NAME>
spec:
はじめに
Argo CD でデプロイパイプラインを構築すると、連携されたリポジトリのコードが更新される度に自動的にデプロイが実施されます。そのため、変更を通知する機構がないと、Kubernetes や Argo CD のコンソールからでしか変更を確認できません。
そこで、この記事では、Argo CD の Application の状態の変化を Slack に通知する方法を紹介します。
Argo CD の通知機能
Argo CD は Application の状態を監視し、状態の変更を Slack やメールに通知する機能があります。この通知機能は Argo CD を Kubernetes 上にデプロイすると、作成される argocd-notifications-controller
Deployment によって実行されます。
通知するにはメッセージの内容、通知条件と通知先を設定すると、Application の状態に応じてメッセージが通知されます。
通知するメッセージの内容とその方法、通知先の設定先は、項目によって異なります。それぞれの設定先は次の通りです。
- 通知するメッセージの内容と通知条件: ConfigMap
argocd-notifications-cm
- メッセージの通知先: Application
通知するメッセージの内容と通知条件に基づいて通知する機能は、それぞれテンプレートとトリガーという機能を使い実現しています。
テンプレート
テンプレートは Go の html/template パッケージを使い実装されており、通知するメッセージの内容を定義します。次のように、ConfigMap argocd-notifications-cm
の data に template で始まる内容で定義されます。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
template.sample-template: |
message: |
Application {{.app.metadata.name}} sync is {{.app.status.sync.status}}.
Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}.
テンプレートでは、次の値を参照することができます。
-
app
: Application が有する値 (Application 名、状態など) -
context
: ユーザー定義の値 -
secrets
:argocd-notifications-secret
に定義された値 -
serviceType
: 通知の種別※ -
recipient
: 通知先
※ Argo CD Notification で通知できるサービスの種類はこちらをご確認ください。
Secret からの参照方法
Argo CD Notification は、Secret argocd-notifications-secret
の値を参照できます。
apiVersion: v1
kind: Secret
metadata:
name: argocd-notifications-secret
stringData:
sampleWebhookToken: secret-token
type: Opaque
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
template.trigger-webhook: |
webhook:
sample-webhook:
method: POST
path: 'webhook/endpoint/with/auth'
body: 'token={{ .secrets.sampleWebhookToken }}&variables[APP_SOURCE_PATH]={{ .app.spec.source.path }}
上の例は、webhook サービスを使って、通知するときにトークン情報を使う方法を表わしています。argocd-notifications-secret.yaml
で sampleWebhookToken を定義し、argocd-notifications-cm.yaml
のテンプレート定義で .secrets.sampleWebhookToken
という変数でその値を参照しています。
Argo CD Notification で使う秘匿情報は、必ず Secret argocd-notifications-secret
に定義してください。
トリガー
トリガーは antonmedv/expr を使い Application の状態を評価して、メッセージをいつ送付するか、通知するときにどのテンプレートを使うかを定義する機能です。次のように、ConfigMap argocd-notifications-cm
の data に trigger で始まる内容で定義されます。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
trigger.on-sync-succeeded: |
- when: app.status.sync.status == 'Succeeded'
send: [sample-template]
when
に通知されるトリガーが実行されるときの Application の状態を定義します。send
にメッセージを通知するときに使うテンプレートを定義します。
expr による Application の状態の評価に使える演算子は、こちらをご確認ください。
通知先の設定
通知先の認証情報などの設定は、Configmap argocd-notifications-cm
の data.service.<SERVICE KIND>
に通知先のサービスの種類ごとに辞書型で定義します。例えば、Slack の場合は次のように定義します。
data:
service.slack: |
token: <SLACK APP TOKEN>
ここでの <SLACK APP TOKEN>
は Slack アプリの認証トークンです。その他、Slack サービスに設定できる項目は、こちらをご確認ください。
Application のメッセージの受信
ConfigMap argocd-notifications-cm
のテンプレートとトリガーを使い通知するには Application にどのトリガーを使いどこに通知するかを定義します。
Application の metadata.annotations
に notifications.argoproj.io/subscribe.<trigger>.<service>: <recipient>
の形式で定義すると、状態に応じてメッセージが送信されます。以下は on-sync-succeeded
トリガーを slack
サービスを使って、Slack の channel
チャンネルに通知させる例です。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
notifications.argoproj.io/subscribe.on-sync-succeeded.slack: channel
Application の状態を Slack へ通知
Argo CD でのデプロイ結果を Slack に通知するシステムを次のように構築します。
Google Cloud 上に Google Kubernetes Engine (以降 GKE と呼びます)を構築し、GKE 上に Argo CD をデプロイします。Argo CD のインターネットへの公開には、Gateway を使い公開します。また、External Secret を使い Google Cloud の Secret Manager の値を Secret argocd-notifications-secret
に連携します。
Slack への通知は Slack アプリを使います。Slack アプリの認証情報を Secret Manager に登録します。
この構成を構築するために次を実施します。
- Slack の設定
- Google Cloud と Kubernetes でのリソース作成
- Argo CD の設定
Slack の設定では、Slack アプリを作成し通知先のチャンネルに作成したアプリを追加します。Google Cloud と Kubernetes でのリソース作成では、Google Cloud 上に GKE を構築して、Argo CD をデプロイします。また、Slack アプリの認証情報を格納する Secret Manager を作成してデータを格納します。そして、GKE 上に External Secret を作成して、Secret argocd-notifications-secret
に連携します。
最後に Argo CD の設定で、ConfigMap argocd-notifications-cm
を作成して、テンプレートとトリガーを作成します。そして、通知する Application を作成して Slack に通知させます。
Slack の設定
Slack アプリを作成し、認証情報の作成と通知先のチャンネルの設定を紹介します。
まず、Slack api のページから、Argo CD への通知用のアプリを作成します。
From scratch
を選び、App Name と 通知先の workspace を選択してアプリを作成します。
OAuth & Permissions
から認証トークンを作成します。
Scopes
の Bot Token Scopes
の Add an OAuth Scope
を選択し、Bot Token Scopes を作成します。このとき Scope に chat:write
を選択して作成します。
同じページの Advanced token security via token rotation
の OAuth Tokens
の Install to <Workspace>
をクリックし、Workspace にアプリケーションをインストールします。
Bot User OAuth Token
を認証に使います。
続いて、通知先のチャンネルを作成します。
チャンネル詳細を開く
のインテグレーションのアプリを追加する
から作成したチャンネルに先のアプリケーションを追加します。
Google Cloud と Kubernetes でのリソース作成
Google Cloud で GKE、Secret Manager、Service Account の作成、Kubernetes で Argo CD、Secret Manager を作成する方法を紹介します。
Slack の認証情報を保存する Secret Manager は次のように作成します。
resource "google_secret_manager_secret" "main" {
secret_id = <SECRET MANAGER ID>
project = var.project
}
Cloud コンソールから Secret Manager にアクセスし、先程作成した Secret Manager に Slack アプリの Bot User OAuth Token を格納します。
続いて、Kubernetes から External Secret を使って Secret に連携するために Kubernetes で使うサービスアカウントを作成して、先の Secret Manager に roles/secretmanager.secretAccessor
の権限を付与します。
resource "google_service_account" "main" {
account_id = <SERVICE ACCOUNT ID>
project = var.project
}
resource "google_service_account_iam_member" "workload_identity_argocd-server" {
service_account_id = google_service_account.main.id
role = "roles/iam.workloadIdentityUser"
member = format("serviceAccount:%s.svc.id.goog[%s/%s]", var.project, "argocd", "external-secret")
}
resource "google_secret_manager_secret_iam_member" "main" {
secret_id = google_secret_manager_secret.main.secret_id
project = google_secret_manager_secret.main.project
role = "roles/secretmanager.secretAccessor"
member = google_service_account.main.member
}
GKE の構築、Argo CD のデプロイについては、こちらの記事をご確認ください。
最後に Kubernetes に External Secret を次のコマンドでインストールします。
#!/bin/bash
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets -n external-secrets --create-namespace
External Secret による Secret Manager のデータ連携
External Secret を使って、Google Cloud の Secret Manager のデータを Kubernetes の Secret argocd-notifications-secret
に連携します。
まず、Kubernetes が使う Service Account を作成します。
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-secret
namespace: argocd
annotations:
iam.gke.io/gcp-service-account: <SERVICE ACCOUNT EMAIL>
次に ClusterSecretStore と ExternalSecret を作成して、Slack の認証情報を格納した Secret Manager を argocd-notifications-secret
に連携します。
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: argocd-css
namespace: argocd
spec:
provider:
gcpsm:
projectID: <PROJECT ID>
auth:
workloadIdentity:
clusterLocation: <GKE REGION>
clusterName: <GKE CLUSTER NAME>
serviceAccountRef:
name: external-secret
namespace: argocd
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: es-slack-app-token
namespace: argocd
spec:
refreshInterval: 1h
secretStoreRef:
name: argocd-css
kind: ClusterSecretStore
target:
name: argocd-notifications-secret
creationPolicy: Owner
data:
- secretKey: slack-token
remoteRef:
key: <SECRET MANAGER ID>
version: latest
Argo CD の設定
次のような条件で Slack に通知されるように ConfigMap argocd-notifications-cm
に定義します。Application の状態が Succeeded
のとき、app-sync-succeeded
のテンプレートを使い通知させます。
テンプレート app-sync-succeeded
は、【SUCCESS】 Argo CD <APPLICATION NAME> Application Manifest Sync
というメッセージを Slack に通知します。
また、<APPLICATION NAME>
は、Application の値を参照する app
変数を使い代入します。
Slack のメッセージを Slack の Legacy API を使い作成します。
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
data:
service.slack: |
token: $slack-token
template.app-sync-succeeded: |
slack:
attachments: |
[{
"color": "#36a64f",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "【SUCCESS】 Argo CD {{.app.metadata.name}} Application Manifest Sync"
}
}
]
}]
deliveryPolicy: Post
groupingKey: ""
notifyBroadcast: false
trigger.on-sync-succeeded: |
- description: Application syncing has succeeded
send:
- app-sync-succeeded
when: app.status.operationState != nil and app.status.operationState.phase in ['Succeeded']
続いて、次のように metadata.annotations を定義して Application を作成して、作成した Slack チャンネル argocd-notification-sample
に通知するようにします。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: helloworld
namespace: argocd
annotations:
notifications.argoproj.io/subscribe.on-sync-succeeded.slack: 'argocd-notification-sample'
spec:
destination:
namespace: default
server: https://kubernetes.default.svc
project: default
source:
path: <MANIFEST PATH>
repoURL: <GITHUB REPOSITORY URL>
targetRevision: HEAD
syncPolicy:
automated: null
Application を作成して、SYNC して Slack に成功メッセージを通知させてみます。
さいごに
Argo CD でのデプロイ結果を Slack に通知する方法を紹介しました。CD パイプラインはデプロイ作業を自動化するため、通知機能がないと失敗に気づけません。失敗時にメンションを飛ばすテンプレートを作成するなどして、すぐに失敗に気づけるようにしてみてください。
Discussion