PagerDutyとAsanaをzapierをつかって連携させてみた
zapierをつかってPagerDutyとAsanaを連携させる方法をまとめます。
モチベーション
PagerDutyのIncidentをSlackに通知をして、その対応をAsanaでタスク化して運用をするうえで Asanaのタスク化
を自動化させたい。そんなときzaiperは zap
という単位でAサービスで発生したイベントをトリガーにBサービスにアクションを行うという一連の運用フローを自動化することができる。
PagerDuty
でIncidentが新しく作られたら Asana
でタスクを作成する、このような運用フローがzaiperのダッシュボードからポチポチと設定するだけで自動化できる。
連携させてみた
zaiperのダッシュボードは直感的で設定フローの理解もすぐにできた。
PagerDutyをトリガーにAsanaでタスクを作るというフローだけど、他にもステップを追加することができる。例えばGoogleCalendarにイベントを追加したりgithubでissue化したり認証できるサービスであれば多様なステップを作ることができる。
ここからはzaiperの設定フローで補足したいところをまとめていく。
設定フローの補足
PagerDutyの設定
- Incidentの発生条件はオプションで設定できる。
- Incidentが誰にアサインされたかを指定したり、どのイベントタイプをトリガーにするか指定できる。
- 今回は誰にアサインされたかは指定せず、イベントタイプは
Trigger
とした。つまり認知していない新規のIncidentの発生がトリガーとなる。
- zaiperはPagerDutyのイベントを検知するためにEndpoinURLを生成するのでPagerDuty側でそのURLをWebhookに追加する必要がある。
Asanaの設定
- 今回はAsanaのタスクを作成するアクションにしたが、
Story
やProject
など他のアクションも設定できる。 - タスクを生成するうえでタスクのタイトルやメモなどをテンプレートとして設定できる。
- PagerDutyのIncidentから要素を取得することができるので、タイトルにIncidentの
ServiceName
やメモにIncidentのURL
やStatus
などを変数としてテンプレート化できる。 - 今回は次のように設定してみた。
- PagerDutyのIncidentから要素を取得することができるので、タイトルにIncidentの
- その他にもタスクを誰にアサインするかなどタスクの要素を細かく設定できる。
動かしてみる
あらかじめPagerDutyとAsanaはSlackと連携させているのでIncidentとタスクのイベントに応じてSlackに通知されることが確認できた。
実際にPagerDutyでIncidentを発生させてみて、Incidentが発生した通知の後にAsanaのタスクが作成されていることが分かる。
AsanaのタスクにはIncidentの情報が参照されていてzaiperで設定したAsanaのテンプレートが適応されていることが確認できる。
まとめ
zaiperをつかって運用フローの自動化を試してみた。zaiperのダッシュボードは使いやすい印象でつくってる方たちも好印象だった。
zaiperのプランはzapとタスクの数でグレードが分かれている。あとはzapierが稼働するのがBasicだと15分毎
でBusiness以降は5分毎
なので運用要件に合わせたプラン選択が必要だと感じた。
他のzapの組み合わせとしてはGoogleカレンダーにイベントが登録されたのをトリガーにSlackにイベントを通知する連携方法なども試しみたりした。
GoogleカレンダーのイベントをトリガーにしてSlackで告知するような運用はよくあるケースなので、まずはこういったところから導入を始めて、運用に合わせてzapを増やしていくとよさそうである。
KotlinでgRPC。SSL/TLSを有効にする方法をまとめた。
前回のエントリではgrpc/grpc-javaをベースにkotlinでgRPCを試しました。今回はSSL/TLSを有効にする方法をまとめていきます。grpc/grpc-java/SECURITY.mdを参照しながら進めました。
証明書を準備する
手元に適当な証明書がなかったのでgrpc-go/testdataにある証明書を利用しました。
Subject Alternative Name
を確認するとマルチドメインに*.test.google.fr
, waterzooi.test.google.be
, *.test.youtube.com
が定義されていますので、hostsにwaterzooi.test.google.be
を追加しました。
openssl x509 -text -in ./server1.pem
127.0.0.1 waterzooi.test.google.be
OpenSSLを有効にする
netty-tcnativeをプロジェクトに追加します。
buildscript { repositories { mavenCentral() } } dependencies { compile 'io.netty:netty-tcnative-boringssl-static:1.1.33.Fork26' }
netty-tcnativeはDynamic
とStatic
があります。このエントリではStatic
を利用しました。grpc/grpc-java/SECURITY.mdを参照するとStatic
の利用を推奨していますがOpenSSLのセキュリティパッチが提供された場合、Static
ではパッチ反映が即座には行われないためプロジェクト方針によってはDynamic
の利用を検討する必要があります。
GrpcSslContextsでSslContextを生成する
サーバ側とクライアント側ではGrpcSslContexts
に定義されているforServer
とforClient
のメソッドをつかってSslContext
を生成します。
サーバ側
(serverBuilder as NettyServerBuilder).sslContext( GrpcSslContexts.forServer( File(classLoader.getResource("server1.pem").file), File(classLoader.getResource("server1.key").file)) .clientAuth(ClientAuth.OPTIONAL) .build())
クライアント側
NettyChannelBuilder.forAddress("waterzooi.test.google.be", 50051) .sslContext( GrpcSslContexts.forClient() .trustManager(File(classLoader.getResource("ca.pem").file)) .build()) .build()
コードを公開しています
このエントリのコードはgithubに公開しています。
SSL/TLSを有効にするにあたり情報が少ない印象をもちました。java or kotlinで実装をする方に少しでも参考になると嬉しいです。
関連エントリ
KotlinでgRPC。実運用にも活かせるWEBアプリケーション構成で試してみた。
KotlinでgRPCを試していきます。protocol buffersがkotlinに対応していないのでjavaに生成したものを使います。次のようなアプリケーション構成でKotlinを使ったgRPC通信を試してみました。
アプリケーション構成
- エンドクライアントからのアクセスは
Gateway Server
が窓口となりHTTP/1.1
で通信を行います。 Gateway Server
のバックエンドにいるgRPC Server
とはgRPC(HTTP/2)
で通信を行います。monitoring tool
はGateway Server
とgRPC Server
の監視を行いHTTP/1.1
で通信を行います。
モチベーション
何度かgRPCについてのエントリをまとめてきました。kotlinでgRPCを試してみたいと感じていたのとSpring Framework 5.0のリリースを控えた状況でSpring Framework 5 on Kotlinを試してみたい欲求がありました。 そのためアプリケーション構成図にあるとおりGateway Server
にはRouter機能を試したいので spring-webflux
でアプリケーションを作りました。
次のエントリではSpring Framework 5.0でReactive Programmingを活用しながらkotlinらしいコードの紹介がされています。
またgRPC Server
ではHTTP/1.1
とgRPC(HTTP2)
の2つの通信方式を有効にしたいです。Spring Bootでどのように実現するのか?この課題についても理解を深める必要がありました。
そして実戦に向けて実運用をイメージしたアプリケーション構成を構築する必要がありました。
ここからは構築にいたるまでの勘所や課題などについてまとめていきます。
gRPC Server
まずはgRPC Serverからです。
ここでの課題はHTTP/1.1
とgRPC(HTTP2)
の2つの通信方式を有効にすることです。
monitoring tool
からはヘルスチェックなどの監視リクエストに応えるためにHTTP/1.1
で通信を行いたいGateway Server
との通信にはgRPC(HTTP2)
で通信を行いたい
この課題を解決するために次のspring-boot-starterを使いました。
こちらを使えばgRPC Serverを実装したクラスに@GRpcService
をつけるだけでgRPC SeverをSpring Boot上に起動できます。またSpring Boot(spring-boot-starter-web)で起動していますのでHTTP/1.1
の通信も有効です。
@GRpcService class EchoServer : EchoServiceGrpc.EchoServiceImplBase() { override fun echoService(request: EchoMessage?, responseObserver: StreamObserver<EchoMessage>?) { val msg = EchoMessage.newBuilder().setMessage("echo \\${request?.message}/").build() responseObserver?.onNext(msg) responseObserver?.onCompleted() } }
レポジトリのREADMEにあるとおりinterceptor
の提供(ログ差し込んだり)やServerビルド定義もカスタマイズできます。
$ ./gradlew clean generateProto bootRun ・・・ 2017-04-13 14:48:45.479 INFO 30602 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2017-04-13 14:48:45.482 INFO 30602 --- [ main] o.l.springboot.grpc.GRpcServerRunner : Starting gRPC Server ... 2017-04-13 14:48:45.528 INFO 30602 --- [ main] o.l.springboot.grpc.GRpcServerRunner : 'app.grpc.server.EchoServer' service has been registered. 2017-04-13 14:48:45.531 INFO 30602 --- [ main] o.l.springboot.grpc.GRpcServerRunner : 'app.grpc.server.GreetServer' service has been registered. 2017-04-13 14:48:45.765 INFO 30602 --- [ main] o.l.springboot.grpc.GRpcServerRunner : gRPC Server started, listening on port 50051. ・・・
8080ポート(HTTP/1.1)と50051ポート(gRPC/HTTP2)の両方が起動ログで確認できます。これでgRPC Serverの課題は解決です。
Gateway Server
次にGateway Serverです。
ここではspring-web-fluxを使いreactor coreベースでアプリケーションが動いています。そしてエンドクライアントからリクエストをgRPC Serverへ渡すgatewayの役割を担います(gRPCクライアントの役割)。
spring-web-fluxを使うとnon-blockingなservletが起動するためgRPCクライントには okhttp
を使います。gRPCのクライアントは標準でnettyが使われるためokhttp
を指定します。これをしないとreactor coreのアプリケーションとgRPC Serverのnon-blokingなところがバッティングしてしまうようです。
private fun getChannel() = OkHttpChannelBuilder.forAddress(appProperties.grpc.server.hostname, appProperties.grpc.server.port!!) // for testing .usePlaintext(true) .build()
もしGateway Server
とエンドクライアント
との通信にgRPCを使いたい場合はGateway ServerにgRPC Server
を置く必要がありバッティング問題を解消しなくてはなりません。これに関してはSpring Framework5.0の正式リリースやマイルストーンの動きを見て試していく必要があり課題として残りました。
protobuf-gradle-plugin
protoclo bufferの生成には次のgradleプラグインを使っています。
起動時に.proto
からprotocol bufferを生成するようにgradleに次ような設定をしています。
protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.2.0' } plugins { grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" } } generateProtoTasks { ofSourceSet('main').each { task -> task.builtins { java { outputSubDir = 'protoGen' } } task.plugins { grpc { outputSubDir = 'protoGen' } } } } generatedFilesBaseDir = "$projectDir/src/" } task cleanProtoGen { doFirst{ delete("$projectDir/src/main/protoGen") } } clean.dependsOn cleanProtoGen
上記の定義により./gradlew clean generateProto
を実行することでprotocol bufferを再生成できます。起動時に最新の.proto
からprotocol bufferを使われるように起動コマンドは./gradlew clean generateProto bootRun
を使っています。
まとめ
- 現バージョンの
Spring Boot 1.5.2
ではLogNet/grpc-spring-boot-starter
を使うことでHTTP/1.1
とgRPC(HTTP2)
の共存課題は解決できました。 - Spring Framework 5ではreactor coreの採用からgRPC Serverとの共存には課題が残りました。今後のjavaのエコシステムなどを使いながら課題解決に取り組みます。
コードを公開しています
今回のKotlinでgRPCを試したコードのすべてはgithubに公開しています。 起動して確認するにはgithubのコードからできますのでREADMEを参照してください。