BotkubeでSlackからKubernetes管理してみよう

この記事は [Kubernetes2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/kubernetes2) 12日目の記事です。
## はじめに

Kubernetesを運用していて、kubectlコマンドを実行することってどれくらいありますか？
複数クラスタを管理する場合、監視システムやダッシュボード的なものでステータス確認したり、デプロイもCD環境から実行するようにしてたりすると思うので、あまりないかもしれないです。
でも、デプロイ後のステータスを、エビデンス目的や、他の人への連絡のためにkubectlを実行して、結果をSlackにコピペしたりすることないですか？
また、複数クラスタ管理していて、ターミナルからkubeconfig切り替えながらkubectl実行してると、どのクラスタの作業しているのかわからくなったり・・・ってことないですか？
そんなときはBotkubeを使うといいかもしれないです。

## Botkube?
Slackからkubectlの実行ができたり、イベントをSlackに通知できたり、ChatOps的なことができるようになるツールです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/f91c8d74-4815-63f5-1639-5c914918022a.png)
https://www.botkube.io/
## インストール
- Slack
    - [Slack App](https://alpacajp.slack.com/apps/AF5DZLHPC-botkube)のページからインストールして、Tokenを取得します。
    
- Kubernetes
    - helmでインストールできます。 v3だとtillerいらないので楽ですね

```bash:
helm repo add infracloudio https://infracloudio.github.io/charts
helm install --version v0.9.1 --name-template botkube --namespace botkube -f values.yaml infracloudio/botkube
```

インストールに成功すると指定したSlack Channelにこんなんが出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/bbc76469-f140-c5cc-d469-0bbb45643442.png)

Daemonsetではないので、 [Fargate for EKS](https://aws.amazon.com/jp/blogs/news/amazon-eks-on-aws-fargate-now-generally-available/) でも動きました。


## 設定
https://www.botkube.io/configuration/
https://github.com/infracloudio/botkube/blob/master/helm/botkube/values.yaml
自分の環境のvalues.yamlはこんな感じです。

```values.yaml
config:
  communications:
    slack:
      enabled: true
      channel: '(channel名 #不要)'
      token: '(SlackのToken xoxb-XXX)'
      notiftype: short   

  settings:
    clustername: (cluster_name)
    allowkubectl: true
    configwatcher: true
    upgradeNotifier: false

  resources:
    - name: pod
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: service
      namespaces:
        include:  
          - all
        ignore:
          - 
      events:
        - error
    - name: deployment
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: statefulset
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: ingress
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: node
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - create
        - delete
        - error
    - name: namespace
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: persistentvolume
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: persistentvolumeclaim
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: configmap
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: daemonset
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: job
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: role
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: rolebinding
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
    - name: clusterrole
      namespaces:
        include:
          - all
        ignore:
          - 
      events:
        - error
    - name: clusterrolebinding
      namespaces:
        include:  
          - all
        ignore:
          -
      events:
        - error
        - 
resources: 
  limits:
   cpu: 100m
   memory: 128Mi
  requests:
   cpu: 100m
   memory: 128Mi
```

使っている設定だけ簡単に説明しておきます。

- config.communications.slack.notiftype
    - メッセージのフォーマットです。
    - `short` にすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/5976e970-407b-e9b2-7c63-2b4d2334503b.png)

    - `long` にすると 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/a976fa9d-99ad-b7f6-d899-1493c4b715cd.png)

- config.settings.allowkubectl
    - `true` にすると後述のSlack上でのkubectlの実行ができるようになります。
- config.settings.configwatcher
    - `true` にするとSlack上でbotkubeの設定が確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/c1107b74-c4ac-2ef0-6051-e0112fad64ac.png)
- config.settings.upgradeNotifier
  - `true` にすると、バージョンアップしたことを通知してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/485dc60f-4e94-1d48-7c89-6bbe628316ed.png)

- config.resources
    - 通知させたいリソース、イベントを列挙します。自分の環境では、各リソースのerrorのみ通知、Nodeに関してはAutoScaleを実行しているため、create、delete、errorすべてを通知するようにしています。
    - Fargate for EKS の場合、PodごとにNodeが起動するので、 Nodeに関する項目は削除して通知させないほうがいいかと思います。

