部门持续集成的后续思路

今天我要先讨论一下,我们部门里边后续做这个持续集成的建设思路。

首先,说一下我对这个建设思路的总体的一些想法。我们主要是想建设一个标准化,集中化,自动化的持续集成解决方案。

什么是标准化?我认为就是学习成本比较低,有一些套路,新人来了之后可以很快的上手。这个集中化呢,我觉得就是配置脚本都是要集中化的,集中在一个地方去管理,而不是分散在各个角落,它或许是存在于这个代码仓库里边,另外集成环境的机器也是对等的,环境没有差异。最后一个自动化,应该是比较好理解的,就是减少人工的干预,过程可以预测。

简单来说,一个任务,做法要标准化,多个任务,是集中管理的,所有任务,都是自动管理的。

我现在来总结一下,当前我们的一些进展,去年的时候我们都已经是使用这个Jenkins了,然后又引入了这个K8S来管理这个Jenkins的所有执行节点,已经在很大程度上解决了集中化部署的一些问题。当前已经托管了上百个代码工程,一个月数万次构建任务,还算稳定。

另外我们构建了一个叫pipeline的Jenkinsfile文件集中管理的工程,实现了gitlab和Jenkins的配置的统一管理,对于常见的代码工程,我们可以很方便的管理它的持续集成脚本,也不需要关心Jenkins的配置和gitlab的配置究竟是怎样的,这些都可以做到自动管理的。

后面我们对于原来在svn上的一些工程,肯定将逐步迁移到这个工程上,这个问题不大。在这个基础上后续要开展第三方依赖管理的管控工作也比较方便。

但是我们还有不少是CMO(配置管理员)他们才需要的脚本,例如部署到各个环境的脚本,例如做一些清理,扫描工作的东西,这些脚本呢,目前来说啊,我觉得是没有一个统一的标准管理,散落在各个服务器,或者是组织形式也不完全相同,实现思路也千差万别。

我有个想法,就是把这些脚本的集中化的管理,然后呢,按配置即代码的思路,通过一套DSL(job dsl plugin)把他们生成对应的Jenkins任务,这样我们只要在一个地方(某个代码仓库)维护,很容易做一些标准化的脚本或操作。

当然,这里还有其他一些实现思路,例如打造一个发布管理用的工具,但是呢,这个就看CMO他对这个东西的接受程度,或者是迫切程度,或者是他们更期望使用jenkins这种比较熟悉的方式来管理他们的脚本。

我觉得这两种方式都没有什么问题,但是最主要是先要对齐我们这个集中化的思路,用标准化的方式去做这个事情,并且尽快的开展起来。

代码评审的开展思路

先说背景,目前的开发团队一共有好几百号人,划分了许多大小的项目组,但交付的主体还是以合作公司为主的,人员流动比较大,很多项目充斥着新人,当战线特别长的情况下,容易忽视交付质量,上线频频出现一些低级错误。

在这样的背景下,怎样去做代码质量提升的工作?

其实周末我们有个研讨活动,其中也有提到一个观点,所有代码变更是否都需要评审。虽然有些人是反对意见,但我个人是举双手赞成的。我想,无论这个人再厉害都好,但代码就是人写出来的,是个人总有可能会犯错,更不用说很多人是新手,面对的是复杂的系统。

代码评审要开展,这是没有问题的,但怎么操作确实需要仔细想想。我原本的想法是一步到位,先树立一个标杆,希望大多数人能够自发去做这个事情,但发现就是不现实的。

后来想想,这是为什么?主要是很多人还没认识到这个东西的价值,虽然嘴上说是认同的,但是实际上是没有感受到的。所以做这个事情的意愿不强。

我们总说任务分配的时候,要考虑意愿和能力两个方面。意愿比较好,能力比较强,当然是我们最希望看到的。但是这种情况有时候真的是不现实,需要我们应该去引导,最后走进一个正向循环的过程。

要达到一个比较好的效果,只能先把事情做起来,或许得用上行政的命令,无论怎样先做起来,然后慢慢加强改进,引导一部分有意识的人继续把这个事情做好。

我想了想,两个原则。

第一,规则要简单。一开始做,对评审规则的要求一定要比较简单,所以我只是列举了10条,没有明细的指引,也不做过多场景化的解释。虽然这10条严格执行要求也是很高的,但事无巨细的指导,要求太多,在一开始肯定是个灾难。

