LoginSignup
10
9

More than 5 years have passed since last update.

ローカル(オンプレミス)のKubernetes(minikube)上で動く Slash Command 用 Golang Bot

Last updated at Posted at 2017-03-20

Golang Bot for Slash Command running on local(on-premises) Kubernetes(minikube)

0. はじめに

今回GolangとKubernetes/Dockerの勉強のためにMattermost(Slack Clone)のSlash Commandに応答するGolangの簡単なBotサンプルを作成しましたので、自己整理も兼ねて以下一通りを記事にします。

  1. GolangでSlash Commandのメッセージに対して分岐応答する簡易Bot作成
  2. Botを含んだDockerイメージのビルド
  3. Kubernetes(minikube)上へk8sマニフェストファイルを利用してBot及びBot確認用Mattermostのサービス及びデプロイメントの設定
  4. Mattermost上でSlash Commandを設定し、Botの応答を確認

まだまだ勉強中のため、至らないところや冗長な部分などがあると思いますので何かありましたらコメントいただければと思います。

なお、Botの動作環境は、Kubernetes/Docker/Golangを選択可能です。
またMattermost(Slack Clone)に対応していますのでローカルやオンプレミス環境で動作可能です。

Botについて今回ローカルやオンプレミスでの動作検証を想定しています。
外部へ公開などをする場合は、セキュリティ対策を含めたデータのチェック機能などを別途実装して下さい。
また、k8s上のMattermost(Slack Clone)については、Botの動作確認用途のためデータの永続化などは行っていません。

検証環境等でのChatOpsデモ、素振り用などの参考にして頂ければと思います。

その他、本記事で利用するソースコードはgithubでも公開しています。
https://github.com/tbuchi888/golang-slashcommand-k8s.git

1. 動作環境等

1.1. 環境

以下環境を前提としています。
- minikube version: v0.17.1
- VirtualBox: バージョン 5.0.16 r105871
- mac OSX Yosemite

Kubernetesはminikubeを利用しています。
インストールについてはKubernetes公式サイト「minikubeでローカルKubernetesクラスタを5分でつくる方法」を参考にしてください。

1.2.構成

以下構成で確認ました。

k8s.png

  • Mattermostは動作確認用途なので、データの永続化などは行わずに、単純にreplicas: 1としてhttps://hub.docker.com/r/mattermost/platform/ を動かします。

  • tbuchi888/gobotblue:v1は後述しますローカルでビルドしたDockerイメージで、ここでGolangのBotを動かします。

2. コード

2.1. Golang Bot

こちら「SlackのSlash CommandsをApp Engineで稼働させる」を参考にSlash Commandのメッセージをswitch文で分岐処理して応答するようにしています。利用用途に合わせて適宜修正をしてください。
またTokenの環境変数からの取得と、MethodやTokenの確認、リッスンするport番号(3000番)の指定など行っています。

main.go
package main

import (
        "bytes"
        "encoding/json"
        "net/http"
        "os"

        "github.com/favclip/ucon"
)

func main() {
        ucon.Orthodox()

        ucon.HandleFunc("POST", "/", func(w http.ResponseWriter, r *http.Request) {
                if err := r.ParseForm(); err != nil {
                        w.Write([]byte(err.Error()))
                        return
                }

                w.Header().Set("Content-Type", "application/json")

                // Check method and token
                if r.Method != "POST" {
                    w.WriteHeader(http.StatusBadRequest)
                    return
                }
                if r.PostFormValue("token") != os.Getenv("GOBOTTOKEN") {
                    w.WriteHeader(http.StatusUnauthorized)
                    return
                }
                w.WriteHeader(http.StatusOK)

                data := map[string]string{
                        "response_type": "in_channel",
                        "username": "gobot",
                        "icon_url": "https://golang.org/doc/gopher/gophercolor.png",
                }

                // Switch by text
                t := r.PostFormValue("text")
                switch t {
/*--------------------------------------------------------------------------------
                        ここへ追記
                        case "条件となる文字列を指定" :
                やらせたい処理などを記載しMD記法で応答メッセージをセット。
                                data["text"] = "## 応答メッセージ"
--------------------------------------------------------------------------------*/
                        case "" :
                                data["text"] = "## メッセージが設定されていません。"
                        case "今日の天気は?" :
                                data["text"] = "## わかりません。。。"
                        default:
                                data["text"] = "## " + t + "gobotより自動返信しています。"
                }

                var buf bytes.Buffer
                json.NewEncoder(&buf).Encode(data)
                w.Write(buf.Bytes())
        })

        ucon.ListenAndServe(":3000")
        ucon.DefaultMux.Prepare()
        http.Handle("/", ucon.DefaultMux)
}

