背景:
K8S由于有弹性缩扩容、资源隔离、高可用、移植性良好等优点,在公有云或私有化项目交付中发挥着 巨大的作用。因此,客户或领导经常要求将应用K8S容器化去生产环境部署。
正常来说,如果只是容器化一个JAVA应用非常简单,我们只需要在Dockerfile的entrypoint或cmd中做一个类似java -jar xxx.jar这种命令,而且由于java应用多是无状态服务,只需写一个deployment,将配置以configmap挂到容器里,再写一个service暴露nodeport差不多就完事。
那么我们如何将一个陌生的应用容器化呢。本文就笔者最近容器化的一个项目谈谈。
应用情况:
笔者容器化的这个应用是公司内部封装的一整套某个中间件的高可用的解决方案。由于是另外一个部门的产品,笔者最初也只有一份的部署运维手册和应用部署包,信息非常有限。启动服务就一个命令,类似 sh <ip1>,<ip2> start.sh。
为什么这个应用的容器化会存在难度呢?
1、执行脚本之前需要先处理一些东西。
2、启动脚本sh <ip1>...<ip2> start.sh这个脚本是针对多个机器的。这种情况下,正常思路,我们需要将脚本在每台物理机上的相同逻辑都做成docker的entrypoin。然而,大致分析了一下,这个start.sh在每台物理机上执行的逻辑都有点复杂,而且这个启动脚本违反单一职责,以这套此为基础,理清楚在每台物理机上的逻辑,再拆写出一个脚本比较浪费时间。
解决方案:
面对这种情况,有一种非常快的方法,可以快速将应用以容器化的方式交付出去。
1、我们可以先在物理机上部署一个标准的服务。然后看看物理机上跟这个服务相关的进程,然后看看这些进程用到了文件,整理一下。
2、基于和物理机相同的linux基础版本的镜像启动容器。
3、将第一步整理好的需要用到的文件都拷贝到第二步拉起的容器里,在容器里完全模拟出一个单机版的和物理机一样的环境。
4、基于第三步的容器,docker commit能得到一个新镜像。这个新镜像具备了服务可以拉起的所有资源。
5、梳理各个进程之间的关系,及梳理哪些配置是动态的。为编写k8s资源做准备。
6、在第4步的得到的镜像基础上再打个新镜像,编写dockerfile。并写个entrypoint脚本,把entrypoint脚本放到容器里,目的是为了容器起来时能物理机环境一样把所有的进程都起来。进程之间依赖逻辑的实现和一些配置的动态修改在entrypoint脚本中体现。
7、编写deployment和statefulset。由于笔者的这个应用有主从之分,所以采用statefulset。第6步梳理的动态的配置和变量可以以ENV的形式或者直接以configmap的形式挂载出来。
8、把POD拉起来,找研发这个应用部门的人确认这个K8S版本的应用是否和物理机上部署的环境一样OK。有问题再调整。
思路总结:
有的人可能觉得low,因为没有镜像分层,不能复用,但是我觉得这种方式是最实际最快的~~
未完待续~~~