Condividi tramite


Hosting Kubernetes

Kubernetes è una scelta comune per l'hosting di applicazioni Orleans. Orleans verrà eseguito in Kubernetes senza una configurazione specifica, ma può anche sfruttare informazioni aggiuntive che la piattaforma di hosting può fornire.

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, che esegue le azioni seguenti:

Si noti che il pacchetto di hosting Kubernetes non usa Kubernetes per il clustering. 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 sulla modalità di distribuzione del servizio:

  • I nomi dei silo devono corrispondere ai nomi dei pod.
  • I pod devono avere un'etichetta orleans/serviceId e orleans/clusterId, che corrispondano al ServiceId e al ClusterIddel silo. Il metodo sopra menzionato propagherà quelle etichette nelle opzioni corrispondenti in Orleans 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 is used to identify the service to Orleans
        orleans/serviceId: dictionary-app

        # This label is used to identify an instance of a cluster to Orleans.
        # Typically, this will be the same value as the previous label, or any
        # fixed value.
        # In cases where you are not using rolling deployments (for example,
        # blue/green deployments),
        # this value can allow for distinct clusters which do not communicate
        # directly with each others,
        # but which 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 which Orleans uses
          - containerPort: 11111
          - containerPort: 30000
          env:
          # The Azure Storage connection string for clustering is injected as an
          # environment variable
          # It must be created 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 is 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 per il controllo degli accessi in base al ruolo (RBAC), potrebbe essere necessario concedere anche l'accesso all'account di servizio per i pod su 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: ''

Sonde di vitalità, prontezza e avvio

Kubernetes può sondare i pod per determinare lo stato di salute di un servizio. Per altre informazioni, vedere Configurare attività, idoneità e probe di avvio nella documentazione di Kubernetes.

Orleans usa un protocollo di appartenenza al cluster per rilevare e ripristinare tempestivamente da un processo o da errori di rete. Ogni nodo monitora un subset di altri nodi, inviando probe periodici. Se un nodo non risponde a più sonde successive da più altri nodi, sarà rimosso con forza dal cluster. Una volta che un nodo non riuscito apprende che è stato rimosso, termina immediatamente. Kubernetes riavvierà il processo terminato e tenterà di rientrare nel cluster.

I probe di Kubernetes possono aiutare a determinare se un processo in un pod è in esecuzione e non è bloccato in uno stato zombie. Le sonde non verificano la connettività tra pod né la reattività né eseguono controlli delle funzionalità a livello di applicazione. Se un pod non risponde a una verifica di liveness, Kubernetes potrebbe eventualmente terminare il pod e riprogrammarlo. Le sonde di Kubernetes e le sonde Orleanssono quindi complementari.

L'approccio consigliato consiste nel configurare le sonde di liveness in Kubernetes, che eseguono un semplice controllo locale per verificare che l'applicazione stia funzionando correttamente. Queste sonde servono per terminare il processo in caso di blocco totale, ad esempio a causa di un errore di esecuzione o di un altro evento improbabile.

Quote di risorse

Kubernetes funziona insieme al sistema operativo per implementare quote di risorse. In questo modo è possibile applicare prenotazioni di CPU e memoria e/o limiti. Per un'applicazione primaria che gestisce il caricamento interattivo, è consigliabile non implementare limiti restrittivi, a meno che non sia necessario. È importante notare che le richieste e i limiti sono sostanzialmente diversi nel loro significato e dove vengono implementati. Prima di impostare richieste o limiti, dedicare il tempo necessario per comprendere in dettaglio 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 nel modo 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. È possibile controllare eseguendo il comando seguente kubectl exec -it <pod_name> /bin/bash -c env.
  • Assicurati che automountServiceAccountToken venga impostato su vero nel tuo Kubernetes deployment.yaml. Per ulteriori informazioni, vedere Configurare gli account di servizio per i pod.