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
y30000
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
yorleans/clusterId
que corresponda a losServiceId
yClusterId
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
yKUBERNETES_SERVICE_PORT
estén establecidas dentro del Pod. Puede comprobar ejecutando el siguiente comandokubectl exec -it <pod_name> /bin/bash -c env
. - Asegúrese de que
automountServiceAccountToken
está establecido en true en eldeployment.yaml
de Kubernetes. Para más información, consulte Configuración de cuentas de servicio para pods.