老实说,这是一个挺大的话题,盲目谈论有点大言不惭,不过,笔记打算从自己的工作经历中聊聊这个话题。
彼时,笔者还在成都,那时Golang还很新,版本还牌1.10以下,容器化在当时的技术领域是一项非常时髦的技术,当时我所在的团队,已经开始尝试服务容器化了,容器的管理平台使用的时开源的容器管理平台Rancher 1.x版本(当时还没有使用k8s,不过运维团队已开始预研),当时团队自动化程度较高,Dockerfile
也不是开发自己写的,而是由项目初始化工具生成Dockerfile及.gitlab-ci.yml
模板,然后经由CI/CD平台(用的是gitlab runner)编辑打包然后部署,整个流程如下所示:
当时测试环境有test
、demo
等,都是相互隔离的,以提交时的分支名确定应该部署到哪个环境,比如当时时test
分支,提交代码之后,应用就部署到test
环境。这一套流程最大的好处是从提交代码开始,CI/CD就开始进行,且中间没有阻隔,所以开发测试的效率非常高,迭代很迅速,这段工作经历是我的DevOps思想的启蒙。
来到杭州以后,第一份工作是在某操做容器化的推进,公司的技术栈以Java为主,推进容器化的动机是因为测试环境非常混乱,希望能够通过服务容器化,减少测试环境的机器,以达到节省成本的目的。(值得一提的是,当时还没有谈到推进容器化上生产这一步,对此我表示很惊讶)。当时测试环境的混乱情况到了何种地步,且我娓娓道来:
其中选择空闲机器这一步,因为机器不足分布不均的有关系,会出现张三将机器上某个应用A杀掉从而部署应用B;触发jenkins任务这一步经常会失败,因为这一步通常是由测试人员去完成的,编译打包过程出现一些问题也在所难免,最后又得找到开发;再说部署这一步,因为应用部署前需要将自己注册到网关,这一步因为某些原因经常出现异常,从而导致部署中断,此时测试人员又得找到运维……我描述的还只是当时所见到的一小部分,这种混乱主要原因在于开发、运维、测试的割裂,各自完成自己所做的那一部署然后就不管了,由于常见的部门墙等因素,跨部门合作也不算很容易,所以经常可见的项目延期上线,以我的角度,DevOps几近于没有,因为我没有看到合作,团队和部门都是各自为政,当然,这也并非个案。
在这种情况下要推进容器化并非易事(话又说回来,要是容易的话,也就没我什么事了)。出于个人经验,你首先想到的是改造CI/CD,将我在前司的研发流程带到公司。于是,从DevOps的受益者变成设计者,我首先完成了一套基于gitlab的CI/CD流程的demo,在团队内做了一次分享,不过可惜的是,当时团队成员觉得思路挺好,就是和现有以Jenkins为主的流程有些差异,不容易为人所接受。现有想想,当时也确实过于激进,毕竟我所接触到的同事,他们也只用过Jenkins,而且由于职能的原因,每个人相对只关心于自己的任务线。虽说有点受挫,不过笔者当时并没有放弃,而是找gitlab的维护人员,希望他们能够安装gitlab runner,不过得到的回复是:我们现在已经有了jenkins,没有必要也不能安装gitlab runner了……
没法,容器化总也要推进,根据当时的服务容器化的需求,当然,是直接上k8s的,我们首先做的一件事情是进行硬件资源评估,然后申请机器部署k8s集群,然后着手公司服务拓扑图,没想到在这一步遇到了难题,由于业务线各自为政,没有一个全局的服务依赖关系,无奈之下,经过商议,为了证明容器化的可用性,只好先将某一个业务线的服务部署到我们的k8s集群中,由于业务不熟悉,期间也花了不少时间在打包以及调试上。
其中渲染资源文件模板本来是可以用helm的chart包来替代的,不过自己写deployment
、service
、ingress
模板其实也可以达到目的,只不过因为要部署到k8s的关系,需要另做一套平台来部署,其实并没做DevOps,只是硬生生的将原有的那一套流程搬到容器化中而已,所以,即使我离职已经一年有余,这一套流程听说也没有最终落地,实在令人唏嘘。
前司某医的容器化之路也是坎坷,项目起步于2018年,容器化的动机据不完全了解是为了让公司跟上技术的发展潮流。公司技术栈同样以Java为主,不过还有少数php、golang以及python应用(当然,我用golang写的监控服务必须是容器化的)。整个流程如下所示
所谓个性化部署参数这里要特别解释一下:就是写一个CRD,这个CRD定义了一些参数如:appname、requests、limits、port等,简单说就是将deployment的参数以CRD的形式暴露出来,最后形成所下所示的k8s资源:
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: myapp
labels:
appname: myapp
spec:
replicas: 1
template:
spec:
containers:
- name: myapp
image: myapp:5.0.3
ports:
- containerPort: 80
resources:
limits:
memory: 600Mi
cpu: 1
requests:
memory: 300Mi
cpu: 500m
……
如果定义一个服务也有三类资源如:deployment
、service
、ingress
,那么这个CRD的作用就在于依据入参生成这三类资源并且部署到k8s集群中,由controller来保证每个应用,这三种资源都保持与CRD的定义一致。这也是容器化的一种思路,也是典型的CRD应用。
坦白说,就算不写CRD,也能达到这个目的,写CRD的目的是为了将应用模型进行统一,形式上就是尽可以将通用的资源参数暴露出来以供个性化使用,无奈之处在于还是在走容器化适配应用的路数,还不是将应用进行容器化适配,比如,dubbo的服务发现由zk提供,不过zk目前是在k8s外围,从功能上来讲,zk一定程序上跟k8s的service存在重复;应用内存使用是4G起步,虽说是为了保险起见,不过,这说明服务本身过重了,当然,硬件资源充足的情况下,这也不算是很大的问题;dubbo有自己的负载均衡,jvm可能也能限制资源的使用,作为容器化的拥趸,我不禁对java容器化的意义产生了一丝怀疑,诚然,k8s可以做hpa,可以自动重启,这些都是优势,但是到底真正的收益在哪里呢?
(截止文章发布之日,前司的容器化之路依然还在进行中)
容器化固然只是一句口号而已,而这句口号,却常常伴随着DevOps这个词语,依我个人的浅见,DevOps是一种开放合作的文化,它打破了软件开发过程中的各个职能界限,最终是为了提高工作效率,从提高工作效率这个角度来看,DevOps在我的职业生涯中依旧少见。
毫不掩饰的说,我对Jenkins有一丝偏见,因为我从事的公司中,使用Jenkins的方式无一例外,都是反DevOps的,设置流程的障碍,需要多方介入,但这种使用形成了一种习惯,我并不反对Jenkins,但如果使用Jenkins让事情变得更容易,我自然欣然接受,比如使用gitlab的CI/CD,就让人觉得很舒服,扩展性也挺好,这也是一个习惯问题。
前司的容器化之路依旧在进行中,而我,也有自己对于容器化的想法,如下所示
以轻巧的k3s作为CI平台,可以将gitlab runner接入进来,当然,每个应用有自己对于CI的需求,对于资源的需求,所以项目repo中也应该包含.gitlab-ci.yml
、Dockerfile
等,选择k3s来做CI的运行平台自然是为了利用k8s的资源调度和扩展性了;选择gitops是为了将CI/CD解耦,这样,就有DevOps内味了。
自己的一点浅见,欢迎各位拍砖!
有疑问加站长微信联系(非本文作者)