高校外包公司自动化部署生存指南
菜你都做好了,如何端给用户?
前言
《外包公司,等你长大》这一篇预告很久了,一直没有成笔,今天写的可以算是其中一小点,只是聚焦于应用分发和交付的问题,为什么会写这一篇,这一切,都要从一只蝙蝠说起。。。
因为疫情的缘故,高校最近密集上了包括健康打卡、不见面办理、视频会议和网络教学等相关的应用。各个信息化部门也乘机在里面夹带了各种私货,包括推广某些平时很难推动的平台,对师生进行信息素养教育提高等等工作。每一次危机,其实都伴随着机遇,就看你如何能够及时把握。
这些应用都有高并发高流量的需求,而且时间紧,需求变化快。如何快速平稳交付是一个比较大的问题。
在这里,云平台也冒出来了。高校原先是比较排斥云的,不知道什么缘故,大家总认为,物理上在学校内部,才是自主可控的。但是这次不同,师生都在校外,只有云和CDN才是最接近用户的。
云存储和CDN有毒,用了就停不下来。
然后在我最近跟他们交流中,我发现了一些应用交付上的问题。
大部分外包公司,都还是很原始的手工部署,而且部署人员的技术水平和安全意识在公司整体属于比研发低一点。
如果从DevOps来说,这也有研发的锅。研发开发完成,哪管你运维人员怎么部署。
外包公司总是向我们拿更多的CPU、更多的内存、更高的空间占用,拿硬件负载均衡,拿Oracle。因为这些在我们这边是增加成本,但是对他们是节省成本,节省软件框架优化的成本。外包公司还会向我们拿更多的系统维护停机时间,更长的小版本更新周期,更长的操作系统和基础软件更新周期。这些在我们这里是影响用户体验和系统安全的,让信息化部门被用户打低分的。对他们来说,还是节省成本。为了性能,CPU、内存等等我们也会愿意给,但是这要有一个度,因为一个应用,如果不从框架或代码方面去做优化,给多少资源都是没用的。甚至于,有些应用,我们想给更多的资源,但是他消耗不了。
所以我认为,如果可以,外包公司请尽快迁移到自动化部署上去吧。如果能直接二进制打包War、Docker给我们更好,因为现在存储实在太便宜,我们不再需要为了解决空间占用而带来的各种依赖共享、动态加载、各种不同版本化的库。然而大的外包公司,历史包袱重,转身很难,如果一个老的CTO,只求稳不寻求技术更新,那新技术就很难推进。迁移肯定是有阵痛的,短期内成本是上升的,但是长期会以另外一种形式补贴你。对客户来说,能给你提意见的才是优质客户,批评越重,那都是真爱,希望你成长为101年的企业,毕竟你死了,大家都不好过。
自动化部署
我们维护400个学校的2000台机器
这时候更需要自动化部署,自动化部署具有高效率和较快的部署能力,而且不容易出错。不同学校不同的配置文件进入.gitignore隔离。当然,自动太自动了,脚本出错影响面也很大。这是另外一个问题。
比如,自动化,也不推荐只用一台主控机。我们一般自动化部署,会有Test机器列表,Staging机器列表,Production机器列表,通过不同脚本跑,假设你使用工作用机来当主控机,所以你所有机器列表要对主控机都开通SSH防火墙,然后有天你手抖了,正在Test上修改配置,然后跑了Production脚本,就悲剧了。所以一般都建议,主控机根据不同环境分隔开来。
Test或者Staging环境
这些环境应当和Production环境一致,然后定期同步数据库和共享文件。现在一般很少这么做,成本较高,或者Production环境部署10台,但是Test环境才2台,而且数据不一定同步。这些都会造成一些问题,比如压力测试可能就做不了,查错还是OK的。
多个环境一定要非常小心,特别是rsync,mysqldump,再困再累,也要对命令行左右路径double check一下。
小版本升级、迁移正确的打开方式
如果完全按DevOps的理念,不可变服务器,每次升级,都重新构建一台全新的服务器,然后扔掉旧服务器,这个很多学校还做不到。如果还遇到大版本升级,或者有架构方面大的升级,还需要更长的停机时间。
- 提前一段时间通知用户即将停机维护
- 在进入停机模式,Nginx接管所有流量,给用户一个维护模式页面
- 如果可以,应先在备用环境演练迁移时间,将所有时间压缩到最低,比如数据库可以使用binlog传输变化量就不需要整库倒数据,文件传输rsync传输变化量等等。
能不能从Web小版本升级
用过WordPress的人都体验过从Web安装,从Web自动升级,能否引入这种机制,不要再从SSH跑命令升级了,让升级更傻瓜一点。当然,要做到这步,考虑需要更多,比如安全性问题,脚本运行超时问题等等。
VPN和堡垒机
我们维护的院校,60%是需要VPN的,30%是需要堡垒机的,光VPN软件就几十种。
当前维护一个学校,只能登录1个学校的VPN,比如我在维护厦门大学的时候,就无法同时部署清华大学、北京大学
这里面存在2个误解。
- 有责任的外包公司,如果看到学校的服务器维护居然可以不用VPN,不用双因素认证的堡垒机,应当不是窃喜而是告知学校,这样子很不安全!
- 是可以同时拨号10个学校VPN并通过路由指定网段走哪个VPN网关的。
当然,这有学校的问题,90%以上的高校的VPN设置手册可能都是一大堆图文并茂告诉用户如何一步步设置VPN,很多管理员不知道其实可以直接打开PowerShell窗口(Windows8、Windows10以上)输入以下命令一键配置,并且拷贝黏贴保证不会出错:
Add-VpnConnection -Name "XmuIKEv2" -ServerAddress "mask.xmu.edu.cn" -TunnelType "IKEv2" -EncryptionLevel "Optional" -AuthenticationMethod Eap -RememberCredential
注意后面一定不要有-PassThru,宁愿再跑一次Get-VpnConection,否则会污染rasphone.pbk文件。
针对以上外包公司来说,他只要加参数 -SplitTunneling $True 取消默认网关,然后就可以通过 Add-VpnConnectionRoute 。这个方案比route -p ADD好的地方在于,不会永久破坏你的路由表,只会在拨号VPN后生效。或者你也可以每次拨号VPN后手动route ADD。
查看你加了多少路由没有Get-VpnConnectionRoute命令,通过以下查看:
$conn = Get-VpnConnection -Name "XmuIKEv2"
$conn.routes
SaaS、Semi-SaaS、On-Premises
如果能打包成容器部署更好,当然容器也在不停演进,安全性不是太乐观,内核漏洞和容器漏洞都会导致容器逃逸。最新的有安全容器,在容器外面再套一层轻量级的虚拟化都是可以研究的。
因为交付很麻烦,有些外包公司直接给你提供SaaS服务。也有提供半SaaS服务,你多给点钱,他帮你在云平台开虚拟机部署,甚至还可以给你机器密码,纯的SaaS你是拿不到数据库权限,半SaaS可能可以拿到。但是这里就要注意到安全问题,半SaaS服务为了方便,他们可能直接SSH端口直接对外全部开放,不走堡垒机等等问题。
多台Web
Web不是说想扩就扩的,Web要变多台,你必须处理几台Web共享数据和状态问题。而且Web扩完后日志也不是集中的。多台Web升级代码也是比较麻烦的。这里一般采用滚动升级或者使用负载均衡引流灰度升级。比如我部署的一个应用,前端一台Nginx,后端10台Web,我单独划出一台给我自己在线调试查错,就简单通过Nginx判断remote_addr是我的IP,直接引流到某台Web。
整个应用对外也应当对CDN友好,最近上了CDN我才发现,CDN针对动态网页、静态资源、流媒体点播、云存储等不同缓存的价格是不同的,所以有能力应当使用多个域名隔离这些资源,使得对CDN友好,节省学校的带宽成本。
共享Session
编程语言一般都可以设置Session保存到一个集中的数据库,比如关系型数据库,甚至内存数据库。当然,你如果保证可以ip_hash到同一台Web,Session可以直接放在Web,但是这个不够健壮。如果Web当了一台,Session会丢失。
共享Cache
一些全局的Cache也可以考虑类似Session来处理。
Cache
必须大量采用Cache。页面必须解构,动态内容和静态内容分开,缓存时间不同的分开,JavaScript、Image全部版本化,输出Cache-Control。我最近在安装Moodle,Moodle这方面做得非常完美。
共享存储
NFS已经进化到v4了,但是因为有网络参与,速度还是不容乐观,考虑用户传一个1G的文件到NFS,他需要先经过CDN->Nginx->Web->NFS,至少Web和NFS会有两次落盘读写,时间会被延长20%。所以这个需要权衡。当然,如果有异步机制,这个时间可以省下来,后端多台Web再和NFS进行rsync同步。或者直接上分布式文件存储,云存储,并且跟CDN做好对接,应当可以缓存有权限判断的文件。
数据库
不要一上来就拿Oracle,是否可以采用MySQL,分库分表?读写分离?
版本化
版本化一切,包括源代码和数据库。如果用过开源软件,或者类似Django的Database Migrate机制就会很清楚。数据库有自己的版本,一个版本字符串写在表结构内。Web来访问必须匹配版本号,否则无法运行,提示升级。这样子可以防止,假如你有10台Web,但是运维没睡好,只升级了其中9台,漏了一台,也不会影响数据库的安全。这10%的用户就会收到一个提示,也可以更快发现错误。如果你可以把学校代码也写入源代码和数据库,就不会出现清华大学的代码误传到厦门大学并跑起来了。
定制呢?改首页呢?
这个我们也遇到过,明明一个错误已经修正了,怎么又跑出来?原来是运维升级错版本了,覆盖客制化内容了。升级好了,首页怎么乱了?客制化忘记修正了。所以这里一定要做好各个不同学校的内容的隔离,使用配置文件。git flow要认认真真去学习,如何做个主master仓库,如何develop,hotfix,feature,release,不同学校的release版本。
当然对于学校来说,尽量减少定制,即使要定制,也要争取定制内容进入公司产品主仓库。定制是恶魔。
压力测试
一般公司会说我们在哪个学校试过压力测试,可以达到多少并发等等。但是这个不准,各个学校硬件环境和数据库内容差异很大,没有可比性,如果可以的话,尽量应当在本地直接压力测试。
因为压力测试录制脚本很麻烦,还需要处理登录问题,如果可能,应当有专门的代码,直接从数据库生成JMeter脚本,对登录做Hack,直接通过某种机制绕过登录,在跟生产环境基本一致的服务器上做压力测试。也就是,压力测试也是要自动化,想要跑就可以跑的。
监控和日志
在我以前说过,如果请外包公司做运维,应当将监控和日志向运维公司开放。因为你一旦将Web拓展到多台以后,查找Log是非常麻烦的,你很难知道自己被ip_hash到哪台Web了,所以必须中心化日志。并且要定期查看500错误,不要等用户来报。
很多外包公司认为这个是学校的事情,确实,监控和日志是安全合规的事情,学校一般也会已经建立,但是是否可以分权限给你查看这个得看学校买的日志集中化产品的支持,甚至得看你能否进入学校安全核心网段。所以如果有能力,应当自己采用开源软件也建立一套简单的日志采集工具,只给自己定位错误使用。
备份
备份友好也要考虑。比如你将文件都写入数据库很省心,会造成数据库很大,很难备份。或者文件写的路径尽量按上传时间分离而不是某个奇怪的hash算法。当然备份学校也会有一套自己的规则,可以不用考虑太多。知悉学校的备份策略,也为自己运维人员操作留下后路。