Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions src/main/charts/common/templates/_jmx.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,36 @@ Jmx config volume mount
Jmx init container
*/}}
{{- define "common.jmx.initContainer" -}}
{{- if and .Values.monitoring.exposeJmxMetrics .Values.monitoring.fetchJmxExporterJar }}
{{- if and .Values.monitoring.exposeJmxMetrics (not .Values.monitoring.jmxExporterCustomJarLocation) }}
- name: fetch-jmx-exporter
image: {{ .Values.monitoring.jmxExporterImageRepo}}:{{ .Values.monitoring.jmxExporterImageTag}}
command: ["cp"]
args: ["{{ .Values.monitoring.jmxExporterInitContainer.jmxJarLocation | default "/opt/bitnami/jmx-exporter/jmx_prometheus_javaagent.jar" }}", "{{ .Values.volumes.sharedHome.mountPath }}"]
image: curlimages/curl:latest
command: ["/bin/sh"]
args:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's still a draft - just wanted to mention that we should make it configurable enough to make sure things work in air gapped environments. It should be possible to override both image and command.

- -ec
- |
AGENT_PATH="{{ .Values.volumes.sharedHome.mountPath }}/jmx_prometheus_javaagent.jar"
VERSION="{{ .Values.monitoring.jmxExporter.version }}"
BASE_URL="{{ .Values.monitoring.jmxExporter.mavenBaseUrl }}"
EXPECTED_SHA256="{{ .Values.monitoring.jmxExporter.sha256 }}"

# Download the agent
curl -L "${BASE_URL}/${VERSION}/jmx_prometheus_javaagent-${VERSION}.jar" -o $AGENT_PATH

# Verify SHA256
echo "${EXPECTED_SHA256} ${AGENT_PATH}" | sha256sum -c -

# Set permissions
chmod 644 $AGENT_PATH

# Verify JAR structure
if ! unzip -l $AGENT_PATH | grep -q "META-INF/MANIFEST.MF"; then
echo "Invalid JAR file"
exit 1
fi
if ! unzip -l $AGENT_PATH | grep -q "JavaAgent.class"; then
echo "Not a valid Java agent JAR"
exit 1
fi
{{- if .Values.monitoring.jmxExporterInitContainer.resources }}
resources:
{{- with .Values.monitoring.jmxExporterInitContainer.resources }}
Expand Down
54 changes: 30 additions & 24 deletions src/main/charts/jira/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -998,18 +998,12 @@ monitoring:

# -- Expose JMX metrics with jmx_exporter https://github.com/prometheus/jmx_exporter
#
exposeJmxMetrics: false
exposeJmxMetrics: true

# -- JMX exporter init container configuration
# -- JMX exporter init container configuration
#
jmxExporterInitContainer:

# -- The location of the JMX exporter jarfile in the JMX exporter image
# Leave blank for default bitnami image
#
jmxJarLocation:

# -- Whether to run JMX exporter init container as root to copy JMX exporter binary to shared home volume.
# -- Whether to run JMX exporter init container as root to set permissions
# Set to false if running containers as root is not allowed in the cluster.
#
runAsRoot: true
Expand All @@ -1033,18 +1027,15 @@ monitoring:
#
jmxServiceAnnotations: {}

# -- Fetch jmx_exporter jar from the image. If set to false make sure to manually copy the jar
# to shared home and provide an absolute path in jmxExporterCustomJarLocation
#
fetchJmxExporterJar: true

# -- Image repository with jmx_exporter jar
#
jmxExporterImageRepo: bitnami/jmx-exporter

# -- Image tag to be used to pull jmxExporterImageRepo
# -- Maven Central configuration for JMX exporter
#
jmxExporterImageTag: 0.18.0
jmxExporter:
# -- Version of JMX exporter to use
version: 0.18.0
# -- Maven Central base URL
mavenBaseUrl: https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent
# -- SHA256 checksum for verification
sha256: d3ba4ce8eccd3461463358c5e19f8becb99ed949f159c37c850e53b89b560f97

# -- Port number on which metrics will be available
#
Expand All @@ -1060,15 +1051,30 @@ monitoring:

