购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.7 部署简单的有状态数据库

虽然从概念上来说,部署有状态的应用和部署前端这样的客户端应用并无二致,但是应用程序的状态让部署变得更加复杂。首先,在Kubernetes中,Pod可能由于各种原因被重新调度,例如节点的健康状态、系统升级或者节点之间重新平衡。一旦发生上述情况,Pod就可能被迁移到其他机器上。如果Redis实例相关联的数据位于某台特定的机器或容器自身内,那么这些数据将会在容器迁移或者重启时丢失。为了避免这种情况,在Kubernetes中运行有状态的应用程序时,使用远端的PersistentVolume来管理应用程序的状态至关重要。

虽然PersistentVolume在Kubernetes中有着各种不同的实现,但是它们都具备共同的特征。就像之前描述的Secret Volume一样,它们被关联到Pod并挂载到容器的某个特定位置。与Secret Volume不同的是,PersistentVolume通常是一类基于某种网络协议挂载的远端存储,例如基于文件的NFS(网络文件系统)和SMB(服务器消息块),以及基于块的iSCSI和云端磁盘等。对于数据库等应用程序来说,选择基于块的磁盘存储通常更为合适,因为它们提供更好的性能。但是如果不考虑性能的因素,基于文件的磁盘存储有时会提供更大的灵活性。

000 一般来说,管理状态是很复杂的,对于Kubernetes也不例外。如果应用程序的运行环境支持有状态服务(例如,MySQL即服务、Redis即服务),直接使用这些服务通常是最好的方式。在开发初期,有状态的SaaS(软件即服务)的成本溢价很昂贵,但是考虑到这些状态数据所需的运维要求(备份、数据局部性、冗余等),以及状态的存在使得应用程序很难在Kubernetes集群之间移动的事实,显而易见,在绝大多数情况下存储型的SaaS是物有所值的。在无法使用存储型SaaS的本地环境中,让专门的团队为整个组织提供存储即服务的做法也绝对比让各个团队自主管理更为可取。

我们使用StatefulSet资源来部署Redis服务。在Kubernetes早期版本发布后,StatefulSet作为对ReplicaSet资源的补充加入新版本中,它提供了更为强大的保证机制,例如一致的名称(而非随机散列号),以及明确的缩放顺序。对于部署单实例的应用程序来说,这些特性可能无关紧要,但是当你想要部署有状态的应用程序副本时,这些特性将会为我们带来便利。

我们使用PersistentVolumeClaim(持久卷声明)来获取Redis的PersistentVolume。你可以将Claim(声明)视为“对资源的请求”。我们的Redis声明它需要50GB的存储空间,由Kubernetes集群决定如何供给适当的PersistentVolume。这是为了让我们编写的StatefulSet可以在不同的云环境和本地环境之间移植,即便磁盘的详细信息在不同环境中可能会有所不同。此外,因为很多PersistentVolume类型只支持挂载到单个Pod,我们可以使用卷声明来编写可复制的模板,为多副本中的每个Pod分配自己独有的PersistentVolume。

以下示例展示了一个带有PersistentVolume的Redis StatefulSet:

000

上述StatefulSet会为你部署单实例的Redis服务,假设你需要扩展Redis集群以增强数据读取和故障恢复的能力。为此,你将需要扩展到三个副本,并确保两个新的副本连接到Redis写服务器。

当你为Redis StatefulSet创建一个无头服务(headless Service)时,它将创建一个DNS条目 redis-0.redis ,并指向第一个副本的IP地址。你可以用它来创建一个可以在所有容器中运行的简单的启动脚本:

000

你可以将此脚本创建为ConfigMap:

000

然后,将它添加到StatefulSet并将其作为容器的启动命令。此外,我们还要添加本章前面创建的身份验证密码。

包含三个Redis副本的完整StatefulSet如下所示: VdWWVA0zYzv8hG6Q1es1yZ9g10kTlM+vMXEIC/3G2DjQZrAO8T3nS/rvg0kLES51

000
点击中间区域
呼出菜单
上一章
目录
下一章
×