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&#x