slackでサーバーレスにプログラムを実行~slack-lambda~

こんにちは、久保田です。

最近よくslackにRTMBotを作り、色んな発言をきっかけに動くBotを作り業務を改善しています。
例えば、

  • IPSより攻撃の報告があった場合にチケットページにアクセスし情報をまとめる
  • ファン故障などの障害があった際に対象の仮想基盤に乗っている仮想マシンの一覧を出力する

などです。

こんな事をしていると、slackの可能性には驚かされます。
そしてある日、ふと思いました。

slackでプログラムが動かせたら面白くない?

と。

botは基本的にslack上で起こる何かに反応して動きますし、その先にプログラムがあるだけならば、
いっその事slackでプログラムが実行できたら色々と夢が広がる気がします。

例えば

  • チームのメンバーがいるチャンネルで簡単な検証プログラムを動かす
  • 障害時に社外から、スマホでプログラムが動かせる
  • slackのreminder機能を使って、登録しておいたプログラムを動かす

などなどです。

というわけで今回はslack上でサーバーレスでプログラムを実行できる環境を作ったお話、「slack-lambda」のお話です。

動作例

百聞は一見に如かずなので、早速ご覧ください。

rubyでfib

f:id:AdwaysEngineerBlog:20171031184320g:plain

以下、入力値です。


@slack-lambda exec
language: ruby
version: 2.4

def num(n)
  return $n_0 if n == 0
  return $n_1 if n == 1
  num(n-1) + num(n-2)
end

n = 10
$n_0 = 1  #num(0)
$n_1 = 2  #num(1)
puts num(n)

goでbubble sort

f:id:AdwaysEngineerBlog:20171031184110g:plain

以下、入力値です。


@slack-lambda exec
language: go
version: 1.8

package main

import (
    "fmt"
)

func main() {
    arr := []int{6,10,2,1,5}

    fmt.Println(bubbleSort(arr))
}

func bubbleSort(arr []int) []int {
    lastIndex := len(arr) - 1

    for {
        if lastIndex == 0 {
            return arr
        }

        for i := 0; i < lastIndex; i++ {
            a := arr[i]
            b := arr[i+1]
            if a > b {
                arr[i] = b
                arr[i+1] = a
            }
        }

        lastIndex--
    }

}

システム構成

システムの構成は以下の様になっています。

f:id:AdwaysEngineerBlog:20171031185042p:plain

dockerをメインで使うようにしており、その後ろにgoでできたサーバーが2台存在しています。

proxy-serverの方はリクエストとして投稿された文字列を受け取り、jsonに変換します。
そしてjsonを後ろのlambda-serverに送ります。

lambda-serverがjsonを受け取り、渡されたパラメータに沿ってdockerのコンテナを立ち上げ、プログラムを実行します。
そしてその標準出力を返し、proxy-serverがまた送信元に返す、という流れです。

全てGoでできており、lambda-serverの処理はゴルーチンにより並列化がされているので、多くのリクエストを捌ける(はず)です。 今回は並列化のため、Go並列化パターンのpipelineを使用しました。(https://blog.golang.org/pipelines)

github.com

機能

機能は、以下のものがあります。

  • プログラムの実行(インライン)
  • プログラムの登録
  • 登録されたプログラムの実行
  • 登録されたプログラムの削除
  • 登録されたプログラムの一覧表示

まとめ

プログラムって便利だなって思いました。

今はgoとrubyしかサポートしていませんが、色々やりたいと思います。