Argoproj 社群釋出第一個版本的通知引擎!

2021-05-28 15:00:26

作者:Alexander Matyushentsev

Argoproj 社群已經研究通知功能有一段時間了。我們嘗試了幾種不同的方法,並從早期使用者那裡學到了很多東西。根據我們的學習,我們提出了通知引擎的想法[1],它解決了所有 Argo 專案甚至其他專案的各種通知相關用例。

第一個通知引擎使用者是argocd-notifications[2]專案,它為 Argo CD Application CRD 和快為 Argo Rollouts 提供通知。今天,我們很高興地宣佈第一個版本的通知引擎[3](Notifications Engine)!

通知引擎是什麼?

通知引擎是一個基於 Golang 的庫,它實現了 Kubernetes 控制器的通知功能。一流的通知支援通常是 Kubernetes 控制器的第二個想法。這在一般情況下很難解決,因為通知本質上是非常主觀的。很難預測終端使用者希望收到什麼型別的事件通知,特別是通知應該是什麼樣子的。此外,有很多通知服務,所以很難決定先支援哪一個。通知引擎正試圖解決這些挑戰:

  • 提供一個靈活的設定驅動的觸發器和模板機制,允許 CRD 控制器管理員適應終端使用者的需求,而無需進行任何程式碼更改;

  • 提供與數十個通知服務(Slack、SMTP、Telegram 等)的開箱即用的整合,還有更多的整合尚未到來;

通知引擎提供的特性支援以下用例:

  • 通知使用者 Kubernetes 叢集中發生的重要事件。事件範例是降級部署;無效的證書設定;成功地完成工作等。

  • 在叢集中的資源和公司外部工具之間構建自定義整合。例如,你可能在 Argo CD Application 成功部署後觸發 CI 流水線,或者在外部祕密控制器未能從 AWS secret Manager 檢索祕密時開啟 Jira 票據。

  • 設定一個審計系統,用於捕獲重要事件的資訊並將其推播到持久儲存中。

特性

一旦將通知引擎整合到專案中,專案終端使用者將獲得一個強大的設定驅動機制,用於向數十個通知服務傳送通知。

通知、觸發器和模板

該引擎引入了通知觸發器和模板,允許捕獲重要的客製化資源事件並行送完全客製化的通知。觸發器是一個命名條件,它監視 Kubernetes 資源並決定是否該傳送通知,而通知模板是一個無狀態函數,用於生成通知內容。

觸發器和模板通常由控制器維護人員設定一次,並由執行控制器的管理員自定義。下面的例子演示了一個通知使用者 Argo CD 應用程式問題的觸發器:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
data:
  trigger.on-sync-status-unknown: |
    - when: app.status.sync.status == 'Unknown'
      send: [app-sync-status]
  template.app-sync-status: |
    message: |
      Application {{.app.metadata.name}} sync is {{.app.status.sync.status}}.
      Application details: {{.context.argocdUrl}}/applications/{{.app.metadata.name}}.

通知服務

除了觸發器和模板之外,管理員還需要設定與支援的通知服務的整合。通知引擎開箱即用支援 Slack、MS Teams、Email、Mattermost、Telegram、Rocket Chat、OpsGenie。支援的整合列表並不僅僅以基於文字的通知結束。使用者可以利用通知引擎更新 Github 中的提交狀態,建立 Grafana 註解或設定完全自定義整合使用通用的基於 webhook 的服務。下面的例子演示了與 Slack 的整合:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
data:
  service.slack: |
    token: $slack-token
---
apiVersion: v1
kind: Secret
metadata:
  name: argocd-notifications-secret
stringData:
  slack-token: <my-slack-token>

使用者友好的訂閱

一旦管理員設定了觸發器、模板和服務,終端使用者只需「訂閱」他們感興趣的觸發器。為了訂閱,使用者需要新增 notifications.argoproj.io/subscribe. . 註釋,並在註釋值中指定通知收件人。以下範例建立 on-sync-succeeded 觸發器的訂閱,向兩個 Slack 通道傳送通知:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  annotations:
    notifications.argoproj.io/subscribe.on-sync-succeeded.slack: my-channel1;my-channel2
view raw

如何整合通知引擎?

你是否對通知引擎感到興奮,並希望將其整合到你的專案中?你必須編寫一些 Golang 程式碼,但好訊息是你不需要編寫太多程式碼。通常,你必須建立一個 main.go 檔案,其中包含與 Kubernetes 通訊的樣板程式碼,以及引導通知控制器的幾行程式碼。

演示!

一個演示勝過千言萬語。在庫的情況下,演示是演示如何使用庫的教學。下面的段落解釋瞭如何為Cert-Manager[4] Certificate CRD 構建通知。完整的範例可以在通知引擎倉庫中的examples/certmanager[5]目錄中找到。

