
研究生实习期间,完成第一次自主开发产品新模块,老大要求做一次部门分享,在此写下这篇文章。
1)轻量级的虚拟化:每个微容器里都有一个微服务或独立应用,例如你可以将Tomcat运行在一个Docker上,而MySQL运行在另外一个Docker,两者可以运行在同一个服务器,或多个服务器上。未来可能每个应用都要Docker化。
2)简化配置:这是Docker初始目的,虚拟机VM最大的好处是基于你的应用配置能够无缝运行在任何平台上。Docker提供同样类似VM的能力,但是没有任何副作用,它能让你将环境和配置放入代码然后部署,同样的Docker配置能够在各种环境中使用,这实际是将应用环境和底层环境实现了解耦。
3)代码管道化管理:能够对代码以流式pipeline管道化进行管理,从开发者的机器到生产环境机器这个流程中都能有效管理。因为在这个流程中会有各种不同的环境,每个都可能有微小的区别,Docker提供了跨越这些异构环境以一致性的微环境,从开发到部署实现流畅发布。
4)开发人员的生产化:在一个开发环境,我们希望我们的开发环境能更加接近于生产环境,我们会让每个服务运行在自己的VM中,这样能模拟生产环境,比如有时我们并不总是需要跨越网络连接,这样我们可以将多个Docker装载一系列服务运行在单机上最大程度模拟生产分布式部署的环境。
5)应用隔离:有很多理由你需要在一台机器上运行多个应用,这就需要将原来铁板一块monolithic的应用切分为很多微服务。实现应用之间的解耦,将多个应用服务部署在多个Docker中能轻松达到这个目的。
6)服务合并:使用Docker也能合并多个服务以降低费用,不多的操作系统内存占用,跨实例共享多个空闲的内存,这些技术Docker能以更加紧密资源提供更有效的服务合并。
7)多租户:Docker能够作为云计算的多租户容器,使用Docker能容易为每个租户创建运行应该多个实例,这得益其灵活的快速环境以及有效diff命令。
8)快速部署:Docker通过创建进程的容器,不必重新启动操作系统,几秒内能关闭,你可以在数据中心创建或销毁资源,不用担心额外消耗。典型的数据中心利用率是30%,通过更积极的资源分配,以低成本方式对一个新的实例实现一个更聚合的资源分配,我们很容易超过这个利用率,大大提高数据中心的利用效率。
转载于:
https://blog.csdn.net/shursulei/article/details/74296097https://blog.csdn.net/shursulei/article/details/74296097https://blog.csdn.net/shursulei/article/details/74296097
部门安全测试提出的安全漏洞,如下:
当前模块功能主要是将自动化的安全测试脚本传入到python虚拟环境中运行。
安全测试提出这块风险较大,然后架构初步的解决方案是让我把这个模块全部封装到docker容器中:从脚本的生成到提取到运行到结果返回前端都从当前框架中拿出来在java8这个容器中执行。
由于刚来部门实习,对各功能模块业务不熟悉,能力也有限,以及部门没有用docker做容器化部署的先例,还有部门大佬们都没时间去碰这块的知识。我决定潜下心来按部就班打好基础,学习docker这块的知识,厚积薄发。(可能公司也没想我能搞出来,让我打发打发时间,做出来血赚,做出来也不亏)
2.学习过程主要还是在某站上搜了一下docker然后挑了一个播放量最高的进去开始学习,以及配合菜鸟教程上指令。开始学习时候,还是觉得有点难度,但到开发结束才知道,学习知识是最轻松的,而最难的是如何应对具体问题去解决各种bug。
话不多说,直接从第一个dockerfile开始说起!
1.1开发1.0在经历过半个多月对docker的初步学习,我了解了想要实现具体需求的容器你都是需要自己在基础镜像(python、java、centos等)去构建满足需求的镜像。于是带着这样的思路,我初定了第一个"幼稚1.0”方案:把模块的所有内容直接扔到java8中,然后启动容器执行jar包。(太特么天真了!)
第一张dockerfile如下:
FROM java:8 #基础镜像java8 MAINTAINER dockerfile1.0 #作者 ADD /script-engine/. / #添加本地文件script-engine到镜像的根目录下 RUN /bin/bash ENTRYPOINT ["java","-jar","/script-engine.jar"] #执行jar包
一切顺理成章合理自然,只要在dockerfile的目录下执行docker build -t [image-name] . (有个点),即可生成镜像,然后run指令去运行一个容器就可以了。
然鹅,这么大公司随便开发个模块这么简单??想多了把!
jar包执行结果如下:
模块脚本执行结果如下:
虽然显示完成,但逻辑正常的化应该会返回调试信息。
无论在大模块上怎么执行脚本,jar包的日志是没有。(只要不傻都应该能明白里面有很大问题了吧。)
1.2问题分析1.01)在我自己明白自己对功能模块不了解的前提下,我需要去了解模块原码,以及一些细节。
2)我有点急性子,在每天的开会中什么成果都没拿出来使我更加急于求成。
静下心来,去虚心请教开发这个模块的前辈,发现他是通过配置文件里的ip地址去连接主模块的内网才能让jar包里的模块连接上主模块,具体如下:
(新版本改为连接nacos的地址)
1.3问题解决1.0第一阶段我是以模块之间连接上为里程碑。在我的不懈努力下,终于springboot可以报异常的日志了(虽然主模块还是显示测试通过,不输出调试信息):
注意这个EOF,虽然到完成这个功能我都不知道具体是什么意思,但这个地方的标签对我寻找错误原因很有帮助。
忘记在一次组会还是和这个模块的负责人的讨论中,我才明白这个脚本运行使用的是python环境。当然归根结底是因为我急于求成,没有回归源码,分析逻辑。这么一想就明白了,之前的安全测试脚本知识获取到了并没有执行。带着这样的思路,制定了在java8镜像中手动构建python环境再执行jar包。
一开始为了省事去网上找了一些python-java-maven的images,但是不是有问题就是只能传jar包,甚至连文件挂载都无法实现。
于是我开始了自己整合python和java环境到容器。
先是尝试在原有的java8容器中安装python,在网上找了很多方法,都没办法下载甚至很多指令在容器中都无法使用(容器的精简化、小而专)。眼珠一转,计上心来,换个python2.7的容器(模块使用的这个版本,目前已经停更python2.7的容器),在这个容器里离线搭建java环境,于是有了第二张dockerfile。
第二张dockerfile如下:
FROM python:2.7 MAINTAINER dockerfile WORKDIR /script-engine RUN mkdir /usr/local/java ADD jdk-8u271-linux-x64.tar.gz /usr/local/java/ ENV JAVA_HOME=/usr/local/java/jdk1.8.0_271 ENV JRE_HOME $JAVA_HOME/jre ENV CLASSPATH $JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH ENV PATH $JAVA_HOME/bin:$PATH VOLUME /script-engine ENTRYPOINT ["python"] #容器启动可以直接执行python文件
搭建过java环境的都很熟悉了,不多解释,其余基本和第一张一样。
执行结果依然没有多大改变。
2.2问题分析2.0依然是去回归源码分析代码逻辑,找到执行shell命令的脚本,如下:
代码分析:在启动jar包后里面有功能执行这个脚本,调用python的virtualenv的包,执行脚本。
我分析是容器里的脚本寻找虚拟环境径不对,没找到虚拟环境包。
2.3问题解决2.0进入容器寻找python虚拟环境的包
启动容器,建议用docker exec -it [container-name] /bin/bash,直接进入work_dir,不然会直接进入编译器。
慢慢寻找python包的路径,终于找到了!
很遗憾,没有虚拟环境。(回过头再看,大概因为python容器本身就是隔离的状态,没必要再在容器里装入虚拟环境了)
正打算第二天加入虚拟环境的包试试,在上开会讨论了一下问题,老大说这样做两个环境的代价太大(镜像也很大),直接在docker里执行python脚本返回结果就行了。
好家伙,又一脸懵逼了,当然老大也提示了,可以在脚本中执行docker指令时参数化传参。
带着2.0的疑惑、蒙圈,我来到了3.0的开发。学习了一下传参执行docker指令。docker是支持传参执行的,毕竟也是shell命令。
带着这样的修改脚本的思路,我开始了第三轮的开发。
因为整个模块不进入docker,现在我只需要一个python2.7的容器就可以了。
于是有了第三张dockerfile:
FROM python:2.7
MAINTAINER dockerfile
WORKDIR /usr/work
VOLUME /usr/work
ENTRYPOINT ["python"]
接着就是解决将脚本传入python容器的问题了,查找一下代码中代码中执行虚拟环境的脚本并改成在pthon容器中执行。
启动脚本的代码语句:
我只需要修改virtualenv.sh这个脚本里的指令即可,修改后:
修改完成以后,执行结果依然没有更改,但是日志异常变了:
说明是有效果了。
3.2问题分析3.0返回脚本看看是否有逻辑问题,发现docker指令的最后一个参数有问题,应当是文件名,而不是文件路径。粗心大意!!!
3.3问题解决3.0找到文件名的参数,传入脚本。
修改后:
再次启动主模块,执行脚本,结果如下:
终于,输出脚本结果了!泪目!但只是在环境外去启动jar包连接主模块成功了,接着还要写入环境。
除了以上提到的主要问题,在整个开发过程中还有很多很多细节的问题,例如:
1)外部jar包连接nacos的倾城成功后,我开始写入环境。写的时候发现这个功能模块的权限不是root,导致docker指令无法执行,但我在测试的时候测试的docker -version指令,是可以执行的,因为docker -version指令不需要root权限,导致我的docker容器无法启动,也就无法执行。之后切换了模块的ini文件里的分组权限到root,执行成功;
2)在模块ini文件修改后需要使用socctl update moudle-name指令重启模块,而restart是无法让修改的ini文件执行的;
3)传参给docker指令添加soar_temp_script_env=$2这个环境变量时,需要传入字符串格式(类似soar_temp_script_env='content',$2本身是json格式),开始使用了很多的转义符在参数$2外面加上单引号,后来发现docker报错环境变量格式不对,研究发现传参时是默认字符串格式的,不需要加单引号;
4)在执行docker run指令时一定要用--rm(即用即删模式)或者-dit(后端交互运行模式)模式,如果用-d模式则会返回容器id而不是脚本结果,主模块无法解析。
5)还有自动化安装docker和镜像打包导入导出的问题这里就不多赘述。前一个问题对我使用Linux和脚本语言有很大的提升;后一个让我明白docker真的很“便携”。
这是目前实习期间做的比较有深度有意义的一次模块开发,让我有了很大的提升和感触,比如说:
1)刚工作的新员工,能力有限,业务不熟,一定要多问、多试、多尝试沟通。我周围的大哥都很牛也都不摆架子,而且也很乐意去帮助你,但是自己的态度一定要谦逊,有请教的样子。
2)仔细回顾,理顺逻辑。代码开发这块是个很细致、很讲逻辑的事情。有时候写着会陷入局部的思维定势。
3)学习能力很重要。互联网企业更多时候选择的是学习能力,而不仅仅是开发能力。
4)技术方面,本身我的基础不算好,所以技术方面的提升还是很大的。特别是Linux服务器操作上,现在使用起来基本没问题(大学的时候基本用不上,所以大学学的一塌糊涂)。
用我没有思路的一筹莫展的时候,老大给我的tip来结尾吧。“在你没有思路、一筹莫展的情况下,那一定是你对某块知识存在盲区了。”