Partager via


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 de 30000 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 et orleans/clusterId qui correspond aux ServiceId et ClusterIddu 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 et KUBERNETES_SERVICE_PORT sont définies à l’intérieur de votre pod. Vous pouvez vérifier en exécutant la commande suivante kubectl exec -it <pod_name> /bin/bash -c env.
  • Vérifiez que automountServiceAccountToken a la valeur true dans votre fichier deployment.yaml Kubernetes. Pour plus d’informations, consultez Configurer des comptes de service pour les pods.