FabricClient を使用してアプリケーションのデプロイと削除を実行する


アプリケーションの種類をパッケージ化した後は、Azure Service Fabric クラスターにデプロイできる状態になっています。 デプロイには、次の 3 つの手順が含まれます。

  1. アプリケーション パッケージのイメージ ストアへのアップロード
  2. アプリケーションの種類を登録する
  3. イメージ ストアからのアプリケーション パッケージの削除
  4. アプリケーション インスタンスを作成する

アプリケーションをデプロイし、インスタンスをクラスターで実行した後、アプリケーションのインスタンスとそのアプリケーションの種類を削除することができます。 以降の手順に従って、クラスターからアプリケーションを完全に削除します。

  1. 実行中のアプリケーションのインスタンスを削除する
  2. アプリケーションの種類が不要になったら、その登録を解除する

Visual Studio を使ってローカルの開発クラスターでアプリケーションのデプロイとデバッグを行う場合、前述のすべての手順は、PowerShell スクリプトによって自動的に処理されます。 このスクリプトは、アプリケーション プロジェクトの Scripts フォルダーにあります。 この記事では、このスクリプトが実行する内容の背景を説明し、Visual Studio の外部で同じ操作を実行できるようにします。

クラスターに接続する

この記事のいずれかのコード例を実行する前に、FabricClient インスタンスを作成してクラスターに接続します。 ローカル開発クラスターやリモート クラスター、または Microsoft Entra ID、X509 証明書、Windows Active Directory で保護されたクラスターに接続する例については、「セキュリティ保護されたクラスターに接続する」をご覧ください。 ローカル開発クラスターに接続するには、次の例を実行します。

// Connect to the local cluster.
FabricClient fabricClient = new FabricClient();

アプリケーション パッケージをアップロードする

MyApplication という名前のアプリケーションを Visual Studio でビルドしてパッケージするとします。 ApplicationManifest.xml に既定で表示されるアプリケーション タイプ名は、"MyApplicationType" です。 必要なアプリケーション マニフェスト、サービス マニフェスト、コード/構成/データ パッケージを含むアプリケーション パッケージは、C:\Users<username>\Documents\Visual Studio 2019\Projects\MyApplication\MyApplication\pkg\Debug にあります。

アプリケーション パッケージをアップロードすると、そのパッケージは内部 Service Fabric コンポーネントがアクセスできる場所に保存されます。 Service Fabric は、アプリケーション パッケージの登録時に、アプリケーション パッケージを検証します。 ただし、アプリケーション パッケージをローカルで検証する (つまり、アップロード前に検証する) 場合は、Test-ServiceFabricApplicationPackage コマンドレットを使用します。

CopyApplicationPackage API はアプリケーション パッケージをクラスター イメージ ストアにアップロードします。

アプリケーション パッケージが大きい場合や含まれるファイルの数が多い場合は、PowerShell を使用してアプリケーション パッケージを圧縮し、イメージストアにコピーできます。 圧縮により、ファイルのサイズを小さくし、ファイル数を減らすことができます。

イメージ ストアとイメージ ストア接続文字列に関する補足情報は、イメージ ストア接続文字列の理解に関するページを参照してください。

アプリケーション パッケージを登録する

アプリケーション マニフェストで宣言されたアプリケーションの種類とバージョンは、アプリケーション パッケージを登録すると、利用できるようになります。 システムは、前の手順でアップロードされたパッケージを読み取り、パッケージを検証し、パッケージのコンテンツを処理し、処理済みのパッケージを内部システムの場所にコピーします。

ProvisionApplicationAsync API はアプリケーションの種類をクラスターに登録し、デプロイできるようにします。

GetApplicationTypeListAsync API は正常に登録されたすべてのアプリケーションの種類に関する情報を提供します。 この API を使用して、登録がいつ完了したかを判断できます。

イメージ ストアからのアプリケーション パッケージの削除

アプリケーションが正常に登録されたら、アプリケーション パッケージを削除することをお勧めします。 イメージ ストアからアプリケーション パッケージを削除すると、システム リソースが解放されます。 使用されていないアプリケーション パッケージを保持すると、ディスク ストレージが消費され、アプリケーションのパフォーマンスの問題につながります。 アプリケーション パッケージをイメージ ストアから削除するには、RemoveApplicationPackage API を使用します。

アプリケーション インスタンスを作成する

CreateApplicationAsync API を使用して、正常に登録されているアプリケーションの種類を指定し、アプリケーションをインスタンス化することができます。 各アプリケーションの名前は、"fabric:" スキームで開始され、(クラスター内の) 各アプリケーション インスタンスに対して一意でなければなりません。 ターゲット アプリケーションの種類のアプリケーション マニフェストに定義されている既定のサービスも作成されます。

登録されたアプリケーションの種類の任意のバージョンに対して、複数のアプリケーション インスタンスを作成できます。 各アプリケーション インスタンスは分離して実行され、独自の作業ディレクトリと一連のプロセスを使用します。

クラスターで実行されている名前付きのアプリケーションとサービスを確認するには、GetApplicationListAsync API と GetServiceListAsync API を実行します。