控制器

監視自定義資源和傳送通知所需的工作由通知控制器執行。製造控制器所需的工作由pkg/controller[6]和pkg/api[7]包提供。在開始實現控制器之前,我們需要編寫樣板程式碼,這些程式碼需要與 Kubernetes 叢集通訊,並通過觸發器和模板提供對 Kubernetes ConfigMap 和 Secret 的存取:

informersFactory := informers.NewSharedInformerFactoryWithOptions(
 kubernetes.NewForConfigOrDie(restConfig),
 time.Minute,
 informers.WithNamespace(namespace))
secrets := informersFactory.Core().V1().Secrets().Informer()
configMaps := informersFactory.Core().V1().ConfigMaps().Informer()
notificationsFactory := api.NewFactory(api.Settings{
 ConfigMapName: "cert-manager-notifications-cm",
 SecretName:    "cert-manager-notifications-secret",
 InitGetVars: func(cfg *api.Config, configMap *v1.ConfigMap, secret *v1.Secret) (api.GetVars, error) {
  return func(obj map[string]interface{}, dest services.Destination) map[string]interface{} {
   return map[string]interface{}{"cert": obj}
  }, nil
 },
}, namespace, secrets, configMaps)

下一步是編寫程式碼來範例化控制器本身:

certClient := dynamic.NewForConfigOrDie(restConfig).Resource(schema.GroupVersionResource{
 Group: "cert-manager.io", Version: "v1", Resource: "certificates",
})
certsInformer := cache.NewSharedIndexInformer(&cache.ListWatch{
 ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
  return certClient.List(context.Background(), options)
 },
 WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
  return certClient.Watch(context.Background(), metav1.ListOptions{})
 },
}, &unstructured.Unstructured{}, time.Minute, cache.Indexers{})
ctrl := controller.NewController(certClient, certsInformer, notificationsFactory)

最後一步是啟動控制器:

go informersFactory.Start(context.Background().Done())
go certsInformer.Run(context.Background().Done())
if !cache.WaitForCacheSync(context.Background().Done(), secrets.HasSynced, configMaps.HasSynced, certsInformer.HasSynced) {
 log.Fatalf("Failed to synchronize informers")
}
ctrl.Run(10, context.Background().Done())

我們差不多完成了!控制器已經準備好。要開始使用它,我們需要設定觸發器、模板,並設定與一些通知服務的整合。以下 YAML 將我們的通知控制器與 Slack 整合在一起,並在證書管理器成功設定任何證書時向我們傳送訊息:

apiVersion: v1
kind: ConfigMap
metadata:
  name: cert-manager-notifications-cm
data:
  trigger.on-cert-ready: |
    - when: any(cert.status.conditions, {.reason == 'Ready' && .status == 'True'})
      send: [cert-ready]
  template.cert-ready: |
    message: |
      Certificate {{.cert.metadata.name}} is ready!
  service.slack: |
    token: $slack-token

為了檢視控制器的執行情況,我們仍然需要設定演示環境。不幸的是,它不適合一個部落格,但這裡有一些連結:

  • 獲取 Minikube 叢集:https://minikube.sigs.k8s.io/docs/start/

  • 安裝 Cert Manager:https://cert-manager.io/docs/installation/

  • 設定 Slack 整合:https://github.com/argoproj/notifications-engine/blob/master/docs/services/slack.md

最後,執行控制器,享受 Slack 的通知!

下一步

除了控制器工具箱之外,通知引擎還包括故障排除工具。這些工具包括幫助建立和驗證觸發器和模板的 Prometheus 指標和 CLI。在通知引擎檔案[8]中瞭解關於這些特性的更多資訊。不要猶豫,在CNCF Slack 頻道[9]分享你的反饋,或建立 Github 問題,要求更多的整合或報告一個 bug!

參考資料

[1] 想法: https://docs.google.com/document/d/1nw0i7EAehNnjEkbpx-I3BVjfZvRgetUFUZby4iMUSWU/edit#heading=h.efmu907hcczu

[2] argocd-notifications: https://github.com/argoproj-labs/argocd-notifications

[3] 通知引擎: https://github.com/argoproj/notifications-engine

[4] Cert-Manager: https://cert-manager.io/

[5] examples/certmanager: https://github.com/argoproj/notifications-engine/tree/master/examples/certmanager

[6] pkg/controller: https://github.com/argoproj/notifications-engine/blob/master/pkg/controller

[7] pkg/api: https://github.com/argoproj/notifications-engine/blob/master/pkg/api

[8] 檔案: https://github.com/argoproj/notifications-engine/tree/master/docs

[9] CNCF Slack 頻道: https://cloud-native.slack.com/archives/C01UKS2NKK3

展開閱讀全文