1 背景
随手记,测试环境资源不足,一台服务器有多个服务,存在以下问题:
- 服务输出过多日志,写满磁盘,导致整个环境不可用
- 服务使用直接内存,占用内存导致 load、swap 飙升
- 服务密集使用CPU,时间分片短,CPU压力大
2 资源隔离
虚拟机也可以限制 cpu、memory、disk 的使用,但要在 host os 的基础上运行一个 guest os,资源消耗较大,所以选取了更轻量的 docker 容器。
3 容器编排
虚拟机的运维可以使用 Ansible,容器的运维则需要容器编排平台,有3个基本要求:
- 调度。选择出最合适的宿主机,并启动容器
- 故障转移。通过存活探针对容器健康检查,并适时重启、再调度
- 水平伸缩。容器算力不够时自动扩容
此外,编排平台还可以支持服务发现、负载均衡等功能。
前期容器化的服务不多,我们使用 swarm 做容器编排。但服务多起来后,出现调度失败,负载均衡跟不上再调度等情况。
swarm 集群单个 leader,这就决定它无法横向扩展,如果开启负载均衡,那么 leader 的单点问题会更突出。
我们需要能在生产运行的容器编排平台,这里综合比对 Kubernetes 和 mesos。
3.1 集群规模
kubernetes 是面向容器的编排工具,帮助淘宝在 2017 年管理近 8000个节点。
mesos 是面向资源的调度平台,帮助 twitter 管理上万个节点。
随手记线上机器规模在 500 台左右,两者都可以考虑。
3.2 维护成本
mesos 只关心资源,应用层通过 framework 实现。
我们几乎所有容器都运行长期伺服型应用,除了安装 marathon,还要安装 marthon-lb 实现负载均衡,安装 mesos-dns 实现服务发现。
痛点是技术栈混杂,其中 marthon 用 c++ 实现,marthon-lb 用 scala 使用,mesos-dns 用 python 实现,难以维护。
kubernetes 从调度器 Scheduler,到插件 CSI、CNI,甚至底层数据库 etcd 都是 go 实现,对随手记这种规模的公司更加友好。
3.3 健康检查
mesos 初衷是建立一个大数据场景下的资源共享池,没有考虑对容器的支持,后天弥补的健康检查有性能缺陷。
健康检查由 marthon 实现,有两个痛点:
- 检测进程、应用进程不在同一主机,带来额外的网络负担,并且不稳定的网络也会导致错误的检查结果
- marthon 的首要任务是调度,同时做健康检查可能引起过高的IO负载
kubernetes 在每一个节点有一个 kube-proxy 进程,负责对同主机的应用进程做健康检查,并上报到 kube-api,设计精良。
3.3 网络
mesos 提供主机模式、桥接模式。主机模式下的端口由容器使用,可能会导致端口冲突。桥接模式下,容器端口使用端口映射桥接到动态分配的主机端口。
kubernetes 开放 CNI 网络插件,使用 veth pair 实现内部网络,也支持通过外部网络暴露服务。
网络方面,二者功能相当,均可考虑。
3.4 存储
masos + marthon 提供本地存储、外部存储。
kubernetes 开放 CSI 存储插件,同时抽出 PV、PVC,方便开发、运维工作分离。
随手记有部分业务读写文件系统,如果没有外部存储,再调度后去到别的节点,就看不到上次生成的文件。
由于 marthon 的外部存储是 beta 特性,因此考虑 kubernetes。
3.5 调度逻辑
亲密关系调度
要把两个容器调度在同一个宿主机。超亲密关系调度
要让两个容器共享同一个 namespace(网络、存储)。
假设容器A申请1G内存,容器B申请0.5G内存,现在要统一调度它们:
- mesos 悲观调度,也就是资源囤积,当所有设置了 Affinity 约束的任务都达到时,才开始统一调度。调度效率低,并存在死锁问题
- borg 乐观调度,先调度,不满足了再回滚。调度效率高
- kubernetes 原子调度,将两个容器需要的资源捆绑在一起申请。调度效率、资源利用率平衡
3.6 社区活跃度
关注度 mesos 4.6k,kubernetes 71.3k
参与度 mesos 17,kubernetes 865
issue mesos 0,kubernetes 2k
综上,kubernetes 在技术、生态层面比 mesos 都领先,所以选择 kubernetes。