Skip to content

Commit 695620e

Browse files
committed
Build jmx_exporter from upstream prometheus releases
Currently the jmx-javaagent docker image is built from https://github.com/amuraru/jmx_exporter In order to bring that dependency in-tree here, this PR extends kafka image(s) release (kafka-*) action to also build a docker image directly from https://github.com/prometheus/jmx_exporter The image is published to: https://github.com/adobe/koperator/pkgs/container/koperator%2Fjmx-javaagent
1 parent 05cca73 commit 695620e

File tree

12 files changed

+229
-47
lines changed

12 files changed

+229
-47
lines changed

.github/workflows/publish-kafka-docker.yml

Lines changed: 91 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ env:
1313
# GitHub Container Registry
1414
GHCR_REGISTRY: ghcr.io
1515
# github.repository as <account>/<repo>
16-
GHCR_IMAGE_NAME: ${{ github.repository }}/kafka
17-
# Docker Hub image name
16+
GHCR_KAFKA_IMAGE_NAME: ${{ github.repository }}/kafka
17+
GHCR_JMX_IMAGE_NAME: ${{ github.repository }}/jmx-javaagent
18+
# Docker Hub image name (only for Kafka)
1819
DOCKERHUB_IMAGE: adobe/kafka
1920

2021
jobs:
@@ -34,7 +35,7 @@ jobs:
3435
run: |
3536
echo "built_at=$(date --rfc-3339=date)" >> $GITHUB_OUTPUT
3637
37-
build-kafka:
38+
build-and-push-kafka-image:
3839
runs-on: ubuntu-latest
3940
needs: prepare
4041
permissions:
@@ -47,40 +48,122 @@ jobs:
4748
uses: docker/setup-qemu-action@v3
4849
- name: Set up Docker Buildx
4950
uses: docker/setup-buildx-action@v3
51+
- name: Extract Kafka version from tag
52+
id: kafka_version
53+
run: |
54+
KAFKA_VERSION=$(echo "${{ needs.prepare.outputs.tag }}" | sed 's/kafka-//')
55+
echo "kafka_version=$KAFKA_VERSION" >> $GITHUB_OUTPUT
56+
- name: Check if Kafka image already exists
57+
id: image_exists
58+
run: |
59+
IMAGE_NAME="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_KAFKA_IMAGE_NAME }}:${{ steps.kafka_version.outputs.kafka_version }}"
60+
echo "Checking if image exists: $IMAGE_NAME"
61+
62+
# Try to inspect the manifest using docker
63+
if docker manifest inspect "$IMAGE_NAME" > /dev/null 2>&1; then
64+
echo "exists=true" >> $GITHUB_OUTPUT
65+
echo "Image $IMAGE_NAME already exists, skipping build"
66+
else
67+
echo "exists=false" >> $GITHUB_OUTPUT
68+
echo "Image $IMAGE_NAME does not exist, will build"
69+
fi
5070
- name: Login to DockerHub Registry
51-
if: startsWith(github.ref, 'refs/tags/')
71+
if: startsWith(github.ref, 'refs/tags/') && github.repository == 'adobe/koperator' && steps.image_exists.outputs.exists == 'false'
5272
uses: docker/login-action@v3
5373
with:
5474
username: ${{ secrets.DOCKER_USERNAME }}
5575
password: ${{ secrets.DOCKER_PASSWORD }}
5676
- name: Log into GitHub Container Registry ${{ env.GHCR_REGISTRY }}
57-
if: startsWith(github.ref, 'refs/tags/')
77+
if: startsWith(github.ref, 'refs/tags/') && steps.image_exists.outputs.exists == 'false'
5878
uses: docker/login-action@v3
5979
with:
6080
registry: ${{ env.GHCR_REGISTRY }}
6181
username: ${{ github.actor }}
6282
password: ${{ secrets.GITHUB_TOKEN }}
6383
- name: Extract Docker metadata
84+
if: steps.image_exists.outputs.exists == 'false'
6485
id: meta
6586
uses: docker/metadata-action@v5
6687
with:
6788
images: |
68-
${{ env.DOCKERHUB_IMAGE }}
69-
${{ env.GHCR_REGISTRY }}/${{ env.GHCR_IMAGE_NAME }}
89+
${{ github.repository == 'adobe/koperator' && env.DOCKERHUB_IMAGE || '' }}
90+
${{ env.GHCR_REGISTRY }}/${{ env.GHCR_KAFKA_IMAGE_NAME }}
7091
tags: |
7192
type=match,pattern=kafka-(.*),group=1
7293
labels: |
7394
org.opencontainers.image.description=Apache Kafka with OpenJDK 21
7495
- name: Build and push kafka image
96+
if: startsWith(github.ref, 'refs/tags/') && steps.image_exists.outputs.exists == 'false'
7597
uses: docker/build-push-action@v6
7698
with:
7799
context: docker/kafka
78100
platforms: linux/amd64,linux/arm64
79-
push: ${{ startsWith(github.ref, 'refs/tags/') }}
101+
push: true
80102
tags: ${{ steps.meta.outputs.tags }}
81103
labels: ${{ steps.meta.outputs.labels }}
82104
annotations: ${{ steps.meta.outputs.annotations }}
83105
build-args: |
84106
VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}
85107
BUILT_AT=${{ needs.prepare.outputs.built_at }}
86108
COMMIT=${{ github.sha }}
109+
110+
build-and-push-jmx-agent-image:
111+
runs-on: ubuntu-latest
112+
needs: prepare
113+
permissions:
114+
contents: read
115+
packages: write
116+
steps:
117+
- name: Checkout code
118+
uses: actions/checkout@v5
119+
- name: Set up QEMU
120+
uses: docker/setup-qemu-action@v3
121+
- name: Set up Docker Buildx
122+
uses: docker/setup-buildx-action@v3
123+
- name: Extract JMX exporter version from Dockerfile
124+
id: jmx_exporter_version
125+
run: |
126+
JMX_VERSION=$(grep "ARG JMX_EXPORTER_VERSION=" docker/jmx_exporter/Dockerfile | cut -d'=' -f2 | cut -d' ' -f1)
127+
echo "jmx_version=$JMX_VERSION" >> $GITHUB_OUTPUT
128+
- name: Check if JMX exporter image already exists
129+
id: image_exists
130+
run: |
131+
IMAGE_NAME="${{ env.GHCR_REGISTRY }}/${{ env.GHCR_JMX_IMAGE_NAME }}:${{ steps.jmx_exporter_version.outputs.jmx_version }}"
132+
echo "Checking if image exists: $IMAGE_NAME"
133+
134+
# Try to inspect the manifest using docker
135+
if docker manifest inspect "$IMAGE_NAME" > /dev/null 2>&1; then
136+
echo "exists=true" >> $GITHUB_OUTPUT
137+
echo "Image $IMAGE_NAME already exists, skipping build"
138+
else
139+
echo "exists=false" >> $GITHUB_OUTPUT
140+
echo "Image $IMAGE_NAME does not exist, will build"
141+
fi
142+
- name: Log into GitHub Container Registry ${{ env.GHCR_REGISTRY }}
143+
if: startsWith(github.ref, 'refs/tags/') && steps.image_exists.outputs.exists == 'false'
144+
uses: docker/login-action@v3
145+
with:
146+
registry: ${{ env.GHCR_REGISTRY }}
147+
username: ${{ github.actor }}
148+
password: ${{ secrets.GITHUB_TOKEN }}
149+
- name: Extract Docker metadata for JMX exporter
150+
if: steps.image_exists.outputs.exists == 'false'
151+
id: meta
152+
uses: docker/metadata-action@v5
153+
with:
154+
images: |
155+
${{ env.GHCR_REGISTRY }}/${{ env.GHCR_JMX_IMAGE_NAME }}
156+
tags: |
157+
type=raw,value=${{ steps.jmx_exporter_version.outputs.jmx_version }}
158+
labels: |
159+
org.opencontainers.image.description=Prometheus JMX Exporter for Kafka monitoring
160+
- name: Build and push JMX exporter image
161+
if: startsWith(github.ref, 'refs/tags/') && steps.image_exists.outputs.exists == 'false'
162+
uses: docker/build-push-action@v6
163+
with:
164+
context: docker/jmx_exporter
165+
platforms: linux/amd64,linux/arm64
166+
push: true
167+
tags: ${{ steps.meta.outputs.tags }}
168+
labels: ${{ steps.meta.outputs.labels }}
169+
annotations: ${{ steps.meta.outputs.annotations }}

