Kubernetes-Hosting
Kubernetes ist eine beliebte Wahl zum Hosten von Orleans-Anwendungen. Orleans kann in Kubernetes ohne spezifische Konfiguration ausgeführt werden, kann jedoch auch von zusätzlichem Wissen profitieren, das die Hostingplattform bereitstellt.
Das Paket Microsoft.Orleans.Hosting.Kubernetes
fügt die Integration zum Hosten einer Orleans-Anwendung in einem Kubernetes-Cluster hinzu. Das Paket stellt die Erweiterungsmethode UseKubernetesHosting bereit, die die folgenden Aktionen ausführt:
- SiloOptions.SiloName wird auf den Podnamen festgelegt.
- EndpointOptions.AdvertisedIPAddress wird auf die IP-Adresse des Pods festgelegt.
- EndpointOptions.SiloListeningEndpoint und EndpointOptions.GatewayListeningEndpoint sind so konfiguriert, dass alle Adressen mit den konfigurierten SiloPort und GatewayPort überwacht werden. Die Standardportwerte
11111
und30000
werden verwendet, wenn keine Werte explizit festgelegt werden. - ClusterOptions.ServiceId wird auf den Wert der Podbezeichnung mit dem Namen
orleans/serviceId
festgelegt. - ClusterOptions.ClusterId wird auf den Wert der Podbezeichnung mit dem Namen
orleans/clusterId
festgelegt. - Zu Beginn des Startvorgangs wird Kubernetes vom Silo untersucht, um zu ermitteln, welche Silos nicht über entsprechende Pods verfügen, und diese Silos als inaktiv zu markieren.
- Derselbe Prozess wird zur Laufzeit für eine Teilmenge aller Silos ausgeführt, um die Last auf dem API-Server von Kubernetes zu entfernen. Standardmäßig überwachen zwei Silos im Cluster Kubernetes.
Beachten Sie, dass das Kubernetes-Hostingpaket nicht Kubernetes für das Clustering verwendet. Für das Clustering ist weiterhin ein separater Clusteringanbieter erforderlich. Weitere Informationen zum Konfigurieren des Clusterings finden Sie in der Dokumentation zur Serverkonfiguration.
Diese Funktionalität stellt einige Anforderungen an die Bereitstellung des Diensts:
- Silonamen müssen mit Podnamen übereinstimmen.
- Pods müssen Bezeichnungen für
orleans/serviceId
undorleans/clusterId
aufweisen, dieServiceId
undClusterId
des Silos entsprechen. Die oben genannte Methode verteilt diese Bezeichnungen in die entsprechenden Optionen in Orleans aus Umgebungsvariablen. - Für Pods müssen die folgenden Umgebungsvariablen festgelegt sein:
POD_NAME
,POD_NAMESPACE
,POD_IP
,ORLEANS_SERVICE_ID
,ORLEANS_CLUSTER_ID
.
Das folgende Beispiel zeigt, wie diese Bezeichnungen und Umgebungsvariablen richtig konfiguriert werden:
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
Für RBAC-fähige Cluster muss dem Kubernetes-Dienstkonto für die Pods möglicherweise auch der erforderliche Zugriff gewährt werden:
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: ''
Live-, Bereitschafts- und Starttests
Kubernetes kann Pods testen, um die Integrität eines Diensts zu ermitteln. Weitere Informationen finden Sie unter Configure Liveness, Readiness and Startup Probes (Konfigurieren von Live-, Bereitschafts- und Starttests) in der Kubernetes-Dokumentation.
Orleans verwendet ein Clustermitgliedschaftsprotokoll, um einen Prozess- oder Netzwerkfehler umgehend zu erkennen und den ursprünglichen Zustand wiederherzustellen. Jeder Knoten überwacht eine Teilmenge anderer Knoten und sendet regelmäßige Tests. Wenn ein Knoten auf mehrere aufeinanderfolgende Tests von mehreren anderen Knoten nicht reagiert, wird er zwangsweise aus dem Cluster entfernt. Sobald ein fehlerhafter Knoten erfährt, dass er entfernt wurde, wird er sofort beendet. Kubernetes startet den beendeten Prozess neu, und dieser versucht erneut, dem Cluster beizutreten.
Kubernetes-Tests können helfen, zu ermitteln, ob ein Prozess in einem Pod ausgeführt wird oder sich in einem Zombiezustand befindet. Tests überprüfen die Konnektivität zwischen Pods oder die Reaktionsfähigkeit nicht und führen keine Funktionsüberprüfungen auf Anwendungsebene durch. Wenn ein Pod längere Zeit nicht auf einen Livetest reagiert, kann Kubernetes diesen Pod beenden und neu planen. Die Teste von Kubernetes und Orleans ergänzen sich somit.
Der empfohlene Ansatz besteht darin, Livetests in Kubernetes zu konfigurieren, die einfach lokal überprüfen, ob die Anwendung wie vorgesehen ausgeführt wird. Diese Tests dienen dazu, den Prozess zu beenden, wenn es zu einem vollständigen Einfrieren kommt, z. B. aufgrund eines Laufzeitfehlers oder eines anderen unwahrscheinlichen Ereignisses.
Ressourcenkontingente
Kubernetes implementiert in Verbindung mit dem Betriebssystem Ressourcenkontingente. Dadurch können CPU- und Arbeitsspeicherreservierungen oder -grenzwerte erzwungen werden. Für eine primäre Anwendung, die interaktive Last bereitstellt, wird empfohlen, keine restriktiven Grenzwerte zu implementieren, sofern dies nicht erforderlich ist. Es ist wichtig zu beachten, dass Anforderungen und Grenzwerte sich in ihrer Bedeutung und dem Ort, an dem sie implementiert werden, erheblich unterscheiden. Nehmen Sie sich vor dem Festlegen von Anforderungen oder Grenzwerten Zeit, sich ein ausführliches Verständnis der Implementierung und Durchsetzung dieser Anforderungen zu verschaffen. Beispielsweise wird der Arbeitsspeicher möglicherweise nicht einheitlich zwischen Kubernetes, dem Linux-Kernel und Ihrem Überwachungssystem gemessen. CPU-Kontingente werden möglicherweise nicht wie erwartet erzwungen.
Problembehandlung
Pods stürzen ab und geben die Beschwerde aus: KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
.
Vollständige Ausnahmemeldung:
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()
- Vergewissern Sie sich, dass die Umgebungsvariablen
KUBERNETES_SERVICE_HOST
undKUBERNETES_SERVICE_PORT
in Ihrem Pod festgelegt sind. Sie können dies überprüfen, indem Sie den Befehlkubectl exec -it <pod_name> /bin/bash -c env
ausführen. - Stellen Sie sicher, dass
automountServiceAccountToken
für Ihre Kubernetes-Dateideployment.yaml
auf true festgelegt ist. Weitere Informationen finden Sie unter Konfigurieren von Dienstkonten für Pods.