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です。
https://azure.microsoft.com/en-us/blog/introducing-azure-functions/
今回は、Azure Function Appsを使ったWebhook処理をいくつかC# で書いてみましょう。
Azure Functions
実際にAzure Functionsで何ができるかは、公式ドキュメントが詳しいです。
https://azure.microsoft.com/en-us/services/functions/
https://azure.microsoft.com/en-us/documentation/articles/functions-overview/
幸いにもコード処理部分は動画になっており、ただの文章よりもそうとう理解が進みます。もう少し複雑な処理も動画に追加されるともっと嬉しいです。
https://azure.microsoft.com/en-us/documentation/services/functions/
あとは先人の知恵もあります。
https://blog.xin9le.net/entry/2016/04/01/042452
今後、あっという間に、AWS Lambda相当の記事はどんどん出るんじゃないですかね。Advent Calendarとかも作るといいでしょう。
価格
AWS Lambdaもですが、Azure Functionsは実行した分のみの課金です。計測は2つあります。
https://azure.microsoft.com/en-us/pricing/details/functions/
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.
@shibayanさんが詳細を調べてらっしゃいました。さすがです。
テスト
リモートデバッグを含めてAWS Lambdaが提供できていない高度なデバッグビリティを担保しているのはとても素晴らしいですね。AWS頑張れ。
https://azure.microsoft.com/en-us/documentation/articles/functions-test-a-function/
困ったときは
公式にstackoverflowやMSDNフォーラムと案内があります。特にstackoverflowは中の人もちょくちょく回答してくださっているので、オススメです。
https://stackoverflow.com/questions/tagged/azure-functions
https://social.msdn.microsoft.com/Forums/en-US/home?forum=AzureFunctions
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での制御ができないものでしょうか....?
https://github.com/projectkudu/AzureFunctions/search?UTF-8=%E2%9C%93&q=webHookType
できないと幾つか考慮が必要になります。
- 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する処理をサクッと書きます。
https://gist.github.com/guitarrapc/21a7f8cf8d53769f50dada1abdd83636
Azure FunctionsもLambda同様、サンプルとなるjsonをRequest Bodyにおいておきます。
https://gist.github.com/guitarrapc/22ab70d175667bfa65b033615edaba8b
この辺のデバッグやローカルで書き書き処理は、Visual StudioよりLinqPadが安定ですねぇ。わたしは。
ローカルでサクッと動いたら、SaveしてからRunしましょう。
問題なくSlackに通知が来ましたね。
GitHub Issue へのコメント を Webhook で受け取ってSlack に通知
次はGitHub IssueへのコメントをGitHub Webhookで受け取って、Slackに通知してみましょう。
今回のはここを参考にするといいでしょう。
デモをみたり、テンプレートをみると、GitHub Webhook - Node
が目に留まりC# がないのでコレを選びたくなるのですが、言語が違うので今回はGeneric WebHookをまず選択します。
とはいえ、サンプルJSONや処理の参考になるので一個作っておくといいでしょう。ということで、みてみるとなるほどです。
GitHub の Webhook 設定
さて、C# - Generic WebHookで作成したAzure Functionsですが、まずはGitHub Webhook対応しましょう。Integrate
タブに行ってIntegrate
を GitHub に変更します。
これでDevelop
タブに、GitHub Secret欄が出ています。
次にGitHub のWebhook を掛けたいリポジトリ > Settings > Webhooks % services
に行きます。
Payload URLにAzure FunctionsのFunction UrlのURL
をいれて、Function UrlのURL
にAzure FunctionsのFunction UrlのURL
を入れればokです。
Azure Functions のコード
さて、コメントをする前にコードを書きましょう。とりあえずGitHub Commentが書かれたときに内容を受け取るだけならこれでokです。*4
https://gist.github.com/guitarrapc/e3ed9363bf2d44dc4a1ecb37a1cb5927
これでGitHub Issueにコメントすれば、GitHub WebhookでトリガーされてAzure FunctionsのLogsに表示されます。
Slack への通知
さて、あとはSlack通知のAzure FunctionsにPOSTするようにコードを付け加えます。
https://gist.github.com/guitarrapc/f08665041b1e39b589ef3ec22561d627
Saveしてからコメントしてみると、Slackに通知されますね。
VSTS のビルド完了を Webhok で受け取ってSlack に通知
残りはVisual Studio Team Serviceのビルド完了通知をSlackに通知してみましょう。XamarinのTest Cloudなども含めて、VSTSは機能強化が著しいです。
従来は、Web AppsでASP.NET WebHooksを使うかZapierが王道でした。
https://blogs.msdn.microsoft.com/webdev/2015/09/04/introducing-Microsoft-asp-net-webhooks-preview/
ただ両者に一長一短があります。この隙間にほしかったのが、Lamdba相当の処理、つまりAzure Functionsです。ただし、NuGetが使えないためHook が来た VSTS Job を参照して
、Hook が来た VSTS Job を参照して
、といった処理には向いていません。しかたないので待ちましょう。
処理 | メリット | デメリット |
---|---|---|
ASP.NET Webhooks | ごにょごにょ処理を噛ませることができるのでかなり自在に色々できます。 | - Web Apps でいつ来るかわからない通知のためにずっと起動という無駄半端なさ - エラーが起こったときに例外で死ぬ可能性がある - Webhookを処理したいだけなのに持ち味が全く生かしきれません。 |
Zapier | Webhook の解析、実行は完全お任せ最高です | - Zapが5分単位のためリアルタイム性が損なわれる - いろいろごにょごにょしようとすると、JavaScriptを書くことになる - あれこれできないため若干窮屈な思いをします |
Azure Functions | - ごにょごにょ処理を噛ませることができるのである程度自在に色々できます。 - 必要な時にだけ処理されるのでコスト面も起動も気にしなくてok |
- NuGet が使えないため楽にできることに制約があります。 - いろいろごにょごにょしようとするとそれなりにコードを書く必要があります |
さっそくGeneric WebHookで作ってみましょう。
今回のは、ここを参考にするといいでしょう。
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埋めて、テストを容易にします。
https://gist.github.com/guitarrapc/13c38ee8c739a1b0d07c6886dc0cbcb4/edit
また、JSONをdynamicではなくクラスとして変換すると、LinqPadでのデバッグはとても楽ちんです。*5ということでサクッと書きます。
https://gist.github.com/guitarrapc/6e5530f05872d3fbbcbc72b16802ac8f
ちなみにRESOURCE VERSION 1.0の場合はこんな感じのクラスでJSONをデシリアライズできます。
https://gist.github.com/guitarrapc/f21614008a5daeae69b523386afacf9a
テストでRun実行してみると問題なく解釈できていますね。
VSTSのWebhookからTestしても問題なくトリガーされています。
Slack への通知
最後にSlack通知のAzure FunctionsにPOSTするようにコードを付け加えます。
https://gist.github.com/guitarrapc/802a65c7734de3b4eb27327000b9a00e
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してみましょう。