# -- Custom JMX config with the rules
#
jmxExporterCustomConfig: {}
# rules:
# - pattern: ".*"
jmxExporterCustomConfig:
rules:
- pattern: "java.lang<type=Memory><HeapMemoryUsage>.*"
name: jvm_memory_heap_$3
attrNameSnakeCase: true
- pattern: "java.lang<type=Memory><NonHeapMemoryUsage>.*"
name: jvm_memory_nonheap_$3
attrNameSnakeCase: true
- pattern: "java.lang<type=GarbageCollector, name=(.*)><.*>.*"
name: jvm_gc_$1_$2
attrNameSnakeCase: true
- pattern: "Catalina<type=ThreadPool, name=\"(.*)\">(.*)"
name: tomcat_threadpool_$2
labels:
pool: $1
- pattern: "com.atlassian.jira<type=ThreadMonitor>(.*)"
name: jira_thread_$1
attrNameSnakeCase: true

serviceMonitor:

# -- Create ServiceMonitor to start scraping metrics. ServiceMonitor CRD needs to be created in advance.
#
create: false
create: true

# -- ServiceMonitorSelector of the prometheus instance.
#
Expand Down
54 changes: 42 additions & 12 deletions src/test/java/test/JmxMetricsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ void expose_jmx_metrics_enabled_init_container(Product product) throws Exception
StatefulSet statefulSet = resources.getStatefulSet(product.getHelmReleaseName());

// assert jmx_exporter init container
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("image")).hasTextEqualTo("bitnami/jmx-exporter:0.18.0");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("command").get(0)).hasTextEqualTo("cp");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(0)).hasTextEqualTo("/opt/bitnami/jmx-exporter/jmx_prometheus_javaagent.jar");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("image")).hasTextEqualTo("curlimages/curl:latest");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("command").get(0)).hasTextEqualTo("/bin/sh");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(0)).hasTextEqualTo("-ec");

assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(1)).hasTextEqualTo(sharedHomePath);
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("volumeMounts").get(0).path("mountPath")).hasTextEqualTo(sharedHomePath);
Expand Down Expand Up @@ -164,14 +164,44 @@ void expose_jmx_metrics_enabled_custom_vol_paths(Product product) throws Excepti
void expose_jmx_metrics_enabled_custom_init_container(Product product) throws Exception {
final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
"monitoring.exposeJmxMetrics", "true",
"monitoring.jmxExporterImageRepo", "myregistry/myrepo",
"monitoring.jmxExporterImageTag", "0.17.0"
"monitoring.jmxExporter.version", "0.17.0",
"monitoring.jmxExporter.sha256", "custom_sha256"
));

StatefulSet statefulSet = resources.getStatefulSet(product.getHelmReleaseName());

// assert jmx_exporter init container
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("image")).hasTextEqualTo("myregistry/myrepo:0.17.0");
var initContainer = statefulSet.getInitContainer("fetch-jmx-exporter").get();
assertThat(initContainer.path("image")).hasTextEqualTo("curlimages/curl:latest");

// Verify custom version is used
assertThat(initContainer.path("args").get(1)).hasTextContaining("VERSION=\"0.17.0\"");
assertThat(initContainer.path("args").get(1)).hasTextContaining("EXPECTED_SHA256=\"custom_sha256\"");
}

@ParameterizedTest
@EnumSource(value = Product.class, names = {"bamboo_agent"}, mode = EnumSource.Mode.EXCLUDE)
void expose_jmx_metrics_maven_central_download(Product product) throws Exception {
final var resources = helm.captureKubeResourcesFromHelmChart(product, Map.of(
"monitoring.exposeJmxMetrics", "true",
"monitoring.jmxExporter.version", "0.18.0",
"monitoring.jmxExporter.sha256", "d3ba4ce8eccd3461463358c5e19f8becb99ed949f159c37c850e53b89b560f97"
));

StatefulSet statefulSet = resources.getStatefulSet(product.getHelmReleaseName());
var initContainer = statefulSet.getInitContainer("fetch-jmx-exporter").get();

// Verify init container setup
assertThat(initContainer.path("image")).hasTextEqualTo("curlimages/curl:latest");
assertThat(initContainer.path("command").get(0)).hasTextEqualTo("/bin/sh");
assertThat(initContainer.path("args").get(0)).hasTextEqualTo("-ec");

// Verify script content
assertThat(initContainer.path("args").get(1)).hasTextContaining("curl -L");
assertThat(initContainer.path("args").get(1)).hasTextContaining("sha256sum -c");
assertThat(initContainer.path("args").get(1)).hasTextContaining("chmod 644");
assertThat(initContainer.path("args").get(1)).hasTextContaining("META-INF/MANIFEST.MF");
assertThat(initContainer.path("args").get(1)).hasTextContaining("JavaAgent.class");
}

