BEACHSIDE BLOG

MicrosoftとかC#を好むレンジャーの個人メモ

Azure Function V2 (C#) で Run From Package の CICD と Azure DevOps (4/4)

Azure Functions V2 の Release pipeline の作成その2です。前回はローカルにデプロイしましたが、今回は Blob にデプロイするバージョンです。前回より実践的な方法となります。
ただ、2018年12月時点だと Azure DevOps で Azure Functions V2 の Run From Package をいい感じに Release する方法がないなーと悩んでいます。とりあずちょっとイケてない方法ですがリリースのパイプラインを作ってみました。

いい感じにやるのは自分で Custom の Task 作るしかないのか...ダサくてももうセットアップして動いてるからまぁいいかーという感じの今日この頃です。


Build パイプラインは、前回作ったものをそのまま利用して、Blob に配置する Release のパイプラインを構築します。実際にやるべきことは以下となります。

  • Blob Storage に Build パイプラインの Artifact である zip のパッケージをアップロードする
  • アップロードした Blob に Azure DevOps がアクセスできるよう SAS トークンを生成する
  • (Blob の URL +) Blob の SAS トークンを環境変数にセットする

Release Pipeline の作成: リモート (Blob) へ zip デプロイ編

Releases の一覧で 「New」> 「New release pipeline」をクリックして新規にパイプラインを作成します。

f:id:beachside:20181221162241p:plain


テンプレートは、「Empty」を選択します。

f:id:beachside:20181221162316p:plain


Artifact の設定

画面上部のパイプラインの名前、画面右側の Stage name を適当に入力し、最初に「Add an artifact」を選択します。

f:id:beachside:20181221163655p:plain


Artifact を追加します。ここでは Build の Artifact をとるようにしています。Default version はここでは適当に選んでるだけなので、運用に合わせて選びましょう。「Add」ボタンをクリックして追加します。

f:id:beachside:20181221163944p:plain


Job の設定: Azure File Copy

ここでは、Build パイプラインの Artifact を Blob にコピーします。

前述のArtifact の設定後「1job, 0task」をクリックします。

f:id:beachside:20181221164050p:plain


Agent job の「+」をクリックし、task で「Azure File Copy」を選択します。検索で「azure file copy」と入力するとすぐ見つかります。

f:id:beachside:20181221163312p:plain


追加された Azure File Copy をクリックして設定を行います。あくまで私の Artifact やソースに依存した名称になります。

項目 備考
Display name (任意) 任意にわかりやすいものを入力です。
Source $(System.DefaultWorkingDirectory)/_App25 Build/drop Build の Artifact が出力されるディレクトリを指定します。事前に Artifact を設定しておくことでフォルダーの選択ダイアログで選べます。ファイルではなく、フォルダーを選ぶ必要があります。
Azure Connection Type Azure Resource Manager
Azure Subscription (自分のやつ) 利用するBlob のサブスクリプションを指定します。
Destination Type Azure Blob
MR Storage Account (自分のやつ) Functions のリソースに紐づいている Blob Storage を指定します。
Container Name function-releases 任意になりますが、func のコマンドでこの名称のコンテナーに出力されるため合わせました。
Blob Prefix $(Build.BuildNumber) 任意になりますが、何もないと常に同じzipの名前が上書きで置かれてしまうため、ファイル名を変える用途で BuildNumber を使っています。私の場合、Build パイプラインのBuildNumberがRelease のユニーク単位になるので問題ないですが、そうでない方は別の方法がよいと思います。

なんか色々と制約を持たなければならいので苦しいです。func コマンドのようにファイル名をユニークになるようリネームして配置するのがよさげですが、それもめんどいのでこんな感じにしました。

Output でStorage Container の URI が取れますがそれだけだと使えないのと、SASトークンも出力できますがコンテナのSASだし、有効期限が4Hなので使えんです。

Job の設定: Azure CLI

ここでは以下のことをやります。

  • Blob にアップロードした zip の SAS トークンを生成し、取得
  • Functions の アプリケーション設定に値をセット

Agent job の「+」をクリックし、「Azure CLI」を選択します。これも検索で「azure cli」と入力した方がよいです。

f:id:beachside:20181221171050p:plain


設定内容は以下の感じです。

|Display name|Copy to Blob|任意にわかりやすいものを入力です。| |Azure Subscription|(自分のやつ)| 利用するサブスクリプションを指定します。| |Script Location|Inline script|今回はInline を選んでますが、Scriptをファイル化して呼び出した方が管理もしやすいのでよいと思います。| |Inline Script|...|後述します|

今回書いたスクリプトは以下です。超愚直に書いただけでダサく辛み修羅みを感じますがざっくり解説します。

  • まず、SAS を取得します。Blob は、前タスクで指定した Blob アカウントや Container名を指定します。ファイル名は前タスクで「Source」を指定した際にフォルダーの下に見えているはず(一度Buildパイプラインを実行すれば...)なので、その名前を指定します。
  • 後は、同様にSAS をとってきて Functions のアプリケーション設定にURL+SASトークンを設定しています。ここでは、WEBSITE_RUN_FROM_PACKAGE ではなく旧名称の WEBSITE_RUN_FROM_ZIP に設定しています。事情がなければ WEBSITE_RUN_FROM_PACKAGE に設定した方が良いでしょう。

私の場合、開発環境では func コマンドでデプロイして試すこともあって泣く泣くその動作に合わせている...とにかくカオスなので、とりあえず WEBSITE_RUN_FROM_ZIP の方に設定しています。

for /f %%i in ('az storage blob generate-sas --account-name bssample23b57b -c function-releases -n $(Build.BuildNumber)/functionsApp25.zip --expiry 2099-12-31T23:59:59Z --permissions r -o tsv') do set SAS="%%i"
for /f %%i in ('az storage blob url --account-name bssample23b57b -c function-releases -n $(Build.BuildNumber)/functions25.zip -o tsv') do set URL="%%i"
SET FULL_URL="%URL:"=%?%SAS:"=%"

az webapp config appsettings set -g functions.run-from-package-sample -n FunctionApp25 --settings WEBSITE_RUN_FROM_ZIP=%FULL_URL%

保存して Release パイプラインを実行すると、無事に Blob から Run From Package ができました。
うまく動かないときは、Release のこれらの Job のログを見てみましょう。
Blob のパスや環境変数に設定された値と、実際のBlob のパスなどを見比べるとよいと思います。 どこに何をしたっていうログが表示されているのでおかしいところがわかると思います。


イケてな過ぎて後味がわるい...。それでもパイプラインがないよりはましかぁ...。