Kubernetes 托管

Kubernetes 是托管 Orleans 应用程序的常用选择。 Orleans 将在没有特定配置的情况下在 Kubernetes 中运行,但是,它还可以利用托管平台可以提供的额外知识。

Microsoft.Orleans.Hosting.Kubernetes 包添加了集成,用于在 Kubernetes 群集中托管 Orleans 应用程序。 该包提供了一个扩展方法(即 UseKubernetesHosting),该方法执行以下操作:

请注意,托管包的 Kubernetes 不使用 Kubernetes 进行聚类分析。 对于群集,仍然需要单独的群集提供程序。 有关配置群集的详细信息,请参阅服务器配置文档。

此功能对如何部署服务施加了一些要求:

  • 接收器名称必须与 Pod 名称匹配。
  • Pod 必须具有 orleans/serviceIdorleans/clusterId 标签,该标签与接收器的 ServiceIdClusterId 相对应。 上述方法会将这些标签从环境变量传播到 Orleans 中的相应选项。
  • Pod 必须具有以下环境变量集:POD_NAMEPOD_NAMESPACEPOD_IPORLEANS_SERVICE_IDORLEANS_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_HOSTKUBERNETES_SERVICE_PORT 环境变量。 可以通过执行以下命令 kubectl exec -it <pod_name> /bin/bash -c env 来检查。
  • 确保 automountServiceAccountToken 在 Kubernetes 上设置为 truedeployment.yaml。 有关详细信息,请参阅为 Pod 配置服务帐户