## 使い方

`/botkubehelp` と入力するとHelpが出力されます。

```
BotKube Help

Usage:
    @BotKube <kubectl command without kubectl prefix> [--cluster-name <cluster_name>]
    @BotKube notifier [stop|start|status|showconfig]
    @BotKube ping [--cluster-name <cluster-name>]
    @BotKube filters [list|enable|disable] [filter-name]

Description:

Kubectl commands:
    - Executes kubectl commands on k8s cluster and returns output.

    Example:
        @BotKube get pods
        @BotKube logs podname -n namespace
        @BotKube get deployment --cluster-name cluster_name

    Allowed kubectl commands:
        get, top, cluster-info, describe, explain, logs, version, auth, api-resources, api-versions, diff

Cluster Status:
    - List all available Kubernetes Clusters and check connection health. 
    - If flag specified, gives response from the specified cluster.

    Example:
        @BotKube ping
        @BotKube ping --cluster-name mycluster

Notifier commands:
    - Commands to manage incoming notifications (Runs only on configured channel).

    Example:
        @BotKube notifier stop          Stop sending k8s event notifications to Slack
        @BotKube notifier start         Start sending k8s event notifications to Slack
        @BotKube notifier status        Show running status of event notifier
        @BotKube notifier showconfig    Show BotKube configuration for event notifier

Filters commands:
    - Command to manage filters run on K8s events (Runs only on configured channel).

        Example:
        @BotKube filters list                     Show list of available filters
        @BotKube filters disable ImageTagChecker  Disable filter
        @BotKube filters enable ImageTagChecker   Enable filter

Options:
    --cluster-name                  Get cluster specific response
```

### kubectlの実行
`@Botkube` のあとにコマンドを入力すると結果が出力されます。

- kubectl get

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/125637b5-5ddb-89a9-a873-4babf4ad9312.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/1cbf1f70-2889-93a0-0504-6881c6453447.png)

Namespaceの指定もできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/dd151eb3-be6c-f306-1ece-2ed3b5e1f8a8.png)

- kubectl describe
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/31595aa9-6f96-808b-a1d7-9900851fd422.png)

- kubectl logs
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/f0c853ff-5348-4828-5535-ea81766511ee.png)

サイズが大きいときはテキストファイルとしてダウンロードされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/11e320f4-dff2-8bbb-b8e0-660f31bfce16.png)

Helpにあるとおり、実行できるのは下記の参照系コマンドのみです。

```
    Allowed kubectl commands:
        get, top, cluster-info, describe, explain, logs, version, auth, api-resources, api-versions, diff
```

これ以外を実行するとエラーになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/712e7698-3dd8-035a-0ac3-0b98c6587672.png)

このへんはRBACの設定変えても実行できないようになっているみたいです。


## 入力がめんどくさい？

慣れてくると `@Botkube` とか入力するのもめんどうになってきます。
そんな場合は、SlackのWorkflowでメニューから呼び出したり、emojiリアクションで実行できるようにしとくといいかもしれないです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/95ba6268-3f5e-f2ed-b2da-fc2aa314ded9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/5d7a26eb-eae2-c9a5-6b4b-a55d02ef1585.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/71e62aa4-6789-5515-41ec-2b2b1e8ad80d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/dcbfd407-bc5b-0f24-48d7-dd0beecd526e.png)



自分の環境ではCDにArgoCDを使っていて、Syncの開始/終了をHookでSlackに投げるようにしているので、その通知にリアクションすると状態が確認できるようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3246/db361e7e-16dc-19c9-4836-571e3c5c2880.png)

## まとめ
Botkubeを使えばちょっとした確認をしたいときに、簡単にkubectlを実行できるようになります。
また、SlackのChannelとクラスタを紐付けておけば、ターミナル上での環境切り替えもいらなくなるし、間違いも起こりにくくなるのではないかと思います。
通知については、Namespaceや、create/delete/error等おおまかな設定しかできないので、アクションが必要な障害の検知などは監視システムで行うべきだと思いますが、なにかが起きたっていうのが分かるレベルでいいのであれば、十分利用できるのではないかと思います。