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.

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.