# 在 Kubernetes 上运行“别人的”应用

在帮助企业进行基于私有环境的云原生转型的过程中，帮客户把存量应用迁移到 Kubenrnetes 上，是个常规任务。通常说来，在解决了初步的技术可行性之后，接下来要解决的就是资源分配的问题，我们已经讨论过，在近乎同样的资源总量情况下，[少量大节点构成的集群和大量小节点构成的集群的一些差异](https://blog.fleeto.us/post/someting-about-cluster-size/)，然而这里还是缺少一个完整的方法——如何把现有应用的需求转换为资源设计呢？

## 调研

要为应用分配资源，首先要明确资源所包含的项目，除了显而易见的 CPU 和内存之外，往往还会包含一些因地制宜的项目，例如：

- 每节点 Pod 数量上限：例如 Kubernetes 缺省限制为 110，而在新面世的 AutoPilot 中，缺省上限就只有 32 个了。
- Pod IP：有些环境中，Pod 会具有神奇的直通 IP，这些 IP 通常是用 IP 池的方式进行管理的，这也是一个受限资源。
- GPU：GPU 这种高价资源，自然是受限的，并且不同驱动方式的用法也有不同，例如 TKEStack 的 [GPU Manager](https://github.com/tkestack/gpu-manager) 能够用千分之一为单位进行分配。
- 存储：原本运行在虚拟机上的应用可能会使用一定量的存储，在这里需要对其用法进行正确的区分，按需转换为使用临时存储、本地存储、分布式（块/文件）存储。
- 对集群外提供的服务：所需的域名和转换规则等。
- ...

在把各种资源分门别类都罗列清楚之后，就可以给业主方设计一份应用资源问卷了，其中应包含如下要素：

- 工作负载类型：普通服务应用、批处理、定时任务等。
- 资源需求：应用属主需填写自己每个应用下，每个组件的的副本数量、资源用量上下限；如果存在 HPA 需求，应该了解伸缩的上下限。
- 权限需求：对于内核能力、root 用户等的特殊要求，如无要求，通常设置为非 root 访问的非特权模式。
- 注明对内对外的依赖关系：用于后续的网络策略设计。

> 这里对资源需求部分还有一个需要注意的点就是 Sidecar 以及一些“隐藏”进程，例如监控 Agent 等，这些东西同样会占用系统资源，有时用量还比较大，并且这些进程是随着应用组件实例进行伸缩的，因此其资源需求应该并入到所在的主要进程。

实践过程中，这个步骤会占用相当多的时间，在独占虚拟机/物理机运行时，很多业务方其实并不清楚应用的具体资源需求，是否能够构建镜像、是否能够在 Kubernetes 中运行也都是未知数，因此在调研过程中可能需要进行更多的沟通和培训工作。关于应用自身对 Kubernetes 的适应性，我通常会有几个简单的问题：

- 能够多副本运行么？
- 需要用 Root 身份启动么？
- 能够随意重启么？
- 能够自动水平扩容么？
- 重新部署的标准步骤是怎样的？
- 日志和临时存储的用法和用量？
- 镜像尺寸。
- 更新频率和方法。
- 健康和存活检测的方法。

这些问题本身的答案并不重要，重要的是能够提醒对方，对于自身应用行为应该有一个深入且诚实的了解。

## 规划

在得到调研结果之后，就可以据此进行设计了。除了调研结果中的几个变量之外，Kubernetes 的实施过程中还包含些隐含的约束条件，这些约束条件一方面限制了对于集群的设计规模，另一方面也能够辅助我们对集群进行资源配置。

- 节点数量：通常我们会使用 3 Master 的结构设计集群，如果 3 个控制节点如果只有 2 个计算节点，可能会显得非常古怪，因此通常计算节点都应该数倍于管理节点的数量。
- Pod 数量：一个生产环境中的计算节点，即使在空载环境下，也会运行一些系统需要的 Daemonset，例如常见的 kube-proxy、node-exporter，所以在一个计算节点上的业务容器数量和资源，至少也不应该少于这些常驻 Pod 的数量。
- 资源冗余：节点容量通常应该是总量-系统占用-保留量，分配到每个节点上容器（包括业务、系统）的资源 Request 和 Limit 总和，不应超出节点容量。
- 空余节点：部署应用后，集群所有容器容量上限和集群业务节点总容量的差，最少应该大于集群中的最大计算节点的容量，以此保证在遭遇节点故障时可以有一个基本的容错能力。
- 服务疏散：一般来说，我们会建议多副本服务平均分散在多个节点之中，因此节点数量不应少于任何服务的副本数量。
- 节点疏散：在使用虚拟机作为节点时时，建议分布到不同的物理机上，避免因为物理节点故障导致大范围容器节点问题。

在有了这一系列的文档之后，基本上是可以设计出来一个有理有据的合适规模的集群的。

## 实施和反馈

在应用成功在集群上试运行成功之后，应该有一段重点观察期，我们可以用 Prometheus 对新晋应用进行监控，有几个指标需要重点关注：

- 容器的重启动次数：应用的最基本存活状况，如果应用发生频繁重启，应该进行有针对性的分析。
- 应用运行时，各项资源消耗的平均值、中位数、最大值等，将其和应用申请资源的最小和最大值进行比较，以此评估应用的实际资源需求并作出整改。
- 集群总体资源的消耗和空闲量，以此来评估节点的总体资源使用情况。
- 存储占用量的监控：防止因为存储溢出造成意外损失。
- 工作副本设计数和实际数的差：不为 0 的情况需要针对性调查。

## 补充

这里提到的内容都是非常基础的内容，针对的也是基础的业务应用容器化转型工作。相信在实际工作中，还会有更多的资源考量、监控指标以及非功能性限制加入到这个设计过程中，帮助读者更好地进行集群规模的设计。