サービス インスタンスを作成する

CreateServiceAsync API を使用して、サービスの種類からサービスをインスタンス化できます。 サービスがアプリケーション マニフェストで既定のサービスとして宣言されている場合、アプリケーションがインスタンス化されるときに、サービスがインスタンス化されます。 既にインスタンス化されているサービスで CreateServiceAsync API を呼び出すと、型が FabricException の例外が返されます。 例外には、FabricErrorCode.ServiceAlreadyExists の値を持つエラー コードが含まれます。

サービス インスタンスを削除する

サービス インスタンスが不要になったときは、DeleteServiceAsync API を呼び出して実行中のアプリケーション インスタンスから削除できます。

警告

この操作は元に戻すことはできず、サービスの状態を復元することはできません。

アプリケーション インスタンスの削除

アプリケーション インスタンスが不要になったときは、DeleteApplicationAsync API を使用して名前を指定して実行すれば完全に削除できます。 DeleteApplicationAsync はアプリケーションに属するすべてのサービスを自動的に削除します。その結果、すべてのサービスの状態が完全に削除されます。

警告

この操作は元に戻せません。また、アプリケーションの状態を復元できません。

アプリケーションの種類の登録解除

特定のバージョンのアプリケーションの種類が不要になった場合は、Unregister-ServiceFabricApplicationType API を使用して、その特定のバージョンのアプリケーションの種類の登録を解除する必要があります。 使用していないバージョンのアプリケーションの種類の登録を解除すると、イメージ ストアで使用されているストレージ領域が解放されます。 アプリケーションの種類のバージョンは、そのアプリケーションの種類のバージョンに対してアプリケーションがインスタンス化されていない限り、登録を解除できます。 また、アプリケーションの種類は、アプリケーションの種類のそのバージョンを参照している保留中のアプリケーション アップグレードを持つことはできません。

トラブルシューティング

Copy-ServiceFabricApplicationPackage がImageStoreConnectionString を求める

Service Fabric SDK 環境には、適切な既定値を事前に設定しておく必要があります。 ただし、すべてのコマンドの ImageStoreConnectionString が、Service Fabric クラスターによって使用されている値に一致していなければならない場合もあります。 この ImageStoreConnectionString は Get-ServiceFabricClusterManifest コマンドと Get-ImageStoreConnectionStringFromClusterManifest コマンドを使用して取得したクラスター マニフェストで見つけることができます。

PS C:\> Get-ImageStoreConnectionStringFromClusterManifest(Get-ServiceFabricClusterManifest)

Service Fabric SDK PowerShell モジュールの一部である Get-ImageStoreConnectionStringFromClusterManifest コマンドレットは、イメージ ストアの接続文字列の取得に使用します。 SDK モジュールをインポートするには、次のコマンドを実行します。

Import-Module "$ENV:ProgramFiles\Microsoft SDKs\Service Fabric\Tools\PSModule\ServiceFabricSDK\ServiceFabricSDK.psm1"

ImageStoreConnectionString は、クラスター マニフェスト内にあります。

<ClusterManifest xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" Name="Server-Default-SingleNode" Version="1.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">

    [...]

    <Section Name="Management">
      <Parameter Name="ImageStoreConnectionString" Value="file:D:\ServiceFabric\Data\ImageStore" />
    </Section>

    [...]

イメージ ストアとイメージ ストア接続文字列に関する補足情報は、イメージ ストア接続文字列の理解に関するページを参照してください。

大規模なアプリケーション パッケージをデプロイする

問題: (GB 単位の) 大規模なアプリケーション パッケージで CopyApplicationPackage API がタイムアウトする。 次の操作を試してください。

  • timeout パラメーターを使用して、CopyApplicationPackage メソッドのタイムアウト値を大きくします。 既定では、タイムアウトは 30 分です。
  • ソース コンピューターとクラスターの間のネットワーク接続を確認します。 接続が低速な場合は、ネットワーク接続が高速なコンピューターを使用することを検討してください。 クライアント コンピューターがクラスターとは別のリージョンにある場合は、クラスターと同じかより近いリージョンにあるクライアント コンピューターの使用を検討してください。
  • 外部で調整されていないかどうかを確認してください。 たとえば、イメージ ストアが Azure Storage を使用するように構成されている場合、アップロードが調整される可能性があります。

問題: パッケージのアップロードが正常に完了したが、ProvisionApplicationAsync API がタイムアウトする。次の操作を試してください。

  • イメージ ストアにコピーする前にパッケージを圧縮します。 圧縮によってファイル サイズが小さくなりファイル数が減るため、トラフィックの量と Service Fabric が実行する必要のある処理が減ります。 (圧縮時間を含めた場合は特に) アップロード操作が遅くなる場合がありますが、アプリケーションの種類の登録と登録解除は高速になります。
  • timeout パラメーターを使用して、ProvisionApplicationAsync API のタイムアウト値を大きくします。

多数のファイルを含むアプリケーション パッケージをデプロイする

