快速回顾
Ops 中配置管理的一些常见的方式,以及一些配置文件常见的组织形式
参考来源
极客时间-全栈工程师修炼指南-OPS三部曲之配置管理
什么是配置管理?–IBM
为啥需要配置管理?
CM 的主要目标是控制复杂系统的演变,并创建监督记录流程,以简化和加速 IT 资产管理。CM 实践确保系统的设计、实施和操作信息始终保持同步,促进有效的版本管理,并防止未经跟踪的修改可能导致的系统不稳定。 --引用Ibm网站
需要明确的是,我今天要讲的配置管理,我认为就是 Ops 的一个重要部分,它关注的是软
件代码以各种形式,在项目的各个阶段存在的配置。几乎每个做运维的人都要经常去修改大
量的线上配置,无论是来自操作系统还是应用本身
常见的配置方式
1. 源代码中的常量
代码常量是一种最典型的配置方式,它的特点是定义和使用方便,且只对开发人员友好。每次变更的时候,都需要改动代码,经过一定的测试和 Code Review,之后还要通过指定流程的部署,才能发布到产品线上。
通常来说,项目中常量类的定义有着明确的规约,比如这样的示例代码:
你看,上面的常量类包含的要点有:
类名直白且具体,这个 Product 修饰很重要,避免了过于一般化的常量类定义,从而限制了它的职责范围;而这个 Constants 则说明了类的属性,一眼就知道它是干什么的。
被定义为无法实例化的(即将构造器私有化),无法被继承的(即使用 final 修饰)。
常量都使用 public static 修饰,这样就可以直接访问,而不需要实例化这个类。
值得一提的是,在我参与过的项目中,有的程序员为了强制编码的时候只能定义 static 属性来表示常量,会使用 interface 这样的方式,即使用接口来存放常量。效果自然是能达到的,但是这个方法有些投机取巧(毕竟和 interface 关键字所应该表示的含义有明显偏差
了),我认为这是一种反模式。
2. 代码中的配置文件
代码中的配置文件也很常见,它们从 Java、Python 这样的编程语言中脱离出来,但是依然作为源代码的一部分而存在。那为什么要这样做呢?
简单来说,就是为了“解耦”。
而就是这个“解耦”,带来了诸多好处。例如最小职责,单一职责,即配置文件做且只能做配置;再例如可以将同一类的资源放在更合适的地方统一管理了。
3. 环境配置文件和环境变量
接着我们来讲讲环境下的配置。这里的“环境”(Environment),指的是代码部署的环境,可以是用于开发的笔记本电脑,也可以是生产线上的机器。对于不同的环境,虽说代码是同一份,但是可以通过不同的环境配置文件和环境变量,让代码执行不同的逻辑。
还有一种类似的方式是环境变量,环境变量和环境配置文件,有时允许同时存在,但是有一定的优先级顺序。比如说,如果环境变量使用 REGION 也指定了上述文件中的 region,发生了冲突,这就要根据优先级的关系来决定使用哪一个配置,通常来说,环境变量比环境配
置文件优先级更高。
那为什么要允许配置不同方式的覆写呢?这是为了给应用的部署赋予灵活性,举例来说,/etc/region 已经确定了值为 EU(欧洲),那么如果需要在该物理机器上部署两份环境 ,第二份就可以通过环境变量 REGION 强制指定为 NA(北美)
4. 运行参数
运行参数,可以说是最为具体的一种配置方式,真正做到了应用级别,即一个应用可以配置
一个参数。这种情况其实对于开发人员来说非常熟悉,比如在项目中应用 log4j2 这个日
志工具时,启动应用的 java 命令上,增加如下参数:
-Dlog4j.configurationFile=xxx/log4j2.xml
通过这样的运行参数指定的方式,指定 log4j2 配置文件的位置。
当然,也可以通过规约优于配置的方式,不显式指定位置,而在 classpath 中放置一个名
为 log4j2.component.properties 的文件,里面指定类似的配置,而 log4j2 在系统启动
的时候可以自动加载。
5. 配置管理服务
常见的配置方式中,我们最后来讲一下配置管理服务。尤其对一个较大的系统来说,配置管
理是从整个系统的层面上抽取并统一管理配置项的方式。通常来说,这样的配置管理系统会
被包装成一个服务,当然,也有少数是单纯放到数据库的某张表里,不过这种数据库访问层
面的耦合通常并不推荐。
一旦配置管理成为了独立的服务,就说明这个系统已经复杂到一定程度了,通常也意味着这
个服务的用户,不再只是开发人员了,往往还有运维人员,甚至是一些非技术的管理人员。
配置文件常见的组织形式
配置的层级关系
资源文件,本质上也算是代码的一部分,通过合理的设计,可以让资源文件具备编程语言代
码一般的继承关系。比如这样的配置文件组织结构:
conf 目录下,rules.conf 文件就像是基类,存放了默认的规则配置;下面的 CN 目录下的
rules.conf 则存放了中国区的增量配置,就像是子类,里面的配置项优先级高于“基类”的
配置,起到一个有选择性地覆写的作用;而再下面的 Zhejiang 目录下的 rulels.conf 则表
示浙江省的规则配置,优先级更高。
在这种方式下,配置代码不但清晰易懂,而且减少了重复,易于维护。
规约优于配置
终极偷懒大法”——规约优于配置
(CoC,Convention over Configuration)。在这种方式下,系统和配置的用户会建
立“隐性的契约”,通过遵从一定的规则,比如命名规则,达到自动应用配置的目的。
当时我们举了一个 Spring 的 ControllerClassNameHandlerMapping 的例子来说明,现
在我们来举另外一个 Grails 的例子。这里使用 Grails 举例,是因为 Grails 是我接触过的
应用 CoC 原则应用得最好的 Web 应用框架了,使用它搭建起一个 Web 应用极其简洁。
如果你使用过 Spring Boot 并对它印象还不错的话,你可以尝试这个将快速和简洁履行得
更为彻底的 Grails。
配置模板
对于某些复杂或灵活的软件系统来说,配置会变成实际上的 DSL(Domain Specific Language),复杂程度可以不亚于一门编程语言写的代码。于是,有一种常见的帮助使用者理解和修改配置的方法就出现了,它就是创建配置模板,写好足量的配置默认值和配置说
明,这样使用者就可以复制一份模板,并在其之上按需修改,比如 Nginx 的配置模板。
亲自配置一下 Nginx 并让它工作起来
/usr/local/etc/nginx/nginx.conf