# notification-manager **Repository Path**: zhbit/notification-manager ## Basic Information - **Project Name**: notification-manager - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-11-11 - **Last Updated**: 2021-11-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Notification Manager Notification Manager manages notifications in multi-tenant K8s environment. It receives alerts or notifications from different senders and then send notifications to various tenant receivers based on alerts/notifications' tenant label like "namespace". Supported senders includes: - Prometheus Alertmanager - Custom sender (Coming soon) Supported receivers includes: - Email - [WeCom](https://work.weixin.qq.com/) - Slack - Webhook - DingTalk ## Architecture Notification Manager uses CRDs to store notification configs like email, WeCom and slack. It also includes an operator to create and reconcile NotificationManager CRD which watches all notification config CRDs, updates notification settings accordingly and sends notifications to users. ![Architecture](docs/images/architecture.png) ## Integration with Alertmanager Notification Manager could receive webhook notifications from Alertmanager and then send notifications to users in a multi-tenancy way. ![Notification Manager](docs/images/notification-manager.png) ### Config Alertmanager to send alerts to Notification Manager Notification Manager uses port `19093` and API path `/api/v2/alerts` to receive alerts sent from Alertmanager. To receive Alertmanager alerts, add webhook config like below to the `receivers` section of Alertmanager configuration file: ```shell "receivers": - "name": "notification-manager" "webhook_configs": - "url": "http://notification-manager-svc.kubesphere-monitoring-system.svc:19093/api/v2/alerts" ``` ## CustomResourceDefinitions Notification Manager uses the following CRDs to define the desired alerts/notifications webhook and receiver configs: - NotificationManager: Defines the desired alerts/notification webhook deployment. The Notification Manager Operator ensures a deployment meeting the resource requirements is running. - Config: Defines the dingtalk, email, slack, webhook, wechat configs. - Receiver: Define dingtalk, email, slack, webhook, wechat receivers. The relationship between receivers and configs can be demonstrated as below: ![Receivers & Configs](docs/images/receivers_configs.png) Receiver CRDs like EmailReceiver, WechatReceiver, SlackReceiver and WebhookReceiver can be categorized into 2 types `global` and `tenant` by label like `type = global`, `type = tenant` : - A global EmailReceiver receives all alerts and then send notifications regardless tenant info(user or namespace). - A tenant EmailReceiver receives alerts with specified tenant label like `user` or `namespace` Usually alerts received from Alertmanager contains a `namespace` label, Notification Manager uses this label to decide which receiver to use for sending notifications: - For KubeSphere, Notification Manager will try to find workspace `user` in that `namespace`'s rolebinding and then find receivers with `user = xxx` label. - For other Kubernetes cluster, Notification Manager will try to find receivers with `namespace = xxx` label. For alerts without a `namespace` label, for example alerts of node or kubelet, user can set up a receiver with `type = global` label to receive alerts without a `namespace` label. A global receiver sends notifications for all alerts received regardless any label. A global receiver is usually set for an admin role. Config CRDs can be categorized into 2 types `tenant` and `default` by label like `type = tenant`, `type = default`: - Tenant EmailConfig is to be selected by a tenant EmailReceiver which means each tenant can have his own EmailConfig. - If no EmailConfig selector is configured in a EmailReceiver, then this EmailReceiver will try to find a `default` EmailConfig. Usually admin will set a global default config. A receiver could be configured without xxxConfigSelector, in which case Notification Manager will try to find a default xxxConfigSelector with `type = default` label, for example: - A global EmailReceiver with `type = global` label should always use the default EmailConfig which means emailConfigSelector needn't to be configured for a global EmailReceiver and one default EmailConfig with `type = default` label needs to be configured for all global EmailReceivers. - Usually a tenant EmailReceiver with `type = tenant` label could have its own tenant emailConfigSelector to find its tenant EmailConfig with `type = tenant` label. - A tenant EmailReceiver with `type = tenant` label can also be configured without a emailConfigSelector, in which case Notification Manager will try to find the default EmailConfig with `type = default` label for this tenant EmailReceiver. ## QuickStart Deploy CRDs and the Notification Manager Operator: ```shell kubectl apply -f https://raw.githubusercontent.com/kubesphere/notification-manager/master/config/bundle.yaml ``` ### Deploy Notification Manager in KubeSphere (Uses `workspace` to distinguish each tenant user): #### Deploy Notification Manager ```shell cat < wechatApiSecret: key: wechat name: < wechat-api-secret > wechatApiCorpId: < wechat-api-corp-id > wechatApiAgentId: < wechat-api-agent-id > --- apiVersion: notification.kubesphere.io/v2beta1 kind: Receiver metadata: name: global-wechat-receiver labels: app: notification-manager type: global spec: wechat: # wechatConfigSelector needn't to be configured for a global receiver # optional # One of toUser, toParty, toParty should be specified. toUser: - user1 - user2 toParty: - party1 - party2 toTag: - tag1 - tag2 --- apiVersion: v1 data: wechat: dGVzdA== kind: Secret metadata: labels: app: notification-manager name: < wechat-api-secret > namespace: kubesphere-monitoring-system type: Opaque EOF ``` > - wechatApiAgentId is the id of app which sends messages to user in your WeCom. > - wechatApiSecret is the secret of this app. > - You can get these two parameters in App Management of your WeCom. > - Note that any user, party or tag who wants to receive notifications must be in the allowed users list of this app. #### Deploy the default SlackConfig and global SlackReceiver ``` cat < --- apiVersion: notification.kubesphere.io/v2beta1 kind: Receiver metadata: name: global-slack-receiver labels: app: notification-manager type: global spec: slack: # slackConfigSelector needn't to be configured for a global receiver channels: - channel1 - channel2 --- apiVersion: v1 data: token: dGVzdA== kind: Secret metadata: labels: app: notification-manager name: < slack-token-secret > namespace: kubesphere-monitoring-system type: Opaque EOF ``` > Slack token is the OAuth Access Token or Bot User OAuth Access Token when you create a Slack app. This app must have the scope chat:write. The user who creates the app or bot user must be in the channel which you want to send notification to. #### Deploy the default WebhookConfig and global WebhookReceiver ``` cat < - The `rootCA` is the server root certificate. > - The `certificate` is the clientCertificate of client. > - The format of bearerToken is `Authorization `. #### Deploy the default DingTalkConfig and a global DingTalkReceiver ``` cat < - DingTalkReceiver can both send messages to `conversation` and `chatbot`. > - If you want to send messages to conversation, the application used to send messages to conversation must have the authority `Enterprise conversation`, and the IP which notification manager used to send messages must be in the white list of the application. Usually, it is the IP of Kubernetes nodes, you can simply add all Kubernetes nodes to the white list. > - The `appkey` is the key of the application, the `appsecret` is the secret of the application. > - The `chatids` is the id of the conversation, it can only be obtained from the response of [creating conversation](https://ding-doc.dingtalk.com/document#/org-dev-guide/create-chat). > - The `webhook` is the URL of a chatbot, the `keywords` is the keywords of a chatbot, The `secret` is the secret of chatbot, you can get them in the setting page of chatbot. #### Deploy the default SmsConfig and a global SmsReceiver ``` apiVersion: notification.kubesphere.io/v2beta2 kind: Receiver metadata: labels: app: notification-manager type: global name: global-sms-receiver spec: sms: enabled: true phoneNumbers: ["13612345678"] --- apiVersion: notification.kubesphere.io/v2beta2 kind: Config metadata: labels: app: notification-manager type: default name: default-sms-config spec: sms: defaultProvider: huawei providers: huawei: url: https://rtcsms.cn-north-1.myhuaweicloud.com:10743/sms/batchSendSms/v1 signature: "xxx" templateId: "xxx" sender: "12323313" appSecret: valueFrom: secretKeyRef: namespace: "default" key: huawei.appSecret name: default-sms-secret appKey: valueFrom: secretKeyRef: namespace: "default" key: huawei.appKey name: default-sms-secret aliyun: signName: xxxx templateCode: xxx accessKeyId: valueFrom: secretKeyRef: namespace: "default" key: aliyun.accessKeyId name: default-sms-secret accessKeySecret: valueFrom: secretKeyRef: namespace: "default" key: aliyun.accessKeySecret name: default-sms-secret tencent: templateID: xxx smsSdkAppid: xxx sign: xxxx secretId: valueFrom: secretKeyRef: namespace: "default" key: tencent.secretId name: default-sms-secret secretKey: valueFrom: secretKeyRef: namespace: "default" key: tencent.secretKey name: default-sms-secret --- apiVersion: v1 data: aliyun.accessKeyId: eHh4eA== aliyun.accessKeySecret: eHh4eA== tencent.secretId: eHh4eA== tencent.secretKey: eHh4eA== huawei.appKey: eHh4eA== huawei.appSecret: eHh4eA== kind: Secret metadata: labels: app: notification-manager name: default-sms-secret type: Opaque ``` For SMS templates, you can create them in your SMS provider's SMS console. For Huawei Cloud SMS provider, pls make your custom SMS template containing ten placeholders. For a detailed description, if you have a template like this: ``` [KubeSphere alerts] alertname = ${TEXT}, severity = ${TEXT}, message = ${TEXT}, summary = ${TEXT}, alerttype = ${TEXT}, cluster = ${TEXT}, node = ${TEXT}, namespace = ${TEXT}, workload = ${TEXT}, pod = ${TEXT} ``` Then you will receive the notification as below: ``` [KubeSphere alerts] alertname = test, severity = warning, message = this is a test message, summary = node node1 memory utilization >= 10%, alerttype = metric, cluster = default, node = node1, namespace = kube-system, workload = nginx-deployment, pod = pod1 ``` #### Deploy the default PushoverConfig and global PushoverReceiver ``` cat < --- apiVersion: notification.kubesphere.io/v2beta2 kind: Receiver metadata: name: global-pushover-receiver labels: app: notification-manager type: global spec: pushover: # pushoverConfigSelector needn't to be configured for a global receiver profiles: - userKey: < Pushover-User-Key > title: "test title" # optional sound: "classical" # optional devices: ["iphone"] # optional --- apiVersion: v1 data: token: < Pushover-Application-Token > kind: Secret metadata: labels: app: notification-manager name: < pushover-token-secret-name > namespace: kubesphere-monitoring-system type: Opaque EOF ``` > You can add a profile object for each user under `profiles`. This object includes: >* UserKey: Required. A unique identifier for the user. Each Pushover user is assigned a user key, same as an username. Each user who intends to receive alerts via Pushover will have to configure their user key here. >* Devices: Optional. Device names to send the message directly to that device, rather than all of the user's devices. >* Title: Optional. Message's title, otherwise your app's name is used. >* Sound: Optional. Sound refers to the name of one of the [sounds](https://pushover.net/api#sounds) supported by device clients ### Deploy Notification Manager in any other Kubernetes cluster (Uses `namespace` to distinguish each tenant user): Deploying Notification Manager in Kubernetes is similar to deploying it in KubeSphere, the differences are: Firstly, change the `tenantKey` to `namespace` like this. ``` apiVersion: notification.kubesphere.io/v2beta1 kind: NotificationManager metadata: name: notification-manager spec: receivers: tenantKey: namespace ``` Secondly, change the label of receiver and config from `user: ${user}` to `namespace: ${namespace}` like this. ``` cat < ``` To set template for each type of receivers: ```yaml apiVersion: notification.kubesphere.io/v2beta1 kind: NotificationManager metadata: name: notification-manager spec: receivers: options: email: subjectTemplate: template: