Golang Bot for Slash Command running on local(on-premises) Kubernetes(minikube)
0. はじめに
今回GolangとKubernetes/Dockerの勉強のためにMattermost(Slack Clone)のSlash Commandに応答するGolangの簡単なBotサンプルを作成しましたので、自己整理も兼ねて以下一通りを記事にします。
- GolangでSlash Commandのメッセージに対して分岐応答する簡易Bot作成
- Botを含んだDockerイメージのビルド
- Kubernetes(minikube)上へk8sマニフェストファイルを利用してBot及びBot確認用Mattermostのサービス及びデプロイメントの設定
- 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.構成
以下構成で確認ました。
-
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番)の指定など行っています。
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マニフェストファイル
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
からビルドしたものを指定しています。
環境変数GOBOTOTOKEN
のvalue: Your_slashcommand_token
についてはMattermost(Slack)側のSlashCommand設定時に払出されたTokenへ置き換えるか、デプロイメント作成後にkubectl apply -f
またはkubectl edit deployment
コマンドで別途変更してください。
これを変更しないとTokenのチェックで401エラーとなります。
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/
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へブラウザからアクセスし、初期アカウントの登録を行います。
左上チーム名横のメニュー(...)からSystemConsole
を選択
INTEGRATIONS
-Custom Integrations
の設定で以下をtrue
へ変更します。
Enable Custom Slash Commands:
Enable integrations to override usernames:
Enable integrations to override profile picture icons:
左上チーム名横のメニュー(...)からSwitch to チーム名
でSystemConsole
を抜けます。
左上チーム名横のメニュー(...)からIntegrations
を選択します。
Slash Command
を登録します。なお、Request URL
へ3.1.で確認したminikube service gobotsv --url
の実行結果を設定します。
Kubernetesのgobotblue
デプロイメントの環境変数GOBOTTOKENの値(Your_slashcommand_token)を先ほど控えたToken
に変更します。
先ほど登録したSlashComannd(今回の例では/gobot
)を呼び出して作成したGobotが応答することを確認します。
5.その他
文中での引用以外に以下を参考にさせて頂きました。
- https://docs.mattermost.com/developer/slash-commands.html
- https://github.com/favclip/ucon