LoginSignup
4

More than 1 year has passed since last update.

[Tips] GitHub Actions で VNet 内の Azure Functions (C#) にデプロイする方法

Last updated at Posted at 2021-09-24

これまでは、GitHub は個人で利用し、業務では Azure DevOps を使う機会が多く、結果として CI/CD パイプラインは Azure DevOps が提供する Azure Pipelines を使うことがほとんどでした。GitHub が Microsoft に Join し、GitHub / GitHub Enterprise を業務で利用できるようになったことで、私自身、GitHub Actions を使う機会が徐々に増えてきました。

今回は、アプリケーション開発で頻繁に利用する Azure Functions (Function App) に対して、GitHub Actions を使ったデプロイ自動化の手順を整理します。エンタープライズ向けの開発では、Function App を Private Endpoint (インバウンド側の組み込み) を利用して、VNet に組み込む方法が一般的になってきましたが、その場合、インバウンドはプライベート通信しかサポートされない為、標準の GitHub-hosted Runner (ビルド&デプロイ サーバー) を使ったパブリック IP 通信でのデプロイができず、その VNet に配置した VM 上に Self-hosted Runner をインストールして利用する必要があります。

1. 環境

本稿では、以下の環境を利用しています。尚、GitHub リポジトリや GitHub Desktop の詳細な使い方は割愛します。

2. Azure Functions (Function App) の作成

Azure Portal から以下のリソースを作成します。VNet に組み込んだ環境も作る為、Function App 以外のリソースも作成します。

  • Resource Group : TEST_GitHub
  • VNet : VNET_JE_GitHub
  • Linux VM : seijim-linux-vm-github
  • Function App : seijim-func-github

(1) Resource Group の作成

50_Azure_RG.png

(2) VNet の作成

サブネットは以下を作成します。

  • Private Endpoint 配置用サブネット : func-inbound-pe
  • Function App VNet 統合用サブネット : func-outbound-integrated
  • VM 配置用サブネット : vm

51_Azure_VNet.png

52_Azure_VNet.png

(3) Linux VM の作成

イメージは、Data Science Virtual Machine - Ubuntu (ソフトウェアの追加インストールが不要) を指定し、ネットワークは、VNET_JE_GitHub の vm サブネットを指定します。
03_Azure_VM.png

54_Azure_VM.png

(4) Function App (C#) の作成

Function App は、Private Endpoint による接続をサポートしている Functions Premium Plan を選択します。Private Endpoint は、App Service Plan の PremiumV2, PremiumV3 でもサポートされています。閉域網でのデプロイが不要な場合は、実行プランの制約はありません。この段階では、VNet への組み込みはせずに、後のステップで実施します。

55_Azure_FuncApp.png

56_Azure_FuncApp.png

3. Function App のコード作成

(1) GitHub リポジトリの作成

GitHub Desktop を使って、Function App のコードを作成する前に、新しいリポジトリを作成しておきます。
01_GitHub_Desktop_NewRepo.png

(2) Visual Studio で Function App のコード作成

Visual Studio を起動して、「新しいプロジェクトの作成」をクリックします。
02_VS_NewProject.png

テンプレートの検索で、「function」と入力して、「Azure Functions」を選択します。
03_VS_SearchTemplate.png

プロジェクト名を入力して、ローカル Git リポジトリのパスを指定します。
04_VS_FileName.png

「Http trigger」を選択します。
05_VS_TriggerType.png

関数名を変更したい場合は、FunctionName 属性の「Function1」を変更してください。ここではそのままにしておきます。
06_VS_EditFunc.png

デバッグ実行「▷」ボタンをクリックして、ローカル環境で動作確認を行います。
07_VS_DebugFunc.png

ブラウザを起動し、アドレス バーに、コマンド ウィンドウに表示されている URI をコピーして、クエリ パラメーター「name」に適当な文字列を設定して実行します。以下のような画面が表示されれば成功です。
08_VS_DebugFuncEdge.png

(3) GitHub に Function App ソリューション/プロジェクトをプッシュ

Function App のコードをコミットして、GitHub リポジトリのプッシュします。
09_GitHub_Desktop_PushOrigin.png

4. GitHub Actions の構成

手順については、GitHub リポジトリ Azure/functions-action の Readme の「Using Publish Profile as Deployment Credential (recommended)」セクションに記載されています。以下の手順となりますので、このステップを1つずつ確認して行きます。

  • Azure Portal で当該 Function App に行く
  • 「発行プロファイルの取得」をクリックして、.PublishSettings ファイルをダウンロードする
  • .PublishSettings ファイルを開き、中身をコピーしておく
  • GitHub に行き、Repository > Settings > Secrets で、コピーしておいた XML を貼り付けて新しいシークレットを作成する
  • Azure/functions-action に用意されたテンプレートを利用して、リポジトリに .github/workflows/.yml を作成する
  • 「env:」セクションにある変数を当該 Function App に合わせて変更する
  • プロジェクト (コード) を GitHub リポジトリにコミット&プッシュすると、新しい GitHub ワークフローが Actions タブで開始される

(1) Azure Portal で Function App 発行プロファイルを取得

Azure Portal で対象の Function App に行き、概要ページの上部にある「発行プロファイルの取得」をクリックし、.PublishSettings ファイルをダウンロードします。

20_Azure_Func_Profile.png
21_Azure_Func_Profile_download.png

(2) .PublishSettings ファイルの中身をコピー

ダウンロードした .PublishSettings ファイルを開き、中身をコピーします。
22_Azure_Func_Profile_Copy.png

(3) GitHub で新しいシークレットの作成

自分の GitHub リポジトリに行き、「Settings」タブの「Secrets」を選択して、「New repository secret」ボタンをクリックします。
23_GitHub_SettingsSecrets.png

「Name」に AZURE_FUNCTIONAPP_PUBLISH_PROFILE、「Value」には直前の手順でコピーしておいた XML を貼り付け、「Add secret」ボタンをクリックして、新しいシークレットを作成します。
24_GitHub_New_Secret.png
25_GitHub_New_Secret.png

(4) GitHub ワークフロー (GitHub Actions) の作成

GitHub Azure/functions-action に行き、Readme の以下セクションにあるテンプレートの表から DotNet 行 / Windows 列にある「windows-dotnet-functionapp-on-azure.yml」のリンクをクリックします。
26_GitHub_New_GitHub_Actions.png

このテンプレート ファイル「windows-dotnet-functionapp-on-azure.yml」の中身をコピーしておきます。
27_GitHub_New_GitHub_Actions.png

自分の GitHub リポジトリの「Actions」タブで、「set up a workflow yourself」リンクをクリックします。
28_GitHub_New_GitHub_Actions.png

生成された「main.yml」ファイルの中身を事前にコピーしておいたテンプレートの中身で置き換えます。
29_GitHub_New_GitHub_Actions.png

(5) GitHub ワークフロー (GitHub Actions) の修正

「main.yml」にコピペしたテンプレート (Function App のビルド&デプロイ) を自分の Function App の環境に合わせる為、「env:」セクションにある以下の変数を修正します。尚、DOTNET_VERSION については、こちらのサイトを確認して、3.x の最新バージョンを選択しています。

  • AZURE_FUNCTIONAPP_NAME: seijim-func-github # Function App name
  • AZURE_FUNCTIONAPP_PACKAGE_PATH: './FuncGitHub/FuncGitHub/' # VS Project (csproj) file directory
  • DOTNET_VERSION: '3.1.413' # Latest .NET SDK 3.x version

30_GitHub_New_GitHub_Actions.png

変数を修正したら、「Start commit」をクリックします。
31_GitHub_New_GitHub_Actions.png

(6) GitHub ワークフロー (GitHub Actions) の実行結果を確認

「Actions」タブを開くと、ワークフロー (この場合、main.yml) の実行結果を確認することができます。今回は、main.yml のコミットでワークフローが実行されましたが、ソースコードの変更がコミットされると、同様にワークフローが実行されます。
32_GitHub_New_GitHub_Actions.png

「Start commit」を実施した際のコミット名称をクリックすると、ジョブ毎の実行結果が表示されます。
33_GitHub_New_GitHub_Actions.png

ジョブ名をクリックすると、各ステップ毎の実行結果が表示されます。
34_GitHub_New_GitHub_Actions.png

(7) Function App のデプロイ後のテスト

Azure Portal で対象の Function App に行き、「関数」ページから対象の関数 (この場合、Function1) をクリックし、「コードとテスト」ページ上部の「関数の URL の取得」をクリックします。
35_GitHub_New_GitHub_Actions.png
36_GitHub_New_GitHub_Actions.png

表示された URL をコピーし、ブラウザを起動して、アドレスバーに貼り付け、クエリパラメーター「name=Azure!!」を追加して実行してみます。ローカルで実行した時と同じように、以下のような表示になれば、成功です。
37_GitHub_New_GitHub_Actions.png

5. Function App を VNet に組み込む (閉域化)

2章の手順 4 でも記載しましたが、Function App が Functions Premium Plan (もしくは、App Service Plan - PremiumV2 or PremiumV3) になっていることを確認してください。

(1) インバウンド通信の閉域化

Function App では、インバウンド通信とアウトバウンド通信それぞれで VNet への組み込み方が異なります。ここでは、インバウンド通信を Private Endpoint/Link 機能を使って組み込みます。

Azure Portal で対象の Function App に行き、「ネットワーク」ページで、「受信トラフィック」ボックスの「プライベート エンドポイント」をクリックします。
60_Azure_FunctionApp_閉域化.png

「プライベート エンドポイント接続」ページで、「+ 追加」をクリックします。
61_Azure_FunctionApp_閉域化.png

Private Endpoint の名称の他、2章で作成した VNet および サブネットを指定し、「OK」をクリックします。
62_Azure_FunctionApp_閉域化.png

「接続状態」が「Approved」になっていれば、Private Endpoint は有効です。
63_Azure_FunctionApp_閉域化.png

(2) アウトバウンド通信の閉域化

アウトバウンド通信は、VNet 統合機能を使って組み込みます。「ネットワーク」ページの「送信トラフィック」ボックスの「VNET 統合」に該当しますが、今回の検証において、アウトバウンド通信 (DB などへのアクセス) は発生しない為、ここでは 割愛します。
60_Azure_FunctionApp_閉域化.png

(3) GitHub ワークフローで再度ビルド&デプロイを実行

GitHub リポジトリの「Code」タブで、Function1.cs ファイルを編集モードで開き、ログ出力部分のコードを修正し、コミットします。
image.png

修正前

Function1.cs
log.LogInformation("C# HTTP trigger function processed a request.");

修正後

Function1.cs
log.LogInformation("C# HTTP trigger function processed a request!!!!!");

(4) GitHub ワークフローの実行結果

Function App の閉域化によって、デプロイ先にアクセスが出来ず、ワークフローが失敗することが分かります。
65_Azure_FunctionApp_閉域化.png
66_Azure_FunctionApp_閉域化.png

6. Self-hosted Runner による閉域環境への対応

5章で、標準の GitHub-hosted Runner (ビルド&デプロイ サーバー) では、パブリック IP 通信でのデプロイができないことが分かりました。これに対処する為、Function App を組み込んだ VNet に Self-hosted Runner を立てる必要があります。ここでは、その手順を記載します。

(1) GitHub での操作

GitHub リポジトリで、「Settings」タブの「Actions」>「Runners」を開き、「New self-hosted runner」ボタンをクリックします。
70_GitHub_Self-hostedRunner.png

2章で作成した Linux VM を使う為、「Runner Image」は「Linux」を選択します。ここに Self-hosted Runner のダウンロード、セットアップの手順が示されています。
71_GitHub_Self-hostedRunner.png

(2) SSH クライアントでの操作

2章で作成した Linux VM に SSH 接続を行い、前の手順 (1) で表示しているページに記載された Self-hosted Runner のダウンロード、セットアップ手順通りに実行します。以下は実行例ですので、必ず自分の GitHub 上の手順に従ってください。

Download(例)
# Create a folder
mkdir actions-runner && cd actions-runner
# Download the latest runner package
curl -o actions-runner-linux-x64-2.283.1.tar.gz -L https://github.com/actions/runner/releases/download/v2.283.1/actions-runner-linux-x64-2.283.1.tar.gz
# Optional: Validate the hash
echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  actions-runner-linux-x64-2.283.1.tar.gz" | shasum -a 256 -c
# Extract the installer
tar xzf ./actions-runner-linux-x64-2.283.1.tar.gz
Configure(例)
# Create the runner and start the configuration experience
./config.sh --url https://github.com/seijim/seijim-func-github --token XXXXXXXXXXXXXXXXXXXXXXXXXXXXX

./config.sh のステップを実行すると、GitHub に接続した後、いくつか入力を促されますが、基本的には Enter で大丈夫です。ラベル付けについては、既定のラベル ('self-hosted', 'Linux', 'X64') 以外が必要な場合に入力しておきます。ここでは、「runner1」と入力しました。
72_GitHub_Self-hostedRunner.png

最後に ./run.sh で Self-hosted Runner を起動します。

Configure(例)
# Last step, run it!
./run.sh

以下のメッセージが表示されれば、Self-hosted Runner が正常に起動し、ジョブを待機している状態を示しています。
73_GitHub_Self-hostedRunner.png

(3) GitHub での状況確認

GitHub リポジトリの「Settings」タブで、「Actions」>「Runners」を開きます。作成した Self-hosted Runner が表示され、「Status」が「Idle」となっていれば、正常です。
74_GitHub_Self-hostedRunner.png

(4) GitHub ワークフローの修正

GitHub リポジトリの「Code」タブで、./github/workflow/main.yml を開き、「runs-on」セクションで「windows-latest」から Self-hosted Runner のラベル ('self-hosted', 'Linux', 'X64', 'runner1') を設定することで、ワークフローを Self-hosted Runner で実行することができます。

main.yml
jobs:
  build-and-deploy:
    runs-on: [self-hosted, linux, x64, runner1]

(5) GitHub ワークフロー実行結果の確認

GitHub リポジトリの「Actions」タブで、ワークフローの実行結果を確認します。Function App の閉域環境においても、デプロイが成功することが分かります。
76_GitHub_Self-hostedRunner.png

SSH クライアントでも成功を確認することができます。
75_GitHub_Self-hostedRunner.png

(6) Self-hosted Runner のサービス化

サービス化については、こちらのページで、手順をご確認ください。

まとめ

いかがだったでしょうか。比較的つまずくポイントは少ないのではないかと思います。
また、Windows OS を選択した Azure Functions へのビルド&デプロイに Linux VM を使えるというのは、面白かったのではないでしょうか。
.NET (C#) が完全なマルチプラットフォーム OSS 言語ランタイムであることが分かるケースとなります。

参照

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4