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 中配置运行情况探测,该探测执行简单的仅限本地检查(即应用程序是否按预期方式执行)。 这些探测用于在完全冻结时(例如,由于运行时错误或其他不太可能的事件)终止进程。
资源配额
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 配置服务帐户