Azure Functions のインプロセスモデルを .NET 6 から .NET 8 に移行する検証をしてみた

LTS 版の .NET 6 が 2024年11月12日にサポート終了となるようなので、よく使っている Azure Functions インプロセスモデルを簡単に移行したいと思います。.NET 8 の Azure Functions では、分離ワーカーモデルが推奨のようですが、コードに修正を加える必要があるので、設定だけで移行できる方法を探していました。そこで、csproj と環境変数だけで移行可能な方法ができたようなので試してみました。

※ 最初に osx-arm64 の azure-functions-core-tools で試しましたが動作しなかったので、今回は Ubuntu 24.04 で試しました。

## 検証時のバージョン

```bash:bash
$ func --version
4.0.5907

$ dotnet --version
8.0.107
```

## 検証用 Functions を作成

```bash:bash
$ func init mnrdn6 --dotnet

$ cd mnrdn6

$ func new --name SampleHttp --template HttpTrigger
```

## ランタイムバージョンを表示するコードに修正

```bash:bash
$ vi SampleHttp.cs
```

```cs:SampleHttp.cs
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace mnrdn6
{
    public static class SampleHttp
    {
        [FunctionName("SampleHttp")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            return new OkObjectResult($"{Environment.Version}");
        }
    }
}
```

## まずは .NET 6 でランタイムバージョンを確認

```bash:bash
$ func start

$ curl http://localhost:7071/api/SampleHttp
6.0.3
```

## csproj を .NET 8 に変更

```bash:bash
$ vi mnrdn6.csproj
```

`TargetFramework` の `net6.0` を `net8.0` に書き換えます。

```xml:mnrdn6.csproj
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.4.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
</Project>
```

## 追加の環境変数 `FUNCTIONS_INPROC_NET8_ENABLED` を local.settings.json に追加


```bash:bash
$ vi local.settings.json
```

`FUNCTIONS_INPROC_NET8_ENABLED` の値は `1` にします。

```json:local.settings.json
{
    "IsEncrypted": false,
    "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
        "FUNCTIONS_INPROC_NET8_ENABLED": 1
    }
}
```

## インプロセス用の `func` に実行権限が無いというエラー

```bash:bash
$ func start
Failed to start the in-process model host. An error occurred trying to start process '/usr/lib/azure-functions-core-tools-4/in-proc8/func' with working directory '/home/mnr/work/mnrdn6/bin/output'. Permission denied
```

実行権限を付与する。

```bash:bash
$ sudo chmod +x /usr/lib/azure-functions-core-tools-4/in-proc8/func
```

## .NET 8 でランタイムバージョンを確認

```bash:bash
$ func start

$ curl http://localhost:7071/api/SampleHttp
8.0.6
```

## 参考

https://azure.microsoft.com/en-us/updates/v2/Azure-Functions-supports-NET8-using-in-process-model

https://github.com/Azure/azure-functions-host/issues/9951

https://dotnet.microsoft.com/ja-jp/platform/support/policy/dotnet-core#lifecycle