Takin一键部署教程:https://news.shulie.io/?p=3661
在使用Takin时,绕不开接入探针的问题。目前大多数的企业系统应用均部署在k8s平台容器,通过镜像部署方式来接入探针是比较简单的方式,但这种方式也有自己的缺点:
- 每次探针升级(bug或者新功能)都要重做基础镜像
- 基础镜像需要经过公司内部的安全扫描
- 应用需要选择新镜像,重启后才能完成升级
- 其他探针也使用此方式时,需要防止相互覆盖
有没有什么接入方式可以绕过这些问题呢?
这就是今天要跟大家分享的内容——无侵入式容器化探针接入。
技术方案概述
应用场景举例:一个Pod里部署一个镜像,镜像不能重新打包,不能挂在宿主机目录,在这个前提下要使用探针。
解决方案概述:可将探针目录打进一个镜像,部署到应用所在的pod里,修改k8s的yml文件,生成一个共享数据卷,在探针镜像启动成功后将探针目录拷贝到共享数据卷中,这样在启动应用镜像时就可以通过共享数据卷来获得探针的目录以达到加载探针的目的。
具体实现步骤
1.打探针镜像
探针Dockfile
#基础镜像通过java8来的
#根据系统的类型选择合适的镜像,这里用的是openjdk:oraclelinux8
FROM openjdk:oraclelinux8
#将当前文件中所有*.jar 拷贝到项目的app.jar中(这个app.jar是自己生成的)
COPY app.jar /app/shulie_data/app.jar
COPY simulator-agent /app/shulie_data/simulator-agent
#映射地址
CMD ["--server.prot=8080"]
#暴露端口
EXPOSE 8080
#执行命令java -jar
# ENTRYPOINT ["java","${JAVA_OPTS}","-jar","/app.jar"]
ENTRYPOINT java -jar /app/shulie_data/app.jar
在Dockerfile当前目录,拷贝应用包到当前目录, 命名为app.jar,执行如下命令生成探针镜像:
docker build -t runoob/ubuntu:v1 .
这个镜像的主要目的是将探针目录放入到Pod里,实际的app.jar不需要什么内容,只要一个能运行的jar包就行,这个更多的是测试使用,实际其实并不会用到。但探针在打进去之前需要做好准备,所有相应的配置文件都要配置好,打进镜像就不能调整了。
探针的空应用可以用这个: 由于附件无法上传请添加小树回复关键词【app.jar】获取空应用包
应用Dockfile
这个镜像是用来验证共享数据卷的技术方案可行性的,是一个demo应用,非必需的。
#基础镜像通过java8来的
FROM openjdk:oraclelinux8
#将当前文件中所有*.jar 拷贝到项目的app.jar中(这个app.jar是自己生成的)
COPY *.jar /app.jar
#映射地址
CMD ["--server.prot=8080"]
#暴露端口
EXPOSE 8080
ENV JAVA_OPTS="\
-XX:MetaspaceSize=256M \
-XX:MaxMetaspaceSize=256M \
-Xbootclasspath/a:$JAVA_HOME/lib/tools.jar \
-javaagent:/app/shulie/simulator-agent/simulator-launcher-instrument.jar \ #共享数据卷的探针目录
-Dsimulator.app.name=zto-new-agent \
-Dsimulator.delay=0 \
-Djdk.attach.allowAttachSelf=true"
#执行命令java -jar
# ENTRYPOINT ["java","${JAVA_OPTS}","-jar","/app.jar"]
ENTRYPOINT java ${JAVA_OPTS} -jar /app.jar
2.加载探针
这里有2种方式可以实现:
- 修改启动命令:可以修改应用Dockerfile来指向探针目录,也可以通过docker run -e的形式覆盖Dockerfile里的JAVA_OPTS来动态加载探针,或者通过k8s来实现docker run -e的同等效果
- 设置环境变量:可以通过定义”JAVA_TOOL_OPTIONS” 这个环境变量来动态的设置jvm启动参数,比如
export JAVA_TOOL_OPTIONS="-javaagent:/app/shulie/simulator-agent/simulator-launcher-instrument.jar -javaagent:/app/shulie/simulator-agent/bootstrap/transmittable-thread-local-2.12.1.jar -Dsimulator.app.name=app_name"
此时在启动java应用时时会在jvm启动参数上附加
-javaagent:/app/shulie/simulator-agent/simulator-launcher-instrument.jar
-javaagent:/app/shulie/simulator-agent/bootstrap/transmittable-thread-local-2.12.1.jar
-Dsimulator.app.name=app_name
这是利用JNI的内置机制:JNI在启动jvm时会将制定环境变量 JAVA_TOOL_OPTIONS 的值添加到jvm参数里。
3.配置k8s共享数据卷
数据卷含义图:
配置k8s的pod文件
apiVersion: v1
kind: Pod
metadata:
name: agent-app
labels:
name: agent-app
spec:
nodeSelector: #这个是k8s选择主从节点的,看情况添加
shulie: agent
volumes: #生成一个数据卷,类型是emptyDir,可在pod内多个容器间共享目录
- name: shared-data
emptyDir: {}
containers:
- name: agent #探针镜像
image: agent-docker:v3
volumeMounts: #定义数据卷
- name: shared-data
mountPath: /app/shulie_agent #共享数据卷路径,多个容器不能重复
#定义一个command,会覆盖默认的java -jar command
command: ["/bin/sh"]
#将镜像里的探针目录拷贝到共享数据卷/app/shulie_agent, 设置JAVA_TOOL_OPTIONS环境变量 ,同时启动应用。探针镜像的/app/shulie_agent对应着app镜像的 /app/shulie,拷贝后应用就能在/app/shulie里看到探针
args: ["-c","cp -rf /app/shulie_data/simulator-agent /app/shulie_agent;
export JAVA_TOOL_OPTIONS='-javaagent:/app/shulie/simulator-agent/simulator-launcher-instrument.jar -javaagent:/app/shulie/simulator-agent/bootstrap/transmittable-thread-local-2.12.1.jar -Dsimulator.app.name=app_name';
java -jar /app/shulie_data/app.jar"]
- name: app #应用镜像
image: app-docker-noagent:v1
#image: app-docker:v2
volumeMounts:
- name: shared-data
mountPath: /app/shulie #应用镜像里通过-javaagent来指定共享数据卷的探针目录,也可以在启动镜像是通过环境变量来设置-javaagent