ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

在 Kubernetes 上托管 Orleans:网络、生命周期、探针与滚动更新的生产级实践指南

在 Kubernetes 上托管 Orleans:网络、生命周期、探针与滚动更新的生产级实践指南 后端微服务【免费下载链接】orleansCloud Native application framework for .NET项目地址https://gitcode.com/gh_mirrors/or/orleans点击查看免费下载导读本指南围绕 Orleans 官方部署文档 docs/site/src/content/docs/deployment/kubernetes.md 展开系统讲解如何在没有专用托管包的情况下将 Orleans 集群silo直接部署到 Kubernetes从基于 Downward API 的 Pod 名与 Pod IP 的显式端点配置到生产基线清单探针、资源、PodDisruptionBudget、滚动更新策略、可选托管包Microsoft.Orleans.Hosting.Kubernetes的适用边界与权限模型以及健康探针、资源限额、优雅停机与滚动扩容的底层原理。读完本文你将掌握一套可直接落地的 Kubernetes 托管方案并能根据仓库源码理解每个配置项背后的实现机制。为什么 Kubernetes 不需要 Orleans 专用托管包Kubernetes 可以托管 Orleans 集群前提是Pod 之间具备直接的网络连通性即 Pod IP 可路由、可直达应用使用生产级聚类clustering提供程序如 Azure Table、AdoNet、Consul、ZooKeeper 等。Orleans 本身不要求Kubernetes 专用托管包。官方推荐的做法是从 Kubernetes Downward API 提供的 Pod 名与 Pod IP 出发为每个 silo显式配置其通告地址、监听端点与 silo 名称。这样做的核心原因是 Orleans 的集群成员协议基于真实的端点地址每个 silo 必须通告一个其他 silo 可以直接连接的 IP而 Pod IP 正是这个地址。关于 Azure 网络、工作负载标识workload identity、可用区、节点池、自动扩缩、托管升级与 Azure Monitor 的专门指导参见 docs/site/src/content/docs/deployment/azure-kubernetes-service.md。配置 silo从 Pod 元数据驱动端点代码骨架部署时需要引用Microsoft.Orleans.Server以及一个生产级聚类提供程序包如Microsoft.Orleans.Clustering.AzureStorage、Microsoft.Orleans.Clustering.AdoNet等。silo 配置的核心代码见 DeploymentSnippets.cs 中的KubernetesSnippetsusing System.Net; var builder WebApplication.CreateBuilder(args); var podName builder.Configuration[POD_NAME] ?? throw new InvalidOperationException(POD_NAME isnt configured.); var podIp IPAddress.Parse( builder.Configuration[POD_IP] ?? throw new InvalidOperationException(POD_IP isnt configured.)); builder.Host.UseOrleans(siloBuilder { siloBuilder // Configure one production clustering provider here. .ConfigureClusterOptions(options { options.ServiceId builder.Configuration[ORLEANS_SERVICE_ID] ?? throw new InvalidOperationException(ORLEANS_SERVICE_ID isnt configured.); options.ClusterId builder.Configuration[ORLEANS_CLUSTER_ID] ?? throw new InvalidOperationException(ORLEANS_CLUSTER_ID isnt configured.); }) .ConfigureSiloOptions(options options.SiloName podName) .ConfigureEndpoints( advertisedIP: podIp, siloPort: 11_111, gatewayPort: 30_000, listenOnAnyHostAddress: true); }); builder.Services.ConfigureHostOptions(options { options.ShutdownTimeout TimeSpan.FromSeconds(120); }); var app builder.Build(); // Map application-owned startup, readiness, and liveness endpoints. app.Run();要点拆解POD_NAME与POD_IP由 Kubernetes 通过环境变量注入对应清单中的fieldRef代码中以强校验方式读取缺失即抛异常避免在错误配置下带病启动。ClusterOptions.ServiceId/ClusterId同样从环境变量ORLEANS_SERVICE_ID/ORLEANS_CLUSTER_ID读取。所有 silo 与客户端必须使用相同的 ServiceId、ClusterId 与聚类提供程序这是 Orleans 集群成员识别的唯一依据。ConfigureEndpoints(advertisedIP: podIp, siloPort: 11_111, gatewayPort: 30_000, listenOnAnyHostAddress: true)通告地址设为 Pod IPsilo 监听端口固定为11111、网关端口固定为30000并监听 Pod 的所有接口。HostOptions.ShutdownTimeout 120 秒为优雅停机预留时间下文与 Pod 的terminationGracePeriodSeconds: 150配套解释。与底层EndpointOptions的关系上述代码最终落到 EndpointOptions位于 src/Orleans.Core/Configuration中的四个关键字段字段示例值含义AdvertisedIPAddressPod IP写入成员表、供其他 silo/客户端连接的通告地址SiloListeningEndpointIPAddress.Any:11111本机监听端点silo 间通信GatewayListeningEndpointIPAddress.Any:30000本机监听端点客户端网关SiloPort/GatewayPort11111/30000与监听端点配合的端口号在容器环境中监听端点应绑定到IPAddress.Any即 Pod 内所有网卡而通告地址必须是具体的 Pod IP。二者分离正是 Orleans 在 NAT/容器/云环境中的标准配置模式与 docs/site/src/content/docs/deployment/containers.md 中容器场景的配置思路一致。生产基线清单一份可直接落地的 YAML文档给出的生产基线清单orleans.yaml包含三部分Deployment含探针、资源、滚动策略、PodDisruptionBudget以及通过 Downward API 注入的环境变量。清单有意省略了聚类提供程序的凭据与应用入口ingress——这两者应分别通过工作负载标识workload identity和提供程序专用配置来提供。apiVersion: apps/v1 kind: Deployment metadata: name: dictionary-app spec: replicas: 3 minReadySeconds: 30 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0 maxSurge: 1 selector: matchLabels: app.kubernetes.io/name: dictionary-app template: metadata: labels: app.kubernetes.io/name: dictionary-app spec: automountServiceAccountToken: false terminationGracePeriodSeconds: 150 containers: - name: app image: registry.example.com/dictionary-app:10.0.0 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 protocol: TCP - name: silo containerPort: 11111 protocol: TCP - name: gateway containerPort: 30000 protocol: TCP env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP - name: ORLEANS_SERVICE_ID value: dictionary-app - name: ORLEANS_CLUSTER_ID value: production startupProbe: httpGet: path: /health/startup port: http periodSeconds: 5 timeoutSeconds: 2 failureThreshold: 60 readinessProbe: httpGet: path: /health/ready port: http periodSeconds: 5 timeoutSeconds: 2 failureThreshold: 2 livenessProbe: httpGet: path: /health/live port: http periodSeconds: 10 timeoutSeconds: 2 failureThreshold: 3 resources: requests: cpu: 500m memory: 512Mi limits: memory: 1Gi --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: dictionary-app spec: minAvailable: 2 selector: matchLabels: app.kubernetes.io/name: dictionary-app应用清单kubectl apply --namespace namespace --filename orleans.yaml在专用或恰当共享的命名空间中应用该清单。几点生产级考量automountServiceAccountToken: false基线默认不挂载 Service Account Token因为 Orleans 本身不需要调用 Kubernetes API。只有应用功能确实需要时才为工作负载添加专用 Service Account 与权限见下文可选托管包一节。minReadySeconds: 30Pod 就绪后需保持 30 秒才被视为可用配合滚动更新避免刚就绪就被替换的抖动。terminationGracePeriodSeconds: 150与代码中的 120 秒ShutdownTimeout配套——Kubernetes 先发SIGTERM.NET 主机在 120 秒内完成优雅停机Pod 再保留 30 秒缓冲。maxUnavailable: 0, maxSurge: 1滚动更新期间不允许可用 Pod 数下降同时允许先多启动 1 个 Pod 作为缓冲保证集群在滚动期间始终保有足够就绪 silo。用 Aspire 部署Aspire 可以在 AppHost 中对 Orleans 应用及其支撑资源建模Aspire.Hosting.Kubernetes集成可以将该应用模型发布为Helm chart或直接部署到当前kubectlcontext 选中的集群。需要强调的是Aspire 不会改变本页所述的 Orleans 网络与生命周期要求。在部署生成资源之前必须在 Orleans 资源模型中配置生产级聚类提供程序与持久化状态提供程序跨故障域运行多个 silo 副本确保每个 silo 获得独立的 Pod 名与 Pod IP并通告该 Pod IP将 silo 与网关容器端口暴露给所需的 Pod 网络与客户端网络添加应用自有的 startup、readiness、liveness 探针依据实测行为设置资源 requests、中断预算、滚动策略与终止宽限期。应用生成的 Helm chart 之前务必人工审查当生成的 workload 不包含上述 Orleans 特定要求时应使用 Kubernetes 集成的资源定制 APIresource customization进行调整。受支持的 API 与部署命令参见 Orleans 与 Aspire 集成 及相关部署文档。可选托管包Microsoft.Orleans.Hosting.KubernetesMicrosoft.Orleans.Hosting.Kubernetes包NuGet 包名见 Orleans.Hosting.Kubernetes.csproj是可选的且通常不推荐使用。它只适用于一种简单拓扑恰好一个 KubernetesDeployment对象对应恰好一个 Orleans 集群。[!IMPORTANT]不要在以下场景使用该包由多个Deployment对象、StatefulSet、自定义控制器组成的集群或共享同一集群标识cluster identity的蓝绿blue-green/金丝雀canary工作负载。这些场景应显式配置端点即使用本文第一部分的显式配置方式。它做了什么对于受支持的简单拓扑KubernetesHostingExtensions.UseKubernetesHosting 会从 Pod 元数据配置 silo 名称、Pod IP、监听端点、ServiceId 与 ClusterId调用 Kubernetes API 来对账reconcileOrleans 成员与匹配的 Pod。从源码看其依赖注入注册见UseKubernetesHosting(IServiceCollection)包括ConfigureKubernetesHostingOptions实现IConfigureOptionsClusterOptions、IConfigureOptionsSiloOptions、IPostConfigureOptionsEndpointOptions、IConfigureOptionsKubernetesHostingOptions负责从环境变量读取配置——POD_NAMESPACE、POD_NAME、POD_IP、ORLEANS_CLUSTER_ID、ORLEANS_SERVICE_ID常量定义见 KubernetesHostingOptions.cs。若未设置POD_NAMESPACE还会回退读取挂载的 Service Account 命名空间文件/var/run/secrets/kubernetes.io/serviceaccount/namespace若未设置POD_NAME回退到Environment.MachineName若未设置POD_IP则通过 DNS 解析 Pod 名并按优先 IANA 私有 IPv4 网段10.x、192.168.x、172.16-31.x的策略挑选 IP。KubernetesHostingOptionsValidator见 KubernetesHostingOptionsValidator.cs校验Namespace与PodName均已设置否则启动即失败。KubernetesClusterAgent见 KubernetesClusterAgent.cs实现ILifecycleParticipantISiloLifecycle在AfterRuntimeGrainServices阶段启动。它会在启动时把orleans/serviceId与orleans/clusterId标签补写到本 PodMergePatch以labelSelector列出命名空间中属于该集群的 Pod把有 Pod 但无对应 silo的条目记为警告把有活跃 silo 但无对应 Pod的条目通过IClusterMembershipService.TryKill标记为 Dead随后启动两个监视循环——MonitorOrleansClustering订阅成员更新流与MonitorKubernetesPodsWatch Pod 事件当 Pod 被删除时把对应 silo 声明为 Dead。重要该包**补充supplement**生产级聚类提供程序**不替代replace**它。集群成员关系仍然依赖你配置的聚类提供程序如 Azure Table、AdoNet 等。如何启用引用Microsoft.Orleans.Hosting.Kubernetes并调用UseKubernetesHosting()。在Deployment的 Pod 模板上添加orleans/serviceId与orleans/clusterId标签。通过 Downward API 提供POD_NAME、POD_NAMESPACE、POD_IP、ORLEANS_SERVICE_ID、ORLEANS_CLUSTER_ID环境变量。挂载专用 Service Account Token并授予如下命名空间级 RoleapiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: orleans-hosting rules: - apiGroups: [] resources: [pods] verbs: [get, list, watch, patch]将该 Role 绑定到工作负载的专用 Service Account。如果显式启用了KubernetesHostingOptions.DeleteDefunctSiloPods默认false见 KubernetesHostingOptions.cs还需额外授予delete权限。除非已充分评估其运维后果否则应保持该选项关闭——它会在 silo 变为 Dead 时直接删除对应 Pod源码中MonitorOrleansClustering会跳过本 silo 自身的变化并在删除时忽略NotFound错误。其他可配置项均可通过configureOptions回调调整MaxAgents默认 2集群中负责监视 Kubernetes 的 silo 数量上限调小可降低 API Server 负载、MaxKubernetesApiRetryAttempts默认 10初始化时 API 调用重试次数。网络要求网络拓扑是 Kubernetes 托管 Orleans 的最关键前提。文档明确要求每个 silo Pod → 每个 silo Pod 的11111端口silo 间通信每个 Orleans 客户端 → 每个 silo Pod 的30000端口客户端网关每个 silo 与客户端 → 聚类提供程序成员表读写仅当启用可选托管包时silo Pod 才需要访问 Kubernetes API。两个易踩的坑不要把 KubernetesService的虚拟 IP 放进EndpointOptions.AdvertisedIPAddress。Orleans 通告的是每个 Pod 的 IP这样对端才能连接到那个具体的 silo。Service可以暴露应用 HTTP 入口但它不能替代 Orleans 成员关系也不能替代 silo 间的直连。如果服务网格service mesh会拦截 TCP 流量务必验证长连接保持、Pod 地址保真、双向 TLS 策略、停机顺序与重试语义若网格无法保持所需语义应将 Orleans 端口从拦截范围中排除。健康探针三探针的正确语义清单中的三个路径对应 健康与可观测性文档 中要求应用自实现的三种探针探针路径语义失败动作Startup/health/startupsilo 加入集群且必要初始化完成后才成功延迟 readiness/liveness 评估超过启动期限才重启Readiness/health/ready关闭开始前、以及应用无法安全接收新流量时变为 false从流量中摘除但不重启Liveness/health/live仅做本地前进forward-progress检查不调用 grain、不访问依赖重启进程关键原则不要让 liveness 依赖聚类提供程序、grain 存储、远端 silo 或其他网络服务——共享依赖故障会导致所有实例同时重启放大故障并抹掉诊断信息。移除 HTTP 端点的流量并不会阻止直达的 Orleans 流量关闭期间必须将 readiness 摘除与优雅主机停机、足够的成员离开时间三者结合。清单中的 startup 探针failureThreshold: 60×periodSeconds: 5给出约5 分钟的启动宽限这只是示例不是通用默认值。应从实测的启动与恢复时间出发设置过于激进的探针会把提供程序延迟或 CPU 压力变成集群级重启循环。资源 requests 与 limits调度与约束不是一回事Kubernetes 用requests做调度用limits约束运行中的容器二者不可互换。文档针对 Orleans 负载给出了明确的资源语义CPU requests预留调度容量。过低会让 Kubernetes 把过多 silo 调度到同一节点在突发或故障转移时造成争抢。CPU limits即使节点有空闲 CPU也会对 .NET 进程进行限流throttle。尾部延迟、成员探针、垃圾回收与激活恢复都会在节流下劣化。基线清单因此特意只设置 CPU request、不设置 CPU limit。Memory requests应覆盖代表性工作集包括激活activations、缓存、序列化缓冲与预期的故障转移增长。Memory limits通过 cgroup 强制超限即终止容器。要为突发与故障转移留足余量不要指望托管的OutOfMemoryException或优雅停机兜底。应监控的指标CPU 节流、工作集、分配速率、垃圾回收、调度延迟、激活数与 Pod 重启次数。当 grain 状态、放置策略、流量、运行时或节点规格变化时重新审视资源设置。还要注意命名空间的ResourceQuota与LimitRange策略可能在准入admission阶段拒绝 Pod 或注入默认值——务必核对准入后的实际 Pod 规格而不是假设提交的清单就是实际运行的配置。关闭、滚动更新与扩缩容SIGTERM与优雅停机Kubernetes 发送SIGTERM并开始 Pod 终止宽限期.NET 主机必须感知信号、报告 not ready并获得足够时间优雅停止 Orleans。示例中 Pod 的 150 秒宽限期大于主机 120 秒关闭超时二者必须这样配套设置停机过程中 readiness 先摘除避免新流量进入正在关闭的 silo。滚动更新当集群无法承受失去一个就绪 silo 时保持maxUnavailable: 0并保留一定的 surge 容量maxSurge: 1。PodDisruptionBudgetminAvailable: 2保护的是自愿中断如节点维护驱逐不能保护节点故障。逐步缩容先确认成员关系稳定、剩余 silo 有容量再移除更多 Pod。更完整的升级与优雅停机流程参见 优雅停机与升级文档。Kubernetes 托管故障排查显式端点配置场景对比POD_NAME、POD_IP、ServiceId、ClusterId 与通告的成员端点是否一致——绝大多数连不上问题源于通告地址错误或集群标识不一致。可选托管包场景若报告缺少KUBERNETES_SERVICE_HOST或KUBERNETES_SERVICE_PORT确认进程确实运行在 Pod 内且服务环境链接service environment links未被禁用。若 API 返回403 Forbidden检查 Pod 的 Service Account、RoleBinding 的命名空间以及所需的 pod 动词get、list、watch、patch是否齐全。源码中KubernetesClusterAgent对Forbidden异常会记录包含示例 RoleBinding 的详细错误日志见 KubernetesClusterAgent.cs 的LogErrorInsufficientPermissions。更全面的排查参见 部署故障排查部署目标对比与共享的生产覆盖矩阵参见 选择部署目标。参考文件速查用途路径官方 Kubernetes 部署文档docs/site/src/content/docs/deployment/kubernetes.md配套代码片段DeploymentSnippets.cs可选托管包扩展方法KubernetesHostingExtensions.cs托管选项与环境变量常量KubernetesHostingOptions.cs选项注入与默认配置ConfigureKubernetesHostingOptions.cs成员对账与 Pod 监视代理KubernetesClusterAgent.cs选项校验KubernetesHostingOptionsValidator.cs健康与可观测性指导docs/site/src/content/docs/deployment/health-and-observability.md容器部署配置docs/site/src/content/docs/deployment/containers.mdAzure Kubernetes Service 专用指南docs/site/src/content/docs/deployment/azure-kubernetes-service.md赞分享后端微服务【免费下载链接】orleansCloud Native application framework for .NET项目地址https://gitcode.com/gh_mirrors/or/orleans点击查看免费下载相关推荐CloudNativePG Image Catalog 完全指南集中管理 PostgreSQL 镜像生命周期与自动滚动更新CloudNativePG Image Catalog 完全指南集中管理 PostgreSQL 镜像生命周期与自动滚动更新 ImageCatalog 与 Cl云原生数据库高可用灾备容器编排kOps 托管 Karpenter 实战指南在 AWS 上以 EC2NodeClass/NodePool 方式纳管节点生命周期kOps 托管 Karpenter 实战指南在 AWS 上以 EC2NodeClass/NodePool 方式纳管节点生命周期 Karpenter 是面向 K云原生集群管理运维IaC企业级IT资产全生命周期管理Snipe-IT系统实践指南企业级IT资产全生命周期管理Snipe IT系统实践指南 一、核心价值重新定义IT资产管理 1.1 企业级痛点解决方案 在传统IT资产管理中企业常面临资产后端企业应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表