前言
距离vpc和容器化过去了快一年, 一直想要完整回顾梳理下整个过程, 最近准备进行swarm->kubernetes的二次迁移, 正好借由这次契机重新回顾下这段历从最初原始时代到vpc,swarm容器化到k8s的经历.
原始时代
16年7月从上家游戏公司离职, 来到了目前的互金公司, 成为唯一的运维, 此时公司java开发人数已经有几十人... 运维的技术栈也由php转移到了java, 刚开始的时候有些不适应和孤独感(只有自己一个运维, 交流主要就是招我进来同时也是前期负责运维这块的CIO, 刚开始下发完任务后交流也不多), 花了一段时间适应和熟悉后, 感觉问题颇多.
现状是开发同学有很多, 但是运维就一个, 初期运维这块内容由CIO兼顾, 同时CIO还是整个架构的主导者和主力程序员. 已有的100多个ECS由puppet下发配置, puppet agent默认半小时刷新一次.
应用类型主要为spring + dubbo, tomcat + nginx
比较关键的几个问题如下
-
经典网络问题: 公司所有计算资源均在阿里云上, 不过阿里云当时并未推出vpc, 所有资源都在经典网络, 直接导致了如下的问题
- 安全问题: 经典网络各租户ip之间并不能保证真正的隔离, 有一定风险, 不过CIO安全公司出身, 很强烈的安全意识, 所有ECS都开启了iptables, 只开放了自有节点的访问, 规则由puppet统一下发, 但是agent半小时才会自动刷新, 过程并无任何监控, 是否生效完全随缘, 而且puppet主机列表是手动维护的一个list文件, 漏没漏很难说.
- 网段问题: 节点都是阿里云自动分配A段的随缘ip, 一个节点一个公网ip, 意味着出口ip各不相同, 新增一个节点, 要加一堆白名单(rds,drds,slb,nas等等),内部内网应用等资源还好说, 调用阿里云api还可以自动操作下, 要是涉及到第三方要报备的时间就很难控制了, 这个导致我们新增节点非常痛苦, 加一次白名单就很要命了, 只能提前部署好一些备机以防万一,平时在备机上跑一些不太重要的任务.
-
项目部署, 有一个专门的编译服务器, 上面分了testbuilder和pordbuilder的用户, 对应测试和线上的构建用户, 开发同学自己登陆到编译服务器用脚本编译和拷贝到NFS目录, 然后到对应的测试或线上服务器一台一台的用NFS中的部署脚本部署
-
各种冲突:
- lib冲突: java同学抽出来的lib包很多, 虽然有maven私服, 但是所有java的lib包全部都是SNAPSHOT版本, 而且基本没有上传私服的习惯, 一旦有公共lib改动在测试环境编译了, 很容易就会导致其他开发同学躺枪.
- 测试环境的资源冲突, 测试环境一共只有有4~5台服务器, 各种tomcat和端口满天飞, 根本无法识别, 该起的没起来, 本来应该停了的跑起来了.
- 代码冲突: 部署脚本都是自己维护, 没有统一模板, 内容千奇百怪, 分支切来切去, 而且都是用的testbuilder和prodbuilder用户, 完全不知道谁之前到底干了啥, 代码冲突也经常发生, 维护完全靠自觉.
- 发布太随意: 开发同学自己掌控线上服务器部署能力, 有时候发布略随意, 不吭声的把未充分测试代码发布到线上导致问题, 事后出现异常才体现出来
- 环境不一致: lib包繁多并且都是SNAPSHOT版本,如果涉及改动的lib太多,测试环境测试正常版本的lib状态,到线上编译的时候不一定和测试一致,就会导致报错.
- 发布时间太长: web基本项目都使用了slb, 部署的流程则是, slb权重调零->跑NFS里的部署脚本(停止应用, 备份老的代码, 从NFS复制新的代码, 启动应用)->挂回SLB,节点多的部署一次可能半小时就没了, 万一要是还有问题需要回滚, 或者高频次发布, 完全就耗在这种重复的事情上了.
-
- 基础服务版本差异: 由于没有标准化模板, tomacat或者nginx之类的基础服务的版本也是千奇百怪, 当中配置文件的差异就更是玄学了
-
权限控制:
- 服务器权限: 有一个现成的中央跳板机, 每个开发同学有一个自己的账号, 应用服务器则是统一使用的xxxx用户, 能否登陆应用服务器, 取决于应用服务器上是否加了跳板机上对应开发的key,开发同学登陆到应用节点后基本就不可控了, 都是同一个账号, 无法区分谁干了啥. 而且当时puppet里面配置的分组只有测试和线上, 要是加一下登陆的key整个线上环境节点的登陆等于全开放了
- 数据库权限: 由CIO直接在数据库开通个人的数据库账号, 通过跳板机创建ssh转发, 用内网ip以跳板机身份去访问RDS, 起了一个简单的tcpdump进程对内网网卡抓包,用perl分析,可以获取发出的明文sql,查起问题来很麻烦, 而且一般是事后了.
-
配置管理:
- 应用的文件配置: 各种properties文件, 项目内resource目录下分了common,dev,prod文件夹, mvn编译的时候传入参数类似 -Ddev 参数来获取对应环境的配置文件. 不过dev环境配置包括账密之类的都是直接写死在文件里提交git, 线上配置则是用占位符比如 {DB_PASSWORD},在编译节点部署的时候,通过脚本替换占位符替换为真实的值.不过既然能登陆编译服务器, 稍微机灵点的看下脚本内容就能找到有着所有明文配置的源配置文件....替换后的应用配置文件也依旧是明文的,到应用服务器或者NFS上还是一览无余, 加上服务器权限开得很奔放且无审计, 组合起来真是灾难. 想想万一有个好奇的看到了源文件配置好奇在服务器上连了下里面数据源或其他内容, 你怕不怕
- 应用内的配置: 这种是应用在启动后读取的实时配置, 现成有个superdiamond,但是是单点的, 整个环境的应用配置都堆在一个页面, 页面加载都要等好久, 没有版本管理,不好回滚, 热加载也是随缘, 有时候改个配置还是要重启. 同样也有明文配置的问题.
-
监控:
- 业务监控: 有一个自研的业务监控系统
- 系统监控: 基本没有.
上面这些问题刚开始的时候用一些粗暴的方式去缓解:
- 监控: 部署zabbix对系统和进程信息进行监控, 加了发现规则自动获取tomcat进程加入监控(经常性线上应用跑挂了不知道, 这个效果还不错), puppet dashboard获取agent节点配置刷新的状态,至少改完配置后不是一脸懵逼傻傻的等, 有时候想要快速生效, 就直接用ansible去批量刷puppet agent.
- 权限回收: 线上应用服务器权限回收, 对已有节点分组, 按需根据应用组或者项目组授权. 编译服务器权限线上编译账号prodbuilder权限回收重新分配, 让开发同学权限尽量最小化.
-
流程和标准化:
- 线上核心应用禁止私自部署, 统一提工单到运维同学, 周知项目相关同学, 由运维同学部署(导致的结果就很直接了,不少时间耗在这了,不过确实因为私下部署而导致问题的情况好了很多)
- tomcat,nginx等应用版本和参数确定好作为模板后放到NFS,后续应用都由模板创建.
- 线上发布的lib统一为master分支, 应用使用online分支.非充分测试的提交禁止合并到部署分支.后续比较重要应用的部署都是运维同学控制,还比较好控制.
- 配置中心: 换成了spring cloud config, 有点重, gitlab全家桶加上开发同学自己写的客户端. 好处是依赖gitlab有了版本管理, 热加载不再是玄学, 但是依旧有着单点的问题,而且客户端不太稳定, 造成了几次大规模出错.
- 提前部署: 需要报备三方的应用, 提前部署起来, 平时先不启动, 节点上可以先跑不太重要的服务.需要扩容的时候直接更新最新代码启动后挂载到对应slb提供服务.
探路
当然上面列出的都是缓兵之计, 大部分问题还是存在, 在前几个月懵逼和饱受白名单问题煎熬后, 慢慢打起了vpc迁移的算盘.
这个迁移很大的一个问题就是, 如何将VPC和经典资源打通呢?下篇继续