api/assets/kafka/jmx-exporter.yml

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,34 @@
1+
httpServer:
2+
threads:
3+
minimum: 5
4+
maximum: 10
5+
keepAliveTime: 120
16
lowercaseOutputName: true
27
rules:
3-
# Special cases and very specific rules
4-
# Export kraft current state metrics
8+
# Export Kraft metrics
9+
## Export Kraft current-state count metrics
510
- pattern: 'kafka.server<type=raft-metrics><>current-state: (.+)'
611
name: kafka_server_raft_metrics_current_state_$1
712
type: GAUGE
813
value: 1
14+
## MetadataLoader count metrics as COUNTERs
15+
- pattern: kafka.server<type=MetadataLoader><>([A-Za-z]+Count)
16+
name: kafka_server_metadataloader_$1_total
17+
type: COUNTER
18+
## Broker metadata error count metrics as COUNTERs
19+
- pattern: kafka.server<type=broker-metadata-metrics><>(metadata-(load|apply)-error-count)
20+
name: kafka_server_broker_metadata_metrics_$1_total
21+
type: COUNTER
22+
## KafkaController ActiveBrokerCount as GAUGE (current state, not cumulative)
23+
- pattern: kafka.controller<type=KafkaController><>ActiveBrokerCount
24+
name: kafka_controller_kafkacontroller_ActiveBrokerCount
25+
type: GAUGE
26+
## KafkaController count metrics as COUNTERs
27+
- pattern: kafka.controller<type=KafkaController><>([A-Za-z]+Count)
28+
name: kafka_controller_kafkacontroller_$1_total
29+
type: COUNTER
30+
# END: Export Kraft metrics
31+
932
- pattern: 'kafka.server<type=(app-info), id=(\d+)><>(Version): ([-.~+\w\d]+)'
1033
name: kafka_server_$1_$3
1134
type: COUNTER

