はじめに
今回は、Argo CDと組み合わせて利用することのできる通知ツールの一つ、Argo CD Notificationsについて、概要と利用方法を紹介します。
Argo CD Notificationsとは
Argo CD Notificationsは、Argo CDのリソースを監視し、実行結果に応じてメール・Slackなどで通知してくれるプロダクトです。Triggerによって通知を送る契機やタイミングを指定、Templateによって通知する内容やフォーマットを指定することが可能です。また、Argo CD Notificationsが監視対象とするのはApplication
AppProject
で、対象のリソースに対してAnnotationを付与することで監視対象とすることができます。
他の通知ツールとの比較
Argo CDのNotificationページには、Argo CD Notificationsのほか、2つのプロダクトが紹介されています。
Argo Kube Notifier: KubernetesリソースをモニタリングするControllerを設置し、指定したルールと一致した場合は通知を送ることができます。Argo CD Notificationsと同じくargoproj-labsの配下にありますが、半年ほど前から開発は止まっているように見えます。
Kube Watch: Kubernetesクラスターをモニタリングしリソースの変更が走った場合はWebhookを通じて通知を送付します。Dockerでの軌道のほか、
kubewatch
コマンドを利用することでローカル環境で起動することができます。Slackを利用する場合はSlack botを利用する必要があります。
Argo CD Notificationsを利用する
ここからは実際にArgo CD Notificationsを利用していきます。今回はArgo CDのイベントに応じてSlackへ通知を飛ばす方法を見ていきます。
検証環境
今回の検証環境は以下の通りです。
- 利用サービス: Amazon EKS
- 構築方法: eksctlによる構築
- ローカル環境: WSL (Ubuntu 18.04.4)
Argo CD Notificationsのインストール
まずはArgo CD Notificationsをクラスター上にデプロイします。
# Namespaceの用意 $ kubectl get ns NAME STATUS AGE default Active 12m kube-node-lease Active 12m kube-public Active 12m kube-system Active 12m $ kubectl create namespace argocd namespace/argocd created $ kubectl get ns NAME STATUS AGE argocd Active 2s default Active 12m kube-node-lease Active 13m kube-public Active 13m kube-system Active 13m # Argo CD Notificationsのデプロイ $ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/stable/manifests/install.yaml serviceaccount/argocd-notifications-controller created role.rbac.authorization.k8s.io/argocd-notifications-controller created rolebinding.rbac.authorization.k8s.io/argocd-notifications-controller created configmap/argocd-notifications-cm created secret/argocd-notifications-secret created deployment.apps/argocd-notifications-controller created # デプロイ後の確認 $ kubectl get -n argocd sa NAME SECRETS AGE argocd-notifications-controller 1 17s default 1 26s $ kubectl get -n argocd role NAME AGE argocd-notifications-controller 25s $ kubectl get -n argocd rolebinding NAME AGE argocd-notifications-controller 30s $ kubectl get -n argocd cm NAME DATA AGE argocd-notifications-cm 0 37s $ kubectl get -n argocd secret NAME TYPE DATA AGE argocd-notifications-controller-token-cvqwg kubernetes.io/service-account-token 3 43s argocd-notifications-secret Opaque 0 43s default-token-tdxr6 kubernetes.io/service-account-token 3 52s $ kubectl get -n argocd all NAME READY STATUS RESTARTS AGE pod/argocd-notifications-controller-64664db97-psnkx 1/1 Running 0 57s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/argocd-notifications-controller 1/1 1 1 58s NAME DESIRED CURRENT READY AGE replicaset.apps/argocd-notifications-controller-64664db97 1 1 1 58s
Slackの設定
次にSlackのほうの設定を行います。設定はArgo CD Notificationsのドキュメントに従って行います。
まずSlackのこちらのページから、対象のWorkspaceを選択してアプリケーションを作成します。
アプリケーションの作成ができたら、次に左のメニューからOAuth &Permissions
を選択します。
次にアプリケーションの実行できる権限を指定するため、Scopeの項目へ移動し、Bot Token Scopesでchat:write
を選択します。
Scopeを設定したら、次の画面上でInstall App to Workspace
を選択します。
アプリケーションがWorkspaceにアクセスする権限をリクエストするので、Allow
を選択します。
次の画面で、発行されたアクセストークンを確認できます。後ほどクラスター上のSecretリソースにこのトークン情報を設定するため、これをコピーしておきます。
また、後ほど通知が飛ぶのを確認するため、テスト用のチャンネルを作成(今回はtest-argocd-notification
というチャンネルを用意)し、テスト用のチャンネルにアプリを追加しておきます。
Argo CD Notificationsの設定
次にArgo CD Notificationsの設定を行います。先ほど表示されたアクセストークンをargocd-notifications-secret
というSecretリソースに設定します。今回は以下のようにマニフェストファイルを用意し、すでに作成されたargocd-notifications-secret
から上書きします。
argocd-notification-secret.yaml
apiVersion: v1 kind: Secret metadata: name: argocd-notifications-secret namespace: argocd stringData: notifiers.yaml: | slack: token: <my-token> type: Opaque
また、Argo CD Notificationsを利用するにはargocd-notifications-cm
というConfigMapに、通知条件と通知時のテンプレートを指定する必要があります。
ここでは、以下のようなマニフェストファイルを利用します。Argo CD Notificationsにはあらかじめ利用可能なTrigger/Templateが用意されており、ここではon-sync-succeeded
というTriggerを指定しています。
argocd-notification-cm.yaml
apiVersion: v1 kind: ConfigMap metadata: name: argocd-notifications-cm namespace: argocd data: config.yaml: | triggers: - name: on-sync-succeeded enabled: true
上記2つのマニフェストファイルを利用して設定を行います。
$ cd argocd-notification $ kubectl apply -f argocd-notification-secret.yaml secret/argocd-notifications-secret configured $ kubectl apply -f argocd-notification-cm.yaml configmap/argocd-notifications-cm configured # 変更後の確認 $ kubectl get secret -n argocd NAME TYPE DATA AGE argocd-notifications-controller-token-cvqwg kubernetes.io/service-account-token 3 23m argocd-notifications-secret Opaque 1 23m default-token-tdxr6 kubernetes.io/service-account-token 3 23m $ kubectl get cm -n argocd NAME DATA AGE argocd-notifications-cm 1 23m
Argo CDのデプロイとSlcakへの通知
ここまででArgo CD Notificationsの通知準備ができたので、ここからはArgo CDの利用準備を進めます。
まずはArgo CDをデプロイします。デプロイや設定などは、以前の記事などをご覧ください。
$ kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml customresourcedefinition.apiextensions.k8s.io/applications.argoproj.io created customresourcedefinition.apiextensions.k8s.io/appprojects.argoproj.io created serviceaccount/argocd-application-controller created serviceaccount/argocd-dex-server created serviceaccount/argocd-server created role.rbac.authorization.k8s.io/argocd-application-controller created role.rbac.authorization.k8s.io/argocd-dex-server created role.rbac.authorization.k8s.io/argocd-server created clusterrole.rbac.authorization.k8s.io/argocd-application-controller created clusterrole.rbac.authorization.k8s.io/argocd-server created rolebinding.rbac.authorization.k8s.io/argocd-application-controller created rolebinding.rbac.authorization.k8s.io/argocd-dex-server created rolebinding.rbac.authorization.k8s.io/argocd-server created clusterrolebinding.rbac.authorization.k8s.io/argocd-application-controller created clusterrolebinding.rbac.authorization.k8s.io/argocd-server created configmap/argocd-cm created configmap/argocd-gpg-keys-cm created configmap/argocd-rbac-cm created configmap/argocd-ssh-known-hosts-cm created configmap/argocd-tls-certs-cm created secret/argocd-secret created service/argocd-dex-server created service/argocd-metrics created service/argocd-redis created service/argocd-repo-server created service/argocd-server-metrics created service/argocd-server created deployment.apps/argocd-application-controller created deployment.apps/argocd-dex-server created deployment.apps/argocd-redis created deployment.apps/argocd-repo-server created deployment.apps/argocd-server created $ kubectl get all -n argocd NAME READY STATUS RESTARTS AGE pod/argocd-application-controller-67bc594796-ntfjn 1/1 Running 0 83s pod/argocd-dex-server-55675b569d-wctwt 1/1 Running 2 83s pod/argocd-notifications-controller-64664db97-psnkx 1/1 Running 0 94m pod/argocd-redis-54b6ff7bf6-2b4bm 1/1 Running 0 83s pod/argocd-repo-server-654d96b48-p5785 1/1 Running 0 83s pod/argocd-server-bdcdd6f7c-hrvk4 1/1 Running 0 83s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/argocd-dex-server ClusterIP 10.100.58.24 <none> 5556/TCP,5557/TCP,5558/TCP 83s service/argocd-metrics ClusterIP 10.100.71.232 <none> 8082/TCP 83s service/argocd-redis ClusterIP 10.100.37.118 <none> 6379/TCP 83s service/argocd-repo-server ClusterIP 10.100.189.69 <none> 8081/TCP,8084/TCP 83s service/argocd-server ClusterIP 10.100.150.191 <none> 80/TCP,443/TCP 83s service/argocd-server-metrics ClusterIP 10.100.69.171 <none> 8083/TCP 83s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/argocd-application-controller 1/1 1 1 83s deployment.apps/argocd-dex-server 1/1 1 1 83s deployment.apps/argocd-notifications-controller 1/1 1 1 94m deployment.apps/argocd-redis 1/1 1 1 83s deployment.apps/argocd-repo-server 1/1 1 1 83s deployment.apps/argocd-server 1/1 1 1 83s NAME DESIRED CURRENT READY AGE replicaset.apps/argocd-application-controller-67bc594796 1 1 1 83s replicaset.apps/argocd-dex-server-55675b569d 1 1 1 83s replicaset.apps/argocd-notifications-controller-64664db97 1 1 1 94m replicaset.apps/argocd-redis-54b6ff7bf6 1 1 1 83s replicaset.apps/argocd-repo-server-654d96b48 1 1 1 83s replicaset.apps/argocd-server-bdcdd6f7c 1 1 1 83s # Argo CD Serverへアクセスするための設定 $ kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}' service/argocd-server patched $ kubectl get svc -n argocd NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE argocd-dex-server ClusterIP 10.100.58.24 <none> 5556/TCP,5557/TCP,5558/TCP 9m18s argocd-metrics ClusterIP 10.100.71.232 <none> 8082/TCP 9m18s argocd-redis ClusterIP 10.100.37.118 <none> 6379/TCP 9m18s argocd-repo-server ClusterIP 10.100.189.69 <none> 8081/TCP,8084/TCP 9m18s argocd-server LoadBalancer 10.100.150.191 a6810607dbc8944c08df1e90108554ed-1651594083.ap-northeast-1.elb.amazonaws.com 80:30635/TCP,443:30162/TCP 9m18s argocd-server-metrics ClusterIP 10.100.69.171 <none> 8083/TCP 9m18s # 初期ログインパスワードの確認 $ kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server -o name | cut -d'/' -f 2 argocd-server-bdcdd6f7c-hrvk4 # argocdコマンドによるログイン $ argocd login a6810607dbc8944c08df1e90108554ed-1651594083.ap-northeast-1.elb.amazonaws.com:443 WARNING: server certificate had error: x509: certificate is valid for localhost, argocd-server, argocd-server.argocd, argocd-server.argocd.svc, argocd-server.argocd.svc.cluster.local, not a6810607dbc8944c08df1e90108554ed-1651594083.ap-northeast-1.elb.amazonaws.com. Proceed insecurely (y/n)? y Username: admin Password: 'admin' logged in successfully Context 'a6810607dbc8944c08df1e90108554ed-1651594083.ap-northeast-1.elb.amazonaws.com:443' updated
今回はこちらのGitHubリポジトリに配置したマニフェストファイルを利用し、アプリケーションを起動します。 こちらは、以前Argo Rolloutsの挙動を見たときに使ったコンテナイメージとマニフェストファイルになります。
Dockerfile-fail
FROM nginx:latest CMD head /foo/bar
deployment.yml
apiVersion: apps/v1 kind: Deployment metadata: name: testdeployment spec: replicas: 1 selector: matchLabels: app: test template: metadata: name: testpod labels: app: test spec: containers: - name: nginx-container image: nginx:latest ports: - containerPort: 80
testapp-fail.yml
apiVersion: apps/v1 kind: Deployment metadata: name: testapp-fail spec: replicas: 1 selector: matchLabels: app: fail template: metadata: name: testpod-fail labels: app: fail spec: containers: - name: nginx-container image: 111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/test/test03:ok ports: - containerPort: 80
application.yml
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: testapp namespace: argocd finalizers: - resources-finalizer.argocd.argoproj.io spec: project: default source: repoURL: https://github.com/FY0323/argocd-test.git targetRevision: HEAD path: testpod destination: server: https://kubernetes.default.svc namespace: default syncPolicy: automated: prune: false selfHeal: false
# アプリケーションのデプロイ $ kubectl apply -f application.yml application.argoproj.io/testapp created # デプロイ後の確認 $ kubectl get app -n argocd NAME AGE testapp 13s $ kubectl get pods NAME READY STATUS RESTARTS AGE testapp-fail-02-6689b9c479-lpcs9 1/1 Running 0 18s testapp-fail-69795ddcc-vb9sn 1/1 Running 0 18s testdeployment-f4796ffcb-kjbn5 1/1 Running 0 18s
Applicationがデプロイされたので、ここでargocd app sync
コマンドやWeb UIからの操作により、GitHubリポジトリとの同期を行うことができますが、この状態ではまだSlackへの通知は実行されません。
Argo CD NotificationsによるSlackへの通知を行うには、Applicationリソースに対し、Slackへの通知と通知先となるチャンネルを指定したAnnotationを付与する必要があります。
# Annotationの付与 $ kubectl patch app testapp -n argocd -p '{"metadata": {"annotations": {"recipients.argocd-notifications.argoproj.io":"slack:test-argocd-notification"}}}' --type merge application.argoproj.io/testapp patched $ kubectl describe app testapp -n argocd | head Name: testapp Namespace: argocd Labels: <none> Annotations: recipients.argocd-notifications.argoproj.io: slack:test-argocd-notification API Version: argoproj.io/v1alpha1 Kind: Application Metadata: Creation Timestamp: 2020-10-21T08:23:06Z Finalizers: resources-finalizer.argocd.argoproj.io
Annotationを付与することで、モニタリング対象のApplicationが設定されたことになり、Argo CD Notificationsのモニタリングが有効となります。
この後、GitHubリポジトリとの同期を行うことで、指定したSlackチャンネルに対する通知が飛ばされます。
# Syncの例 # 実行時ログを失ってしまったため、日時にズレあり $ argocd app sync testapp TIMESTAMP GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE 2020-10-25T17:11:47+09:00 apps Deployment default testapp-fail Synced Healthy 2020-10-25T17:11:47+09:00 apps Deployment default testapp-fail-02 Synced Healthy 2020-10-25T17:11:47+09:00 apps Deployment default testdeployment Synced Healthy 2020-10-25T17:11:48+09:00 apps Deployment default testapp-fail-02 Synced Healthy deployment.apps/testapp-fail-02 unchanged 2020-10-25T17:11:48+09:00 apps Deployment default testapp-fail Synced Healthy deployment.apps/testapp-fail unchanged 2020-10-25T17:11:48+09:00 apps Deployment default testdeployment Synced Healthy deployment.apps/testdeployment unchanged Name: testapp Project: default Server: https://kubernetes.default.svc Namespace: default URL: https://a6810607dbc8944c08df1e90108554ed-1651594083.ap-northeast-1.elb.amazonaws.com/applications/testapp Repo: https://github.com/FY0323/argocd-test.git Target: HEAD Path: testpod SyncWindow: Sync Allowed Sync Policy: Automated Sync Status: Synced to HEAD (9f4d5d7) Health Status: Healthy Operation: Sync Sync Revision: 9f4d5d734d44e3c4412ba5b6a2d0aab6353b8610 Phase: Succeeded Start: 2020-10-25 17:11:47 +0900 JST Finished: 2020-10-25 17:11:48 +0900 JST Duration: 1s Message: successfully synced (all tasks run) GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE apps Deployment default testapp-fail-02 Synced Healthy deployment.apps/testapp-fail-02 unchanged apps Deployment default testapp-fail Synced Healthy deployment.apps/testapp-fail unchanged apps Deployment default testdeployment Synced Healthy deployment.apps/testdeployment unchanged
以上のとおり、Slackへの通知が確認できました。
また、Argo CDはデフォルトで3分おきにリポジトリの状態を確認します。リポジトリ上に変更がない場合に通知を飛ばすか気になっていましたが、しばらく放置しても何の通知も飛ばさなかったため、特に通知をすることはなさそうです。リポジトリにあるマニフェスト情報を更新すれば、しばらくした後に通知が来ることも確認しています。
Argo CD Notificationsの設定を変更する
Argo CD NotificationsはTriggerとTemplateを自分で設定することも可能です。ビルトインで用意されているTrigger/Templateで不十分な場合は、カスタマイズすることができます。
Triggerを変更する
まずは、先ほどargocd-notification-cm.yaml
ConfigMapで指定したTriggerを変更します。ここではSyncに失敗しDegraded
の状態となった場合に通知を飛ばすon-health-degraded
を利用します。
以下のようにargocd-notification-cm.yaml
を書き換えます。
argocd-notification-cm.yaml
apiVersion: v1 kind: ConfigMap metadata: name: argocd-notifications-cm namespace: argocd data: config.yaml: | triggers: - name: on-health-degraded # 変更 enabled: true
# ConfigMapの変更 $ vi argocd-notification-cm.yaml $ kubectl apply -f argocd-notification-cm.yaml configmap/argocd-notifications-cm configured $ kubectl describe cm argocd-notifications-cm -n argocd Name: argocd-notifications-cm Namespace: argocd Labels: <none> Annotations: Data ==== config.yaml: ---- triggers: - name: on-health-degraded enabled: true Events: <none>
次にマニフェストファイルの一部を変更します。
# GitHubのWeb UI上で操作 # GitHub上で以下の箇所を修正しCommit apiVersion: apps/v1 kind: Deployment metadata: name: testapp-fail spec: replicas: 1 selector: matchLabels: app: fail template: metadata: name: testpod-fail labels: app: fail spec: containers: - name: nginx-container image: 111111111111.dkr.ecr.ap-northeast-1.amazonaws.com/test/test03:fail # イメージタグの変更 ports: - containerPort: 80
上記箇所を変更し、argocd app sync
コマンドを実行します。
$ argocd app sync testapp TIMESTAMP GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE 2020-10-21T22:53:53+09:00 apps Deployment default testapp-fail Synced Healthy 2020-10-21T22:53:53+09:00 apps Deployment default testapp-fail-02 Synced Healthy 2020-10-21T22:53:53+09:00 apps Deployment default testdeployment Synced Healthy 2020-10-21T22:53:54+09:00 apps Deployment default testapp-fail-02 Synced Healthy deployment.apps/testapp-fail-02 unchanged 2020-10-21T22:53:55+09:00 apps Deployment default testdeployment Synced Healthy deployment.apps/testdeployment unchanged 2020-10-21T22:53:55+09:00 apps Deployment default testapp-fail Synced Healthy deployment.apps/testapp-fail configured 2020-10-21T22:53:55+09:00 apps Deployment default testapp-fail OutOfSync Progressing deployment.apps/testapp-fail configured Name: testapp Project: default Server: https://kubernetes.default.svc Namespace: default URL: https://a6810607dbc8944c08df1e90108554ed-1651594083.ap-northeast-1.elb.amazonaws.com/applications/testapp Repo: https://github.com/FY0323/argocd-test.git Target: HEAD Path: testpod SyncWindow: Sync Allowed Sync Policy: Automated Sync Status: OutOfSync from HEAD (a6c2f93) Health Status: Progressing Operation: Sync Sync Revision: 06215a95898d03b264481cc1c592016f8f1a43d8 Phase: Succeeded Start: 2020-10-21 22:53:56 +0900 JST Finished: 2020-10-21 22:53:57 +0900 JST Duration: 1s Message: successfully synced (all tasks run) GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE apps Deployment default testapp-fail-02 Synced Healthy deployment.apps/testapp-fail-02 unchanged apps Deployment default testdeployment Synced Healthy deployment.apps/testdeployment unchanged apps Deployment default testapp-fail OutOfSync Progressing deployment.apps/testapp-fail configured
しばらくするとDegraded
の状態となり、Slackに通知が飛んできます。
$ argocd app get testapp Name: testapp Project: default Server: https://kubernetes.default.svc Namespace: default URL: https://a6810607dbc8944c08df1e90108554ed-1651594083.ap-northeast-1.elb.amazonaws.com/applications/testapp Repo: https://github.com/FY0323/argocd-test.git Target: HEAD Path: testpod SyncWindow: Sync Allowed Sync Policy: Automated Sync Status: Synced to HEAD (a6c2f93) Health Status: Degraded GROUP KIND NAMESPACE NAME STATUS HEALTH HOOK MESSAGE apps Deployment default testapp-fail-02 Synced Healthy deployment.apps/testapp-fail-02 unchanged apps Deployment default testdeployment Synced Healthy deployment.apps/testdeployment unchanged apps Deployment default testapp-fail Synced Degraded deployment.apps/testapp-fail configured
Templateを変更する
次にTemplateのほうを変更してみます。Argo CD NotificationsはGoのhtml/templateをベースにtemplateを利用しており、titleとbodyを設定することが可能です。またapp
fieldでApplicationの情報を利用することや、time
repo
といった関数を利用することもできます。
今回は以下のようなTemplateを用意しました。
argocd-notification-cm.yaml
apiVersion: v1 kind: ConfigMap metadata: name: argocd-notifications-cm namespace: argocd data: config.yaml: | triggers: - name: test-trigger template: test-template condition: time.Now().Sub(time.Parse(app.status.operationState.startedAt)).Minutes() <= 5 enabled: true templates: - name: test-template body: | "Application: {{.app.metadata.name}} sync status is {{.app.status.sync.status}}" "Repository: {{.app.spec.source.repoURL}}" "Images: {{.app.status.summary.images}}" "Revision: {{.app.status.sync.revision}}"
上記ファイルについて補足します。
triggers
: 以下の4つの項目を設定することができます。name
: Triggerの名前template
: 利用するTemplateを指定condition
: 通知を飛ばす条件を指定します。time … <= 5
:app.status.operationState.startedAt
、つまり同期開始から5分以内に同期が完了した場合に通知します
enabled
: Triggerの有効・無効を選択します
templates
: 以下の2つの項目を設定することができます。name
: Templateの名前title
: 通知時のタイトルを指定します(今回は使用せず)body
: 通知時の内容を指定します。今回はApplicationの中で必要そうな情報を並べただけになります
上記マニフェストファイルを利用し、ConfigMapを更新します。
$ kubectl apply -f argocd-notification-cm.yaml configmap/argocd-notifications-cm configured $ kubectl describe cm argocd-notifications-cm -n argocd Name: argocd-notifications-cm Namespace: argocd Labels: <none> Annotations: Data ==== config.yaml: ---- triggers: - name: test-trigger template: test-template condition: time.Now().Sub(time.Parse(app.status.operationState.startedAt)).Minutes() <= 5 enabled: true templates: - name: test-template body: | "Application: {{.app.metadata.name}} sync status is {{.app.status.sync.status}}" "Repository: {{.app.spec.source.repoURL}}" "Images: {{.app.status.summary.images}}" "Revision: {{.app.status.sync.revision}}" Events: <none>
上記ファイルをデプロイ後、argocd app sync
コマンドを実行すると、以下のようなメッセージが確認できます。