云原生在京东丨如何在 Kubernetes 上部署有状态的云原生应用?(上)
云妹导读:
Kubernetes 是云计算历史上增长最快的基础设施项目之一。在短短的五年内,它已经达到了现代基础设施的成熟水平。从公有云中的托管容器即服务(CaaS)到数据中心中的平台即服务(PaaS)再到边缘计算,Kubernetes 已经无处不在。
Kubernetes 的出现使得广大开发同学也能运维复杂的分布式系统,它大幅降低了容器化应用部署的门槛,用户通过它提供的 Deployment、ReplicaSet 控制器可以方便地部署一套高可用、可扩展的分布式无状态服务,这类应用的特点是不在本地存储数据,通过简单的负载均衡策略可实现请求分发。但是越来越多的开发人员希望把项目中依赖的数据库这类有状态服务也部署到Kubernetes里面,通过其进行编排部署,使应用与所依赖的后端存储尽量靠近一些,因为有状态服务的复杂性,这一过程并不容易。
在 Kubernetes 中有多种运行有状态应用程序的技术,每种技术各有优缺点。本文试图介绍在 Kubernetes 中运行有状态应用程序的关键方法,并探讨了在 Kubernetes 上部署有状态的服务的几种可行方案。
第一种方法是将 Kubernetes 集群与 Samba、NFS 或 GlusterFS 等传统的存储基础设施集成在一起,这种方法可以轻松扩展到基于云的共享文件系统,例如 Amazon EFS、Azure 文件和 Google Cloud Filestore,在这种架构中,存储层与 Kubernetes 管理的计算层完全脱钩。由于底层存储的持久性,工作负载完全与其分离,这使得 Pod 可以在任何节点上进行调度,而无需定义节点亲和性。
但是,这种方法对于需要高 I/O 吞吐量的有状态工作负载并不理想。共享文件系统并非旨在提供关系型数据、NoSQL 数据库和其他写入密集型工作负载所需的 IOPS。此方法的典型应用场景应该是内容管理系统,机器学习系统和数字资产管理系统等。
Kubernetes 中引入 StatefulSet 控制器来运行有状态的集群工作负载,保证属于 StatefulSet 的 Pod 具有稳定的唯一标识符,它们遵循可预测的命名约定,还支持有序、便捷的部署和扩展。StatefulSet 中的每个 Pod 都有一个对应的持久卷声明(PVC),该声明遵循相似的命名约定。当 Pod 终止并在其他节点上重新调度时,Kubernetes 控制器将确保 Pod 与同一 PVC 关联,以此来保证集群的状态。
由于 StatefulSet 中的每个 Pod 都有专用的 PVC 和 PV,因此使用共享存储没有特别的规定。但是可以预期 StatefulSet 能获得快速、可靠、持久的存储层(例如基于 SSD 的块存储设备)的支持,在确保将写操作完全提交到磁盘后,可以从块存储设备中获取常规备份和快照。典型的应用场景如 Apache ZooKeeper,Apache Kafka,MySQL,PostgreSQL 等。
虽然用户可以基于 StatefulSet 在 Kubernetes 中部署运维一套高可用有状态服务,如高 MySQL,PostgreSQL 等。但过程相对复杂,用户既要熟悉各种 Kubernetes 资源对象,又要学习很多应用相关的操作细节,同时还需维护一套复杂的管理脚本,为了降低在 Kubernetes 中部署复杂应用的门槛 CoreOS 公司推出了 Operator。
Operator 是用来打包、部署和管理需要运行在 Kubernetes 之上复杂应用的一种方法,Operator将运维人员对软件操作的知识代码化,同时综合运用 Kubernetes 中的各种资源对象来实现复杂应用的部署和运维。Operator 通过 CustomResourceDefinition(CRD)为服务定义了新的资源对象,同时通过自定义控制器来保证应用处于预期状态。
Operator 的工作流程可抽象成以下三个步骤:
Observe - 通过 Kubernetes API 观察目标对象的状态;
Analyze - 分析当前状态与期望状态的差别;
Act - 执行编排操作,将当前状态调整为期望状。
由于开源社区的推进,Operator 越来越普及。但是应用于各种常规服务的 Operator 成熟度各不相同,具体细节请参考 github 开源项目 awesome-operators。Operator 典型的应用场景有 MySQL 高可用集群、TiDB 集群、 TensorFlow 集群、Hadoop 生态相关集群等。
预告
下一篇我们将以最先进的开源数据库 PostgreSQL 为例,介绍如何在 Kubernetes 上部署运维有状态云服务,敬请期待!