次の方法で共有


Kubernetes ホスティング

Kubernetes は、Orleans アプリケーションをホストするための一般的な選択肢です。 Orleans は、特定の構成なしで Kubernetes で実行されます。ただし、ホスティング プラットフォームが提供する追加の知識を利用することもできます。

Microsoft.Orleans.Hosting.Kubernetes パッケージは、Kubernetes クラスターで Orleans アプリケーションをホストするための統合を追加します。 パッケージには、次のアクションを実行する拡張メソッド UseKubernetesHostingが用意されています。

  • SiloOptions.SiloNameをポッド名に設定します。
  • EndpointOptions.AdvertisedIPAddressをポッド IP に設定します。
  • 構成されたEndpointOptions.SiloListeningEndpointEndpointOptions.GatewayListeningEndpointを使用して、任意のアドレスをリッスンするようにSiloPort &GatewayPortを構成します。 1111130000の既定のポート値は、値が明示的に設定されていない場合に使用されます。
  • ClusterOptions.ServiceIdを、orleans/serviceIdという名前のポッド ラベルの値に設定します。
  • ClusterOptions.ClusterIdを、orleans/clusterIdという名前のポッド ラベルの値に設定します。
  • スタートアップ プロセスの早い段階で、サイロは Kubernetes を調査して、対応するポッドを持たないサイロを見つけ出し、それらのサイロを死んだものとしてマークします。
  • Kubernetes の API サーバーの負荷を軽減するために、すべてのサイロのサブセットに対して実行時に同じプロセスが発生します。 既定では、クラスター内の 2 つのサイロが Kubernetes を監視します。

Kubernetes ホスティング パッケージでは、クラスタリングに Kubernetes は使用されません。 別のクラスタリング プロバイダーが引き続き必要です。 クラスタリングの構成の詳細については、サーバー構成 ドキュメントを参照してください。

.NET Aspire を使用して Kubernetes にデプロイする

.NET Aspire は、AppHost 構成から Kubernetes マニフェストを自動的に生成することで、Kubernetes のデプロイを簡略化します。 YAML ファイルを手動で書き込む代わりに、アプリケーションの依存関係グラフに基づいて、必要なデプロイ、サービス、および構成リソースを生成できます。

Kubernetes ホスティング統合を追加する

まず、AppHost プロジェクトに 、Aspire.Hosting.Kubernetes NuGet パッケージをインストールします。

dotnet add package Aspire.Hosting.Kubernetes

次に、Kubernetes 環境を AppHost に追加します。

var builder = DistributedApplication.CreateBuilder(args);

// Add the Kubernetes environment
var k8s = builder.AddKubernetesEnvironment("k8s");

// Add your Orleans silo project
var silo = builder.AddProject<Projects.MySilo>("silo");

builder.Build().Run();

必要に応じて、Kubernetes 環境のプロパティをカスタマイズできます。

builder.AddKubernetesEnvironment("k8s")
    .WithProperties(k8s =>
    {
        k8s.HelmChartName = "my-orleans-app";
    });

Kubernetes マニフェストを生成する

アスパイア CLI を使用して、アスパイア プロジェクトから Kubernetes マニフェストを生成します。

aspire publish -o ./k8s-manifests

これにより、次のような Kubernetes YAML ファイルの完全なセットが、指定された出力ディレクトリに生成されます。

  • AppHost 内の各サービスのデプロイメントまたは StatefulSet
  • ネットワーク接続用のサービス
  • 構成用の ConfigMaps と Secrets
  • デプロイ管理を容易にする Helm チャート
  • ストレージ リソースのPersistentVolumes と PersistentVolumeClaims

クラスターにデプロイする

マニフェストを生成した後、 kubectl または Helm を使用してマニフェストをデプロイします。

# Using kubectl
kubectl apply -f ./k8s-manifests

# Or using Helm (if Helm charts were generated)
helm install my-orleans-app ./k8s-manifests/charts/my-orleans-app

Aspireによって生成されたマニフェストの利点

  • 一貫性のある構成: 環境変数、ポート、およびリソース参照は自動的に同期されます。
  • 依存関係管理: サービスは、正しい接続文字列とサービス参照で構成されます。
  • Orleans対応: Orleans ホスティング統合により、適切なサイロ構成が確実に含まれます。
  • Helm のサポート: 生成された Helm グラフを使用すると、複数の環境でパラメーター化されたデプロイが可能になります。

ヒント

運用環境のデプロイの場合は、必要に応じて、生成されたマニフェストを確認してカスタマイズします。 外部パラメーターを使用して、環境固有の値を構成します。

アスパイア Kubernetes 統合の詳細については、 アスパイア Kubernetes 統合ドキュメントを参照してください

.NET Aspire を使用して Orleans を構成する方法の詳細については、「 .NET Aspire Orleans 統合」を参照してください。

Kubernetes の手動構成

この機能により、サービスのデプロイにいくつかの要件が課されます。

  • サイロ名はポッド名と一致する必要があります。
  • ポッドには、サイロのorleans/serviceIdorleans/clusterIdに対応するServiceIdラベルとClusterIdラベルが必要です。 UseKubernetesHosting メソッドは、これらのラベルを環境変数の対応するOrleans オプションに伝達します。
  • ポッドには、POD_NAMEPOD_NAMESPACEPOD_IPORLEANS_SERVICE_IDORLEANS_CLUSTER_IDの環境変数が設定されている必要があります。