問題: (数千個の) 多数のファイルを持つアプリケーション パッケージに対する ProvisionApplicationAsync がタイムアウトする。 次の操作を試してください。

  • イメージ ストアにコピーする前にパッケージを圧縮します。 圧縮により、ファイル数を減らすことができます。
  • timeout パラメーターを使用して、ProvisionApplicationAsync メソッドのタイムアウト値を大きくします。

コードの例

次の例では、アプリケーション パッケージをイメージ ストアにコピーし、アプリケーションの種類をプロビジョニングします。 その後、アプリケーション インスタンスを作成し、サービス インスタンスを作成します。 最後に、アプリケーション インスタンスを削除し、アプリケーションの種類のプロビジョニングを解除し、イメージ ストアからアプリケーション パッケージを削除します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading.Tasks;

using System.Fabric;
using System.Fabric.Description;
using System.Threading;

namespace ServiceFabricAppLifecycle
{
class Program
{
static void Main(string[] args)
{

    string clusterConnection = "localhost:19000";
    string appName = "fabric:/MyApplication";
    string appType = "MyApplicationType";
    string appVersion = "1.0.0";
    string serviceName = "fabric:/MyApplication/Stateless1";
    string imageStoreConnectionString = "file:C:\\SfDevCluster\\Data\\ImageStoreShare";
    string packagePathInImageStore = "MyApplication";
    string packagePath = "C:\\Users\\username\\Documents\\Visual Studio 2019\\Projects\\MyApplication\\MyApplication\\pkg\\Debug";
    string serviceType = "Stateless1Type";

    // Connect to the cluster.
    FabricClient fabricClient = new FabricClient(clusterConnection);

    // Copy the application package to a location in the image store
    try
    {
        fabricClient.ApplicationManager.CopyApplicationPackage(imageStoreConnectionString, packagePath, packagePathInImageStore);
        Console.WriteLine("Application package copied to {0}", packagePathInImageStore);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("Application package copy to Image Store failed: ");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Provision the application.  "MyApplicationV1" is the folder in the image store where the application package is located. 
    // The application type with name "MyApplicationType" and version "1.0.0" (both are found in the application manifest) 
    // is now registered in the cluster.            
    try
    {
        fabricClient.ApplicationManager.ProvisionApplicationAsync(packagePathInImageStore).Wait();

        Console.WriteLine("Provisioned application type {0}", packagePathInImageStore);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("Provision Application Type failed:");

        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Delete the application package from a location in the image store.
    try
    {
        fabricClient.ApplicationManager.RemoveApplicationPackage(imageStoreConnectionString, packagePathInImageStore);
        Console.WriteLine("Application package removed from {0}", packagePathInImageStore);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("Application package removal from Image Store failed: ");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    //  Create the application instance.
    try
    {
        ApplicationDescription appDesc = new ApplicationDescription(new Uri(appName), appType, appVersion);
        fabricClient.ApplicationManager.CreateApplicationAsync(appDesc).Wait();
        Console.WriteLine("Created application instance of type {0}, version {1}", appType, appVersion);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("CreateApplication failed.");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Create the stateless service description.  For stateful services, use a StatefulServiceDescription object.
    StatelessServiceDescription serviceDescription = new StatelessServiceDescription();
    serviceDescription.ApplicationName = new Uri(appName);
    serviceDescription.InstanceCount = 1;
    serviceDescription.PartitionSchemeDescription = new SingletonPartitionSchemeDescription();
    serviceDescription.ServiceName = new Uri(serviceName);
    serviceDescription.ServiceTypeName = serviceType;

    // Create the service instance.  If the service is declared as a default service in the ApplicationManifest.xml,
    // the service instance is already running and this call will fail.
    try
    {
        fabricClient.ServiceManager.CreateServiceAsync(serviceDescription).Wait();
        Console.WriteLine("Created service instance {0}", serviceName);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("CreateService failed.");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Delete a service instance.
    try
    {
        DeleteServiceDescription deleteServiceDescription = new DeleteServiceDescription(new Uri(serviceName));

        fabricClient.ServiceManager.DeleteServiceAsync(deleteServiceDescription);
        Console.WriteLine("Deleted service instance {0}", serviceName);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("DeleteService failed.");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Delete an application instance from the application type.
    try
    {
        DeleteApplicationDescription deleteApplicationDescription = new DeleteApplicationDescription(new Uri(appName));

        fabricClient.ApplicationManager.DeleteApplicationAsync(deleteApplicationDescription).Wait();
        Console.WriteLine("Deleted application instance {0}", appName);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("DeleteApplication failed.");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Un-provision the application type.
    try
    {
        fabricClient.ApplicationManager.UnprovisionApplicationAsync(appType, appVersion).Wait();
        Console.WriteLine("Un-provisioned application type {0}, version {1}", appType, appVersion);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("Un-provision application type failed: ");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    Console.WriteLine("Hit enter...");
    Console.Read();
}        
}
}

次のステップ

Service Fabric アプリケーションのアップグレード

Service Fabric の正常性の概要

Service Fabric サービスの診断とトラブルシューティング

Service Fabric のアプリケーションのモデル化