第二,强调线上平台。我一直强调必须是在线评审,别跟我说你们用线下评审,因为那个过程数据不好跟踪。只有借助一些工具,后续我们才有持续做下去的可能。

开展了以后,如何去跟踪改进?

在起步阶段,前面一个月是要持续关注的,可以做一个简单的评比,看看趋势是怎么样的,有什么人,什么项目比较活跃。下一步呢?我们可能对问题进行整理,然后再对Top问题进行识别分类,这样容易制定改进计划,例如加强某个编码规范,也可以做好一些业务代码上的checklist。

在这个过程中,更重要是希望识别到有意愿做这个事情的人,实现少数人带动多数人。他意识到这是有价值的,值得花时间投入。他发现评审可以发现问题,可以培养新人,进而把项目做得更加轻松。下一步我们才能完善能力建设,大家有能力去识别更有意义的,一些有价值,更深层次的一些问题,这样在评审过程中才能有的放矢。

我觉得,一上来就说能力建设,谈赋能,虽说不一定不行,但是效果很可能不太好,甚至就有反作用。

这就是从意愿到能力的曲折前进。共勉。

关于个人成长与知识管理的碎碎念

其实,这是重提旧事,希望再催促一下大家勤记笔记,也写总结,把知识管理做实一点。这个小地方,还是有几百号人的团队,项目节奏快,流动性也挺大,对团队而言,知识管理的重要性不言而喻。

但我想从自身出发,谈对个人的意义,希望迸发多一点点动力。团队那么多人,先鼓动一部分人(对,说的就是你),先富带动后富。

先说一下问题,关于知识管理产出的质量问题。我们知道量变到一定程度会产生质变,但无脑的量变是很难产生好的质变的。我们搞知识管理,一开始可能就是先做大再做强,要大量产出,很多是需要全员参与的(摊派任务),或者是有指标,或者是有晾晒比对,造成大量的被动的产出。例如,

  • xxx数据查找,sql一贴
  • xxx需求,用例一贴
  • 问题定位,结果一贴

这些是有价值的,特别是基于数据挖掘、信息整理之后,对于日常工作还是有帮助的,可以解决很多小问题。但是我们还需要一些产生有更大价值的分享。这个问题之前和某些同事谈过,到头来得靠某一小团体(按二八原则,20%),我们可以打开来看,除去角色定位不同,和其他人有什么不同,竞争力在哪?难道是更好的服从性?吃苦耐劳?996?来到知识管理也是一样,你的产出是否比别人的更多、更好?

缺少核心价值,才是个人成长最大的障碍,年轻还好,越大越慌乱(:>你看我就挺慌的)。写总结,做分享,把点汇聚成面,慢慢的形成自己的核心价值。

当然,你说我不写总结,我知道就好;我很忙,写起来很麻烦,又不考核。是的,无所谓,只是友情提示。你知道可能不是真的知道,可能是以为自己知道,总结是一个照妖镜。另外,分享有更大的价值,助人为乐嘛。

最近,要求研发团队的一些同学写总结,做分享,可能某个东西你不熟悉,短期还会造成一定困扰,但还是想大家尽量去做,无非就是想督促大家去学习,去进步。我知道发挥主观能动性是挺难的,还好我还是佛系的,最终还是要看个人意愿,如果没有意愿,下次就不找你了,我找另外更有意愿的人。

最后,有总结分享,不要藏着掖着,发出来让大家看看。藏着掖着,不是怕人偷就是怕人笑话,放出来,只是怕人不点赞。:)

Nginx中Host Header相关问题

问题描述

nginx<ip1:1293>  ----> ingress<ip2:1089> ---->service --> pod<:8080>

最近新上的一个webservice的应用在k8s上不能访问,最后发现是pod里边的axis2框架生成的wsdl端口不对,一直显示是1089。最后修改了nginx的配置,并重启pod才修复,下面进行总结。

nginx的Host基础知识

nginx和Host头相关的变量有:

  • $host 表示请求过来的Host头(如果有的话),或者请求的域名(不带端口)
  • $http_host 表示请求过来的Host头(如果有的话),或者空
  • $proxy_host 表示upstream的请求地址

默认情况下,通过proxy_pass之后Host会被改写,指向$proxy_host,也就是

proxy_set_header Host $proxy_host

这样upstream server就不能获取到原始的地址,所以做法是:

proxy_set_header Host $host:$server_port

或者