次の例は、これらのラベルと環境変数を正しく構成する方法を示しています。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dictionary-app
  labels:
    orleans/serviceId: dictionary-app
spec:
  selector:
    matchLabels:
      orleans/serviceId: dictionary-app
  replicas: 3
  template:
    metadata:
      labels:
        # This label identifies the service to Orleans
        orleans/serviceId: dictionary-app

        # This label identifies an instance of a cluster to Orleans.
        # Typically, this is the same value as the previous label, or any
        # fixed value.
        # In cases where you don't use rolling deployments (for example,
        # blue/green deployments),
        # this value can allow for distinct clusters that don't communicate
        # directly with each other,
        # but still share the same storage and other resources.
        orleans/clusterId: dictionary-app
    spec:
      containers:
        - name: main
          image: my-registry.azurecr.io/my-image
          imagePullPolicy: Always
          ports:
          # Define the ports Orleans uses
          - containerPort: 11111
          - containerPort: 30000
          env:
          # The Azure Storage connection string for clustering is injected as an
          # environment variable.
          # You must create it separately using a command such as:
          # > kubectl create secret generic az-storage-acct `
          #     --from-file=key=./az-storage-acct.txt
          - name: STORAGE_CONNECTION_STRING
            valueFrom:
              secretKeyRef:
                name: az-storage-acct
                key: key
          # Configure settings to let Orleans know which cluster it belongs to
          # and which pod it's running in.
          - name: ORLEANS_SERVICE_ID
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['orleans/serviceId']
          - name: ORLEANS_CLUSTER_ID
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['orleans/clusterId']
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
          - name: DOTNET_SHUTDOWNTIMEOUTSECONDS
            value: "120"
          request:
            # Set resource requests
      terminationGracePeriodSeconds: 180
      imagePullSecrets:
        - name: my-image-pull-secret
  minReadySeconds: 60
  strategy:
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1

RBAC 対応クラスターの場合、ポッドの Kubernetes サービス アカウントに必要なアクセス権を付与することも必要な場合があります。

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: orleans-hosting
rules:
- apiGroups: [ "" ]
  resources: ["pods"]
  verbs: ["get", "watch", "list", "delete", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: orleans-hosting-binding
subjects:
- kind: ServiceAccount
  name: default
  apiGroup: ''
roleRef:
  kind: Role
  name: orleans-hosting
  apiGroup: ''

liveness probe、readiness probe、startup probe

Kubernetes はポッドをプローブしてサービスの正常性を判断できます。 詳細については、Kubernetes ドキュメントの 「Liveness、Readiness、Startup Probes の構成 」を参照してください。

Orleans では、クラスター メンバーシップ プロトコルを使用して、プロセスまたはネットワークの障害を迅速に検出して復旧します。 各ノードは、定期的なプローブを送信して、他のノードのサブセットを監視します。 ノードが他の複数のノードから複数の連続するプローブに応答できない場合、クラスターはそれを強制的に削除します。 障害が発生したノードが削除を確認すると、直ちに終了します。 Kubernetes は終了したプロセスを再起動し、クラスターへの再参加を試みます。

Kubernetes プローブは、ポッド内のプロセスが実行されていて、ゾンビ状態でスタックしていないかどうかを判断するのに役立ちます。 これらのプローブは、ポッド間接続や応答性を検証したり、アプリケーション レベルの機能チェックを実行したりしません。 ポッドがライブネス プローブに応答できない場合、Kubernetes は最終的にそのポッドを終了し、スケジュールを変更する可能性があります。 したがって、Kubernetes プローブと Orleans プローブは補完的です。

推奨される方法は、アプリケーションが意図したとおりに実行する単純なローカルのみのチェックを実行する Kubernetes で Liveness Probe を構成することです。 これらのプローブは、たとえば、ランタイム エラーや他のありそうもないイベントが原因で、完全にフリーズした場合にプロセスを終了するのに役立ちます。

リソース クォータ

Kubernetes はオペレーティング システムと連携して リソース クォータを実装します。 これにより、CPU とメモリの予約や制限を適用できます。 対話型読み込みを提供するプライマリ アプリケーションの場合、制限の厳しい制限を実装することは、必要でない限り推奨されません。 要求と制限は、意味と実装の場所で大きく異なされることに注意することが重要です。 要求または制限を設定する前に、実装と適用方法の詳細を理解するために時間がかかります。 たとえば、Kubernetes、Linux カーネル、監視システムの間でメモリが一様に測定されない場合があります。 CPU クォータが想定どおりに適用されない場合があります。

トラブルシューティング

ポッドがクラッシュし、「KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined」というエラーメッセージが表示される

完全な例外メッセージ:

Unhandled exception. k8s.Exceptions.KubeConfigException: unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
at k8s.KubernetesClientConfiguration.InClusterConfig()
  • KUBERNETES_SERVICE_HOST環境変数とKUBERNETES_SERVICE_PORT環境変数がポッド内に設定されていることを確認します。 コマンド kubectl exec -it <pod_name> /bin/bash -c envを実行して確認します。
  • automountServiceAccountTokenが Kubernetes truedeployment.yamlに設定されていることを確認します。 詳細については、「ポッド のサービス アカウントの構成」を参照してください。