2.2. Dockerfile

Dockerファイルはgolang:1.8をベースに追加モジュールgithub.com/favclip/uconのインストールと今回作成するBot main.goのコピー及びコンパイル等をしています。

Dockerfile

FROM golang:1.8

RUN go get -u github.com/favclip/ucon

COPY ./main.go /go/src/main/
RUN go install main

ENTRYPOINT /go/bin/main

2.3. Kubernetes

GolangBot用のService定義k8sマニフェストファイル

gobotsv.yml
apiVersion: v1
kind: Service
metadata:
  name: gobotsv
  labels:
    name: app
    app: gobot
spec:
  ports:
    - name: gobot
      port: 3000
      targetPort: 3000
  selector:
    name: app
    app: gobot
    color: blue
  type: LoadBalancer

GolangBot用のDeployment定義k8sマニフェストファイル
blue/greenデプロイメントなど可能なようにdeploymentの定義を別にしています。
イメージは上述のDokcerfileからビルドしたものを指定しています。
環境変数GOBOTOTOKENvalue: Your_slashcommand_tokenについてはMattermost(Slack)側のSlashCommand設定時に払出されたTokenへ置き換えるか、デプロイメント作成後にkubectl apply -fまたはkubectl edit deploymentコマンドで別途変更してください。
これを変更しないとTokenのチェックで401エラーとなります。

gobotblue.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: gobotblue
  labels:
    name: app
    app: gobot
    color: blue
spec:
  minReadySeconds: 30
  strategy:
    type: RollingUpdate
  replicas: 4
  template:
    metadata:
      name: gobotblue
      labels:
        name: app
        app: gobot
        color: blue
    spec:
      containers:
      - image: tbuchi888/gobotblue:v1
        name: gobot
        ports:
          - containerPort: 3000
        env:
          - name: GOBOTTOKEN
            value: Your_slashcommand_token

Mattermost用のService及びDeployment定義k8sマニフェストファイル
Botの動作確認用途なので、データの永続化などは行わずに、単純にreplicas: 1としてk8s上で動かします。
なお、利用しているコンテナイメージは以下となります。
https://hub.docker.com/r/mattermost/platform/

mattermost.yml
apiVersion: v1
kind: Service
metadata:
  name: mattermostsv
  labels:
    name: app
    app: mattermost
spec:
  ports:
    - name: mattermost
      port: 8065
      targetPort: 8065
  selector:
    name: app
    app: mattermost
    color: blue
  type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mattermostdep
  labels:
    name: app
    app: mattermost
    color: blue
spec:
  minReadySeconds: 30
  strategy:
    type: RollingUpdate
  replicas: 1
  template:
    metadata:
      name: mattermostdep
      labels:
        name: app
        app: mattermost
        color: blue
    spec:
      containers:
      - image: mattermost/mattermost-preview:latest 
        name: mattermost
        ports:
          - containerPort: 8065

3.使い方

git clone または、こちらの記事から参考にソースファイルを用意します。

Git clone https://github.com/tbuchi888/golang-slashcommand-k8s.git
cd golang-slashcommand-k8s.git

ディレクトリ構成は以下となります。(git clone時)

golang-slashcommand-k8s
    ├── Dockerfile
    ├── LICENSE
    ├── README.md
    ├── k8s
    │   ├── gobotblue.yml
    │   ├── gobotsv.yml
    │   ├── mattermost.yml
    │   └── readme.md
    └── main.go