proxy_set_header Host $http_host

第一个是当前外层nginx的写法,第二个是nginx ingress controller的默认配置(实际是$best_http_host,但他们是同一个变量)。

两者区别在于请求有没有带Host头的情况,但这个只针对Http/1.0比较特殊,1.1之后都要求带Host头,否则会返回400。

验证结果

测试结果如下,结果都是根据request的getServername,getServerPort获取的:

  • 直接ingress访问,没有Host的情况,应用看到ip2:80
  • GET http://ip2:1089/health.jsp HTTP/1.0
  • 直接ingress访问,按Host信息来,应用看到ip2:1089
  • GET http://ip2:1089/health.jsp HTTP/1.1
  • Host: ip2:1089
  • 直接ingress访问,按Host信息来,应用看到ip1:1293,通过外层nginx之后的Host就是这个结果
  • GET http://ip2:1089/health.jsp HTTP/1.1
  • Host: ip1:1293
  • 通过外层nginx访问,没有Host头,应用能够看到IP,但端口是看不到了
  • GET http://ip1:1293/health.jsp HTTP/1.0
  • 通过外层nginx访问,正常
  • GET http://ip1:1293/health.jsp HTTP/1.1
  • Host: ip1:1293
  • Http1.1不带头,返回400
  • GET http://ip1:1293/health.jsp HTTP/1.1

总结

  • Http/1.0已经绝迹,所以不需要考虑Host缺少的情况,这种情况下nginx和ingress的配置方式没有区别
  • 对于axis2,如果开启modifyUserWSDLPortAddress参数,那么wsdl的soap location会重新生成,但ip部分每次请求都变化,port部分在第一次访问后就固定。所以如果涉及Host端口调整,应用需要重启才能生效。
  • 基于第二点,由于端口第一次会固定,所以不应该把访问wsdl作为pod的探针,以免端口被错误固定。

IOS14无法安装企业自签名App案例

问题描述

前阵子苹果发布了IOS14,很多人就发现企业的自签名App就无法安装了。很不走运,我们有个App也遇到了。网上找了一圈,大多数文章都说要升级TLSv1.2,但也很不走运,这个办法对我们也没用。

解决方案

以ios14、self signed certificate等作为关键字在stackoverflow、apple developer forum找了一圈,发现不少人遇到这个问题,最终碰运气了一堆方案,总算能安装了。

下面简单记录一下配置的关键点。

配置项 配置要求 备注
TLS协议版本 TLSv1.2 基本要求,1.2+
签名算法 SHA-256 基本要求,至少SHA1是不行的
公钥算法 RSA2048 基本要求,RSA2048+
证书时间 按ios13的说法不能大于825天 测试发现,设置10年也没有问题
扩展字段(DNS设置) 在Subject Alternative Name标识对应的DNS 官方特殊要求,只在CommonName标识DNS是不够的
扩展字段(ExtendedKeyUsage) 在ExtendedKeyUsage标识serverAuth 官方特殊要求
扩展字段(IP设置) 在Subject Alternative Name标识对应的IP 在苹果论坛看到的,没有找到官方出处,但试了有影响
扩展字段(basicConstraints) 要标识CA:TRUE,pathlen:0 设置为CA证书,没有特别验证真伪

设置后,如果是公网的话,可以通过一些在线工具来验证,例如https://myssl.com/, 工具箱比较齐全,报告也比较详细。如果没有环境,那可以通过chrome来验证,众所周知,chrome的证书验证是很严格的,安装信任证书(自签名),打开网站后通过看看是不是绿色的,有问题的话,也可以通过F12 + Security这个Tab页来具体查看。

步骤参考

  • 证书生成命令
openssl req \
-newkey rsa:2048 \
-x509 \
-nodes \
-keyout myKey.key \
-new \
-out myCert.crt \
-subj /CN=hello.com \
-config ./myConfig.cnf \
-reqexts SAN \
-extensions SAN \
-sha256 \
-days 365
  • 配置信息
cat myConfig.cnf
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = SAN
extensions = SAN
[ req_distinguished_name ]
countryName = CN
stateOrProvinceName = AA
localityName = BB
organizationName = CC
[SAN]
subjectAltName = @alt_names
extendedKeyUsage = serverAuth
basicConstraints=CA:TRUE,pathlen:0
[alt_names]
DNS.1 = hello.com
IP.1 = 1.2.3.4

参考材料