Hébergement Kubernetes
Kubernetes est un choix populaire pour l’hébergement d’applications Orleans. Orleans s’exécutera dans Kubernetes sans configuration spécifique, mais elle peut également tirer parti des connaissances supplémentaires que la plateforme d’hébergement peut fournir.
Le package Microsoft.Orleans.Hosting.Kubernetes
ajoute l’intégration pour l’hébergement d’une application Orleans dans un cluster Kubernetes. Le package fournit une méthode d’extension, UseKubernetesHosting, qui effectue les actions suivantes :
- SiloOptions.SiloName a la valeur du nom du pod.
- EndpointOptions.AdvertisedIPAddress est défini sur l’adresse IP du pod.
- EndpointOptions.SiloListeningEndpoint & EndpointOptions.GatewayListeningEndpoint sont configurés pour écouter sur n’importe quelle adresse, avec SiloPort et GatewayPort également configurés. Les valeurs de port par défaut de
11111
et de30000
sont utilisées si aucune valeur n’est définie explicitement). - ClusterOptions.ServiceId a la valeur de l’étiquette de pod nommée
orleans/serviceId
. - ClusterOptions.ClusterId a la valeur de l’étiquette de pod nommée
orleans/clusterId
. - Au début du processus de démarrage, le silo sonde Kubernetes pour trouver les silos qui n’ont pas de pods correspondants et marquer ces silos comme morts.
- Le même processus se produit au moment de l’exécution pour un sous-ensemble de tous les silos, afin de supprimer la charge sur le serveur d’API Kubernetes. Par défaut, 2 silos dans le cluster regardent Kubernetes.
Notez que le package d’hébergement Kubernetes n’utilise pas Kubernetes pour le clustering. Pour le clustering, un fournisseur de clustering distinct est toujours nécessaire. Pour plus d’informations sur la configuration du clustering, consultez la documentation relative à la configuration du serveur.
Cette fonctionnalité impose certaines exigences sur le déploiement du service :
- Les noms de silo doivent correspondre aux noms de pods.
- Les pods doivent avoir une étiquette
orleans/serviceId
etorleans/clusterId
qui correspond auxServiceId
etClusterId
du silo. La méthode mentionnée ci-dessus propage ces étiquettes dans les options correspondantes dans Orleans à partir de variables d’environnement. - Les pods doivent avoir les variables d’environnement suivantes définies :
POD_NAME
,POD_NAMESPACE
,POD_IP
,ORLEANS_SERVICE_ID
,ORLEANS_CLUSTER_ID
.
L’exemple suivant montre comment configurer correctement ces étiquettes et variables d’environnement :
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
Pour les clusters avec RBAC, le compte de service Kubernetes pour les pods peut également avoir besoin de se voir accorder l’accès requis :
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: ''
Probes liveness, readiness et startup
Kubernetes peut sonder les pods à l’aide d’une probe pour déterminer l’intégrité d’un service. Pour plus d’informations, consultez Configurer les probes liveness, readiness et startup dans la documentation de Kubernetes.
Orleans utilise un protocole d’appartenance au cluster pour détecter et récupérer rapidement à partir d’un processus ou d’un échec réseau. Chaque nœud surveille un sous-ensemble d’autres nœuds, en envoyant des sondes périodiques. Si un nœud ne répond pas à plusieurs sondes successives de plusieurs autres nœuds, il sera supprimé de force du cluster. Une fois qu’un nœud ayant échoué apprend qu’il a été supprimé, il se termine immédiatement. Kubernetes redémarre le processus terminé et tente de rejoindre le cluster.
Les sondes kubernetes peuvent aider à déterminer si un processus dans un pod s’exécute et n’est pas bloqué dans un état zombie. Les sondes ne vérifient pas la connectivité ou la réactivité entre pods ou n’effectuent aucune vérification des fonctionnalités au niveau de l’application. Si un pod ne répond pas à une probe liveness, Kubernetes peut finir par l’arrêter et le replanifier. Les sondes de Kubernetes et celles de Orleanssont donc complémentaires.
L’approche recommandée consiste à configurer des sondes de vivacité dans Kubernetes, qui effectuent une vérification locale simple pour garantir que l'application fonctionne comme prévu. Ces sondes servent à mettre fin au processus en cas de gel total, par exemple en raison d’une erreur d’exécution ou d’un autre événement peu probable.
Quotas de ressources
Kubernetes fonctionne conjointement avec le système d’exploitation pour implémenter des quotas de ressources. Cela permet d’appliquer les réservations de processeur et de mémoire et/ou les limites. Pour une application principale qui sert de charge interactive, nous vous recommandons de ne pas implémenter de limites restrictives, sauf si nécessaire. Il est important de noter que les demandes et les limites sont sensiblement différentes de leur signification et de leur implémentation. Avant de définir des demandes ou des limites, prenez le temps d’obtenir une compréhension détaillée de la façon dont elles sont implémentées et appliquées. Par exemple, la mémoire peut ne pas être mesurée uniformément entre Kubernetes, le noyau Linux et votre système de surveillance. Les quotas de processeur ne sont peut-être pas appliqués tel que vous le souhaitez.
Dépannage
Les pods plantent, en indiquant KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
Message d’exception complet :
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()
- Vérifiez que les variables d’environnement
KUBERNETES_SERVICE_HOST
etKUBERNETES_SERVICE_PORT
sont définies à l’intérieur de votre pod. Vous pouvez vérifier en exécutant la commande suivantekubectl exec -it <pod_name> /bin/bash -c env
. - Vérifiez que
automountServiceAccountToken
a la valeur true dans votre fichierdeployment.yaml
Kubernetes. Pour plus d’informations, consultez Configurer des comptes de service pour les pods.