Kubernetes 托管
Kubernetes 是托管 Orleans 应用程序的常用选择。 Orleans 在没有特定配置的情况下在 Kubernetes 中运行,但它还可以利用托管平台可以提供的额外知识。
Microsoft.Orleans.Hosting.Kubernetes
包添加了集成,用于在 Kubernetes 群集中托管 Orleans 应用程序。 该包提供一个扩展方法,UseKubernetesHosting,该方法执行以下操作:
- SiloOptions.SiloName 设置为 Pod 名称。
- EndpointOptions.AdvertisedIPAddress 设置为 Pod IP。
- EndpointOptions.SiloListeningEndpoint 和 EndpointOptions.GatewayListeningEndpoint 配置为使用配置的 SiloPort 和 GatewayPort 侦听任何地址。 如果未显式设置任何值,则默认使用端口值
11111
和30000
。 - ClusterOptions.ServiceId 设置为名称为
orleans/serviceId
的 Pod 标签的值。 - ClusterOptions.ClusterId 设置为名称为
orleans/clusterId
的 Pod 标签的值。 - 在启动过程初期,接收器会探测 Kubernetes,以查找哪些接收器没有相应的 Pod,并将这些接收器标记为“死亡”。
- 在运行时,一部分接收器会出现相同的进程,来删除 Kubernetes 的 API 服务器上的负载。 默认情况下,群集中的 2 个接收器将监视 Kubernetes。
请注意,Kubernetes 托管包不使用 Kubernetes 进行群集。 对于群集,仍然需要单独的群集提供程序。 有关配置群集的详细信息,请参阅 服务器配置 文档。
此功能对服务的部署方式提出了一些要求:
- 接收器名称必须与 Pod 名称匹配。
- Pod 必须具有
orleans/serviceId
和orleans/clusterId
标签,该标签与接收器的ServiceId
和ClusterId
相对应。 上述方法会将这些标签传播到环境变量 Orleans 中的相应选项中。 - Pod 必须设置以下环境变量:
POD_NAME
、POD_NAMESPACE
、POD_IP
、ORLEANS_SERVICE_ID
、ORLEANS_CLUSTER_ID
。
以下示例演示如何正确配置这些标签和环境变量:
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
对于已启用 RBAC 的群集,可能还需要向 pod 的 Kubernetes 服务帐户授予所需的访问权限:
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: ''
运行情况、就绪情况和启动探测
Kubernetes 可以探测 Pod 以确定服务的运行状况。 有关详细信息,请参阅 Kubernetes 文档中的配置运行情况、就绪情况和启动探测。
Orleans 使用群集成员身份协议来及时检测和恢复进程或网络故障。 每个节点监视其他节点的子集,同时定期发送探测信号。 如果节点无法响应来自多个其他节点的多个连续探测,则会从群集中强行删除它。 一旦失败的节点得知它已被删除,它将立即终止。 Kubernetes 将重启终止的进程,并尝试重新加入群集。
Kubernetes 的探针可以帮助确定 Pod 中的进程是否正在执行,并且未陷入僵尸状态。 探测不验证 Pod 间连接性或响应能力,也不执行任何应用程序级功能检查。 如果 Pod 无法响应运行情况探测,则 Kubernetes 最终可能会终止该 Pod 并重新计划它。 因此,Kubernetes 的探测和 Orleans“探测是互补的。
建议的方法是在 Kubernetes 中配置 Liveness 探测,以执行仅限本地的简单检查,从而确保应用程序按预期方式运行。 如果存在完全冻结(例如,由于运行时错误或其他不太可能的事件),这些探测将终止进程。
资源配额
Kubernetes 与操作系统结合使用来实现资源配额。 这样就可以强制实施 CPU 和内存预留和/或限制。 对于提供交互式负载的主应用程序,除非有必要,否则不建议实施限制性限制。 请务必注意,请求和限制的含义和实现方式大相径庭。 在设置请求或限制之前,请花时间详细了解如何实施和强制执行它们。 例如,在 Kubernetes、Linux 内核和监视系统之间可能无法统一测量内存。 CPU 配额可能无法按照预期的方式强制执行。
故障 排除
Pod 崩溃,报错 KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined
完整异常消息:
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()
- 检查 Pod 中是否设置了
KUBERNETES_SERVICE_HOST
和KUBERNETES_SERVICE_PORT
环境变量。 可以通过执行以下命令kubectl exec -it <pod_name> /bin/bash -c env
进行检查。 - 确保
automountServiceAccountToken
在 Kubernetes 上设置为 truedeployment.yaml
。 有关详细信息,请参阅为 Pod 配置服务帐户。