AWS Lambda といえば、Amazon Web Service が提供する Node.js や Python、Java を使ったサーバーレスなコード実行基盤です。
これって、単純にコードをサーバーなしに実行できるだけじゃなくて、「AWSリソースのイベントをトリガーに様々なリソースを連動させる」「APIGateway と連動することで、AWS以外の適当なWebHook をトリガーに様々なリソースを連動させる」といったことが可能になります。つまり、本質はリソースとリソースをつなぐ歯車の役割を果たすのです。しかもコードで自在に操作を制御できる。
だからこそグラニもAWS Lambda は大好きで、発表されてすぐに GitHub WebHook でIssue や Pull Request を Chatwork に通知する基盤を Node.js で作ったり、Route53 の処理など様々な箇所で活用しています。
さてBuild 2016 で、ついにAzureによる同様の基盤が発表されました。それが、Azure Functions です。
今回は、Azure Function Apps を使った Webhook 処理をいくつか C# で書いてみましょう。
Azure Functions
実際に Azure Functions で何ができるかは、公式ドキュメントが詳しいです。
https://azure.microsoft.com/en-us/documentation/articles/functions-overview/azure.microsoft.com
幸いにもコード処理部分は動画になっており、ただの文章よりもそうとう理解が進みます。もう少し複雑な処理も動画に追加されるともっと嬉しいです。
https://azure.microsoft.com/en-us/documentation/services/functions/azure.microsoft.com
あとは先人の知恵もあります。
今後、あっという間に、AWS Lambda 相当の記事はどんどん出るんじゃないですかね。Advent Calendar とかも作るといいでしょう。
価格
AWS Lambda もですが、Azure Functions は実行した分のみの課金です。計測は2つあります。
1 つが、メモリ*コンピュート時間
With Azure Functions you only pay for what you use with compute metered to the nearest 100ms at Per/GB price based on the time your function runs and the memory size of the function space you choose. Function space size can range from 128mb to 1536mb. With the first 400k GB/Sec free.
もう1つがリクエスト。100万リクエストまでは無料らしいですね。
Azure Function requests are charged per million requests, with the first 1 million requests free.
Dynamic Hosting Plan ってなんなんですかね? ドキュメントが見つけられない.... Azure Functions 専用のプランらしく、今は気にしなくていいそうですが。ちなみに Azure Functions を作成するときに、Dynamic と Classic を選択できますが、Dynamic を選ぶと実行できるリージョンが今は限定されます。
Azure Functions hosted on the Dynamic Hosting plan will be available via the monthly free grant through April 22nd, with paid preview available after that date.
https://azure.microsoft.com/ja-jp/documentation/articles/azure-web-sites-web-hosting-plans-in-depth-overview/azure.microsoft.com
@shibayan さんが詳細を調べてらっしゃいました。さすがです。
テスト
リモートデバッグを含めて AWS Lambda が提供できていない高度なデバッグビリティを担保しているのはとても素晴らしいですね。AWS頑張れ。
https://azure.microsoft.com/en-us/documentation/articles/functions-test-a-function/azure.microsoft.com
困ったときは
公式に stackoverflow や MSDN フォーラムと案内があります。特に stackoverflow は中の人もちょくちょく回答してくださっているので、オススメです。
Kudu
AppService なのでKuduも見れます。
方法は、見たい Azure Function を選択 > Function App settings > Tools > Kudu
とブレードをたどる方法。
あるいは、AppService 共通の scm を付与したアドレスで。アドレスは例えば、test という Azure Functionsなら https://test.scm.azurewebsites.net/ になります。
Lambda でのメモリとの比較とかできたり面白いです。
Visual Studio Online
また VSO にも対応しています。
これも方法は Kudu 同様で 見たい Azure Function を選択 > Function App settings > Tools > Visual Studio Online
とブレードをたどる方法。
あるいは、AppService 共通の scm を付与したアドレスに末尾 /dev付与で。アドレスは例えば、test という Azure Functionsなら https://test.scm.azurewebsites.net/dev/wwwroot/ になります。
VSO では、見事にC# 実行中身の .csx や .json も見えててとても良いです。
もちろん VSO で編集すると、Azure Functions にも反映します。
Azure Functions の利点
いくつかあります。
幅広い言語対応
AWS Lambda を上回る圧倒的なメリットです。
サービス | 言語対応 |
---|---|
Azure Functions | C#, Node.js(JavaScript), Python, F#, PHP, batch, bash, Java, PowerShell |
AWS Lambda | Node.js (JavaScript), Python, Java (Java 8 互換) |
とはいえ、現状は以下の通り言語によって手厚さが違います。とりあえずメイン対応は、C# と Node.js がそろってる感じです。Python と Java が同程度にそろうとだいぶん使う人を選ばなくなるかなと思います。
言語 | テンプレート対応 |
---|---|
Batch | |
C# | |
JavaScript | |
Bash | |
PHP | |
PowerShell | |
Python |
Azure リソースのイベント駆動処理
AWS Lambda のメリットが、デフォルトで aws-sdk 参照、IAM Role 制御、VPC対応によるAWSリソースの自在なコントロールです。Azure Functions も同様に Azure のリソースをトリガーに処理を走らせることができます。リリース直後の現在の blob について触れている記事もあります。
今は Blob、EventHub、StorageQueue の対応のようですが、AWS Lambda 同様に対応が増えていくでしょう。とりあえず、Cloud Watch 相当の Application Insight でトリガーは Webhook で出来そうなので、モニタリング系の連動はたやすそうですね。
もちろんUser Voice で追加希望は効果が高いでしょう。
個人的な予測では、AWS Lambda 同様、Azure Functions はプラットフォームのリソース間疎結合を担うものという位置づけになるはずなので「クラウドプラットフォームの要」となり急速に発展すると思います。*1
CI 統合
VS だけでなく、VSTS や GitHub、Bitbucket、OneDrive、Dropboxなどからデプロイ統合が可能です。これも AWS Lambda ではとてもつらかった部分で、良く学んで Azure の従来の方法がうまく機能していると思います。
AWS Lambda + API Gateway 同様の処理
HttpTrigger や Generic Webhoook 、TimerTrigger は API Gateway + AWS Lambda で可能です。同様のことが Azure Functions のみでできるのは良いことです。TimerTrigger に至っては Lambda と同じく cron 指定です。違和感なく触れるでしょう。
もちろん Authentication/Authorization もあります。様々な IdP と連動しているのはとてもいいですね。
気になるポイント
AWS Lambda を触っていて Azure Functions を触ると気になるポイントがあります。
リソースアクセス制御
もとから Azure で気になるポイントになりますが、IAM Roleに相当するリソースの他リソースへのアクセス制御ってどうなるのかなというのは気になります。
外部ライブラリの利用
Node.js で async module が欲しい場合など、外部リソースの参照をどうしたものか不明です。AWS Lambda でいうところの Zip アップロード的なものはどうなるのかなと?普通に requires()
が効く感じがしますが。
C# でも、NuGet 参照したいときにどうしたものかなと。C# に関しては、CSharp Scripting のようなので、現状では限定されている感じですが詳細がいまいち不明です。*2
Azure Functions も VS からデプロイできますが、AWS Lambda も Visual Studio から直接デプロイ、現在設定されている Function をもとに新規作成などが可能なので、AWS Console 一切見ずに設定可能です。
Monitor
Coming Soon とのことです。一見すると、かなり良さげです。いや実際これでいいんですよ。AWS Lambda のモニターはみにくいです。
Token による制御
ヘッダに Token ID を入れる認証は単純ですが強力です。しかし、AzureFunctions にはtoken での認証は GitHub Webhook type 以外になさそうな....? Authorization/Authentication でできると思ったのですが、すべて IdP 連携だったため token での制御ができないものでしょうか....?
できないと幾つか考慮が必要になります。
- URL が漏れたら、Functions 作り直してURL変更するしかない? *3
- 連携系で IdP でのID連動はかなりつらい (通常対応してないです)
- webHookType を github にするというのも手でしょうが、X-Hub-Signature の計算とかいちいち入れるのっていう
設定できる気がしますが、見つけれませんでした...。
作成
さくっと Azure Functions を作成します。
Azure Portal で 追加 (+) > 検索窓で Function
と入れれば Function App が表示されます。
Create を選択します。
あとは必要な入力をすればokです。
3分程度で出来上がります。
サンプル
3つ C# での Azure Functions を作ってみましょう。Node.js は AWS Lambda で散々作る羽目になったのでもういいです。
- Slack に通知
- GitHub Issue へのコメント を Webhook で受け取ってSlack に通知
- VSTS のビルド完了を Webhok で受け取ってSlack に通知
Slackに通知
Slack に通知部分を切り出して、他から呼びだすための Azure Functions です。通知が複数回ないならFunctions を分けないほうがいいでしょうが、多くの場合は処理と通知を分けたくなるのではないでしょうか。
Json で受け取って Slack に通知するので、Generic Webhook で作成します。
あとは Slack の Incoming Webhook API に POST する処理をサクッと書きます。
Azure Functions もLambda 同様、サンプルとなるjson を Request Body においておきます。
この辺のデバッグやローカルで書き書き処理は、Visual Studio より LinqPad が安定ですねぇ。わたしは。
ローカルでサクッと動いたら、Save してから Run しましょう。
問題なく Slack に通知が来ましたね。
GitHub Issue へのコメント を Webhook で受け取ってSlack に通知
次は GitHub Issue へのコメントを Github Webhook で受け取って、Slack に通知してみましょう。
今回のはここを参考にするといいでしょう。
https://azure.microsoft.com/en-us/documentation/articles/functions-create-a-web-hook-or-api-function/azure.microsoft.com
デモをみたり、テンプレートをみると、GitHub Webhook - Node
が目に留まり C# がないのでコレを選びたくなるのですが、言語が違うので今回は Generic WebHook をまず選択します。
とはいえ、サンプルJSON や処理の参考になるので一個作っておくといいでしょう。ということで、みてみるとなるほどです。
GitHub の Webhook 設定
さて、C# - Generic WebHook で作成した Azure Functions ですが、まずは GitHub Webhook 対応しましょう。Integrate
タブ に行って WebHook type
を GitHub に変更します。
これで Develop
タブに、Github Secret 欄が出ています。
次に GitHub のWebhook を掛けたいリポジトリ > Settings > Webhooks % services
に行きます。
Payload URL に Azure Functions の Function UrlのURL
をいれて、Secret
に Azure Functions の Github Secretの値
を入れればok です。
Azure Functions のコード
さて、コメントをする前にコードを書きましょう。とりあえず GitHub Comment が書かれたときに内容を受け取るだけならこれでok です。*4
これでGitHub Issue にコメントすれば、GitHub Webhook でトリガーされて Azure Functions の Logs に表示されます。
Slack への通知
さて、あとはSlack通知の Azure Functions に POST するようにコードを付け加えます。
Save してからコメントしてみると、Slack に通知されますね。
VSTS のビルド完了を Webhok で受け取ってSlack に通知
残りは Visual Studio Team Service のビルド完了通知を Slack に通知してみましょう。Xamarin の Test Cloud なども含めて、VSTSは機能強化が著しいです。
従来は、Web Apps で ASP.NET WebHooks を使うか Zapier が王道でした。
ただ両者に一長一短があります。この隙間にほしかったのが、Lamdba 相当の処理、つまり Azure Functions です。ただし、NuGet が使えないため Hook が来た VSTS Job を参照して
、Github を参照して
、といった処理には向いていません。しかたにゃいので待ちましょう。
処理 | メリット | デメリット |
---|---|---|
ASP.NET Webhooks | ごにょごにょ処理を噛ませることができるのでかなり自在に色々できます。 | - Web Apps でいつ来るかわからない通知のためにずっと起動という無駄半端なさ - エラーが起こったときに例外で死ぬ可能性がある - Webhookを処理したいだけなのに持ち味が全く生かしきれません。 |
Zapier | Webhook の解析、実行は完全お任せ最高です | - Zapが5分単位のためリアルタイム性が損なわれる - いろいろごにょごにょしようとすると、JavaScriptを書くことになる - あれこれできないため若干窮屈な思いをします |
Azure Functions | - ごにょごにょ処理を噛ませることができるのである程度自在に色々できます。 - 必要な時にだけ処理されるのでコスト面も起動も気にしなくてok |
- NuGet が使えないため楽にできることに制約があります。 - いろいろごにょごにょしようとするとそれなりにコードを書く必要があります |
さっそく Generic WebHook で作ってみましょう。
今回のは、ここを参考にするといいでしょう。
Using VS Team Services Web Hooks with Azure Functions - Buck Hodges
VSTS の Webhook 設定
Azure Functions を作成したら、Function Url をコピーします。
このFunction Url を VSTS の Webhook に設定します。VSTS の 設定したいProject の Admin画面 > + ボタンで追加 > Web Hooks を選択
します。
Trigger の設定は、Build completed
がいいでしょう。
SETTINGS > URL
に 作成した Azure Functions の URL を貼り付けましょう。
RESOURCE VERSION は、2.0-preview.2 でも1.0 でもいいですが、ここでは 2.0-preview.2 のコードでサンプルを示します。
Azure Functions のコード
VSTS で TEST をすると REQUEST の JSON が拾えます。この JSON でテストするといいでしょう。
Azure Functions の Request Body に JSON 埋めて、テストが容易になるようにしておきます。
また、JSON を dynamic ではなくクラスとして変換すると、LinqPad でのデバッグはとても楽ちんです。*5ということでサクッと書きます。
ちなみに RESOURCE VERSION 1.0 の場合はこんな感じのクラスで JSON をデシリアライズできます。
テストで Run 実行してみると問題なく解釈できていますね。
VSTSの Webhook から Test しても問題なくトリガーされています。
Slack への通知
最後にSlack通知の Azure Functions に POST するようにコードを付け加えます。
Save してからビルドしたり、TEST するとSlack に通知されました。
まとめ
慣れの問題もありますが、Azure Functions を C# で書いていると、AWS Lambda の Node.js で苦労するようなこともまったくなく素直に書けます。癖がほとんどないので、かなり使いやすいでしょう。
あとは、Nuget 周りがいまいち読めない。。。。 #r でリファレンス基本効くらしいですが*6、Newtonsoft.Json 以外にどこまで通るのかしら?#r Microsoft.TeamFoundationServer.Client
とかいけないんですよねぇ。
今後に期待しつつ、aws-sdk など処理を何かしら依存していないものは、Azure Functionsに寄せていこうかと思います。さて、AWS Lambda もいい刺激を受けて、今のデバッグやデプロイといった苦しい箇所がよくなってほしいですね。*7
あ、400記事目でした。
次回は、Azure Functions を GitHub と CI してみましょう。