JavaAgent in SpringBoot Docker image

先前看了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。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料