api/v1beta1/kafkacluster_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ const (
145145

146146
// KafkaBrokerPod.spec.initContainer[jmx-exporter].image
147147
// kafkaClusterDeployment.spec.template.spec.initContainer["jmx-exporter"].image
148-
defaultMonitorImage = "ghcr.io/amuraru/jmx-javaagent:0.19.2"
148+
defaultMonitorImage = "ghcr.io/adobe/koperator/jmx-javaagent:1.4.0"
149149

150150
// KafkaBrokerPod.spec.initContainer["jmx-exporter"].command
151151
// kafkaClusterDeployment.spec.template.spec.initContainer["jmx-exporter"].command

config/samples/banzaicloud_v1beta1_kafkacluster.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ spec:
708708
# monitoringConfig describes the monitoring related configs
709709
#monitoringConfig:
710710
# jmxImage describes the used prometheus jmx exporter agent container
711-
# jmxImage: "ghcr.io/amuraru/jmx-javaagent:0.19.2"
711+
# jmxImage: "ghcr.io/adobe/koperator/jmx-javaagent:1.4.0"
712712
# pathToJar describes the path to the jar file in the given image
713713
# pathToJar: "/jmx_prometheus_javaagent.jar"
714714
# kafkaJMXExporterConfig describes jmx exporter config for Kafka

config/samples/kraft/simplekafkacluster_kraft.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ metadata:
77
spec:
88
kRaft: true
99
monitoringConfig:
10-
jmxImage: "ghcr.io/amuraru/jmx-javaagent:0.19.2"
10+
jmxImage: "ghcr.io/adobe/koperator/jmx-javaagent:1.4.0"
1111
headlessServiceEnabled: true
1212
propagateLabels: false
1313
oneBrokerPerNode: false

config/samples/simplekafkacluster.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ metadata:
77
spec:
88
kRaft: false
99
monitoringConfig:
10-
jmxImage: "ghcr.io/amuraru/jmx-javaagent:0.19.2"
10+
jmxImage: "ghcr.io/adobe/koperator/jmx-javaagent:1.4.0"
1111
headlessServiceEnabled: true
1212
zkAddresses:
1313
- "zookeeper-server-client.zookeeper:2181"

config/samples/simplekafkacluster_with_contour.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ metadata:
66
name: kafka
77
spec:
88
monitoringConfig:
9-
jmxImage: "ghcr.io/amuraru/jmx-javaagent:0.19.2"
9+
jmxImage: "ghcr.io/adobe/koperator/jmx-javaagent:1.4.0"
1010
headlessServiceEnabled: true
1111
zkAddresses:
1212
- "zookeeper-server-client.zookeeper:2181"

controllers/tests/kafkacluster_controller_cruisecontrol_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ func expectCruiseControlDeployment(ctx context.Context, kafkaCluster *v1beta1.Ka
277277
Expect(deployment.Spec.Template.Spec.InitContainers).To(HaveLen(1))
278278
initContainer := deployment.Spec.Template.Spec.InitContainers[0]
279279
Expect(initContainer.Name).To(Equal("jmx-exporter"))
280-
Expect(initContainer.Image).To(Equal("ghcr.io/amuraru/jmx-javaagent:0.19.2"))
280+
Expect(initContainer.Image).To(Equal("ghcr.io/adobe/koperator/jmx-javaagent:1.4.0"))
281281
Expect(initContainer.Command).To(Equal([]string{"cp", "/jmx_prometheus_javaagent.jar", "/opt/jmx-exporter/jmx_prometheus.jar"}))
282282
Expect(initContainer.VolumeMounts).To(ConsistOf(corev1.VolumeMount{
283283
Name: "jmx-jar-data",

docker/jmx_exporter/Dockerfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
ARG JMX_EXPORTER_VERSION=1.4.0 # renovate: datasource=github-releases depName=prometheus/jmx_exporter
2+
3+
FROM maven:3-amazoncorretto-21 AS build
4+
ARG JMX_EXPORTER_VERSION
5+
6+
# Install wget to download the release tarball
7+
RUN yum install -y wget && yum clean all
8+
9+
# Download and extract the JMX exporter release
10+
RUN wget https://github.com/prometheus/jmx_exporter/archive/refs/tags/${JMX_EXPORTER_VERSION}.tar.gz \
11+
-O /tmp/jmx_exporter.tar.gz && \
12+
tar -xzf /tmp/jmx_exporter.tar.gz -C /tmp && \
13+
mv /tmp/jmx_exporter-${JMX_EXPORTER_VERSION} /src && \
14+
rm /tmp/jmx_exporter.tar.gz
15+
16+
WORKDIR /src
17+
RUN mvn -B -Dmaven.javadoc.skip=true -Dskip.javadoc=true \
18+
-Dmaven.compiler.source=21 -Dmaven.compiler.target=21 -Dmaven.compiler.release=21 \
19+
clean package -pl jmx_prometheus_javaagent -am
20+
21+
FROM alpine:latest
22+
ARG JMX_EXPORTER_VERSION
23+
COPY --from=build /src/jmx_prometheus_javaagent/target/jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar /opt/jmx_exporter/
24+
RUN ln -s /opt/jmx_exporter/jmx_prometheus_javaagent-${JMX_EXPORTER_VERSION}.jar /jmx_prometheus_javaagent.jar
25+
CMD ["/bin/sh"]

docker/kafka/Dockerfile

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,67 @@
1+
ARG scala_version=2.13
2+
ARG kafka_version=3.9.1 # renovate: datasource=github-tags depName=apache/kafka
3+
ARG java_version=21
4+
15
FROM alpine:latest@sha256:4bcff63911fcb4448bd4fdacec207030997caf25e9bea4045fa6c8c44de311d1 AS kafka_dist
26

3-
ARG scala_version=2.13
4-
ARG kafka_version=3.9.1
7+
ARG scala_version
8+
ARG kafka_version
59
ARG kafka_distro_base_url=https://downloads.apache.org/kafka
610

711
ENV kafka_distro=kafka_$scala_version-$kafka_version.tgz
812
ENV kafka_distro_asc=$kafka_distro.asc
913

10-
RUN apk add --no-cache gnupg
11-
1214
WORKDIR /var/tmp
1315

14-
RUN wget -q $kafka_distro_base_url/$kafka_version/$kafka_distro
15-
RUN wget -q $kafka_distro_base_url/$kafka_version/$kafka_distro_asc
16-
RUN wget -q $kafka_distro_base_url/KEYS
17-
18-
RUN gpg --import KEYS
19-
RUN gpg --verify $kafka_distro_asc $kafka_distro
20-
21-
RUN tar -xzf $kafka_distro
22-
RUN rm -r kafka_$scala_version-$kafka_version/bin/windows
16+
# Download, verify, extract and clean up Kafka in single layer
17+
RUN apk add --no-cache gnupg wget && \
18+
wget -q $kafka_distro_base_url/$kafka_version/$kafka_distro && \
19+
wget -q $kafka_distro_base_url/$kafka_version/$kafka_distro_asc && \
20+
wget -q $kafka_distro_base_url/KEYS && \
21+
gpg --import KEYS && \
22+
gpg --verify $kafka_distro_asc $kafka_distro && \
23+
tar -xzf $kafka_distro && \
24+
rm -rf kafka_$scala_version-$kafka_version/bin/windows \
25+
kafka_$scala_version-$kafka_version/site-docs \
26+
$kafka_distro $kafka_distro_asc KEYS && \
27+
find kafka_$scala_version-$kafka_version -name "*.bat" -delete
2328

2429

2530
# backported from https://github.com/docker-library/openjdk/blob/master/18/jdk/slim-bullseye/Dockerfile
2631
FROM debian:bullseye-slim@sha256:f807f4b16002c623115b0247dca6a55711c6b1ae821dc64fb8a2339e4ce2115d
2732

28-
ARG scala_version=2.13
29-
ARG kafka_version=3.9.1
33+
ARG scala_version
34+
ARG kafka_version
35+
ARG java_version
3036
ARG VERSION
3137
ARG BUILT_AT
3238
ARG COMMIT
3339

34-
3540
RUN set -eux; \
3641
apt-get update; \
3742
apt-get install -y --no-install-recommends \
3843
ca-certificates p11-kit \
3944
; \
4045
rm -rf /var/lib/apt/lists/*
4146

42-
ENV JAVA_HOME /usr/local/openjdk-21
43-
ENV PATH $JAVA_HOME/bin:$PATH
47+
ENV JAVA_HOME=/usr/local/openjdk-${java_version}
48+
ENV PATH=$JAVA_HOME/bin:$PATH
4449

4550
# Default to UTF-8 file.encoding
46-
ENV LANG C.UTF-8
47-
ENV JAVA_VERSION 21
51+
ENV LANG=C.UTF-8
52+
ENV JAVA_VERSION=${java_version}
4853

4954
RUN set -eux; \
5055
\
5156
arch="$(dpkg --print-architecture)"; \
5257
case "$arch" in \
5358
'amd64') \
54-
downloadUrl='https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz'; \
55-
downloadSha256='https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz.sha256'; \
59+
downloadUrl="https://download.oracle.com/java/${java_version}/latest/jdk-${java_version}_linux-x64_bin.tar.gz"; \
60+
downloadSha256="https://download.oracle.com/java/${java_version}/latest/jdk-${java_version}_linux-x64_bin.tar.gz.sha256"; \
5661
;; \
5762
'arm64') \
58-
downloadUrl='https://download.oracle.com/java/21/latest/jdk-21_linux-aarch64_bin.tar.gz'; \
59-
downloadSha256='https://download.oracle.com/java/21/latest/jdk-21_linux-aarch64_bin.tar.gz.sha256'; \
63+
downloadUrl="https://download.oracle.com/java/${java_version}/latest/jdk-${java_version}_linux-aarch64_bin.tar.gz"; \
64+
downloadSha256="https://download.oracle.com/java/${java_version}/latest/jdk-${java_version}_linux-aarch64_bin.tar.gz.sha256"; \
6065
;; \
6166
*) echo >&2 "error: unsupported architecture: '$arch'"; exit 1 ;; \
6267
esac; \
@@ -81,6 +86,9 @@ RUN set -eux; \
8186
; \
8287
rm openjdk.tgz*; \
8388
\
89+
# Remove JMODs (not needed for runtime, only for jlink custom images)
90+
rm -rf "$JAVA_HOME/jmods"; \
91+
\
8492
apt-mark auto '.*' > /dev/null; \
8593
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
8694
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
@@ -117,18 +125,25 @@ ENV KAFKA_VERSION=$kafka_version \
117125

118126
ENV PATH=${PATH}:${KAFKA_HOME}/bin
119127

120-
RUN mkdir ${KAFKA_HOME} && apt-get update && apt-get -y upgrade && apt-get install curl -y && apt-get clean
128+
# Install minimal dependencies, setup Kafka, and clean up in single layer
129+
RUN apt-get update && \
130+
apt-get install -y --no-install-recommends curl && \
131+
apt-get clean && \
132+
rm -rf /var/lib/apt/lists/* && \
133+
mkdir -p ${KAFKA_HOME}/libs/extensions
121134

122135
COPY --from=kafka_dist /var/tmp/kafka_$scala_version-$kafka_version ${KAFKA_HOME}
123136
COPY opt/kafka/config/log4j.properties ${KAFKA_HOME}/config/log4j.properties
124137

125-
126-
RUN chmod a+x ${KAFKA_HOME}/bin/*.sh
127-
RUN chmod g+rwX ${KAFKA_HOME} && mkdir -p ${KAFKA_HOME}/libs/extensions && chmod g+rwX ${KAFKA_HOME}/libs/extensions
138+
# Optimize Kafka installation: remove unnecessary files and set permissions
139+
RUN chmod a+x ${KAFKA_HOME}/bin/*.sh && \
140+
chmod g+rwX ${KAFKA_HOME} ${KAFKA_HOME}/libs/extensions && \
141+
rm -rf ${KAFKA_HOME}/bin/windows ${KAFKA_HOME}/site-docs && \
142+
find ${KAFKA_HOME} -name "*.bat" -delete
128143

129144
# Add metadata labels
130145
LABEL org.opencontainers.image.title="Apache Kafka"
131-
LABEL org.opencontainers.image.description="Apache Kafka with OpenJDK 21"
146+
LABEL org.opencontainers.image.description="Apache Kafka with Oracle JDK ${java_version}"
132147
LABEL org.opencontainers.image.vendor="Adobe"
133148
LABEL org.opencontainers.image.licenses="Apache-2.0"
134149
LABEL org.opencontainers.image.source="https://github.com/adobe/koperator"

0 commit comments

Comments
 (0)