@ParameterizedTest
Expand Down Expand Up @@ -250,9 +280,9 @@ void expose_jmx_metrics_bitbucket_mesh(Product product) throws Exception {
StatefulSet statefulSet = resources.getStatefulSet(product.getHelmReleaseName() + "-mesh");

// assert jmx_exporter init container
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("image")).hasTextEqualTo("bitnami/jmx-exporter:0.18.0");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("command").get(0)).hasTextEqualTo("cp");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(0)).hasTextEqualTo("/opt/bitnami/jmx-exporter/jmx_prometheus_javaagent.jar");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("image")).hasTextEqualTo("curlimages/curl:latest");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("command").get(0)).hasTextEqualTo("/bin/sh");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(0)).hasTextEqualTo("-ec");

assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(1)).hasTextEqualTo(localHomePath);
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("volumeMounts").get(0).path("mountPath")).hasTextEqualTo(localHomePath);
Expand Down Expand Up @@ -286,9 +316,9 @@ void expose_jmx_metrics_enabled_bitbucket_mirror(Product product) throws Excepti
StatefulSet statefulSet = resources.getStatefulSet(product.getHelmReleaseName());

// assert jmx_exporter init container
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("image")).hasTextEqualTo("bitnami/jmx-exporter:0.18.0");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("command").get(0)).hasTextEqualTo("cp");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(0)).hasTextEqualTo("/opt/bitnami/jmx-exporter/jmx_prometheus_javaagent.jar");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("image")).hasTextEqualTo("curlimages/curl:latest");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("command").get(0)).hasTextEqualTo("/bin/sh");
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(0)).hasTextEqualTo("-ec");

assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("args").get(1)).hasTextEqualTo(sharedHomePath);
assertThat(statefulSet.getInitContainer("fetch-jmx-exporter").get().path("volumeMounts").get(0).path("mountPath")).hasTextEqualTo(sharedHomePath);
Expand Down
38 changes: 32 additions & 6 deletions src/test/resources/expected_helm_output/jira/output.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -262,15 +262,16 @@ data:
useHelmReleaseNameAsContainerName: false
monitoring:
exposeJmxMetrics: true
fetchJmxExporterJar: true
grafana:
createDashboards: false
dashboardAnnotations: {}
dashboardLabels: {}
jmxExporterCustomConfig: {}
jmxExporterCustomJarLocation: null
jmxExporterImageRepo: bitnami/jmx-exporter
jmxExporterImageTag: 0.18.0
jmxExporter:
version: 0.18.0
mavenBaseUrl: https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent
sha256: d3ba4ce8eccd3461463358c5e19f8becb99ed949f159c37c850e53b89b560f97
jmxExporterInitContainer:
customSecurityContext: {}
jmxJarLocation: null
Expand Down Expand Up @@ -453,9 +454,34 @@ spec:
mountPath: "/shared-home"
command: ["sh", "-c", "(chgrp 2001 /shared-home; chmod g+w /shared-home)"]
- name: fetch-jmx-exporter
image: bitnami/jmx-exporter:0.18.0
command: ["cp"]
args: ["/opt/bitnami/jmx-exporter/jmx_prometheus_javaagent.jar", "/var/atlassian/application-data/shared-home"]
image: curlimages/curl:latest
command: ["/bin/sh"]
args:
- -ec
- |
AGENT_PATH="/var/atlassian/application-data/shared-home/jmx_prometheus_javaagent.jar"
VERSION="0.18.0"
BASE_URL="https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent"
EXPECTED_SHA256="d3ba4ce8eccd3461463358c5e19f8becb99ed949f159c37c850e53b89b560f97"

# Download the agent
curl -L "${BASE_URL}/${VERSION}/jmx_prometheus_javaagent-${VERSION}.jar" -o $AGENT_PATH

# Verify SHA256
echo "${EXPECTED_SHA256} ${AGENT_PATH}" | sha256sum -c -

# Set permissions
chmod 644 $AGENT_PATH

# Verify JAR structure
if ! unzip -l $AGENT_PATH | grep -q "META-INF/MANIFEST.MF"; then
echo "Invalid JAR file"
exit 1
fi
if ! unzip -l $AGENT_PATH | grep -q "JavaAgent.class"; then
echo "Not a valid Java agent JAR"
exit 1
fi
securityContext:
runAsUser: 0
volumeMounts:
Expand Down
Loading