摘要:宋体是面向内部基于打造的容器服务平台,旨在提升内部研发效率,帮助改善规范研发流程。宋体作为容器编排框架,可以减轻配置部署管理和监控大规模容器应用的负担。宋体核心原理宋体解释不得不提中两个最具价值的理念声明式和控制器模式。
KUN(Keep UCloud Nimble)是面向 UCloud 内部、基于 Kubernetes 打造的容器服务平台,旨在提升内部研发效率,帮助改善、规范研发流程。在 KUN 平台的建设过程中,内部用户对于一些基础通用的分布式软件如 Redis、Kafka 有强需求,但又不想操心其部署及运维。KUN 团队在分析这些痛点后,决定利用 Kubernetes Operator 的能力,并弥补了开源 Operator 的一些不足,将 Operator 产品化来帮助用户部署和管理这些分布式、带状态的应用。通过 Operator 服务化,KUN 平台扩充了 Kubernetes 交付 Pod、PVC、SVC 的能力,能够快速交付 Redis 等分布式、带状态的系统,提供了一个平台之上的平台。
在这篇文章里,我们主要来聊一下 Operator 对于 Kubernetes 的价值以及我们团队基于 Operator 所做的相关工作。
Operator 是什么,解决了什么问题
为什么需要 Operator
无状态和有状态
2014-2015 年容器和微服务的出现,为软件开发和基础架构带来了巨大的创新和挑战。容器提供了隔离和限制,同时容器的状态是易失的,它对自己外部的状态和数据不关心,专注于单一的服务,比如 Web 应用、日志服务、业务程序、缓存等。这些服务都能作为容器交付和运行,而一旦容器数量形成规模,管理的难度也越来越大。
Kubernetes 作为容器编排框架,可以减轻配置、部署、管理和监控大规模容器应用的负担。事实上早期的 Kubernetes 非常善于管理无状态的应用程序,比如 Kubernetes 提供的 Deployment 控制器。它认为所有的 Pod 都是完全一样的,Pod 间没有顺序和依赖,扩容的时候就根据模板创建一个一样的新的应用,也可以任意删除 Pod。但对于像数据库这样的有状态的应用程序,添加删除实例可能需要不同的节点做不同的配置,与已有的集群进行通信协商等,这些操作通常需要我们人工来干预,这就会增加运维的负担,并且增加出错的可能性,最重要的是它消除了 Kubernetes 的一个主要卖点:自动化。
这是一个大问题,那么如何在 Kubernetes 中管理有状态的应用程序呢?
StatefulSet 的价值和不足
Kubernetes 的 1.5 版本开始出现了 StatefulSet,StatefulSet 提供了一系列资源来处理有状态的容器,比如:volume,稳定的网络标识,从 0 到 N 的顺序索引等。通过为 Pod 编号,再使用 Kubernetes 里的两个标准功能:Headless Service 和 PV/PVC,实现了对 Pod 的拓扑状态和存储状态的维护,从而让用户可以在 Kubernetes 上运行有状态的应用。
然而 Statefullset 只能提供受限的管理,通过 StatefulSet 我们还是需要编写复杂的脚本通过判断节点编号来区别节点的关系和拓扑,需要关心具体的部署工作,并且一旦你的应用没办法通过上述方式进行状态的管理,那就代表了 StatefulSet 已经不能解决它的部署问题了。
既然 StatefulSet 不能完美的胜任管理有状态应用的工作,那还有什么优雅的解决方案呢?答案是 Operator。Operator 在 2016 年由 CoreOS 提出,用来扩充 Kubernetes 管理有状态应用的能力。
Operator 核心原理
解释 Operator 不得不提 Kubernetes 中两个最具价值的理念:“声明式 API” 和 “控制器模式”。“声明式 API” 的核心原理就是当用户向 Kubernetes 提交了一个 API 对象的描述之后,Kubernetes 会负责为你保证整个集群里各项资源的状态,都与你的 API 对象描述的需求相一致。Kubernetes 通过启动一种叫做 “控制器模式” 的无限循环,WATCH 这些 API 对象的变化,不断检查,然后调谐,最后确保整个集群的状态与这个 API 对象的描述一致。
比如 Kubernetes 自带的控制器:Deployment,如果我们想在 Kubernetes 中部署双副本的 Nginx 服务,那么我们就定义一个 repicas 为 2 的 Deployment 对象,Deployment 控制器 WATCH 到我们的对象后,通过控制循环,最终会帮我们在 Kubernetes 启动两个 Pod。
Operator 是同样的道理,以我们的 Redis Operator 为例,为了实现 Operator,我们首先需要将自定义对象的说明注册到 Kubernetes 中,这个对象的说明就叫 CustomResourceDefinition(CRD),它用于描述我们 Operator 控制的应用:redis 集群,这一步是为了让 Kubernetes 能够认识我们应用。然后需要实现自定义控制器去 WATCH 用户提交的 redis 集群实例,这样当用户告诉 Kubernetes 我想要一个 redis 集群实例后,Redis Operator 就能够通过控制循环执行调谐逻辑达到用户定义状态。
所以 Operator 本质上是一个个特殊应用的控制器,其提供了一种在 Kubernetes API 之上构建应用程序并在 Kubernetes 上部署程序的方法,它允许开发者扩展 Kubernetes API,增加新功能,像管理 Kubernetes 原生组件一样管理自定义的资源。如果你想运行一个 Redis 哨兵模式的主从集群或者 TiDB 集群,那么你只需要提交一个声明就可以了,而不需要关心部署这些分布式的应用需要的相关领域的知识,Operator 本身可以做到创建应用、监控应用状态、扩缩容、升级、故障恢复,以及资源清理等,从而将分布式应用的使用门槛降到最低。
Operator 核心价值
在这里我们总结一下 Operator 的价值:
・ Operator 扩展了 Kubernetes 的能力;
・ Operator 将人类的运维知识系统化为代码;
・ Operator 以可扩展、可重复、标准化的方式实现目标;
・ Operator 减轻开发人员的负担。
Operator 服务化目标
聊完 Operator 的能力和价值我们把目光转向 KUN 上的 Operator 平台。前面说过,用户想在 Kubernetes 中快速的运行一些分布式带状态的应用,但是他们本身不想关心部署、运维,既然 Operator 可以灵活和优雅的管理有状态应用,我们的解决方案就是基于 Operator 将 Kubernetes 管理有状态应用的能力方便地暴露给用户。
核心的的目标主要有两方面:
1、针对 Operator 平台
・ 提供一个简单易用的控制台供用户使用,用户只需要点点鼠标就能快速拉起有状态应用。并且能在控制台上实时看到应用部署的进度和事件,查看资源,更新资源等。
・ 通过模板提交声明,参数可配置化,创建应用的参数通用化,将应用名称等通用配置和应用参数(如:redis 的 maxclients、timeout 等参数)解耦。这样带来的好处就是不同的 Operator 可以共用创建页面,而不需要为每种 Operator 定制创建页面,同时 Operator 暴露出更多的应用配置参数时,前端开发也不需关心,由后端通过 API 返回给前端参数,前端渲染参数,用户修改参数后,通过 API 传递到后端,后端将参数与模板渲染成最终的实例声明提交到 Kubernetes 中,节省了前端开发时间。
・ 可以管理通过公共的 Operator 和 Namespace 私有的 Operator 创建的实例。用户可以用我们提供的公用 Operator,也可以把 Operator 部署到自己的 NameSpaces,给自己的项目提供服务,但这两种 Operator 创建的应用实例都可以通过 Operator 控制台管理。
・ 可以无限添加 Operator。
2、针对 Operator 控制器
・ 拉起分布式集群,自动运配置、运维;・ 可以动态更改所控制应用参数;
・ 控制器本身需要无状态,不能依赖外部数据库等;
・ 实时更新状态,维护状态,推送事件;
・ 可以运行在集群范围,也能运行在单 NameSpace,并且可以共存,不能冲突;
针对这些设计目标最终我们的 Operator 控制台如下:
同时我们为 Operator 控制台定制了第一个 Operator:Redis Operator,未来会推出更多的 Operator,接下来我们就来看下 Redis Operator 的实现。
Redis Operator
Redis 集群模式选型
我们知道 Redis 集群模式主要有主从模式、哨兵模式、Redis 官方 Cluster 模式及社区的代理分区模式。
分析以上几种模式,主从模式的 Redis 集群不具备自动容错和恢复功能,主节点和从节点的宕机都会导致读写请求失败,需要等待节点修复才能恢复正常;而 Redis 官方 Cluster 模式及社区的代理分区模式只有在数据量及并发数大的业务中才有使用需求。哨兵模式基于主从模式,但是因为增加了哨兵节点,使得 Redis 集群拥有了主从切换,故障转移的能力,系统可用性更好,而且客户端也只需要通过哨兵节点拿到 Master 和 Slave 地址就能直接使用。因此我们决定为 Kun Operator 平台提供一个快速创建哨兵模式的 Redis 集群的 Redis Operator。
开源 Operator 的不足
目前已经有一些开源的 Redis Operator,通过对这些 Operator 分析下来,我们发现都不能满足我们的需求,这些开源的 Operator:
・ 不能设置 Redis 密码。
・ 不能动态响应更改参数。
・ 没有维护状态,推送事件。
・ 不能在开启了 istio 自动注入的 Namespace 中启动实例。
・ 只能运行在集群或者单 Namespace 模式。
改进工作
当前我们定制开发的 Redis Operator 已经在 Github 上开源
https://github.com/ucloud/redis-operator
。提供:
1. 动态响应更改 Redis 配置参数。
2. 实时监控集群状态,并且推送事件,更新状态。
3. 误删除节点故障恢复。
4. 设置密码。
5. 打开关闭持久化快捷配置。
6. 暴露 Prometheus Metrics。
使用 Redis Operator 我们可以很方便的起一个哨兵模式的集群,集群只有一个 Master 节点,多个 Slave 节点,假如指定 Redis 集群的 size 为 3,那么 Redis Operator 就会帮我们启动一个 Master 节点,两个 Salve 节点,同时启动三个 Sentinel 节点来管理 Redis 集群:
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/117608.html