Skip to content

Commit

Permalink
Issue #37: Added multi-cluster support for displaying cluster specifi…
Browse files Browse the repository at this point in the history
…c information.

Issue #16: Added cluster-name in kubectl, notifier and ping messages from botkube.
  • Loading branch information
mugdha-adhav committed Feb 26, 2019
1 parent aa72ab3 commit f357fa6
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 95 deletions.
2 changes: 0 additions & 2 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,3 @@ settings:
clustername: not-configured
# Set false to disable kubectl commands execution
allowkubectl: false
# Set true only respond to channel in config
checkchannel: false
51 changes: 51 additions & 0 deletions design/multi-cluster.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Multi-cluster Support

#### Assumptions
`@botkube` commands refer to all the commands in the slack bot which currently supports:
- kubectl
- notifier
- ping


### Summary
Add Multi-cluster support for Botkube, where a single bot can monitor multiple clusters and respond to `@botkube` commands with cluster specific results.

### Motivation
Currently in multi-cluster scenario, a Slack bot authenticates all the clusters with a same authentication token. Thus running `@botkube` command returns response from all the configured clusters, irrespective of the slack channel or group. For `@botkube` command execution, we need a particular cluster specific output.

### Design

This design approach adds a flag `--cluster-name` to all `@botkube` commands. Use of that flag is optional in a cluster specific channel.

Botkube `Notifier` commands are restricted to a dedicated channel for a cluster only and `--cluster-name` flag is ignored.

Botkube `ping` command with the `--cluster-name` flag returns `pong` response from the cluster specified in the flag, else you get response from all the clusters. `Ping` command without --cluster-name flag can be used to list all the configured clusters in the slack bot and identify you cluster's name among them.

For `kubectl` commands in a dedicated channel to a cluster, if `--cluster-name` flag is used, it responds with the output for the cluster specified in flag, else it checks if the channel in the request matches the `config.Communications.Slack.Channel` and responds if true else ignores.

For `kubectl` commands in a group, Direct message or channel not dedicated to any cluster, the `--cluster-name` flag is mandatory. The executor checks if the `--cluster-name` flag is present in the request. If yes, it gets the cluster's name from the flag and compares with `c.Settings.ClusterName` from the config file, if it matches then it responds with the required output to the slack bot and if it doesn't match, it ignores the request. And if the `--cluster-name` flag is absent for kubectl commands, it responds to the slack bot saying 'Please specify the cluster-name'.

For example -
```sh
@Botkube get pods --cluster-name={CLUSTER_NAME}
```
where,
`CLUSTER_NAME` is the name of the cluster you want to query.

To get the list of all clusters configured in the slack, you can run the following command in slack.

```sh
@Botkube ping
```

##### Workflow

![Multi_Cluster_Design](workflow.png)


### Drawbacks
The `--cluster-name` flag is mandated for kubectl and notifier commands resulting additional overhead.

### Alternatives
We can add channel specific authentication token or completely dedicate a channel to a particular cluster which requires changes in the slack code.

Binary file added design/workflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 0 additions & 2 deletions helm/botkube/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,6 @@ config:
clustername: not-configured
# Set false to disable kubectl commands execution
allowkubectl: false
# Set true only respond to channel in config
checkchannel: false

resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
Expand Down
1 change: 0 additions & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ type Slack struct {
type Settings struct {
ClusterName string
AllowKubectl bool
CheckChannel bool
}

// New returns new Config
Expand Down
13 changes: 7 additions & 6 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package controller

import (
"fmt"
"os"
"os/signal"
"strconv"
Expand All @@ -20,13 +21,13 @@ import (
"k8s.io/client-go/tools/cache"
)

var startTime time.Time

const (
controllerStartMsg = "...and now my watch begins! :crossed_swords:"
controllerStopMsg = "my watch has ended!"
controllerStartMsg = "...and now my watch begins for cluster '%s'! :crossed_swords:"
controllerStopMsg = "my watch has ended for cluster '%s'!"
)

var startTime time.Time

func findNamespace(ns string) string {
if ns == "all" {
return apiV1.NamespaceAll
Expand All @@ -39,7 +40,7 @@ func findNamespace(ns string) string {

// RegisterInformers creates new informer controllers to watch k8s resources
func RegisterInformers(c *config.Config) {
sendMessage(controllerStartMsg)
sendMessage(fmt.Sprintf(controllerStartMsg, c.Settings.ClusterName))
startTime = time.Now().Local()

// Get resync period
Expand Down Expand Up @@ -127,7 +128,7 @@ func RegisterInformers(c *config.Config) {
signal.Notify(sigterm, syscall.SIGTERM)
signal.Notify(sigterm, syscall.SIGINT)
<-sigterm
sendMessage(controllerStopMsg)
sendMessage(fmt.Sprintf(controllerStopMsg, c.Settings.ClusterName))
}

func registerEventHandlers(resourceType string, events []string) (handlerFns cache.ResourceEventHandlerFuncs) {
Expand Down
Loading

0 comments on commit f357fa6

Please sign in to comment.