CL 的配置中心知识整理
前言
去年在公司推进 K8s+Istio 项目时,好多时间都是在配置 yaml。整个基础设施和云原生方式部署的应用,都是手写 tf 或 yaml 文件,或由 helm 生成 yaml ,然后由 Terraform 来完成多云服务商设施和服务的配置,所有配置文件都有保存在 git。“Infrastructure as Code -- 基础设施即代码”对我们而言真不是说说而已。但,配置文件真的好多好多啊,就算有好的工具,管理好也不是易事。
然后最近在 github 上写一个 Go 框架(https://github.com/xcltapestry/gowk)给自己用,在微服务的配置处理这块还是纠结了蛮久。当然我最后的方案比较简单。回想这几年在微服务下的配置管理这块,因为没有经验在选型、开发、维护过程中吃过不少的苦头,会发现这块真要搞好,细节蛮多的。
这些促使我想把微服务下,配置中心这块的一些知识汇总整理出来,也算是一个备忘。
配置基础知识
在看后面内容之前,请先停下来回想下,如果一个新服务要上线,你需要配置多少东西,花多少时间才能让它正常的运转起来? 你有没有被各类配置坑过?
配置分类
按个人理解,理了一下配置的分类如下:
配置文件类型:
常见的配置文件类型有 .conf、toml、yaml、json、xml 等,其实这个还好,但在实际使用时,会有不同做法:
一类是服务相关的所有配置,都放在一个统一的配置文件中
另一类,是按不同的模块和功能,分散成不同的配置文件,放在一个统一的目录。
除了正常的服务配置文件外,还有一类配置文件,它是把服务用到的所有 sql 语句等抽出来放在单独的文件,通常是 xml 中置于另一目录,服务的启动运行离不开它,但它又有可能没放在配置中心上。
其他还有一些.so 文件、证书文件、字体文件、第三方命令行工具等,也是需要关注的。
配置存储
数据库、git、consul、本地文件、zookeeper、s3
配置同步方式:
推: 客户端与服务端建立长连接如 grpc 之类,一旦有变更,客户端能立马感知。
拉: 客户端定时轮询(如 http 请求)服务端是否有变更
推拉结合:客户端与服务端平时维持一个长连接。同时客户端会定时从配置中心同步最新配置。
当客户端拉到最新配置后,除了应用最新的配置外,还可以选择通过本地文件缓存一份
配置变更方式:
实时热更新
配置变更 -》 实时同步(推/拉) -》配置更新 -》 生效检查
发布更新
非容器化:
配置变更-》审核 -》 更新配置 -》重启服务 -》生效检查
容器化:
配置变更工单 -》审核 -》 发布新容器 -》 切换流量(蓝绿/金丝雀) -> 生效检查
注意:
这里实际选择时,团队内有可能会产生一个小争议。对于在 k8s 等容器化后的服务,配置变更是通过“实时热更新"方式即时让变更生效。还是每次配置变更,必须通过"配置变更单"然后通过发布的方式完成变更, 哪种会更好?
配置中心出现的背景
之所以出现单独的配置中心,通常是人们发现因为配置变更引发的产线事故越来越多,配置的管理复杂度越来越高,如:
配置无法区分运行中,开发,测试还是预发布等不同的运行环境,而这些环境的配置通常会有很多不同。
配置的修改无法追溯,更别提快速回滚了。
日常往往存在各类配置开关,当服务多和开关多了后,分散管理效率低,成本高
微服务下,服务间的相互调用不断增多,同一个资源可能被多个服务同时依赖,依调用链路进行的配置变更,资源配置的变更等,配置管理复杂度成指数升高
还有一些如对于配置的生效时间,成功率,敏感配置的安全方案。在多云服务商等环境下,配置的同步,迁移方案、配置的查看权限,版本对比要求支持等。
总之,大家对各类配置管理的期望,随着业务发展只会越来越高。
配置中心方案考虑
每个人在选择或者自研时,可能所有的场景、所处的阶段、团队和技术积累等,都不一样,所以考虑点都会不同,整理了一些选型或规划时是可以考虑进去的点。实际情况上不需要全部支持,选择适合自己情况的就好。
配置变更流程
理论上配置变更会经历的几个流程:
变更通知 -> 加载新配置 -> 生效检查 -> 失败预案
分别说下:
如何感知到配置变更
推,拉,推拉结合
如何加载变更
2.1 配置的数据来源:
远程缓存? 本地缓存? 本地文件?
2.2 加载配置的优先级?
2.3 各配置和缓存的一致性维护
配置是否生效检查(全部/部份?)
配置版本检查
配置格式正确性检查
配置项异常,是否监控告警规则和 Dashboard. 特别是对新上线服务
配置中心是否能主动监控配置生效后,同比的成功率、超时情况等参数
生效失败后的预案 (全部/部份?)
其他:
是否支持历史版本查看对比及一键回滚
配置是否支持不同服务配置批量变更和回滚,在微服务架构下发大需求时,往往涉及面比较广
敏感配置
敏感配置项使用方案:
1.1 参数值研发自己负责加解密
1.2 配置中心加解密,及展示权限
1.3 存放在第三方(如 aws kms, Vault 之类)
可视化界面和 api 读取上的安全方案
配置多版本,多环境配置管理支持 (prod/uat...)
这个支持技术上不难,难得是要让它变得不容易搞混,部署配置,维护的成本够低。
高可用、性能等稳定性指标
1. 扩容,各类异常的处理,配置中心自身的鲁棒性如何。
2. 当配置澎涨后的性能是否能一如即往。
接入成本
通常来说就是指侵入性和上手成本怎么样? 部署运维是否方便。
细化来说:
1. 是 sdk 还是 api 接口方式,对多开发语言支持怎么样?
2. 是否有可视化管理界面,操作是否简单?功能是否完备?
3. 在产线和非产线等各环境的部署管理难度
4. 如果接入其他系统,如监控告警,cmdb 之类系统方便的话,是加分项
配置分级、多云多数据中心支持
通常需要多数据中心,多云服务商支持时才可能需要考虑到。
权限审计
权限:
对于配置管理的粒度。人员与组织架构的管理等
审计:
变更记录,事后分析或追责
为了合规审计,保证产线变更都有相关记录
依赖分析
首先什么叫配置依赖分析?
1.1 一个资源被多少个应用使用?
1.2 一个服务使用了多少种资源?
1.3 如果资源发生变化或异常,会造成什么影响?
是否有可视化的方案并能支持导出功能?
什么样的配置方式或变更方案能避免或减少影响?
同时这里还有一个隐含需求,是否方便和 cmdb 等内部系统打通?
配置中心落地注意事宜
配置中心的选型很多人会在比对各个配置中心的各项指标上花很大精力,而在具体落地上花的精力相对少些,实际上各个配置中心的实现其实基本都蛮靠谱的,除非你的使用场景很特殊。建议花更多时间在研究怎么落地上,找到怎样才是适合的最佳落地实践。不然有些坑最后的改正成本,会比想象的大多了。
分享几点经验:
配置的标准化规范,最好提前考虑好,不要让大家乱起名字自由发挥。
举几个小例子:
1.1 同类的配置项目,在不同服务叫法不同,有迷惑作用,令人困扰。
1.2 同样的配置项,缺少共同的约定。 在不同开发语言或框架搞法不同,除了通常会放配置文件外,有些会习惯放环境变量,还有些会作为命令行参数在服务启动时传入。
1.3 跨云跨集群时,需要遵守一些约定才能实现,但如果一开始没规范,后面要支持这些难度会非常大
1.4 配置项的值非常大,可能上几百 K,甚至上 MB 的,这类是否合适作为配置项?
1.5 镜像里面的配置与服务本身配置之间的边界?
在配置中心你会按一个个配置项来管理,还是按一个个配置文件来管理?
在微服务很多的情况下,以后增加公共通用配置项的难度。
我踩过的一个坑:15 年刚开始搞微服务时,每个服务代码我都会定义一个大大的 struct,用来保存配置信息,如果要增加新的公共通用配置字段,在每个服务的 struct 加一下,然后重新发布即可。开始还好,但当服务数增长到几百个后,这类变更就变成了一个工作量很大,需要跨团队合作的项目了。这是当初根本没有想到过的。
配置中心上的配置由谁来管理和监控,如果开放给研发,准备开放到什么样的程度?这个事说不清楚,除了容易搞出配置变更事故外,就是容易影响团结。
无效配置项
5.1 人都是喜欢偷懒的,有一个很容易出现的现象是,开新服务时,会找一个已有的配置文件复制过来改改直接用,然后特别是新人,搞不清楚哪有可以删,就没清理,容易保留一些服务实际上用不上的配置项在各个服务间满天飞。
5.2 在配置中心,把 A 服务的配置,配置到了 B 服务,因为也没什么影响,在 A 服务配置正确后,就没去 B 服务清理。
5.3 当初因为某个原因,增加了一个特殊配置,日子久远后,这个配置有可能被废弃了,也有可能没有,更可怕的是,某一天,它被触发激活了而你还一无所知。
微服务的新旧服务上线和配置变更通常是有先后顺序的,而这些服务有可能归属于不同的团队,这事怎么做才能稳而有效率?
大家通常会留很多开关配置项,来控制各种逻辑,当这些开关处于同一调用链路,不同服务,不同团队管理时,怎么才能做到稳而不乱?
配置中心的支持连接数、时延、性能等指标的临限点在哪?配置中心方案的变更是个高风险的大活。
配置项的动态配置
某些配置项的值是可以通过某些条件之类触发自动变更的,理论上是更先进的方式。但一定要注意收拢具体变更它的方法,如果能在多种条件,多个地方都能触发这类变更的直接执行,有可能会是个灾难。
展望
Config Driven Anything 是趋势!
版权声明: 本文为 InfoQ 作者【xcl】的原创文章。
原文链接:【http://xie.infoq.cn/article/50735fc74c7ffd40afbb7acf3】。文章转载请联系作者。
评论