なお、Kubernetes/Docker/golang いずれの場合も
環境変数GOBOTOTOKENの値Your_slashcommand_tokenについてはMattermost(Slack)側のSlash Command設定時に払出されたTokenへ置き換えが必要です。

3.1. on kubernetes(minikube)

以下kubernetes(minikube)上での使用例です。

# use Docker on Kubernetes(minikube)
# macからminikube上のdockerにアクセスするために以下コマンドを実行します。
eval $(minikube docker-env)

# create docker image
docker build -t tbuchi888/gobotblue:v1 ./

# check image
docker images

# create k8s service and deploymnet
kubectl create -f k8s/gobotsv.yml --record
kubectl create -f k8s/gobotblue.yml --record

# get url of service on minikube 
# Mattermost側Slash Command登録時にRequestURLとして利用するので控えておきます。
minikube service gobotsv --url

# below mattermost is for testing
# create k8s service and deploymnet
kubectl create -f k8s/mattermost.yml --record

# get url of service on minikube 
# MattermostのURLのため控えておきます。
minikube service mattermostsv --url

minikube service gobotsv --urlの結果を
後述のMattermost(Slack)側のSlashCommand登録時にRequestURLとして設定します。
また、SlashCommand設定時に払い出されたTokenの値を使って k8s側gobotblue deploymentのTokenの値を変更します。

kubectl apply -f k8s/gobotblue.yml --record
#️ または以下で直接編集
kubectl edit deployment gobotblue

# 新しいpodsに切り替わることを確認(少し時間がかかります)
kubectl get pods

3.2. on Docker (参考)

以下はDokcerfile及びmain.goがあるディレクトリでtbuchi888/gobotblue:v1としてビルドしたイメージを、golang-botというコンテナ名で3000番portを待ち受けとして動作させる例です。
*なお、事前にDokcerのインストールが必要です。

docker build -t tbuchi888/gobotblue:v1 ./
docker run --name golang-bot -d -p 3000:3000 -e GOBOTTOKEN=Your_slashcommand_token tbuchi888/gobotblue:v1

3.3. Golang (参考)

以下はmain.goがあるディレクトリで3000番portを待ち受けとして動作させる例です。
*なお、事前にGolangのインストールやパスの設定等が必要です。

export GOBOTTOKEN="Your_slashcommand_token"
go get -u github.com/favclip/ucon
go install main
./main

4.(参考)Mattermostの設定 及び 実行結果

以下参考までにMattermost側でのSlash Commandの設定及び実行結果の例となります。

3.1のminikube service mattermostsv --url実行結果のURLへブラウザからアクセスし、初期アカウントの登録を行います。
matt01.png

Create New tearmを行います。
matt02.png

matt03.png

matt04.png

左上チーム名横のメニュー(...)からSystemConsoleを選択
matt05.png

INTEGRATIONS-Custom Integrationsの設定で以下をtrueへ変更します。

  • Enable Custom Slash Commands:
  • Enable integrations to override usernames:
  • Enable integrations to override profile picture icons:

左上チーム名横のメニュー(...)からSwitch to チーム名SystemConsoleを抜けます。

matt06.png

matt07.png

左上チーム名横のメニュー(...)からIntegrationsを選択します。

matt09.png

Slash Commandを選択
matt10.png

右上のAdd Slash Commandを選択
matt11.png

Slash Commandを登録します。なお、Request URLへ3.1.で確認したminikube service gobotsv --urlの実行結果を設定します。
matt12.png

表示されるTokenを控えておきます。
matt13.png

Kubernetesのgobotblueデプロイメントの環境変数GOBOTTOKENの値(Your_slashcommand_token)を先ほど控えたTokenに変更します。
matt14.png

Mattermostの適当なチャンネルを選択します。
matt15.png

先ほど登録したSlashComannd(今回の例では/gobot)を呼び出して作成したGobotが応答することを確認します。
matt16.png

5.その他

文中での引用以外に以下を参考にさせて頂きました。

- https://docs.mattermost.com/developer/slash-commands.html
- https://github.com/favclip/ucon
- Kubernetes 速習会 
- Kubernetes: Deployment の仕組み

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9