Kubernetes是托管Orleans应用程序的一个流行选择。 Orleans将在Kubernetes中运行,不需要特定的配置,它也可以利用托管平台可以提供的额外信息。

Microsoft.Orleans.Hosting.Kubernetes包增加了在Kubernetes集群中托管Orleans应用程序的集成。该包提供了一个扩展方法,ISiloBuilder.UseKubernetesHosting,它可以执行以下操作:

  • SiloOptions.SiloName设置为Pod名称
  • EndpointOptions.AdvertisedIPAddress设置为Pod的IP
  • EndpointOptions.SiloListeningEndpointEndpointOptions.GatewayListeningEndpoint配置为监听任意地址,各自的端口号通过SiloPortGatewayPort配置。如果没有显式指定端口号,则默认为1111130000
  • ClusterOptions.ServiceId设置为名为orleans/serviceId的pod标签的值。
  • ClusterOptions.ClusterId设置为名为orleans/clusterId的pod标签的值。
  • 在启动过程的初期,Silo将探测Kubernetes,以发现哪些Silo没有相应的pod,并将这些Silo标记为死亡。
  • 同样的过程将在运行时发生在所有Silo的一个子集上,以消除Kubernetes的API服务器的负载。默认情况下,集群中的2个Silo将用于监视Kubernetes。

注意,Kubernetes托管包并不使用Kubernetes进行集群化。对于集群化,仍然需要一个单独的集群提供者。关于配置集群的更多信息,请参阅服务器配置

这种功能对服务的部署方式提出了一些要求:

  • Silo名称必须匹配Pod名称.
  • Pod必须有orleans/serviceIdorleans/clusterId标签,与Silo的ServiceIdClusterId对应。上述方法将把这些标签传播到Orleans环境变量的相应选项中。
  • Pods必须设置以下环境变量:POD_NAMEPOD_NAMESPACEPOD_IPORLEANS_SERVICE_IDORLEANS_CLUSTER_ID

下面的例子展示了如何正确配置这些标签和环境变量:

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: dictionary-app
  5. labels:
  6. orleans/serviceId: dictionary-app
  7. spec:
  8. selector:
  9. matchLabels:
  10. orleans/serviceId: dictionary-app
  11. replicas: 3
  12. template:
  13. metadata:
  14. labels:
  15. # This label is used to identify the service to Orleans
  16. orleans/serviceId: dictionary-app
  17. # This label is used to identify an instance of a cluster to Orleans.
  18. # Typically, this will be the same value as the previous label, or any
  19. # fixed value.
  20. # In cases where you are not using rolling deployments (for example,
  21. # blue/green deployments),
  22. # this value can allow for distinct clusters which do not communicate
  23. # directly with each others,
  24. # but which still share the same storage and other resources.
  25. orleans/clusterId: dictionary-app
  26. spec:
  27. containers:
  28. - name: main
  29. image: my-registry.azurecr.io/my-image
  30. imagePullPolicy: Always
  31. ports:
  32. # Define the ports which Orleans uses
  33. - containerPort: 11111
  34. - containerPort: 30000
  35. env:
  36. # The Azure Storage connection string for clustering is injected as an
  37. # environment variable
  38. # It must be created separately using a command such as:
  39. # > kubectl create secret generic az-storage-acct `
  40. # --from-file=key=./az-storage-acct.txt
  41. - name: STORAGE_CONNECTION_STRING
  42. valueFrom:
  43. secretKeyRef:
  44. name: az-storage-acct
  45. key: key
  46. # Configure settings to let Orleans know which cluster it belongs to
  47. # and which pod it is running in
  48. - name: ORLEANS_SERVICE_ID
  49. valueFrom:
  50. fieldRef:
  51. fieldPath: metadata.labels['orleans/serviceId']
  52. - name: ORLEANS_CLUSTER_ID
  53. valueFrom:
  54. fieldRef:
  55. fieldPath: metadata.labels['orleans/clusterId']
  56. - name: POD_NAMESPACE
  57. valueFrom:
  58. fieldRef:
  59. fieldPath: metadata.namespace
  60. - name: POD_NAME
  61. valueFrom:
  62. fieldRef:
  63. fieldPath: metadata.name
  64. - name: POD_IP
  65. valueFrom:
  66. fieldRef:
  67. fieldPath: status.podIP
  68. - name: DOTNET_SHUTDOWNTIMEOUTSECONDS
  69. value: "120"
  70. request:
  71. # Set resource requests
  72. terminationGracePeriodSeconds: 180
  73. imagePullSecrets:
  74. - name: my-image-pull-secret
  75. minReadySeconds: 60
  76. strategy:
  77. rollingUpdate:
  78. maxUnavailable: 0
  79. maxSurge: 1

