背景
团队基于Jsonnet(配置语言)和Bazel(构建工具)实现Everything as Code。但是,将近一年的时间里,团队也只有少数人深入参与Everything as Code的代码的编写(其实,大多数人是不需要深入参与)。
最近,组内的一个开发同学——他之前对Everything as Code完全零基础——在运维同事的辅助下,为网关配置增加了金丝雀的能力。
在这种能力下,开发人员可以只需要改几行配置,并部署配置,就可以实现金丝雀发布。这种能力的根本就是:通过Jsonnet动态生成网关“根据Header进行流量路由”的配置的能力。
如果没有这种能力,需要手写大量的重复的YAML配置,即麻烦,又容易出错。
同事使用Everything as Code的工具后有感
在他与Everything as Code“亲密”接触一个多月后,他说出了他的感受:
- 直接写yaml的话,所见即所得,非常直观。但是有个致命缺陷,没法动态化生成配置,所以必须要寻找一个脚本语言。
- jsonnet其实就是一门简单化的脚本语言,通过自定义方法,通过for循环,通过读取自定义的变量,更灵活生成我们想要的json。但是写代码都有一个共性,代码可以写的很复杂,现在用jsonnet了,你想看一个key的value是什么,需要看懂别人的代码才知道value是什么甚至可能理解错别人的代码,违背了配置所见即所得,这对新手来说非常痛苦。很多时候,我们不关心jsonnet的过程,我们只想看到生成最终的配置文件是什么。
- 如果能把云端编译好的jsonnet展示出来,就可以看到生成的最终json是啥了,但是我们没有。所以需要本地搭建bazel,但是bazel对win非常不友好,搞起来非常困难,但是本地如果不能把monorepo buil通过,那么可以宣告你无法彻底搞清楚monorepo,更不可能自定义更多自己想要的东西了。
- 既然是通过代码来生成json,用jsonnet和python和js甚至是用java都可以,现在我觉得jsonnet的设计者对灵活性做了一个取舍,有一些我想要的操作jsonnet没法实现。
然后他又补充到:
只要自己本地能build monorepo,那么就既能享受jsonnet的灵活性,又能通过编译好的文件做到所见即所得。可惜bazel对win不友好,新手能在win 编译通过mainrepo太难了。
总结下来,这位同事:
- 对Jsonnet的理解还不够:Jsonnet并不是脚本语言,而是一门可编程的配置语言,一种为配置而生的DSL(领域特定语言);
- 在Windows系统上使用Bazel遇到了非常大的阻力。
以上是同事针对Jsonnet和构建工具Bazel的感受。
我认为不是Bazel对Windows不友好,而是Bazel在Windows下的生态太弱了。谁叫后端服务是Linux的天下呢?
同事对Everything as Code本身的看法
接着,他说出对Everything as Code的看法:
我觉得everything as code太理想,只能面向开发人员。你不能保证运维的能力,绝对不开放给第三方使用。指不定某天某个需求就需要你的运维的某个能力,让不懂代码的人也要操作。
假如某个运维能力,要开放给产品或者测试来用,要让别人给你学个jsonnet,那要我是产品或者测试只能口吐芬芳了。所以我认为,面向开发者的部分,使用every thing as code是趋势,比较好溯源跟踪,迭代。但是架构设计上,还需要有支持面向第三方的部分,可以做到让不懂代码的人也能用到一些运维的能力。
这位同事实现的是金丝雀配置生成,是需要修改Jsonnet代码的。当产品经理需要将某用户的流量路由到后端服务的某个版本上时,这位同事就认为产品经理就需要去改Jsonnet代码了。
同事认为这就是Everything as Code的问题:不方便非开发人使用。
同事的另一层意思没有说出来:并不是所有的事情都适合as Code。
其实,有这样的误解很正常,“Everything as Code”中的“Everything”字面含义上就是所有的,一切的意思。而Code是代码的意思。
所以,“Everything as Code”字面上完整的意思是:一切皆代码。
从字面上理解“Everything as Code”,只看到了它的表面
Everything as Code的本质
“Everything as Code”中的”Code“,其实指的是配置,即:一切皆配置。
这句话本身是没有错的,如同“道生一,一生二,二生三,三生万物“这句话。
“Everything as Code”这句话并没说什么是配置,以及哪些配置该放哪。这才是我们实践时真正要考虑的问题。
配置的本质是软件的灵活(soft)部分。通过这个”灵活部分“,我们可以根据自己的需求,有限地改变软件的行为。
在上面的案例中,我们需要控制网关的路由行为,需要用到两个配置:
- 网关的行为逻辑的配置。这是技术部分,由程序员或者DevOps决定是否改动;
- 用户列表配置。这是业务部分,由产品经理或测试决定是否改动。
业务部分的配置由业务方——产品经理——决定,我们认为通过界面来实现更合理。
而技术部分的配置放在配置代码中更合适。
通过案例,我想说明的是配置该放哪里,是由以下维度决定的:
- 配置的属性:是技术配置,还是业务配置;
- 配置的改动来源:是技术人员,还是非技术人员;
- 配置的改动频率:是经常改动,还是不经常。”经常“如何定义,我无法给出,要看情况。
接着刚才的案例,在还没有开发出界面让产品经理对用户进行配置前,我们可以通过代码配置用户列表。如果产品经理需要配置,由让开发人员配置一下即可。
所以,配置即代码的实践也是要看具体情况的。我们可以通过以上几个维度判断是否进行as Code。
(完)
Last modified on 2023-04-20