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:
- SiloOptions.SiloName è impostato sul nome del pod.
- EndpointOptions.AdvertisedIPAddress è assegnato all'indirizzo IP del pod.
-
EndpointOptions.SiloListeningEndpoint & EndpointOptions.GatewayListeningEndpoint sono configurati per l'ascolto su qualsiasi indirizzo, con SiloPort e GatewayPortconfigurati. I valori di porta predefiniti di
11111
e30000
vengono usati se non vengono impostati valori in modo esplicito. -
ClusterOptions.ServiceId è impostato sul valore dell'etichetta del pod con il nome
orleans/serviceId
. -
ClusterOptions.ClusterId è impostato sul valore dell'etichetta del pod con il nome
orleans/clusterId
. - All'inizio del processo di avvio, il silo sonderà Kubernetes per individuare quali silo non hanno pod corrispondenti e contrassegnare tali silo come morti.
- Lo stesso processo verrà eseguito in fase di esecuzione per un subset di tutti i silo, per rimuovere il carico nel server API di Kubernetes. Per impostazione predefinita, 2 silo nel cluster osserveranno Kubernetes.
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
eorleans/clusterId
, che corrispondano alServiceId
e alClusterId
del 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
eKUBERNETES_SERVICE_PORT
siano impostate all'interno del Pod. È possibile controllare eseguendo il comando seguentekubectl exec -it <pod_name> /bin/bash -c env
. - Assicurati che
automountServiceAccountToken
venga impostato su vero nel tuo Kubernetesdeployment.yaml
. Per ulteriori informazioni, vedere Configurare gli account di servizio per i pod.