在Kubernetes上运行有状态应用:从StatefulSet到Operator

本文介绍了Kubernetes支持有状态应用的两种方式:StatefulSet和Operator。StatefulSet用于顺序部署和管理有状态应用,确保Pod的网络标识、存储和顺序。Operator则是更高级的自动化管理工具,例如MySQL Operator能实现MySQL集群的创建、备份和恢复。文章探讨了StatefulSet的限制,并展望了Operator在管理有状态应用中的潜力和挑战。
摘要由CSDN通过智能技术生成

    一开始Kubernetes只是被设计用来运行无状态应用,直到在1.5版本中才添加了StatefulSet控制器用于支持有状态应用,但它直到1.9版本才正式可用。本文将介绍有状态和无状态应用,一个通过K8S StatefulSet来编排有状态应用的示例,以及当前有状态应用容器化现状及将来的发展趋势。

1. 有状态应用和无状态应用

无状态应用(Stateless Application)是指应用不会在会话中保存下次会话所需要的客户端数据。每一个会话都像首次执行一样,不会依赖之前的数据进行响应。有状态的应用(Stateful Application)是指应用会在会话中保存客户端的数据,并在客户端下一次的请求中来使用那些数据。

以服务器端组件为例,判断它是有状态的还是无状态的,其依据是两个来自相同发起者的请求在服务器端是否具备上下文关系。如果是有状态的,那么服务器端一般都要保存请求的相关信息,每个请求可以使用以前的请求信息。而如果是无状态的,其处理的过程必须全部来自于请求所携带的信息,以及其他服务器端自身所保存的、并且可以被所有请求所使用的公共信息。最著名的无状态的服务器应用是WEB服务器。每次HTTP请求和以前都没有啥关系,只是获取目标URI。得到目标内容之后,这次连接就被杀死,没有任何痕迹。有状态的服务器应用有更广阔的应用范围,比如网络游戏等服务器。它在服务端维护每个连接的状态信息,服务端在接收到每个连接的发送的请求时,可以从本地存储的信息来重现上下文关系。这样,客户端可以很容易使用缺省的信息,服务端也可以很容易地进行状态管理。比如说,当一个用户登录后,服务端可以根据用户名获取他的生日等先前的注册信息;而且在后续的处理中,服务端也很容易找到这个用户的历史信息。

一个大型应用往往具有许多功能模块,很难简单地将其整体性地设计为有状态或无状态的,而往往将其整个架构分成两个部分,即无状态部分和有状态部分。业务逻辑部分往往作为无状态的部分,而将状态保存在有状态的中间件中,如缓存、数据库、对象存储、大数据平台、消息队列等。这样无状态的部分可以很容易的横向扩展,而状态保存到后端。而后端的中间件是有状态的,这些中间件设计之初,就考虑了扩容的时候状态的迁移、复制、同步等机制,不用业务层关心。

通常应用会有如下几种状态数据:

  • 持久性状态数据:这种状态数据在应用重启或宕机时需要能被保存下来。典型地,这种状态会被保存到一个冗余的数据库层,而且数据会被周期性地备份。建议将应用组件和数据库分开,以便能使得应用组件变成无状态的。

  • 配置状态数据:应用总是会用各种配置数据,比如数据库连接字符串等,过去往往保存在配置文件中。进行容器化时,配置文件应该外部化,或环境变量,或配置中心管理。

  • 会话状态数据:每当用户登录进应用后,应用都会为它产生会话数据。在现代应用中,会话数据都会保存在分布式缓存中,因此可以被所有服务实例访问到。但是在传统web应用中,会话数据会被保存在服务器本地,因此,登录后的该用户的所有请求都必须在这台服务器上才能被处理,这就是所谓的粘滞会话(sticky session)。

  • 连接状态:一些应用使用有状态通信协议,比如Websocket。另外一些协议比如HTTP被认为是无状态的。对于使用有状态协议的应用,客户端的访问必须被路由到指定的容器内。

  • 集群状态:某些应用以集群形式运行多个实例,以满足可用性和规模性。在这种应用中,集群内每个成员需要了解其他成员的状态和角色,比如MySQL集群。现在,Kubernetes提供了StatefulSet控制器来支持这种应用。

  • 日志数据:传统应用的日志通过保存在日志文件中。进行容器化时,要对日志输出格式进行改造,适配集中式日志系统规范,和容器运行时的日志组件对接,使得日志能通过标准输出被收集到再保存到统一容器存储中。

2. Kubernetes StatefulSet控制器

常见的Kubernetes控制器不合适处理有状态应用:

2.1 Kubernetes StatefulSet概述

Kubernetes在1.9版本中正式发布的StatefulSet控制器能支持:

  • Pod会被顺序部署和顺序终结:StatefulSet中的各个 Pod会被顺序地创建出来,每个Pod都有一个唯一的ID,在创建后续 Pod 之前,首先要等前面的 Pod 运行成功并进入到就绪状态。删除会销毁StatefulSet 中的每个 Pod,并且按照创建顺序的反序来执行,只有在成功终结后面一个之后,才会继续下一个删除操作。

  • Pod具有唯一网络名称:Pod具有唯一的名称,而且在重启后会保持不变。通过Headless服务,基于主机名,每个 Pod 都有独立的网络地址,这个网域由一个Headless 服务所控制。这样每个Pod会保持稳定的唯一的域名,使得集群就不会将重新创建出的Pod作为新成员。

  • Pod能有稳定的持久存储:StatefulSet中的每个Pod可以有其自己独立的PersistentVolumeClaim对象。即使Pod被重新调度到其它节点上以后,原有的持久磁盘也会被挂载到该Pod。

  • Pod能被通过Headless服务访问到:客户端可以通过服务的域名连接到任意Pod。

以在K8S中部署高可用的PostgreSQL集群为例,下面是其架构示意图:

该架构中包含一个主节点和两个副本节点共3个Pod,这三个Pod在一个StatefulSet中。Master Service是一个Headless服务,指向主Pod,用于数据写入;Replica Service也是一个Headless服务,指向两个副本Pod,用于数据读取。这三个Pod都有唯一名称,这样StatefulSet让用户可以用稳定、可重复的方式来部署PostgreSQL集群。StatefulSet不会创建具有重复ID的Pod,Pod之间可以通过稳定的网络地址互相通信。

2.2 使用Kubernetes StatefulSet部署高可用MySQL

当前命名空间为testmysql。

(1)创建ConfigMap,用于向mysql传递配置文件。

apiVersion: v1
kind: ConfigMap
metadata:
 name: mysql
 labels:
   app: mysql
data:
 master.cnf: |
    #Apply this config only on the master.
   [mysqld]
   log-bin
 slave.cnf: |
    #Apply this config only on slaves.
   [mysqld]
super-read-only
(2)创建StatefulSet对象,它会负责创建Pod。 
apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: mysql
spec:
 selector:
   matchLabels:
     app: mysql
 ser
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值