一、背景
公司需要提供Saas服务给客户经理通过企业微信进行获客展业,所以需要在企业微信上构建一套营销助手,用于客户经理推销自己的产品。
二、定制镜像
SpringMVC应用跑在tomcat容器上,tomcat封装在docker容器里面,docker容器受K8S管理;所以需要在K8S上构建SpringMVC应用,首先要自定义tomcat容器,然后再把程序放到自定义的容器里面,最后打成业务应用镜像在K8S上运行。
2.1 定制tomcat基础镜像
2.1.1 编写Dockerfile
- 把解压并优化过的tomcat拷贝到centos7.6下的/opt/tomcat
- 拷贝pinpoint agent到centos7.6,下载好的pinpoint-agent已经修改pinpoint.config配置文件中配置为profiler.collector.ip=pp.mg.addr,在宿主机/etc/hosts或阿里云K8S所在专有网络的private zone定义pinpoint服务端地址就可以完成pinpoint客户端上报数据到服务端
- 拷贝arthas-boot.jar到centos7.6,arthas是一款优秀的调试工具,可以很清晰看到指定方法的入参和出参
- CMD为默认执行的命令,如果docker run没有指定任何的执行命令或者dockerfile里面也没有entrypoint,那么就会使用cmd指定的默认的执行命令执行,同时也从侧面说明了entrypoint的含义,entrypoint才是真正的容器启动以后要执行命令,文中的CMD为执行定义好的sysinit.sh脚本,接收位置参数$1,$2。
] # vim Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 1FROM registry.moguyun.com/centos:7.6
2
3ENV CATALINA_HOME /opt/tomcat
4ENV TOMCAT_VERSION apache-tomcat-9.0.26
5ENV PINPOINT_VERSION pinpoint-agent-1.7.4
6ENV RUN_OPTION "-server -Xms256m -Xmx1g -Duser.timezone=GMT+08"
7ENV PNAME "AppName"
8ENV USER tomcat
9
10RUN rm -f /bin/sysinit.sh
11
12ADD $TOMCAT_VERSION $CATALINA_HOME
13ADD $PINPOINT_VERSION /opt/$PINPOINT_VERSION
14COPY sysinit.v6.sh /bin/sysinit.sh
15COPY arthas-boot.jar /opt/arthas-boot.jar
16RUN groupadd -g 1050 $USER && useradd -s /sbin/nologin -d /opt/$USER -M -u 1050
17-g $USER $USER && chown -R $USER:$USER /opt
18
19WORKDIR $CATALINA_HOME
20
21EXPOSE 8080
22CMD ["sh", "-c", "/bin/sysinit.sh \"$RUN_OPTION\" \"$PNAME\""]
23
2.1.2 编写sysinit.v6.sh
- 因为CATALINA_OPTS会被JVM加载,所以我们需要重新定义这个参数
- 定义时区为东八区,接收运行时参数$1,添加pinpoint-agent客户端配置,接收agentId,应用名称$2
- 判断$HOST_FILE是否存在,因为腾讯云是没有K8S集群所在专有网段私有DNS的,所以需要自己写hosts文件然后追加到容器的/etc/hosts文件后面
- 把重定义好的CATALINA_OPTS设置为环境变量,启动tomcat容器
] # vim sysinit.v6.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 1#!/bin/sh
2
3CATALINA_OPTS=/opt/tomcat
4AGENT_JAR=pinpoint-bootstrap-1.7.4.jar
5PINPOINT_VERSION=pinpoint-agent-1.7.4
6AGENT_PATH=/opt/pinpoint-agent-1.7.4
7HOST_FILE=/opt/qwhosts
8
9echo "RUN_OPTION=\"${1}\" PNAME=\"${2}\""
10
11hname=`hostname`;
12agentId=${hname:0-10};
13CATALINA_OPTS="-server -Duser.timezone=GMT+08 ${1} "
14if [ "AppName" != "${2}" ]; then
15 CATALINA_OPTS="$CATALINA_OPTS -javaagent:'$AGENT_PATH'/'$AGENT_JAR' -
16 Dpinpoint.agentId=app-${agentId} -Dpinpoint.applicationName=${2}"
17fi
18
19echo CATALINA_OPTS="$CATALINA_OPTS"
20
21if [ -f "$HOST_FILE" ]; then
22 cat $HOST_FILE >> /etc/hosts
23fi
24
25cat /bin/sysinit.sh
26chown -R tomcat:tomcat /opt
27
28su tomcat -s /bin/bash -c "export CATALINA_OPTS=\"$CATALINA_OPTS\" && cd
29 $CATALINA_HOME/bin && ./catalina.sh run 2>&1 | tee ../logs/catalina.out"
30
2.1.3 制作推送镜像
-
用准备好的Dockerfile在当前目录制作镜像
1
2 1docker build -t registry.moguyun.com/tomcat-jdk8:v6 .
2
-
提送镜像到远程仓库
1
2 1docker push registry.moguyun.com/tomcat-jdk8:v6
2
2.2 定制SpringMVC业务应用镜像
2.2.1 编写业务应用Dockerfile
- 由于程序使用AES加密时,当密钥大于128时程序会报错,需要替换jre下的policy文件,把下载好的policy覆盖tomcat容器里面的policy文件
- 拷贝企业微信小店专有的hosts文件到/opt/目录下
- 拷贝编译好的代码到tomcat容器的webapps目录下
] # vim Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 1FROM registry.moguyun.com/tomcat-jdk8:v4
2MAINTAINER lijun moguyun.com
3ENV SOURCEPATH ./financial-shop-server
4ENV TARGETPATH /opt/tomcat/webapps/financial-shop-server
5ENV RUN_OPTION "-Xms1g -Xmx4g -Xmn256m -Dfile.encoding=UTF-8"
6ENV PNAME financial-d
7ENV limitedPATH /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-1.el7_7.x86_64/jre/lib/security/policy/limited/
8ENV unlimitedPATH /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-1.el7_7.x86_64/jre/lib/security/policy/unlimited/
9ADD *.jar $limitedPATH
10ADD *.jar $unlimitedPATH
11ADD qwhosts /opt/
12ADD $SOURCEPATH $TARGETPATH
13
14EXPOSE 8080
15ENTRYPOINT ["sh","-c","/bin/sysinit.sh \"$RUN_OPTION\" \"$PNAME\""]
16
2.2.2 编写定制化qwhosts
- SpringMVC业务应用会用到MySQL,MongoDB,Redis数据库,在程序中已经定义好别名,在hosts中定义好了实际服务地址
- pinpoint-agent会用到pinpoint服务端别名,在hosts中也已经定义好服务端具体地址
] # vim qwhosts
1
2
3
4
5
6 110.10.8.8 jdbc.mg.addr
210.10.8.9 mongo.mg.addr
310.10.8.9 mongo.readonly.mg.addr
410.10.8.17 redis.mg.addr
510.10.8.10 pp.mg.addr
6
2.2.3 编写制作推送镜像脚本
- 把项目名称,项目分支,当前时间三个参数作为业务镜像的tag用来标识K8S线上环境的镜像唯一性,方便回滚和确认分支
- 通过docker build将当前目录下的Dockerfile打成镜像并通过docker push推动镜像到远程仓库供K8S线上环境使用
] # vim docker.sh
1
2
3
4
5
6
7
8
9
10
11
12
13 1#!/bin/bash
2
3currentTime=`date "+%Y%m%d%H%M%S"`
4echo $currentTime
5projectName=$1
6branch=$2
7echo ${projectName}_${branch}_${currentTime}
8tag=${projectName}_${branch}_${currentTime}
9
10#docker build -t ccr.***.tencentyun.com/work-weixin/moguyun:${tag} . --no-cache
11docker build -t ccr.***.tencentyun.com/work-weixin/moguyun:${tag} .
12docker push ccr.***.tencentyun.com/work-weixin/moguyun:${tag}
13
三、运行镜像
3.1 创建deployment
3.1.1 定义数据卷
- 定义本机路径用来做容器内日志文件的存储,当然也可以不定义,如果不指定数据卷做存储,默认分配主机的临时目录挂载到容器的挂载点
3.1.2 定义实例内容器
- 选择已经做好的SpringMVC镜像和版本,勾选拉取策略【默认使用本地镜像,本地没有则拉取】
- 配置容器内的挂载点【即挂载那个目录到宿主机的目录】,配置CPU/内存限制
- 可以看出,这些环境变量都是在制作镜像的自定义的环境变量,可以修改RUN_OPTION参数动态的修改CATALINA_OPTS参数,实现自定义配置JVM启动时会加载的环境变量CATALINA_OPTS
- Dockerfile里面定义的WORKDIR也被识别出来了,它指定了容器运行后的工作目录
3.2 验证deployment
3.2.1 查看deployment
- 我们的financial deployment跑了6个实例,每个实例下面都对应一个容器组,我们的每个容器组里面跑了一个实例,当然也可以根据业务场景在一个容器组里面跑多个容器
3.2.2 查看服务启动之后的日志
- 查看日志可知自动任务weChatTokenJob已经跑起来了,说明服务启动成功