容器编排中一个重要且复杂的方面是调度应用程序容器。如何将容器适当放置到可用的共享基础架构资源上,是在最佳计算资源使用情况下实现最大性能的关键所在。
Cattle 是 Rancher 1.6 的默认编排引擎,提供了各种调度功能来有效地放置服务:
https://rancher.com/docs/rancher/v1.6/en/cattle/scheduling/#scheduling-services
随着基于 Kubernetes 的 Rancher 2.0 版本的发布,Rancher 现在使用原生的 Kubernetes 调度。在本文中,我们将看看 Rancher 2.0 中可用的调度方法与 Cattle 的调度的比较。
节点调度
根据原生的 Kubernetes 行为,默认情况下,Rancher 2.0 工作负载中的 pod 将分布在可调度且具有足够可用容量的节点(主机)上。但就像 1.6 版本一样,Rancher 2.0 也有助于:
在特定节点上运行所有 pod
使用标签进行节点调度
以下是 1.6 UI 中的调度方式。Rancher 允许您在特定主机上运行所有容器,指定硬/软主机标签,或在部署服务时使用亲和性/反亲和性规则。
以下是 Rancher 2.0 中对应的节点调度 UI,它在部署工作负载时提供相同的功能。
Rancher 使用底层的原生 Kubernetes 构造来指定节点的亲和性/反亲和性。相应的 Kubernetes 的详细文档参考此处:
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
下面的示例中我们将来看看如何使用节点调度选项来调度工作负载 pod,然后看看 Kubernetes YAML 规范和 Rancher 1.6 Docker Compose 配置的对比。
示例:在特定节点上运行所有 Pod
在部署工作负载(导航到 Cluster> Project> Workloads)时,可以将工作负载中的所有 pod 调度到特定节点。
在这里,我使用特定节点上的 nginx 镜像部署 scale = 2 的工作负载。
如果某节点有足够的计算资源可用,Rancher 将选择该节点;如果使用 hostPort,则不会发生端口冲突。如果该工作负载使用与另一个工作负载冲突的 nodePort 来对外暴露,那么部署是可以成功创建的,但它不会创建 nodePort 服务。如此一来,工作负载则完全不会暴露了。
在 “工作负载/Workload” 选项卡上,您可以按节点列出工作负载。在此,我可以看到我的 Nginx 工作负载的两个 pod 都安排在指定的节点上了:
Kubernetes pod 规范中的调度规则如下所示:
示例:主机标签的亲和性/反亲和性
我在 Rancher 2.0 集群中向 node1 添加了标签 foo = bar,以测试基于标签的节点调度规则。
主机标签亲和性:硬
下图展示了如何在 Rancher 2.0 UI 中指定主机标签的亲和性规则。硬亲和性规则意味着所选主机必须满足所有调度规则。如果找不到此类主机,则工作负载将无法部署。
在 PodSpec YAML 中,此规则将转换为字段 nodeAffinity。另外请注意,我已经包含了 Rancher 1.6 docker-compose.yml 以使用标签实现相同的调度行为。
主机标签亲和性:软
如果您是 Rancher 1.6 用户,那么您一定知道软亲和性规则意味着调度程序会尝试按规则部署应用程序,但即使有主机不满足规则也可以成功部署。以下是如何在 Rancher 2.0 UI 中指定此规则:
pod 的相应 YAML 规范如下所示:
主机标签反亲和性
除了key = value
主机标签匹配规则外,Kubernetes 调度结构还支持以下运算符:
因此,要实现反亲和性,可以使用运算符NotIn
和DoesNotExist
作为节点标签。
Rancher 1.6 的其他调度功能
如果您是 Cattle 用户,想必您很熟悉 Rancher 1.6 中提供的一些其他调度功能:
选择使用容器标签的主机:
https://rancher.com/docs/rancher/v1.6/en/cattle/scheduling/#finding-hosts-with-container-labels
能够根据资源约束进行调度:
https://rancher.com/docs/rancher/v1.6/en/rancher-services/scheduler/#resource-constraints
能够仅在主机上调度特定服务:
https://rancher.com/docs/rancher/v1.6/en/rancher-services/scheduler/#restrict-services-on-host
如果您是在 Rancher 1.6 设置中使用这些功能,则可以使用原生的 Kubernetes 调度选项在 Rancher 2.0 中复制它们。在 Rancher v2.0.8 中,在部署工作负载时暂时没有对这些选项的 UI 支持,但您始终可以通过在 Rancher 集群上导入 Kubernetes YAML 规范来使用它们。
使用容器标签进行调度
Rancher 1.6 中的这一功能允许您将容器调度到具有特定标签的容器的主机。要在 Rancher 2.0 上执行此操作,请使用 Kubernetes inter-pod 亲和和反亲和功能:
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
如文档中所述,Kubernetes 允许您根据 pod 标签而不是节点标签来约束 pod 可以被调度到哪些节点。
Rancher 1.6 中最常用的调度功能之一是使用容器上的标签对服务本身进行反亲和。要在 Rancher 2.0 中复制此行为,我们可以在 Kubernetes YAML 规范中使用 pod 反亲和构造。例如,可以考虑使用 Nginx Web 工作负载。要确保此工作负载中的 pod 不在同一主机上,您可以使用podAntiAffinity
构造,如下所示。通过使用标签指定podAntiAffinity
,我们可以确保每个 Nginx 副本不在单个节点上共存。
使用 Rancher CLI,可以将此工作负载部署到 Kubernetes 集群上。请注意,上面的部署指定了三个副本,并且我在 Kubernetes 集群中有三个可调度节点。
由于指定了podAntiAffinity
,因此三个 pod 最终位于不同的节点上。为了进一步检查podAntiAffinity
的应用方式,我可以将部署扩展到四个 pod。请注意,由于调度程序无法找到满足podAntiAffinityrule
的另一个节点,因此无法调度第四个 pod。
基于资源的调度
在 Rancher 1.6 中创建服务时,可以在 UI 的“安全/主机”选项卡中指定内存预留和 mCPU 预留。Cattle 会将服务的容器安排到具有足够可用计算资源的主机上。
在 Rancher 2.0 中,您可以使用 pod 容器规范下的resources.requests.memory
和resources.requests.cpu
指定工作负载 pod 所需的内存和 CPU 资源。您可以在此处找到有关这些规范的更多详细信息:
指定这些资源请求时,Kubernetes 调度程序会将 pod 分配给具有足够容量的节点。
仅给主机调度特定服务
Rancher 1.6 能够在主机上指定容器标签,从而只将特定容器调度给它。
要在 Rancher 2.0 中实现此目的,可以在 pod 规范中使用相应的 Kubernetes 的“添加节点 taints(如主机标签)并使用容差”的功能:
https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
全局服务
在 Rancher 1.6 中,全局服务是指在环境中的每个主机上部署容器的服务:
https://rancher.com/docs/rancher/v1.6/en/cattle/scheduling/#global-service
如果服务的标签为io.rancher.scheduler.global:'true'
,则 Rancher 1.6 调度程序将在环境中的每个主机上调度服务容器。如文档中所述,如果将新主机添加到环境中,并且主机满足全局服务的主机要求,则 Rancher 将自动启动该服务。
下面的示例是 Rancher 1.6 中的全局服务示例。请注意,只需放置所需标签就足以使服务全局化。
我们如何使用 Kubernetes 在 Rancher 2.0 中部署全局服务?
为此,Rancher 为用户的工作负载部署了 Kubernetes DaemonSet 对象(https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)。DaemonSet 的功能与 Rancher 1.6 全局服务完全相同。Kubernetes 调度程序将在集群的每个节点上部署一个 pod,并且随着新节点的添加,调度程序将在它们上启动新的 pod,前提是它们与工作负载的调度要求相匹配。
此外,在 2.0 中,您还可以将 DaemonSet 限制为部署到具有特定标签的节点,具体可参考文档:
https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
使用 Rancher 2.0 UI 部署 DaemonSet
如果您是 Rancher 1.6 用户,要使用 UI 将全局服务迁移到 Rancher 2.0,请导航到 Cluster> Project> Workloads 视图。部署工作负载时,您可以选择以下工作负载类型:
这就是上面的 DaemonSetworkload 相应的 Kubernetes YAML 规范:
从 Docker Compose 到 Kubernetes YAML**
要使用 Compose 配置将 Rancher 1.6 全局服务迁移到 Rancher 2.0,请按照下列步骤操作。
您可以使用 Kompose 工具将 docker-compose.yml 文件从 Rancher 1.6 转换为 Kubernetes YAML,然后使用 Kubernetes 集群中的 Kubectl 客户端工具或 Rancher CLI 部署应用程序。
回头想想上面提到的 docker-compose.yml 规范,其中的 Nginx 服务就是全局服务。如下是使用 Kompose 将其转换为 Kubernetes YAML 的方法:
下面开始针对您的 Kubernetes 集群配置 Rancher CLI,并部署生成的* -daemonset.yaml
文件。
如上所示,我的 Kubernetes 集群有两个可以调度工作负载的工作节点,并且部署global-daemonset.yaml
为 Daemonset 启动了两个 pod,每个节点上有一个 pod。
总结
在本文中,我们回顾了如何将 Rancher 1.6 的各种调度功能迁移到 Rancher 2.0。大多数调度技术在 Rancher 2.0 中都有相同的选项,或者它们可以通过原生的 Kubernetes 结构实现。
评论