Condividi tramite


Hosting Kubernetes

Kubernetes è una scelta comune per l'hosting di applicazioni Orleans. Orleans viene eseguito in Kubernetes senza configurazione specifica; tuttavia, può anche sfruttare informazioni aggiuntive fornite dalla piattaforma di hosting.

Il pacchetto Microsoft.Orleans.Hosting.Kubernetes aggiunge l'integrazione per l'hosting di un'applicazione Orleans in un cluster Kubernetes. Il pacchetto fornisce un metodo di estensione, UseKubernetesHosting, eseguendo le azioni seguenti:

Si noti che il pacchetto di hosting Kubernetes non usa Kubernetes per il clustering. È ancora necessario un provider di clustering separato. Per altre informazioni sulla configurazione del clustering, vedere la documentazione relativa alla configurazione di Server.

Eseguire la distribuzione in Kubernetes con .NET Aspire

.NET Aspire semplifica la distribuzione di Kubernetes generando automaticamente manifesti Kubernetes dalla configurazione di AppHost. Invece di scrivere manualmente file YAML, Aspire può produrre le risorse di distribuzione, servizio e configurazione necessarie in base al grafo delle dipendenze dell'applicazione.

Aggiungere l'integrazione per l'hosting su Kubernetes

Prima di tutto, installare il pacchetto NuGet Aspire.Hosting.Kubernetes nel progetto AppHost:

dotnet add package Aspire.Hosting.Kubernetes

Aggiungere quindi un ambiente Kubernetes ad 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();

Facoltativamente, è possibile personalizzare le proprietà dell'ambiente Kubernetes:

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

Generare manifesti Kubernetes

Usare l'interfaccia della Riga di Comando Aspire (CLI) per generare manifests Kubernetes dal progetto Aspire.

aspire publish -o ./k8s-manifests

In questo modo viene generato un set completo di file YAML Kubernetes nella directory di output specificata, tra cui:

  • Deployment o StatefulSets per ogni servizio in AppHost
  • Servizi per la connettività di rete
  • ConfigMaps e Secrets per la configurazione
  • Grafici Helm per semplificare la gestione della distribuzione
  • PersistentVolumes e PersistentVolumeClaims per le risorse di archiviazione

Distribuire nel cluster

Dopo aver generato i manifesti, distribuirli usando kubectl o 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

Vantaggi dei manifest generati da Aspire

  • Configurazione coerente: le variabili di ambiente, le porte e i riferimenti alle risorse vengono sincronizzati automaticamente.
  • Gestione delle dipendenze: i servizi sono configurati con stringhe di connessione e riferimenti al servizio corretti.
  • Orleans-aware: l'integrazione Orleans dell'hosting garantisce che sia inclusa la configurazione corretta del silo.
  • Supporto Helm: i grafici Helm generati consentono distribuzioni con parametri in ambienti diversi.

Suggerimento

Per le distribuzioni di produzione, esaminare e personalizzare i manifesti generati in base alle esigenze. Usare parametri esterni per configurare valori specifici dell'ambiente.

Per informazioni dettagliate sull'integrazione di Aspire Kubernetes, vedere la documentazione sull'integrazione di Aspire Kubernetes.

Per altre informazioni sulla configurazione Orleans con .NET Aspire, vedere Integrazione di .NET AspireOrleans.

Configurazione manuale di Kubernetes

Questa funzionalità impone alcuni requisiti per la distribuzione del servizio:

  • I nomi dei silo devono corrispondere ai nomi dei pod.
  • I pod devono avere etichette orleans/serviceId e orleans/clusterId corrispondenti a ServiceId e ClusterId del silo. Il metodo UseKubernetesHosting propaga queste etichette nelle opzioni corrispondenti Orleans, derivandole dalle variabili di ambiente.
  • I pod devono avere le variabili di ambiente seguenti impostate: POD_NAME, POD_NAMESPACE, POD_IP, ORLEANS_SERVICE_ID, ORLEANS_CLUSTER_ID.

L'esempio seguente illustra come configurare correttamente queste etichette e variabili di ambiente:

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

Per i cluster abilitati al controllo degli accessi basato sui ruoli, potrebbe essere necessaria anche la concessione dell'accesso necessario all'account del servizio Kubernetes per i pod.

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: ''

Sonde di vitalità, prontezza e avvio

Kubernetes può sondare i pod per determinare l'integrità del servizio. Per ulteriori informazioni, consultare Configura Liveness, Readiness e Startup Probes nella documentazione di Kubernetes.

Orleans usa un protocollo di appartenenza al cluster per rilevare e ripristinare tempestivamente da errori di processo o di rete. Ogni nodo monitora un subset di altri nodi, inviando probe periodici. Se un nodo non risponde a più sonde successive da parte di più nodi diversi, il cluster lo rimuove forzatamente. Una volta che un nodo malfunzionante viene a sapere di essere stato rimosso, termina immediatamente. Kubernetes riavvia il processo terminato, che quindi tenta di ricongiuntare il cluster.

Le probe di Kubernetes consentono di determinare se un processo in un pod è in esecuzione e non è bloccato in uno stato di zombie. Questi probe non verificano la connettività tra pod o la velocità di risposta, né eseguono controlli delle funzionalità a livello di applicazione. Se un pod non risponde a un probe di attività, Kubernetes potrebbe terminare il pod e riprogrammarlo. Le sonde Kubernetes e le Orleans sonde sono quindi complementari.

L'approccio consigliato consiste nella configurazione delle sonde di vitalità in Kubernetes che eseguono un semplice controllo locale per verificare che l'applicazione funzioni come previsto. Queste sonde servono per terminare il processo in caso di un blocco totale, ad esempio a causa di un errore di tempo di esecuzione o di un altro evento improbabile.

Quote di risorse

Kubernetes funziona con il sistema operativo per implementare le quote di risorse. In questo modo è possibile applicare prenotazioni di CPU e memoria e/o limiti. Per un'applicazione primaria che gestisce il carico interattivo, l'implementazione di limiti restrittivi non è consigliata a meno che non sia necessario. È importante notare che le richieste e i limiti differiscono in modo sostanziale nel significato e nella posizione di implementazione. Prima di impostare richieste o limiti, dedicare tempo per comprendere in modo dettagliato il modo in cui vengono implementate e applicate. Ad esempio, la memoria potrebbe non essere misurata in modo uniforme tra Kubernetes, il kernel Linux e il sistema di monitoraggio. Le quote della CPU potrebbero non essere applicate come previsto.

Risoluzione dei problemi

Arresto anomalo dei pod, segnalano che KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined

Messaggio di eccezione completo:

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()
  • Verificare che le variabili di ambiente KUBERNETES_SERVICE_HOST e KUBERNETES_SERVICE_PORT siano impostate all'interno del Pod. Controllare eseguendo il comando kubectl exec -it <pod_name> /bin/bash -c env.
  • Assicurarsi che automountServiceAccountToken sia impostato su true in Kubernetes deployment.yaml. Per ulteriori informazioni, vedere Configurare gli account di servizio per i pod.