Kubernetes 是托管 Orleans 应用程序的常用选择。 Orleans 在没有特定配置的情况下在 Kubernetes 中运行;但是,它还可以利用托管平台提供的额外知识。
Microsoft.Orleans.Hosting.Kubernetes
包添加了集成,用于在 Kubernetes 群集中托管 Orleans 应用程序。 该包提供了一个扩展方法,UseKubernetesHosting执行以下操作:
- 将 SiloOptions.SiloName 设置为 pod 名称。
- 将 EndpointOptions.AdvertisedIPAddress 设置为 Pod IP。
- 使用配置的SiloPort和GatewayPort将EndpointOptions.SiloListeningEndpoint和EndpointOptions.GatewayListeningEndpoint配置为侦听任何地址。 如果未显式设置值,则会使用
11111
和30000
的默认端口值。 - 将ClusterOptions.ServiceId设置为Pod标签名为
orleans/serviceId
的值。 - 将 ClusterOptions.ClusterId 设置为名为
orleans/clusterId
的 Pod 标签的值。 - 在启动早期,探测器会检查 Kubernetes,找出哪些仓库没有对应的 Pod,并将这些仓库标记为不可用。
- 所有孤岛子集在运行时发生相同的过程,以减少 Kubernetes API 服务器上的负载。 默认情况下,群集中的 2 个接收器监视 Kubernetes。
请注意,Kubernetes 托管包不使用 Kubernetes 进行群集。 仍然需要单独的群集提供程序。 有关配置群集的详细信息,请参阅 服务器配置 文档。
此功能对服务部署施加了一些要求:
- 接收器名称必须与 Pod 名称匹配。
- Pod 必须具有与筒仓的
ServiceId
ClusterId
对应的orleans/serviceId
orleans/clusterId
标签。 该方法UseKubernetesHosting
将这些标签从环境变量传播到相应的 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 identifies the service to Orleans
orleans/serviceId: dictionary-app
# This label identifies an instance of a cluster to Orleans.
# Typically, this is the same value as the previous label, or any
# fixed value.
# In cases where you don't use rolling deployments (for example,
# blue/green deployments),
# this value can allow for distinct clusters that don't communicate
# directly with each other,
# but 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 Orleans uses
- containerPort: 11111
- containerPort: 30000
env:
# The Azure Storage connection string for clustering is injected as an
# environment variable.
# You must create it 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's 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 文档中的 配置 Liveness、Readiness 和 Startup Probes。
Orleans 使用群集成员身份协议来及时检测和恢复进程或网络故障。 每个节点监视其他节点的子集,同时定期发送探测信号。 如果节点无法响应来自多个其他节点的多个连续探测,则群集强行删除它。 失败的节点得知其删除后,会立即终止。 Kubernetes 重启终止的进程,然后尝试重新加入群集。
Kubernetes 探针有助于确定 Pod 中的进程是否正在正常执行,并且未停滞在僵尸状态。 这些探测不会验证 Pod 间连接性或响应能力,也不执行应用程序级功能检查。 如果 Pod 无法响应存活探针,Kubernetes 最终可能会终止该 Pod 并重新调度它。 因此,Kubernetes 探测和 Orleans 探测是互补的。
建议的方法是在 Kubernetes 中配置 Liveness Probe,以执行简单的本地检查,确保应用程序按预期运行。 当进程完全冻结时,例如由于运行时故障或其他不太可能发生的事件,这些探测器可用于终止进程。
资源配额
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
进行检查。 - 请确保在 Kubernetes
deployment.yaml
中将automountServiceAccountToken
设置为true
。 有关详细信息,请参阅为 Pod 配置服务帐户。