杏彩体育:不敢把数据库运行在 K8s 上?容器化对数据库性能

2024-03-12 08:34:03   来源:杏彩体育投注网 作者:杏彩体育投注网官网 1

  容器化是一种将应用程序及其依赖项打包到一个独立、可移植的运行环境中的技术。容器化技术通过使用容器...

  容器化是一种将应用程序及其依赖项打包到一个独立、可移植的运行环境中的技术。容器化技术通过使用容器运行时引擎(比如 Docker/Containerd)来创建、部署和管理容器。Kubernetes(通常简称为 K8s)是一个开源的容器编排和管理平台,它提供了一个集中式的、可伸缩的平台来自动化容器的部署、扩展、管理和调度。

  Fig. 1. Usage of containerized workloads by category [4]

  数据库容器化的趋势已经非常明显,如图.1 所示,数据库 + 分析类的 workload 已经占据了半壁江山,但是依然有很多人在做技术选型时面临一个难题:容器化是否对数据库性能有影响?如果有,影响的因素是什么?如何面对容器化带来的性能甚至是稳定性的问题?

  灵活性和可移植性:容器化技术提供了灵活性和可移植性的优势,使得数据库的部署和迁移变得更加简单和可靠。

  资源隔离和可扩展性:容器化技术通过使用容器运行时引擎提供了资源隔离和可扩展性的优势。每个容器都有自己的运行时环境和资源分配,因此数据库实例可以在容器中独立运行,相互之间影响降到最低。这种资源隔离使得数据库实例能够更好地利用计算资源,并提供更好的性能和可靠性。

  更友好的调度策略:由于容器化后的资源粒度更小,对上层调度更为友好,可以在不同场景应用不同的调度策略,比如通过离线和在线混合部署来错峰使用计算资源,通过提升部署密度来降低计算成本。

  说到容器,那就不得不提虚拟化,虚拟化是一种将计算资源进行抽象和隔离的技术,使得多个虚拟实例可以在同一物理服务器上同时运行。它通过在硬件和操作系统之间引入虚拟机监视器(Hypervisor)的软件层,将物理服务器分割为多个虚拟机,并为每个虚拟机提供独立的操作系统和资源。每个虚拟机都可以运行完整的操作系统,并具有独立的内核和资源,类似于在物理服务器上运行一个完整的计算机。

  容器化是一种更为轻量的虚拟化技术,它使用操作系统级别的虚拟化来隔离和运行应用程序及其依赖的环境。容器化和虚拟化一般搭配使用,以满足用户对不同隔离场景的需求。

  用户态内核容器,如 gVisor,也符合 OCI 规范,容器运行时为 runsc,有比较好的隔离性和安全性,但是性能比较差,适合比较轻量的 workload

  微内核容器,使用了 hypervisor,如 Firecracker、Kata-Container,也符合 OCI 规范,容器运行时为 runc 或 runv,有比较好的安全性和隔离性,性能介于标准容器和用户态内核容器之间

  纯虚拟机,如 KVM、Xen、VMWare,是主流云厂商服务器的底层虚拟化技术,一般作为 k8s 中的 Node 存在,比容器要更低一个层次

  runc 是一个符合 OCI 标准的容器运行时,它是 Docker/Containerd 核心容器引擎的一部分。它使用 Linux 的命名空间(Namespace)和控制组(Cgroup)技术来实现容器的隔离。

  在运行容器时,runc 使用命名空间隔离容器的进程、网络、文件系统和 IPC(进程间通信)。它还使用控制组来限制容器内进程的资源使用。这种隔离技术使得容器内的应用程序可以在一个相对独立的环境中运行,与宿主机和其他容器隔离开来。

  runc 的隔离技术虽然引入了一定开销,但是这种开销仅限于命名空间映射、限制检查和一些记账逻辑,理论上影响很小,而且当 syscall 是长耗时操作时,这种影响几乎可以忽略不计,一般情况下,基于 Namespace+Cgroup 的隔离技术对 CPU、内存、I/O 性能的影响较小。

  Kata Containers 是一个使用虚拟机技术实现的容器运行时,它提供了更高的隔离性和安全性。Kata Containers 使用了 Intel 的 Clear Containers 技术,并结合了轻量级虚拟机和容器运行时。

  Kata Containers 在每个容器内运行一个独立的虚拟机,每个虚拟机都有自己的内核和用户空间。这种虚拟化技术能够提供更严格的隔离,使得容器内的应用程序无法直接访问宿主机的资源。然而,由于引入了虚拟机的启动和管理开销,相对于传统的容器运行时,Kata Containers 在系统调用和 I/O 性能方面可能会有一些额外的开销。

  gVisor 是一个使用用户态虚拟化技术实现的容器运行时,它提供了更高的隔离性和安全性。gVisor 使用了自己的内核实现,在容器内部运行。

  gVisor 的内核实现,称为 Sandboxed Kernel,在容器内部提供对操作系统接口的模拟和管理。容器内的应用程序和进程与宿主内核隔离开来,无法直接访问或影响宿主内核的资源。这种隔离技术在提高安全性的同时,相对于传统的容器运行时,可能会引入一些额外的系统调用和 I/O 性能开销。

  Firecracker 是一种针对无服务器计算和轻量级工作负载设计的虚拟化技术。它使用了微虚拟化技术,将每个容器作为一个独立的虚拟机运行。

  Firecracker 使用 KVM(Kernel-based Virtual Machine)技术作为底层虚拟化技术。每个容器都在自己的虚拟机中运行,拥有独立的内核和根文件系统,并使用独立的虚拟设备模拟器与宿主机通信。这种隔离技术提供了较高的安全性和隔离性,但相对于传统的容器运行时,Firecracker 可能会引入更大的系统调用和 I/O 性能开销。

  还有人对 Container Engine 的不同实现做了对比,比如 Containerd 和 CRI-O [3][5],这个对比也不在本文讨论范围内,留给感兴趣的读者自己去了解。

  容器化对数据库有很多正面的影响:比如容器化可以简化数据库的部署和管理、为数据库提供标准的隔离运行环境、可以让数据库在不同的复杂环境中轻松部署和灵活迁移、对数据库的版本管理也更加规范和方便。而且在 k8s 的加持下,数据库中的多种角色和组件可以被灵活有机地编排在一起。

  但是,k8s+ 容器化对数据库也带来了很多挑战,这和数据库本身的特点也有很大关系,与普通的无状态应用相比,数据库有如下特点:

  数据库是一个有多种角色的复杂应用:一个完整的数据库有多种不同的角色,比如 MySQL 主备形态中,同样是两个 MySQL 容器,一个是主,一个是备,角色并不对等,这种不对等的关系需要被正确表达,而且在创建、重启、删除、备份、高可用等各种运维操作中都要被正确管理,本质上这是一种容器之间对于数据状态的互相依赖,对于这种依赖目前的容器和 k8s 都没有很好地抽象与解决。

  数据库对数据的持久性和一致性有很高的需求:数据库对存储有很高的需求,简单的容器化并不能满足一个生产级别的 workload,还需要配套的 CSI 和 PersistentVolume,对存储的选型也影响着数据库可选的操作选项,比如云盘有很高的 durability,提供 snapshot 备份功能,并能在不同的计算节点上 attach 和 detach,对数据库的备份恢复和高可用操作非常友好;但在本地盘上,这种选择就会更窄一些,比如 node 宕机时我们可能就会永远失去一个数据副本,高可用操作处理起来会更有挑战,备份操作也只能选择物理 / 文件(physical)备份或逻辑(logical)的方式。不同的存储方案对应着不同的持久化能力和不一样的数据库架构。

  数据库对性能也有很高的需求:数据库对性能的需求比较多样,如果从 CPU、内存、网络、存储这几个方面来进行划分,有 CPU + 存储 I/O 密集型,如 OLAP 产品 ClickHouse、Greenplum 等;有内存 + 网络 I/O 密集型,如 Redis 和内存数据库;有 CPU + 存储 I/O 密集型,如 MySQL、Postgresql 等传统 OLTP 数据库。而且根据查询场景不同,即使是同一个数据库进程在不同的 SQL 中对资源的需求也大相径庭。

  数据库对安全性的要求:数据库中的数据一般都比较核心和敏感,因此对运行环境隔离、数据访问控制、日志审计都有一定的规范化要求。

  总而言之,将数据库跑在容器 +k8s 上,对数据库是一种很大的挑战,比如数据库要去适应生命周期短暂的容器、浮动的 IP、频繁更新的基础设置、复杂的性能环境;对容器 +k8s 也是很大的挑。