Kubernetes 中的升级和故障域
Upgrade and Failure Domains in Kubernetes
背景
我曾计划使用 Service Fabric(本地)来进行服务和容器编排。但是,由于内部讨论,我正在考虑 Kubernetes。主要是因为太受欢迎了。
Service Fabric 有称为升级域和故障域的概念。 “域”是一组主机节点。
升级域用于推出应用程序服务或容器更新。 Service Fabric 通过一次仅关闭一个升级域来确保升级 service/container 仍然可用。 (更新 Service Fabric 群集软件本身时也会使用这些。)
故障域以类似的方式工作。这个想法是,故障域是根据硬件故障组创建的。 Service Fabric 确保每个故障域中有 service/container 个实例 运行。 (以便在硬件故障期间留出正常运行时间。)
问题
当我在 Kubernetes 上查看文档和收听播客时,我没有看到任何这些概念。它似乎只是托管容器 (Pods)。我听说过一些关于“调度”和“标签”的内容。不过貌似只能手动配置pods.
Kubernetes 中的应用程序升级和容错是手动完成的吗? (也许通过调度 and/or 标签)
或者我缺少某个功能?
进程健康检查
最简单的健康检查形式就是进程级健康检查。 Kubelet不断询问Docker守护进程容器进程是否还在运行ning,如果不是,则重启容器进程。到目前为止,在您拥有 运行 的所有 Kubernetes 示例中,此健康检查实际上已经启用。它适用于 Kubernetes运行 中的每个容器
Kubernetes 支持用户实现的应用程序健康检查。这些检查由 Kubelet 执行,以确保您的应用程序根据您提供的“正确”定义正确运行。
目前,您可以选择三种类型的应用程序健康检查:
- HTTP 健康检查 - Kubelet 将调用网络挂钩。如果returns在200到399之间,则认为成功,否则失败。请在此处查看健康检查示例。
- Container Exec - Kubelet 将在您的容器内执行命令。如果它以状态 0 退出,则将被视为成功。请在此处查看健康检查示例。
TCP 套接字 - Kubelet 将尝试打开容器的套接字。如果它可以建立连接,则容器被认为是健康的,如果不能,则被认为是失败的。
在所有情况下,如果 Kubelet 发现故障,容器将重新启动。
- 节点健康检查
如果 [节点的] 就绪条件的状态为“未知”或“假”的时间超过 pod-eviction-timeout,则将参数传递给 kube-controller-manager 和所有节点上的 Pods 计划由节点控制器删除。默认的逐出超时持续时间为五分钟。在某些情况下,当节点无法访问时,apiserver 无法与其上的 kubelet 通信。删除 pods 的决定无法传达给 kubelet,直到它重新建立与 apiserver 的通信。与此同时,计划删除的 pods 可能会在分区节点
上继续 运行
- 应用升级
用户期望应用程序始终可用,开发人员期望每天多次部署它们的新版本。在 Kubernetes 中,这是通过滚动更新完成的。滚动更新允许部署的更新通过使用新实例增量更新 Pods 个实例来实现零停机时间。新的 Pods 将被安排在具有可用资源的节点上。
这些抽象目前在 kubernetes 中不存在,尽管通常可以以自动化方式实现所需的行为。
kubernetes 的元模型涉及代理(称为控制器和操作员)持续观察集群上的事件和配置,并逐渐协调集群状态与控制器的声明性配置。托管 Pods 的节点突然丢失将导致与丢失的 Pods 相对应的 IP 从那些 Pods 在其他节点上启动新版本的服务和 ReplicationControllers 中删除,否则确保满足协同和反调度约束。
同样,应用程序升级通常通过更改 Deployment 进行,这会导致新的 Pods 被安排,旧的 Pods 以自动、渐进的方式被取消安排。
CustomResourceDefinitions 现在可以使用自定义声明配置,因此该模型是可扩展的。底层原语和机制供某人引入顶级声明性抽象,如 FailureDomains 和 UpgradeDomains,由自定义 Operators 管理。
kube 生态系统如此庞大且发展如此迅速,因此很可能会出现这样的东西,并且也可能会遇到竞争对手的概念。
考虑采用 Kubernetes 的工厂所有者的底线是,Kubernetes 实际上仍然是工具匠的世界。有大量的工具,以及同样大量的未完成产品。
A "domain" is a grouping of host nodes.
没那么简单,你说"A 'domain' is a logical grouping of resources"就更准确了。
要正确理解它,您必须首先孤立地理解大多数组件。我首先推荐这些读物:
那么,我们可以从中抽取几点:
节点不是虚拟机,节点运行在 azure 虚拟机之上。
他们通常有一个1:1映射,但在某些情况下你可以有5:1node/VM映射,一个例子是当你安装本地开发集群时.
Azure 虚拟机具有更新域和故障域,服务结构节点具有升级域和故障域
尽管它们看起来一样,但它们有不同之处:
故障域:
- VM Fault Domains 是用于物理部署的隔离插槽,这意味着:电源、网络、磁盘等...它们受区域限制。
- SF Fault Domains是应用程序部署的逻辑节点槽,也就是说,当SF将一个应用程序部署到节点时,它会分布在不同的故障域上,以使其可靠,大多数时候FD会映射到VM Fault域,但是在复杂的场景下,你可以把它映射到任何东西,比如你可以将整个区域映射到一个SF FD。
.
Update\Upgrade 域:
- VM 更新域是关于 OS\Hardware 补丁和更新,单独的更新域将被隔离处理并且不会同时更新,因此,当需要 OS 更新时带来关闭您的虚拟机,他们将逐域更新。更新域的数量越少意味着更新期间将放下更多的机器。
- SF 升级域使用与 VM 更新域类似的方法,但专注于服务和集群自身升级,一次降低每个 UD,并在前一个 UD 成功时移动到下一个。
- 在这两种情况下,您都将 Update\Upgrade 调整为在升级过程中可以放下 vm\nodes\services 的实例数 (%)。因此,例如,如果您的服务在具有 5 个 UD 的集群上有 100 个实例,则 SF 将一次更新 20 个服务,如果您将 UD 的数量增加到 10 个,例如,下降的实例数将减少到 10 个实例,但部署应用程序的时间将按相同比例增加。
基于此,您可以将 FD 和 UP 视为可靠部署槽的矩阵,拥有多少,可靠性就会增加多少(权衡取舍,例如所需的更新时间)。以下示例取自 SF 文档:
Service Fabric,开箱即用会尽力将您的服务实例放在不同的 FD\UD 上,这意味着,如果可能的话,它们将位于不同的 FD\UD 上,否则它会找到另一个部署的服务实例数量最少。
关于 Kubernetes:
在Kubernetes上,这些特性并不是开箱即用的,k8s有zones的概念,但是根据文档,它们是受地区限制的,不能跨地区。
Kubernetes will automatically spread the pods in a replication controller or service across nodes in a single-zone cluster (to reduce the impact of failures). With multiple-zone clusters, this spreading behaviour is extended across zones (to reduce the impact of zone failures). This is achieved via SelectorSpreadPriority.
This is a best-effort placement, and so if the zones in your cluster are heterogeneous (e.g. different numbers of nodes, different types of nodes, or different pod resource requirements), this might prevent equal spreading of your pods across zones. If desired, you can use homogenous zones (same number and types of nodes) to reduce the probability of unequal spreading.
与 FD 不同,但概念非常相似。
要获得与 SF 类似的结果,需要跨区域部署集群或将节点映射到 VM FD\UD,以便它们作为 SF 上的节点。将标签添加到节点以识别这些域。您还需要在不同 FD 上的节点上创建 NodeType 标签,以便您可以用于在分隔节点上部署 pods。
例如:
- Node01: FD01: NodeType=FrontEnd
- Node02: FD02: NodeType=FrontEnd
- Node03: FD03 : NodeType=FrontEnd
- Node04:FD01:NodeType=后端
- Node05:FD02:NodeType=后端
部署应用程序时,您应该使用 affinity 功能将 PODs 分配给节点,在这种情况下,您的服务将具有:
- 需要 到 NodeType=FrontEnd
- 首选 AntiAfinity 到 ContainerName=[itself]
使用这些设置,亲和性和反亲和性 k8s 的使用将尝试将容器的 replicas\instances 放置在单独的节点上,并且节点已经由 FD\zone 分隔,由 FD\zone 分隔NoteType 标签,然后 k8s 将像 SF 一样处理滚动更新。
因为首选反亲和性规则,k8s 将尽力平衡这些节点,如果没有可用的有效节点,它将开始在已经包含同一容器实例的节点上添加更多实例,
结论
这是一些额外的工作,但与当前在其他解决方案上使用的内容没有太大区别。
这里主要关心的是在 FD\Zones 上配置节点,将节点放在正确的 FD 上后,其余部分将顺利运行。
在 SF 上,你在 Azure 上部署集群时不必担心这个,但如果你从头开始,这是一项艰巨的工作,甚至比 k8s 还要大。
注意:如果您使用 AKS, it will distribute the nodes across availability sets (set which specifies VM fault domains and update domains). Currently, according to this post,AKS 不会为您提供区域分布,因此如果您需要此级别的分布,则必须从头开始。
背景
我曾计划使用 Service Fabric(本地)来进行服务和容器编排。但是,由于内部讨论,我正在考虑 Kubernetes。主要是因为太受欢迎了。
Service Fabric 有称为升级域和故障域的概念。 “域”是一组主机节点。
升级域用于推出应用程序服务或容器更新。 Service Fabric 通过一次仅关闭一个升级域来确保升级 service/container 仍然可用。 (更新 Service Fabric 群集软件本身时也会使用这些。)
故障域以类似的方式工作。这个想法是,故障域是根据硬件故障组创建的。 Service Fabric 确保每个故障域中有 service/container 个实例 运行。 (以便在硬件故障期间留出正常运行时间。)
问题
当我在 Kubernetes 上查看文档和收听播客时,我没有看到任何这些概念。它似乎只是托管容器 (Pods)。我听说过一些关于“调度”和“标签”的内容。不过貌似只能手动配置pods.
Kubernetes 中的应用程序升级和容错是手动完成的吗? (也许通过调度 and/or 标签)
或者我缺少某个功能?
进程健康检查 最简单的健康检查形式就是进程级健康检查。 Kubelet不断询问Docker守护进程容器进程是否还在运行ning,如果不是,则重启容器进程。到目前为止,在您拥有 运行 的所有 Kubernetes 示例中,此健康检查实际上已经启用。它适用于 Kubernetes运行 中的每个容器
Kubernetes 支持用户实现的应用程序健康检查。这些检查由 Kubelet 执行,以确保您的应用程序根据您提供的“正确”定义正确运行。
目前,您可以选择三种类型的应用程序健康检查:
- HTTP 健康检查 - Kubelet 将调用网络挂钩。如果returns在200到399之间,则认为成功,否则失败。请在此处查看健康检查示例。
- Container Exec - Kubelet 将在您的容器内执行命令。如果它以状态 0 退出,则将被视为成功。请在此处查看健康检查示例。
TCP 套接字 - Kubelet 将尝试打开容器的套接字。如果它可以建立连接,则容器被认为是健康的,如果不能,则被认为是失败的。 在所有情况下,如果 Kubelet 发现故障,容器将重新启动。
- 节点健康检查
如果 [节点的] 就绪条件的状态为“未知”或“假”的时间超过 pod-eviction-timeout,则将参数传递给 kube-controller-manager 和所有节点上的 Pods 计划由节点控制器删除。默认的逐出超时持续时间为五分钟。在某些情况下,当节点无法访问时,apiserver 无法与其上的 kubelet 通信。删除 pods 的决定无法传达给 kubelet,直到它重新建立与 apiserver 的通信。与此同时,计划删除的 pods 可能会在分区节点
上继续 运行- 应用升级
用户期望应用程序始终可用,开发人员期望每天多次部署它们的新版本。在 Kubernetes 中,这是通过滚动更新完成的。滚动更新允许部署的更新通过使用新实例增量更新 Pods 个实例来实现零停机时间。新的 Pods 将被安排在具有可用资源的节点上。
这些抽象目前在 kubernetes 中不存在,尽管通常可以以自动化方式实现所需的行为。
kubernetes 的元模型涉及代理(称为控制器和操作员)持续观察集群上的事件和配置,并逐渐协调集群状态与控制器的声明性配置。托管 Pods 的节点突然丢失将导致与丢失的 Pods 相对应的 IP 从那些 Pods 在其他节点上启动新版本的服务和 ReplicationControllers 中删除,否则确保满足协同和反调度约束。
同样,应用程序升级通常通过更改 Deployment 进行,这会导致新的 Pods 被安排,旧的 Pods 以自动、渐进的方式被取消安排。
CustomResourceDefinitions 现在可以使用自定义声明配置,因此该模型是可扩展的。底层原语和机制供某人引入顶级声明性抽象,如 FailureDomains 和 UpgradeDomains,由自定义 Operators 管理。
kube 生态系统如此庞大且发展如此迅速,因此很可能会出现这样的东西,并且也可能会遇到竞争对手的概念。
考虑采用 Kubernetes 的工厂所有者的底线是,Kubernetes 实际上仍然是工具匠的世界。有大量的工具,以及同样大量的未完成产品。
A "domain" is a grouping of host nodes.
没那么简单,你说"A 'domain' is a logical grouping of resources"就更准确了。
要正确理解它,您必须首先孤立地理解大多数组件。我首先推荐这些读物:
那么,我们可以从中抽取几点:
节点不是虚拟机,节点运行在 azure 虚拟机之上。
他们通常有一个1:1映射,但在某些情况下你可以有5:1node/VM映射,一个例子是当你安装本地开发集群时.
Azure 虚拟机具有更新域和故障域,服务结构节点具有升级域和故障域
尽管它们看起来一样,但它们有不同之处:
故障域:
- VM Fault Domains 是用于物理部署的隔离插槽,这意味着:电源、网络、磁盘等...它们受区域限制。
- SF Fault Domains是应用程序部署的逻辑节点槽,也就是说,当SF将一个应用程序部署到节点时,它会分布在不同的故障域上,以使其可靠,大多数时候FD会映射到VM Fault域,但是在复杂的场景下,你可以把它映射到任何东西,比如你可以将整个区域映射到一个SF FD。
.
Update\Upgrade 域:
- VM 更新域是关于 OS\Hardware 补丁和更新,单独的更新域将被隔离处理并且不会同时更新,因此,当需要 OS 更新时带来关闭您的虚拟机,他们将逐域更新。更新域的数量越少意味着更新期间将放下更多的机器。
- SF 升级域使用与 VM 更新域类似的方法,但专注于服务和集群自身升级,一次降低每个 UD,并在前一个 UD 成功时移动到下一个。
- 在这两种情况下,您都将 Update\Upgrade 调整为在升级过程中可以放下 vm\nodes\services 的实例数 (%)。因此,例如,如果您的服务在具有 5 个 UD 的集群上有 100 个实例,则 SF 将一次更新 20 个服务,如果您将 UD 的数量增加到 10 个,例如,下降的实例数将减少到 10 个实例,但部署应用程序的时间将按相同比例增加。
基于此,您可以将 FD 和 UP 视为可靠部署槽的矩阵,拥有多少,可靠性就会增加多少(权衡取舍,例如所需的更新时间)。以下示例取自 SF 文档:
Service Fabric,开箱即用会尽力将您的服务实例放在不同的 FD\UD 上,这意味着,如果可能的话,它们将位于不同的 FD\UD 上,否则它会找到另一个部署的服务实例数量最少。
关于 Kubernetes:
在Kubernetes上,这些特性并不是开箱即用的,k8s有zones的概念,但是根据文档,它们是受地区限制的,不能跨地区。
Kubernetes will automatically spread the pods in a replication controller or service across nodes in a single-zone cluster (to reduce the impact of failures). With multiple-zone clusters, this spreading behaviour is extended across zones (to reduce the impact of zone failures). This is achieved via SelectorSpreadPriority.
This is a best-effort placement, and so if the zones in your cluster are heterogeneous (e.g. different numbers of nodes, different types of nodes, or different pod resource requirements), this might prevent equal spreading of your pods across zones. If desired, you can use homogenous zones (same number and types of nodes) to reduce the probability of unequal spreading.
与 FD 不同,但概念非常相似。
要获得与 SF 类似的结果,需要跨区域部署集群或将节点映射到 VM FD\UD,以便它们作为 SF 上的节点。将标签添加到节点以识别这些域。您还需要在不同 FD 上的节点上创建 NodeType 标签,以便您可以用于在分隔节点上部署 pods。
例如:
- Node01: FD01: NodeType=FrontEnd
- Node02: FD02: NodeType=FrontEnd
- Node03: FD03 : NodeType=FrontEnd
- Node04:FD01:NodeType=后端
- Node05:FD02:NodeType=后端
部署应用程序时,您应该使用 affinity 功能将 PODs 分配给节点,在这种情况下,您的服务将具有:
- 需要 到 NodeType=FrontEnd
- 首选 AntiAfinity 到 ContainerName=[itself]
使用这些设置,亲和性和反亲和性 k8s 的使用将尝试将容器的 replicas\instances 放置在单独的节点上,并且节点已经由 FD\zone 分隔,由 FD\zone 分隔NoteType 标签,然后 k8s 将像 SF 一样处理滚动更新。
因为首选反亲和性规则,k8s 将尽力平衡这些节点,如果没有可用的有效节点,它将开始在已经包含同一容器实例的节点上添加更多实例,
结论
这是一些额外的工作,但与当前在其他解决方案上使用的内容没有太大区别。 这里主要关心的是在 FD\Zones 上配置节点,将节点放在正确的 FD 上后,其余部分将顺利运行。
在 SF 上,你在 Azure 上部署集群时不必担心这个,但如果你从头开始,这是一项艰巨的工作,甚至比 k8s 还要大。
注意:如果您使用 AKS, it will distribute the nodes across availability sets (set which specifies VM fault domains and update domains). Currently, according to this post,AKS 不会为您提供区域分布,因此如果您需要此级别的分布,则必须从头开始。