先前看了SkyWalking, Elastic APM, OpenTelemetry等tracing tool,最快免寫程式的方式都是以-javaagent的方式進行處理,在本機沒什麼問題,但是放在docker與k8s環境就開始是個問題了。
SpringBoot的程式我多半用spring提供的maven或gradle plugin來產生image,但如果要加上-javaagent勢必要走回Dockerfile的模式,花了點時間去找有沒有什麼其他的方案,可以保留用spring plugin來建立layered image。
第一步當然是去找buildpack,想說釜底抽薪,建一個自已的base,把javaagent用的jar放在特定目錄,之後就好辦了,不然加個layer,也能達到我要的結果。不過目前仍是….還沒成功。
2023/01/30 更新:現在有這個了->github.com/paketo-buildpacks/opentelemetry
第二步就是用偷吃步了,將javaagent用的jar當做dependency,放在pom或build.gradle裡,利用buildpack會分layer而且會解開library分為獨立的jar這件事上,可以知道javaagent的jar會放在/workspace/BOOT-INF/lib
目錄下,再利用JAVA_TOOL_OPTIONS
載入javaagent選項,這樣也能達到我要的效果。
以opentelemetry做範例如下
在pom中加入
<dependency>
<groupId>io.opentelemetry.javaagent</groupId>
<artifactId>opentelemetry-javaagent</artifactId>
<version>1.22.1</version>
<scope>runtime</scope>
</dependency>
然後一樣執行mvn spring-boot:build-image
產生image
在docker-compse.yml中可以這樣設定JAVA_TOOL_OPTIONS
spring:
image: elliot/trace:0.0.1-SNAPSHOT
container_name: trace-sv
environment:
- JAVA_TOOL_OPTIONS=-javaagent:/workspace/BOOT-INF/lib/opentelemetry-javaagent-1.22.1.jar
- OTEL_EXPORTER_JAEGER_ENDPOINT=http://jaegertracing:14250
- OTEL_METRICS_EXPORTER=none
- OTEL_SERVICE_NAME=trace-sv
- OTEL_TRACES_EXPORTER=jaeger
ports:
- 8080:8080
這樣啟動時就會自動以javaagent
啟動。
如果不想使用tracing,就將JAVA_TOOL_OPTIONS
這變數拿掉,在控制上也算容易。
順帶一提,如果看到https://github.com/spring-projects/spring-boot/issues/23518,提到用binding的方式,建議就跳過,因為這其實是docker create container裡的Hostconfig->Binds參數,僅是加上固定的Volume,不是真的把檔案包進image。