对于支持RBAC的集群,Kubernetes服务账户的pod可能也需要被授予所需的权限:

  1. kind: Role
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. metadata:
  4. name: pod-reader
  5. rules:
  6. - apiGroups: [ "" ]
  7. resources: ["pods"]
  8. verbs: ["get", "watch", "list"]
  9. ---
  10. kind: RoleBinding
  11. apiVersion: rbac.authorization.k8s.io/v1
  12. metadata:
  13. name: pod-reader-binding
  14. subjects:
  15. - kind: ServiceAccount
  16. name: default
  17. apiGroup: ''
  18. roleRef:
  19. kind: Role
  20. name: pod-reader
  21. apiGroup: ''

存活、就绪和启动探测器

Kubernetes能够探测Pod以确定服务的健康情况。更多信息,参见Kubernetes文档的配置存活、就绪和启动探测器

Orleans使用集群成员协议来及时检测和恢复进程或网络故障。 每个节点监控其他节点的一个子集,定期发送探测器。 如果一个节点未能对来自其他多个节点的连续探测作出反应,那么它将被强行从集群中移除。 一旦一个故障的节点得知自己被移除,它就会立即终止工作。 Kubernetes将重新启动被终止的进程,它将试图重新加入集群。

Kubernetes的探测器可以帮助确定一个pod中的进程是否在执行,而不是停留在僵尸状态。探测器不会验证pod间的连接性或响应性,也不会执行任何应用层面的功能检查。 如果一个pod未能响应一个有效性探测器,那么Kubernetes最终可能会终止该pod并重新调度它。 因此,Kubernetes的探测器和Orleans的探测器是互补的。

推荐的方法是在Kubernetes中配置存活探测器,它只执行简单的本地检查,以确保应用程序按预期执行。 这些探测器的作用是在出现完全冻结的情况下终止进程,例如由于运行时故障或其他小概率事件。

资源配额

Kubernetes与操作系统一起工作,实现资源配额。 这允许CPU和内存保留和/或限制被强制执行。 对于一个为交互式负载服务的主要应用,我们建议除非必要,否则不要实施限制性的上限。 需要注意的是,请求和限制在其含义和实施方式上有很大不同。 在设置请求或限制之前,要花时间详细了解它们是如何实现和执行的。 例如,Kubernetes、Linux内核和你的监控系统之间可能不会统一测量内存。CPU配额可能不会以你期望的方式执行。

故障诊断

Pods崩溃,报错信息为:KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined

异常信息全文:

  1. Unhandled exception. k8s.Exceptions.KubeConfigException: unable to load in-cluster configuration, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
  2. at k8s.KubernetesClientConfiguration.InClusterConfig()
  • 检查KUBERNETES_SERVICE_HOSTKUBERNETES_SERVICE_PORT环境变量是否已在你的Pod内设置。你可以通过执行以下命令来检查kubectl exec -it <pod_name> /bin/bash -c env
  • 确保在你的Kubernetesdeployment.yaml上将automountServiceAccountToken设置为true。欲了解更多信息,请参阅为Pod配置服务账户