オーケストレーション .NET.NET Aspire の概要
.NET
.NET Aspire には、分散アプリケーション内のリソースと依存関係を表す API が用意されています。 これらの API に加えて、いくつかの説得力のあるシナリオを可能にするツール
続行する前に、.NET.NET Aspireで使用される一般的な用語を検討してください。
- アプリ モデル: DistributedApplication 名前空間内で定義された分散アプリケーション (Aspire.Hosting.ApplicationModel) を構成するリソースのコレクション。 より正式な定義については、「アプリ モデルのを定義する」を参照してください。
- App host/Orchestrator プロジェクト: 慣例により .NET サフィックスで名前が付けられた アプリ モデルをオーケストレーションする プロジェクト。
- リソース: リソース は、.NET プロジェクト、コンテナー、実行可能ファイル、データベース、キャッシュ、クラウド サービスなどのアプリケーションの依存部分です。 これは、管理または参照できるアプリケーションの任意の部分を表します。
- 統合: 統合とは、アプリホスト が リソース をモデル化するか、利用アプリで使用するために client を構成するパッケージのいずれかをNuGetパッケージとして提供するものです。 詳細については、.NET.NET Aspire 統合の概要を参照してください。
- リファレンス: WithReference API を使用して依存関係として表されるリソース間の接続を定義します。 詳細については、「リソース 参照」または「既存のリソースを参照する」を参照してください。
手記
.NET .NET Aspireのオーケストレーションは、クラウドネイティブ アプリの構成と相互接続の管理を簡素化することで、ローカル開発 エクスペリエンスを強化するように設計されています。 開発のための非常に貴重なツールですが、Kubernetesなどの運用環境システムを置き換えることを意図したものではありません。これは、そのコンテキストで優れた機能を発揮するように特別に設計されています。
アプリ モデルを定義する
.NET .NET Aspire を使用すると、分散アプリケーションをシームレスに構築、プロビジョニング、デプロイ、構成、テスト、実行、観察できます。 これらの機能はすべて、.NET ソリューション内のリソースとその関係の概要を示す .NET Aspire を使用して実現されます。 これらのリソースには、アプリが依存するプロジェクト、実行可能ファイル、コンテナー、外部サービス、クラウド リソースが含まれます。 すべての .NET.NET Aspire ソリューション内には、指定された アプリ ホスト プロジェクトがあります。ここで、アプリ モデルは、IDistributedApplicationBuilderで使用可能なメソッドを使用して正確に定義されます。 このビルダーは、DistributedApplication.CreateBuilderを呼び出すことによって取得されます。
// Create a new app model builder
var builder = DistributedApplication.CreateBuilder(args);
// TODO:
// Add resources to the app model
// Express dependencies between resources
builder.Build().Run();
アプリ ホスト プロジェクト
アプリ ホスト プロジェクトは、.NET.NET Aspire プロジェクトの一部であるすべてのプロジェクトの実行を処理します。 つまり、アプリ モデル内のすべてのアプリを調整する必要があります。 プロジェクト自体は、.NET📦を参照する Aspire 実行可能プロジェクトです。Hosting.AppHost NuGet パッケージを使用して、IsAspireHost
プロパティを true
に設定し、.NET.NET Aspire SDKを参照します。
<Project Sdk="Microsoft.NET.Sdk">
<Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<IsAspireHost>true</IsAspireHost>
<!-- Omitted for brevity -->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.0.0" />
</ItemGroup>
<!-- Omitted for brevity -->
</Project>
次のコードでは、2 つのプロジェクト参照と Program
キャッシュを持つアプリ ホスト Redis について説明します。
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("cache");
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");
builder.AddProject<Projects.AspireApp_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(cache)
.WaitFor(cache)
.WithReference(apiService)
.WaitFor(apiService);
builder.Build().Run();
上記のコード:
- CreateBuilder メソッドを使用して、新しいアプリ モデル ビルダーを作成します。
-
Redis メソッドを使用して、"cache" という名前の
cache
AddRedis リソースを追加します。 - AddProject メソッドを使用して、"apiservice" という名前のプロジェクト リソースを追加します。
-
AddProject メソッドを使用して、"webfrontend" という名前のプロジェクト リソースを追加します。
- WithExternalHttpEndpoints メソッドを使用して、プロジェクトに外部 HTTP エンドポイントがあることを指定します。
-
cache
リソースへの参照を追加し、WithReference メソッドと WaitFor メソッドを使用して準備が整うのを待ちます。 -
apiservice
リソースへの参照を追加し、WithReference メソッドと WaitFor メソッドを使用して準備が整うのを待ちます。
- Build メソッドと Run メソッドを使用して、アプリ モデルをビルドして実行します。
このコード例では、.NET AspireRedis ホスティング統合を使用します。
アプリ ホスト プロジェクトと説明されているリソースの関係を視覚化するには、次の図を検討してください。
各リソースには一意の名前を付ける必要があります。 この図は、各リソースとその間の関係を示しています。 コンテナー リソースの名前は "cache" で、プロジェクト リソースの名前は "apiservice" と "webfrontend" です。 Web フロントエンド プロジェクトは、キャッシュ および API サービス プロジェクトを参照します。 この方法で参照を表現する場合、Web フロントエンド プロジェクトでは、それぞれ "cache" と "apiservice" という 2 つのリソースに依存していると言われます。
組み込みのリソースの種類
.NET .NET Aspire プロジェクトは、一連のリソースで構成されます。 📦 Aspireの主要な基本リソースのタイプについて、.Hosting.AppHost NuGet パッケージが次の表で説明します。
方式 | リソースの種類 | 説明 |
---|---|---|
AddProject | ProjectResource | .NET プロジェクト、例えば ASP.NET Core Web アプリ。 |
AddContainer | ContainerResource | Docker イメージなどのコンテナー イメージ。 |
AddExecutable | ExecutableResource | Node.js アプリなどの実行可能ファイル。 |
AddParameter | ParameterResource | 外部パラメーターを表現するために使用できるパラメーターリソース は、。 |
プロジェクト リソースは、アプリ モデルの一部である .NET プロジェクトを表します。 アプリ ホスト プロジェクトにプロジェクト参照を追加すると、.NET.NET Aspire SDK によって、参照される各プロジェクトの Projects
名前空間に型が生成されます。 詳細については、「.NET.NET Aspire SDK: プロジェクト参照」を参照してください。
アプリ モデルにプロジェクトを追加するには、AddProject メソッドを使用します。
var builder = DistributedApplication.CreateBuilder(args);
// Adds the project "apiservice" of type "Projects.AspireApp_ApiService".
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");
同じプロジェクトの複数のインスタンスをアプリ モデルに追加することで、プロジェクトをレプリケートおよびスケールアウトできます。 レプリカを構成するには、WithReplicas メソッドを使用します。
var builder = DistributedApplication.CreateBuilder(args);
// Adds the project "apiservice" of type "Projects.AspireApp_ApiService".
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
.WithReplicas(3);
上記のコードは、"apiservice" プロジェクト リソースの 3 つのレプリカをアプリ モデルに追加します。 詳細については、「.NET.NET Aspire ダッシュボード: リソース レプリカ」を参照してください。
参照リソース
参照は、リソース間の依存関係を表します。 たとえば、Web フロントエンドが Redis キャッシュに依存するシナリオを想像できます。 C# コード Program
アプリ ホストの例を次に示します。
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("cache");
builder.AddProject<Projects.AspireApp_Web>("webfrontend")
.WithReference(cache);
"webfrontend" プロジェクト リソースは、WithReference を使用して、"キャッシュ" コンテナー リソースへの依存関係を追加します。 これらの依存関係は、接続文字列またはサービス検出情報を示すことができます。 前の例では、環境変数を "webfronend" リソースに ConnectionStrings__cache="localhost:62354"
が使用する接続文字列が含まれています。
リソースの待機中
場合によっては、別のリソースを開始する前に、リソースの準備が整うのを待つ必要がある場合があります。 たとえば、データベースに依存する API を開始する前に、データベースの準備が整うのを待つ必要がある場合があります。 この依存関係を表すには、WaitFor メソッドを使用します。
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres");
var postgresdb = postgres.AddDatabase("postgresdb");
builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
.WithReference(postgresdb)
.WaitFor(postgresdb);
上記のコードでは、"apiservice" プロジェクト リソースは、"postgresdb" データベース リソースが KnownResourceStates.Runningに入るのを待機します。 コード例は、.NET AspirePostgreSQL 統合を示していますが、同じパターンを他のリソースに適用できます。
その他のケースでは、依存リソースが開始される前に、KnownResourceStates.Exited または KnownResourceStates.Finished のいずれかで、リソースの実行が完了するまで待機することが必要になる場合があります。 リソースの実行が完了するまで待機するには、WaitForCompletion メソッドを使用します。
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres");
var postgresdb = postgres.AddDatabase("postgresdb");
var migration = builder.AddProject<Projects.AspireApp_Migration>("migration")
.WithReference(postgresdb)
.WaitFor(postgresdb);
builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
.WithReference(postgresdb)
.WaitForCompletion(migration);
前のコードでは、"apiservice" プロジェクト リソースは、"移行" プロジェクト リソースが完了するまで待機してから開始します。 "移行" プロジェクト リソースは、"postgresdb" データベース リソースが KnownResourceStates.Runningに入るのを待機します。 これは、たとえば、API サービスを開始する前にデータベース移行を実行するシナリオで役立ちます。
リソースを追加および表現するための API
.NET .NET Aspire ホスティング統合 統合と client 統合 はどちらも NuGet パッケージとして提供されますが、異なる目的で提供されます。 client 統合、アプリ ホストの範囲外でアプリを使用するための client ライブラリ構成を提供しますが、ホスティング統合、アプリ ホスト内のリソースと依存関係を表現するための API を提供します。 詳細については、「.NET.NET Aspire 統合の概要: 統合の責任」を参照してください。
エクスプレス コンテナ リソース
ContainerResource を表現するには、IDistributedApplicationBuilder メソッドを呼び出して AddContainer インスタンスに追加します。
var builder = DistributedApplication.CreateBuilder(args);
var ollama = builder.AddContainer("ollama", "ollama/ollama")
.WithBindMount("ollama", "/root/.ollama")
.WithBindMount("./ollamaconfig", "/usr/config")
.WithHttpEndpoint(port: 11434, targetPort: 11434, name: "ollama")
.WithEntrypoint("/usr/config/entrypoint.sh")
.WithContainerRuntimeArgs("--gpus=all");
詳細については、
上記のコードは、イメージ ollama/ollama
を持つ "ollama" という名前のコンテナー リソースを追加します。 コンテナー リソースは、複数のバインド マウント、名前付き HTTP エンドポイント、Unix シェル スクリプトに解決されるエントリ ポイント、および WithContainerRuntimeArgs メソッドを使用したコンテナー実行引数で構成されます。
コンテナー リソースをカスタマイズする
すべての ContainerResource サブクラスは、特定の要件を満たすようにカスタマイズできます。 これは、コンテナー リソースをモデル化するが変更が必要な ホスティング統合 を使用する場合に便利です。
IResourceBuilder<ContainerResource>
がある場合は、使用可能な API の呼び出しをチェーンしてコンテナー リソースを変更できます。
.NET
.NET Aspire コンテナー リソースは通常、ピン留めされたタグを指しますが、代わりに latest
タグを使用することもできます。
これを例示するために、.NET AspireRedis 統合を使用しているシナリオを想像してください。
Redis 統合が 7.4
タグに依存していて、代わりに latest
タグを使用する場合は、WithImageTag API の呼び出しをチェーンできます。
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("cache")
.WithImageTag("latest");
// Instead of using the "7.4" tag, the "cache"
// container resource now uses the "latest" tag.
使用可能なその他の API の詳細については、「ContainerResourceBuilderExtensions」を参照してください。
コンテナー リソースのライフサイクル
アプリ ホストを実行すると、ContainerResource を使用して、作成して開始するコンテナー イメージが決定されます。 内部 .NET Aspire、Docker または Podmanのいずれかの適切な OCI 準拠コンテナー ランタイムへの呼び出しを委任することで、定義されたコンテナー イメージを使用してコンテナーを実行します。 次のコマンドが使用されます。
まず、docker container create
コマンドを使用してコンテナーを作成します。 次に、docker container start
コマンドを使用してコンテナーが開始されます。
- docker コンテナーの作成: 開始せずに、指定したイメージから新しいコンテナーを作成します。
- docker コンテナ開始: 停止中のコンテナを1つ以上起動します。
これらのコマンドは、接続されたコンテナー ネットワーク、ボリューム、ポートを管理するために docker run
の代わりに使用されます。 これらのコマンドをこの順序で呼び出すと、初期起動時に IP (ネットワーク構成) が既に存在できるようになります。
基本リソースの種類 、ProjectResource、ContainerResource、および ExecutableResource以外にも、.NET.NET Aspire は、アプリ モデルに共通のリソースを追加するための拡張メソッドを提供します。 詳細については、「ホスティング統合」を参照してください。
コンテナー リソースの有効期間
既定では、コンテナー リソースはコンテナーの有効期間
var builder = DistributedApplication.CreateBuilder(args);
var ollama = builder.AddContainer("ollama", "ollama/ollama")
.WithLifetime(ContainerLifetime.Persistent);
上記のコードでは、イメージ "ollama/ollama" と永続的な有効期間を持つ "ollama" という名前のコンテナー リソースが追加されます。
接続文字列とエンドポイント参照
プロジェクト リソース間の依存関係を表すのが一般的です。 次のコード例を考えてみます。
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("cache");
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");
builder.AddProject<Projects.AspireApp_Web>("webfrontend")
.WithReference(cache)
.WithReference(apiservice);
プロジェクト間参照は、適切に定義された接続文字列を持つリソースとは異なる方法で処理されます。 接続文字列が "webfrontend" リソースに挿入される代わりに、サービス検出をサポートする環境変数が挿入されます。
方式 | 環境変数 |
---|---|
WithReference(cache) |
ConnectionStrings__cache="localhost:62354" |
WithReference(apiservice) |
services__apiservice__http__0="http://localhost:5455" services__apiservice__https__0="https://localhost:7356" |
"apiservice" プロジェクトへの参照を追加すると、サービス検出環境変数がフロントエンドに追加されます。 これは、通常、プロジェクト間通信が HTTP/gRPC 経由で行われるためです。 詳細については、サービス検出の .NET.NET Aspireを参照してください。
ContainerResource または ExecutableResourceから特定のエンドポイントを取得するには、次のいずれかのエンドポイント API を使用します。
次に、GetEndpoint API を呼び出して、WithReference
メソッド内のエンドポイントを参照するために使用できるエンドポイントを取得します。
var builder = DistributedApplication.CreateBuilder(args);
var customContainer = builder.AddContainer("myapp", "mycustomcontainer")
.WithHttpEndpoint(port: 9043, name: "endpoint");
var endpoint = customContainer.GetEndpoint("endpoint");
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
.WithReference(endpoint);
方式 | 環境変数 |
---|---|
WithReference(endpoint) |
services__myapp__endpoint__0=https://localhost:9043 |
port
パラメーターは、コンテナーがリッスンしているポートです。 コンテナー ポートの詳細については、「コンテナー ポート」を参照してください。 サービス検出の詳細については、.NET.NET Aspire サービス検出を参照してください。
サービス エンドポイント環境変数の形式
前のセクションでは、WithReference メソッドを使用してリソース間の依存関係を表します。 サービス エンドポイントによって環境変数が依存リソースに挿入される場合、形式が明確でない可能性があります。 このセクションでは、この形式について詳しく説明します。
あるリソースが別のリソースに依存している場合、アプリ ホストは依存リソースに環境変数を挿入します。 これらの環境変数は、依存するリソースに接続するように依存リソースを構成します。 環境変数の形式は .NET.NET Aspire に固有であり、Service Discoveryと互換性のある方法でサービス エンドポイントを表します。
サービス エンドポイント環境変数の前には、services__
(二重アンダースコア)、サービス名、エンドポイント名、最後にインデックスが付きます。 インデックスでは、1 つのサービスに対して複数のエンドポイントがサポートされます。最初のエンドポイントの 0
から始まり、エンドポイントごとにインクリメントされます。
次の環境変数の例を考えてみましょう。
services__apiservice__http__0
上記の環境変数は、apiservice
サービスの最初の HTTP エンドポイントを表します。 環境変数の値は、サービス エンドポイントの URL です。 名前付きエンドポイントは、次のように表される場合があります。
services__apiservice__myendpoint__0
前の例では、apiservice
サービスには myendpoint
という名前付きエンドポイントがあります。 環境変数の値は、サービス エンドポイントの URL です。
既存のリソースを参照する
状況によっては、既存のリソース (おそらくクラウド プロバイダーにデプロイされているリソース) を参照することが保証される場合があります。 たとえば、Azure データベースを参照できます。 この場合は、実行コンテキスト に依存して、アプリ ホストが "実行" モードで実行されているか、"発行" モードで実行されているかを動的に判断します。 ローカルで実行していて、クラウド リソースに依存する場合は、IsRunMode
プロパティを使用して条件付きで参照を追加できます。 代わりに、発行モードでリソースを作成することもできます。 一部の ホスティング統合、接続文字列を直接提供することがサポートされており、これを使用して既存のリソースを参照できます。
同様に、.NET.NET Aspire を既存のソリューションに統合するユース ケースが存在する場合もあります。 一般的な方法の 1 つは、.NET.NET Aspire アプリ ホスト プロジェクトを既存のソリューションに追加することです。 アプリ ホスト内で依存関係を表現するには、プロジェクト参照をアプリ ホストに追加し、アプリ モデルを構築
アプリ ホストのライフ サイクル
.NET .NET Aspire アプリ ホストは、IDistributedApplicationLifecycleHook インターフェイスを実装することによってフックできるいくつかのライフ サイクルを公開します。 次のライフサイクル メソッドを使用できます。
注文 | 方式 | 説明 |
---|---|---|
1 | BeforeStartAsync | 分散アプリケーションが開始される前に実行されます。 |
2 | AfterEndpointsAllocatedAsync | オーケストレーターがアプリケーション モデル内のリソースにエンドポイントを割り当てた後に実行されます。 |
3 | AfterResourcesCreatedAsync | オーケストレーターによってリソースが作成された後に実行されます。 |
アプリ ホストにはライフ サイクル フックが用意されていますが、カスタム イベントを登録することもできます。 詳細については、「
ライフサイクル フックを登録する
ライフ サイクル フックを登録するには、IDistributedApplicationLifecycleHook インターフェイスを実装し、AddLifecycleHook API を使用してアプリ ホストにフックを登録します。
using Aspire.Hosting.Lifecycle;
using Microsoft.Extensions.Logging;
var builder = DistributedApplication.CreateBuilder(args);
builder.Services.AddLifecycleHook<LifecycleLogger>();
builder.Build().Run();
internal sealed class LifecycleLogger(ILogger<LifecycleLogger> logger)
: IDistributedApplicationLifecycleHook
{
public Task BeforeStartAsync(
DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
{
logger.LogInformation("BeforeStartAsync");
return Task.CompletedTask;
}
public Task AfterEndpointsAllocatedAsync(
DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
{
logger.LogInformation("AfterEndpointsAllocatedAsync");
return Task.CompletedTask;
}
public Task AfterResourcesCreatedAsync(
DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
{
logger.LogInformation("AfterResourcesCreatedAsync");
return Task.CompletedTask;
}
}
上記のコード:
-
IDistributedApplicationLifecycleHook インターフェイスを
LifecycleLogger
として実装します。 - AddLifecycleHook API を使用して、ライフ サイクル フックをアプリ ホストに登録します。
- すべてのイベントのメッセージをログに記録します。
このアプリ ホストを実行すると、イベントごとにライフ サイクル フックが実行されます。 次の出力が生成されます。
info: LifecycleLogger[0]
BeforeStartAsync
info: Aspire.Hosting.DistributedApplication[0]
Aspire version: 9.0.0
info: Aspire.Hosting.DistributedApplication[0]
Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
Application host directory is: ..\AspireApp\AspireApp.AppHost
info: LifecycleLogger[0]
AfterEndpointsAllocatedAsync
info: Aspire.Hosting.DistributedApplication[0]
Now listening on: https://localhost:17043
info: Aspire.Hosting.DistributedApplication[0]
Login to the dashboard at https://localhost:17043/login?t=d80f598bc8a64c7ee97328a1cbd55d72
info: LifecycleLogger[0]
AfterResourcesCreatedAsync
info: Aspire.Hosting.DistributedApplication[0]
Distributed application started. Press Ctrl+C to shut down.
アプリ ホストのライフ サイクルにフックする推奨される方法は、イベント API を使用することです。 詳細については、「
実行コンテキスト
IDistributedApplicationBuilder は、アプリ ホストの現在の実行に関する情報を提供する実行コンテキスト (DistributedApplicationExecutionContext) を公開します。 このコンテキストを使用して、アプリ ホストが "実行" モードとして実行されているか、発行操作の一部として実行されているかを評価できます。 次のプロパティについて考えてみましょう。
-
IsRunMode: 現在の操作が実行されている場合に
true
を返します。 -
IsPublishMode: 現在の操作が発行である場合、
true
を返します。
この情報は、現在の操作に基づいてコードを条件付きで実行する場合に役立ちます。
IsRunMode
プロパティの使用例を次に示します。 この場合、拡張メソッドを使用して、ローカル開発実行の RabbitMQ の安定したノード名を生成します。
private static IResourceBuilder<RabbitMQServerResource> RunWithStableNodeName(
this IResourceBuilder<RabbitMQServerResource> builder)
{
if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
{
builder.WithEnvironment(context =>
{
// Set a stable node name so queue storage is consistent between sessions
var nodeName = $"{builder.Resource.Name}@localhost";
context.EnvironmentVariables["RABBITMQ_NODENAME"] = nodeName;
});
}
return builder;
}
実行コンテキストは、多くの場合、既存のリソースを指すリソースまたは接続文字列を条件付きで追加するために使用されます。 実行コンテキストに基づいて Redis または接続文字列を条件付きで追加する例を次に示します。
var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.ExecutionContext.IsRunMode
? builder.AddRedis("redis")
: builder.AddConnectionString("redis");
builder.AddProject<Projects.WebApplication>("api")
.WithReference(redis);
builder.Build().Run();
前のコードでは、次のようになります。
- アプリ ホストが "実行" モードで実行されている場合は、Redis コンテナー リソースが追加されます。
- アプリ ホストが "発行" モードで実行されている場合は、接続文字列が追加されます。
このロジックを簡単に反転して、ローカルで実行しているときに既存の Redis リソースに接続し、発行時に新しい Redis リソースを作成できます。
大事な
.NET
.NET Aspire は、リソース ビルダーのモダリティを制御する一般的な API を提供し、実行モードに基づいてリソースの動作を異なることができます。 fluent API の先頭には、RunAs*
と PublishAs*
が付いています。
RunAs*
API はローカル開発 (または実行モード) の動作に影響しますが、PublishAs*
API はリソースの発行に影響します。
関連項目
.NET Aspire