Compartir vía


Hospedaje de Kubernetes

Kubernetes es una opción popular para hospedar aplicaciones Orleans. Orleans se ejecutará en Kubernetes sin una configuración específica, pero también puede aprovechar los conocimientos adicionales que puede proporcionar la plataforma de hospedaje.

El paquete Microsoft.Orleans.Hosting.Kubernetes agrega integración para hospedar una aplicación de Orleans en un clúster de Kubernetes. El paquete proporciona un método de extensión, UseKubernetesHosting, que realiza las siguientes acciones:

  • SiloOptions.SiloName se establece en el nombre del pod.
  • EndpointOptions.AdvertisedIPAddress se asigna a la IP del pod.
  • EndpointOptions.SiloListeningEndpoint y EndpointOptions.GatewayListeningEndpoint están configurados para escuchar en cualquier dirección, con SiloPort y GatewayPort configurados. Los valores de puerto predeterminados de 11111 y 30000 se usan si no se establecen valores explícitamente).
  • ClusterOptions.ServiceId se establece en el valor de la etiqueta de pod con el nombre orleans/serviceId.
  • ClusterOptions.ClusterId se establece en el valor de la etiqueta de pod con el nombre orleans/clusterId.
  • Al principio del proceso de inicio, el silo sondeará Kubernetes para encontrar qué silos no tienen pods correspondientes y marcar esos silos como inactivos.
  • El mismo proceso se producirá en tiempo de ejecución para un subconjunto de todos los silos, para quitar la carga en el servidor de API de Kubernetes. De forma predeterminada, 2 silos del clúster verán Kubernetes.

Tenga en cuenta que el paquete de hospedaje de Kubernetes no usa Kubernetes para la agrupación en clústeres. Para la agrupación en clústeres, todavía se necesita un proveedor de agrupación en clústeres independiente. Para obtener más información sobre la configuración de clústeres, consulte la documentación de configuración del servidor .

Esta funcionalidad impone algunos requisitos sobre cómo se implementa el servicio:

  • Los nombres de los silos deben coincidir con los nombres de los pods.
  • Los pods deben tener una etiqueta orleans/serviceId y orleans/clusterId que corresponda a los ServiceId y ClusterId de los silos. El método mencionado anteriormente propagará esas etiquetas a las opciones correspondientes de Orleans desde variables de entorno.
  • Los pods deben tener establecidas las siguientes variables de entorno: POD_NAME, POD_NAMESPACE, POD_IP, ORLEANS_SERVICE_ID, ORLEANS_CLUSTER_ID.

En el ejemplo siguiente se muestra cómo configurar correctamente estas etiquetas y variables de entorno:

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

En el caso de los clústeres habilitados para RBAC, es posible que también haya que conceder el acceso necesario a la cuenta de servicio de Kubernetes para los pods:

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: ''

Sondeos de ejecución, preparación e inicio

Kubernetes puede sondear pods para determinar el estado de un servicio. Para más información, consulte Configuración de los sondeos de ejecución, preparación e inicio en la documentación de Kubernetes.

Orleans usa un protocolo de pertenencia al clúster para detectar y recuperarse rápidamente de errores de proceso o de red. Cada nodo supervisa un subconjunto de otros nodos y envía sondeos periódicos. Si un nodo no responde a varios sondeos sucesivos de varios otros nodos, se quitará forzosamente del clúster. Una vez que un nodo fallido aprende que se ha eliminado, termina inmediatamente. Kubernetes reiniciará el proceso finalizado y intentará volver a unir el clúster.

Los sondeos de Kubernetes pueden ayudar a determinar si el proceso de un pod se está ejecutando y no está bloqueado en un estado zombie. los sondeos no comprueban la conectividad entre pods ni la capacidad de respuesta, ni realizan ninguna comprobación de funcionalidad al nivel de la aplicación. Si un pod no responde a un sondeo de ejecución, Kubernetes puede finalizar ese pod y volver a programarlo. Por lo tanto, las sondas de Kubernetes y las sondas de Orleansson complementarias.

El enfoque recomendado es configurar sondas de actividad en Kubernetes que realizan una comprobación sencilla únicamente local de que la aplicación está funcionando como se espera. Estos sondeos sirven para finalizar el proceso si hay un bloqueo total, por ejemplo, debido a un error en tiempo de ejecución u otro evento poco probable.

Cuotas de recursos

Kubernetes trabaja junto al sistema operativo para implementar cuotas de recursos. Esto permite aplicar reservas de CPU y memoria o límites. En el caso de una aplicación principal que atiende la carga interactiva, se recomienda no implementar límites restrictivos a menos que sea necesario. Es importante tener en cuenta que las solicitudes y los límites son sustancialmente diferentes en su significado y dónde se implementan. Antes de establecer solicitudes o límites, tómese el tiempo para comprender detalladamente cómo se implementan y aplican. Por ejemplo, es posible que la memoria no se mida uniformemente entre Kubernetes, el kernel de Linux y el sistema de supervisión. Es posible que las cuotas de CPU no se apliquen de la manera esperada.

Solución de problemas

Los pods se bloquean, con la queja KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined

Mensaje de excepción 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()
  • Compruebe que las variables de entorno KUBERNETES_SERVICE_HOST y KUBERNETES_SERVICE_PORT estén establecidas dentro del Pod. Puede comprobar ejecutando el siguiente comando kubectl exec -it <pod_name> /bin/bash -c env.
  • Asegúrese de que automountServiceAccountToken está establecido en true en el deployment.yaml de Kubernetes. Para más información, consulte Configuración de cuentas de servicio para pods.