Kubernetes 中的基本部署单元是 Pod,它可能包含一个或多个作为逻辑实体(Logical Entity)打包和部署的容器。在 Kubernetes 中运行的云原生应用程序可能包含映射到每个微服务的多个 Pod。Pod 也是 Kubernetes 中的扩展单位。
本文将介绍 5 个最佳实践技巧帮助你在 Kubernetes 中更好地部署 Pod。即使有其他配置可以采用,但万变不离其宗,这 5 个技巧都是最基本最核心的操作。
1、 选择最合适的 Kubernetes Controller
虽然可能很像将容器镜像作为通用的 Pod 部署和运行,但是你需要根据工作负载的特性选择正确的 controller 类型。在 Kubernetes 中有一类称为 controller 的原语(Primitive),它需要与工作负载的关键特性兼容。Deployment、StatefulSet 和 DaemonSet 是 Kubernetes 中最常用的 Controller。
当部署无状态的 Pod 时,通常需要使用 deployment controller 。这一 controller 中的扩展、部署历史记录以及回滚功能使得 Pod 也具备类似 PaaS 的功能。当 Deployment 配置的最小副本数为 2 时,Kubernetes 能够确保始终至少有两个 Pod 处于运行状态,这使得容器具有容错能力。即使仅使用一个副本来部署 Pod,也强烈建议你使用 Deployment Controller,而不是普通的通用 Pod 规范。
对于诸如数据库集群等工作负载来说,StatefulSet controller 将创建一组具有可预测的命名规范的高可用 Pod。 需要高可用有状态的工作负载(如 Cassandra、Kafka、ZooKeeper 和 SQL Server)作为 StatefulSet 部署在 Kubernetes 中。
当你需要在集群的每个节点上运行一个 pod,你应该使用 DaemonSet controller。 由于 Kubernetes 会自动在新配置的 worker 节点中调度 DaemonSet,因此它是配置和准备工作负载节点的理想选择。举个例子,如果你想在部署工作负载之前在节点上挂载一个现有的 NFS 或 Gluster 共享文件,那么你需要打包并将 pod 部署为 DaemonSet。
因此,最后强调一下,在部署 Pod 之前确认你选择的是最合适的 controller 类型。
2、 为 Pod 配置健康检查
默认状态下,所有正在运行的 pod 都会一直启用重启策略,这意味着当容器遇到错误时,在节点内运行的 kubelet 将自动重启 Pod。
基于容器探针(Probe)的机制,kubelet 的健康检查功能大大增强。 可以为每个 Pod 配置 3 类探针——Readiness、liveness 以及 startup。
你可能会遇到 Pod 处于运行状态,但 ready 列显示 0/1 的情况。这表明 pod 没有准备好接收请求。而 readiness 探针可以确保在启动 pod 之前前期准备已经完成。 例如,服务于机器学习模型的 pod 需要在机器开始推理之前下载该模型的最新版本。Readiness 探针会在 pod 处于准备状态之前,不断检查文件是否存在。同样,CMS pod 中的 readiness 探针将确保已经安装好并能够访问到数据库。
Liveness 探针将会预先检查容器的健康状态并报告给 kubelet。 当健康检查失败,那么 pod 将不会接收流量。服务也会忽略该 pod,直到 liveness 探针检测到积极状态。例如,一个 MySQL pod 可能包含了一个不断检查数据库引擎状态的 liveness 探针。
以上健康检查可以使用命令、HTTP 探针以及 TCP 探针进行配置。
具体的配置步骤,请参阅 Kubernetes 官方文档:
3、 利用 Init 容器来准备 Pod
在几个场景中容器需要在处于准备状态之前初始化。可以将初始化操作移动到另一个容器中,以便在 Pod 处于准备状态之前进行一些基础工作。 Init 容器可用于下载文件、创建目录、更改文件权限等。
一个 init 容器甚至可以确保 pod 以特定的顺序启动。例如,在启动 WordPress pod 之前,Init 容器可以一直等待直到 MySQL Pod 可用。
一个 Pod 可能包含多个 init 容器,每个容器执行一个特定的初始化任务。
4、 应用 节点/Pod 亲和性和反亲和性规则
基于资源对 Pod 的需求情况以及集群中资源的消耗情况,Kubernetes scheduler 可以合理地将 pod 分配到相关地节点上。然而,这可能需要控制在节点上调度 Pod 的方式。Kubernetes 为此提供了两种机制—— 节点亲和性/反亲和性以及 pod 亲和性/反亲和性。
节点亲和性增强了本身已经十分强大的 nodeSelector 规则,以覆盖其他场景。就像 Kubernetes annotation 使 label/selector 更具表现力和可扩展性的方式一样,节点亲和性通过附加规则使 nodeSelector 更具表现力。 节点亲和性可以确保 pod 会被调度到符合特定条件的节点上。 例如,一个有状态的数据库 Pod 会被强制调度到已连接 SSD 的节点上。类似地,节点反亲和性可以避免将 Pod 调度到可能会引起问题的节点上。
尽管节点亲和性确实可以在 Pod 和节点之间进行匹配,但是在某些情况下,你可能需要将 pod 放在同一位置以提高性能或合规性。此时,Pod 亲和性规则就适时登场了。 Pod 亲和性可以帮助我们放置需要共享同一节点的 pod。 例如,Nginx web server pod 必须调度到和 Redis Pod 相同的节点上,因为这可以保证 web 应用程序和缓存之间的低延迟。在其他场景中,你可能想要避免在同一个节点上运行两个 pod,pod 反亲和性规则可以满足这一需求。当部署 HA 工作负载时,你可能不想在同一节点上运行同一个 Pod 的两个实例。Pod 反亲和性可以避免这一情况的发生。
分析你的工作负载,以评估是否需要在部署中使用节点和 pod 的亲和性策略。
5、 利用自动伸缩
诸如 Amazon Web Service、Microsoft Azure 和 Google Cloud Platform 之类的超大规模云平台都会具有内置的自动伸缩引擎,可以根据平均资源消耗或外部指标来扩展或缩小一组 VM。
Kubernetes 中有类似的自动弹性伸缩功能,譬如水平 Pod 自动伸缩(HPA)、垂直 Pod 自动伸缩(VPA)以及集群自动伸缩。
在 Replication controller、deployment、replica set 或 stateful set 中 HPA 会根据观察到的 CPU 使用情况自动缩放 pod 的数量 。在 Kubernetes 中 HPA 被表示为一个对象,这意味着可以通过 kubectl CLI 控制的 YAML 文件来对它进行声明。与 laaS 自动缩放引擎类似,HPA 支持定义 CPU 阈值、pod 的最小和最大实例、冷却时间甚至自定义指标。
VPA 消除了 pod 的 CPU 和内存配置的不确定性。 该自动缩放器能够为 CPU 和内存请求和限制推荐适当的值,或者能够自动更新这些值。Auto-update 的标志将决定是否驱逐现有的 pod 或者继续使用旧的配置运行。查询 VPA 对象将显示最合适的 CPU 和内存请求区间。
虽然 HPA 和 VPA 可以缩放 deployment 和 Pod,Cluster Autoscaler 也能扩展和缩小 worker 节点池的规模。它是一个独立工具,可以根据当前的使用率来调整 Kubernetes 集群大小。当由于资源不足而无法在任何当前节点上调度 Pod 时,或当添加新节点会增加集群资源的整体可用性时,Cluster Autoscaler 会增加集群的规模。在后台,Cluster Autosacler 与底层 laaS 进行协商以添加或删除节点。如果将 HPA 与 Cluster Autoscaler 结合使用,那么它们可以提高性能和工作负载的可用性。
评论