From 165464103bbc1a5785b6f0690dff19612adc7e88 Mon Sep 17 00:00:00 2001 From: Ken Liao Date: Sun, 23 Nov 2025 23:58:15 -0800 Subject: [PATCH 1/5] Add basic helm chart for ActiveMQ --- activemq-helm-chart/Chart.yaml | 15 ++ activemq-helm-chart/README.md | 96 +++++++++++++ activemq-helm-chart/activemq_sample.xml | 130 ++++++++++++++++++ activemq-helm-chart/templates/NOTES.txt | 29 ++++ activemq-helm-chart/templates/_helpers.tpl | 49 +++++++ activemq-helm-chart/templates/configmap.yaml | 15 ++ activemq-helm-chart/templates/service.yaml | 19 +++ .../templates/statefulset.yaml | 104 ++++++++++++++ activemq-helm-chart/values.yaml | 70 ++++++++++ 9 files changed, 527 insertions(+) create mode 100644 activemq-helm-chart/Chart.yaml create mode 100644 activemq-helm-chart/README.md create mode 100644 activemq-helm-chart/activemq_sample.xml create mode 100644 activemq-helm-chart/templates/NOTES.txt create mode 100644 activemq-helm-chart/templates/_helpers.tpl create mode 100644 activemq-helm-chart/templates/configmap.yaml create mode 100644 activemq-helm-chart/templates/service.yaml create mode 100644 activemq-helm-chart/templates/statefulset.yaml create mode 100644 activemq-helm-chart/values.yaml diff --git a/activemq-helm-chart/Chart.yaml b/activemq-helm-chart/Chart.yaml new file mode 100644 index 00000000000..b3c364e030f --- /dev/null +++ b/activemq-helm-chart/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +name: activemq +description: A Helm chart for Apache ActiveMQ +type: application +version: 1.0.0 +appVersion: "latest" +keywords: + - activemq + - message queue + - messaging +home: https://activemq.apache.org +sources: + - https://github.com/apache/activemq +maintainers: + - name: activemq \ No newline at end of file diff --git a/activemq-helm-chart/README.md b/activemq-helm-chart/README.md new file mode 100644 index 00000000000..e91bae7b261 --- /dev/null +++ b/activemq-helm-chart/README.md @@ -0,0 +1,96 @@ +# ActiveMQ Helm Chart + +A Helm chart for deploying Apache ActiveMQ on Kubernetes. + +## Introduction + +This chart bootstraps an ActiveMQ deployment on a Kubernetes cluster using the Helm package manager. + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.0+ +- PV provisioner support in the underlying infrastructure (if persistence is enabled) + +## Installing the Chart + +To install the chart with the release name `my-activemq`: + +```bash +helm install my-activemq . +``` + +## Uninstalling the Chart + +To uninstall/delete the `my-activemq` deployment: + +```bash +helm uninstall my-activemq +``` + +## Configuration + +The following table lists the configurable parameters of the ActiveMQ chart and their default values. + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `replicaCount` | Number of replicas | `1` | +| `image.repository` | ActiveMQ image repository | `apache/activemq-classic` | +| `image.tag` | ActiveMQ image tag | `latest` | +| `image.pullPolicy` | Image pull policy | `IfNotPresent` | +| `auth.username` | ActiveMQ admin username | `admin` | +| `auth.password` | ActiveMQ admin password | `changeme` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.port` | OpenWire service port | `61616` | +| `service.webConsolePort` | Web Console port | `8161` | +| `persistence.enabled` | Enable persistence using PVC | `true` | +| `persistence.storageClass` | PVC Storage Class | `""` | +| `persistence.accessMode` | PVC Access Mode | `ReadWriteOnce` | +| `persistence.size` | PVC Storage Request | `8Gi` | +| `resources.limits.cpu` | CPU limit | `1000m` | +| `resources.limits.memory` | Memory limit | `2Gi` | +| `resources.requests.cpu` | CPU request | `500m` | +| `resources.requests.memory` | Memory request | `1Gi` | +| `livenessProbe.enabled` | Enable liveness probe | `true` | +| `readinessProbe.enabled` | Enable readiness probe | `true` | +| `ingress.enabled` | Enable ingress | `false` | +| `config.activemqXmlPath` | Path to custom activemq.xml file | `""` | + +## Accessing ActiveMQ + +### Web Console + +The ActiveMQ Web Console is accessible on port 8161. To access it locally: + +```bash +kubectl port-forward svc/my-activemq 8161:8161 +``` + +Then open http://localhost:8161 in your browser and login with the configured credentials. + +### OpenWire Connection + +Applications can connect to ActiveMQ on port 61616 using the service name: + +``` +tcp://my-activemq:61616 +``` + +## Custom Configuration + +To use a custom `activemq.xml` configuration file, place your file in the chart directory and specify the path: + +```bash +cp activemq_sample.xml mq-activemq.xml +``` + +```yaml +config: + activemqXmlPath: "my-activemq.xml" +``` + +## Persistence + +The ActiveMQ image stores data at the `/opt/apache-activemq/data` path of the container. + +By default, the chart mounts a Persistent Volume at this location. The volume is created using dynamic volume provisioning. \ No newline at end of file diff --git a/activemq-helm-chart/activemq_sample.xml b/activemq-helm-chart/activemq_sample.xml new file mode 100644 index 00000000000..9f32bd90f59 --- /dev/null +++ b/activemq-helm-chart/activemq_sample.xml @@ -0,0 +1,130 @@ + + + + + + + + file:${activemq.conf}/credentials.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/activemq-helm-chart/templates/NOTES.txt b/activemq-helm-chart/templates/NOTES.txt new file mode 100644 index 00000000000..0a4b9e95e08 --- /dev/null +++ b/activemq-helm-chart/templates/NOTES.txt @@ -0,0 +1,29 @@ +1. Get the ActiveMQ Web Console URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[1].nodePort}" services {{ include "activemq.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "activemq.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "activemq.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.webConsolePort }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "activemq.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[1].containerPort}") + echo "Visit http://127.0.0.1:8161 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8161:$CONTAINER_PORT +{{- end }} + +2. Login credentials: + Username: {{ .Values.auth.username }} + Password: {{ .Values.auth.password }} + +3. To connect to ActiveMQ from applications: + Connection URL: tcp://{{ include "activemq.fullname" . }}:{{ .Values.service.port }} \ No newline at end of file diff --git a/activemq-helm-chart/templates/_helpers.tpl b/activemq-helm-chart/templates/_helpers.tpl new file mode 100644 index 00000000000..8427364191d --- /dev/null +++ b/activemq-helm-chart/templates/_helpers.tpl @@ -0,0 +1,49 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "activemq.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "activemq.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "activemq.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "activemq.labels" -}} +helm.sh/chart: {{ include "activemq.chart" . }} +{{ include "activemq.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "activemq.selectorLabels" -}} +app.kubernetes.io/name: {{ include "activemq.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} \ No newline at end of file diff --git a/activemq-helm-chart/templates/configmap.yaml b/activemq-helm-chart/templates/configmap.yaml new file mode 100644 index 00000000000..89eb203cb60 --- /dev/null +++ b/activemq-helm-chart/templates/configmap.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "activemq.fullname" . }}-config + labels: + {{- include "activemq.labels" . | nindent 4 }} +data: + users.properties: | + {{ .Values.auth.username }}={{ .Values.auth.password }} + groups.properties: | + admins={{ .Values.auth.username }} + {{- if .Values.config.activemqXmlPath }} + activemq.xml: | +{{ .Files.Get .Values.config.activemqXmlPath | indent 4 }} + {{- end }} \ No newline at end of file diff --git a/activemq-helm-chart/templates/service.yaml b/activemq-helm-chart/templates/service.yaml new file mode 100644 index 00000000000..bd4fc77ec3c --- /dev/null +++ b/activemq-helm-chart/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "activemq.fullname" . }} + labels: + {{- include "activemq.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: openwire + port: {{ .Values.service.port }} + targetPort: openwire + protocol: TCP + - name: webconsole + port: {{ .Values.service.webConsolePort }} + targetPort: webconsole + protocol: TCP + selector: + {{- include "activemq.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/activemq-helm-chart/templates/statefulset.yaml b/activemq-helm-chart/templates/statefulset.yaml new file mode 100644 index 00000000000..842533f177a --- /dev/null +++ b/activemq-helm-chart/templates/statefulset.yaml @@ -0,0 +1,104 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "activemq.fullname" . }} + labels: + {{- include "activemq.labels" . | nindent 4 }} +spec: + serviceName: {{ include "activemq.fullname" . }} + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "activemq.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "activemq.selectorLabels" . | nindent 8 }} + spec: + containers: + - name: activemq + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: openwire + containerPort: 61616 + protocol: TCP + - name: webconsole + containerPort: 8161 + protocol: TCP + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + tcpSocket: + port: openwire + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + tcpSocket: + port: openwire + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + {{- end }} + volumeMounts: + - name: data + mountPath: /opt/apache-activemq/data + - name: config + mountPath: /opt/apache-activemq/conf/users.properties + subPath: users.properties + - name: config + mountPath: /opt/apache-activemq/conf/groups.properties + subPath: groups.properties + {{- if .Values.config.activemqXmlPath }} + - name: config + mountPath: /opt/apache-activemq/conf/activemq.xml + subPath: activemq.xml + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + configMap: + name: {{ include "activemq.fullname" . }}-config + {{- if not .Values.persistence.enabled }} + - name: data + emptyDir: {} + {{- end }} + {{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: + - {{ .Values.persistence.accessMode | quote }} + {{- if .Values.persistence.storageClass }} + storageClassName: {{ .Values.persistence.storageClass | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- end }} \ No newline at end of file diff --git a/activemq-helm-chart/values.yaml b/activemq-helm-chart/values.yaml new file mode 100644 index 00000000000..3a8abcc677f --- /dev/null +++ b/activemq-helm-chart/values.yaml @@ -0,0 +1,70 @@ +replicaCount: 1 + +image: + repository: apache/activemq-classic + tag: "latest" + pullPolicy: IfNotPresent + +nameOverride: "" +fullnameOverride: "" + +auth: + username: admin + password: changeme + +config: + activemqXmlPath: "" + +service: + type: ClusterIP + port: 61616 + webConsolePort: 8161 + +persistence: + enabled: false + storageClass: "" + accessMode: ReadWriteOnce + size: 8Gi + +resources: + limits: + cpu: 1000m + memory: 2Gi + requests: + cpu: 500m + memory: 1Gi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +podAnnotations: {} + +livenessProbe: + enabled: true + initialDelaySeconds: 120 + periodSeconds: 30 + timeoutSeconds: 20 + failureThreshold: 6 + successThreshold: 1 + +readinessProbe: + enabled: true + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 20 + failureThreshold: 3 + successThreshold: 1 + +ingress: + enabled: false + className: "" + annotations: {} + hosts: + - host: activemq.local + paths: + - path: / + pathType: Prefix + tls: [] \ No newline at end of file From 962490619e4fd178b61d6f75d9ade69bc1dea8b6 Mon Sep 17 00:00:00 2001 From: Ken Liao Date: Tue, 25 Nov 2025 15:43:41 -0800 Subject: [PATCH 2/5] support TLS --- activemq-helm-chart/README.md | 16 +++++++++- activemq-helm-chart/templates/NOTES.txt | 11 ++++++- activemq-helm-chart/templates/service.yaml | 11 +++++++ .../templates/statefulset.yaml | 31 +++++++++++++++++-- activemq-helm-chart/values.yaml | 9 +++++- 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/activemq-helm-chart/README.md b/activemq-helm-chart/README.md index e91bae7b261..13517582bd6 100644 --- a/activemq-helm-chart/README.md +++ b/activemq-helm-chart/README.md @@ -93,4 +93,18 @@ config: The ActiveMQ image stores data at the `/opt/apache-activemq/data` path of the container. -By default, the chart mounts a Persistent Volume at this location. The volume is created using dynamic volume provisioning. \ No newline at end of file +By default, the chart mounts a Persistent Volume at this location. The volume is created using dynamic volume provisioning. + +## TLS Configuration + +To enable TLS, create secrets with your keystore and truststore files: + +```bash +kubectl create secret generic activemq-keystore --from-file=broker.ks=/path/to/broker.ks +kubectl create secret generic activemq-truststore --from-file=broker.ts=/path/to/broker.ts + +helm install my-activemq . \ + --set tls.enabled=true \ + --set tls.keystoreSecret=activemq-keystore \ + --set tls.truststoreSecret=activemq-truststore +``` \ No newline at end of file diff --git a/activemq-helm-chart/templates/NOTES.txt b/activemq-helm-chart/templates/NOTES.txt index 0a4b9e95e08..06cdaae8735 100644 --- a/activemq-helm-chart/templates/NOTES.txt +++ b/activemq-helm-chart/templates/NOTES.txt @@ -26,4 +26,13 @@ Password: {{ .Values.auth.password }} 3. To connect to ActiveMQ from applications: - Connection URL: tcp://{{ include "activemq.fullname" . }}:{{ .Values.service.port }} \ No newline at end of file + Connection URL: tcp://{{ include "activemq.fullname" . }}:{{ .Values.service.port }} +{{- if .Values.tls.enabled }} + SSL Connection URL: ssl://{{ include "activemq.fullname" . }}:{{ .Values.tls.sslPort }} +{{- end }} + +{{- if .Values.tls.enabled }} +4. TLS is enabled. Ensure you have created the required secrets: + - Keystore secret: {{ .Values.tls.keystoreSecret }} + - Truststore secret: {{ .Values.tls.truststoreSecret }} +{{- end }} \ No newline at end of file diff --git a/activemq-helm-chart/templates/service.yaml b/activemq-helm-chart/templates/service.yaml index bd4fc77ec3c..2e421e36576 100644 --- a/activemq-helm-chart/templates/service.yaml +++ b/activemq-helm-chart/templates/service.yaml @@ -7,6 +7,7 @@ metadata: spec: type: {{ .Values.service.type }} ports: + {{- if not .Values.tls.enabled }} - name: openwire port: {{ .Values.service.port }} targetPort: openwire @@ -15,5 +16,15 @@ spec: port: {{ .Values.service.webConsolePort }} targetPort: webconsole protocol: TCP + {{- else }} + - name: openwire-ssl + port: {{ .Values.tls.sslPort }} + targetPort: openwire-ssl + protocol: TCP + - name: webconsole-ssl + port: {{ .Values.tls.webConsoleSslPort }} + targetPort: webconsole-ssl + protocol: TCP + {{- end }} selector: {{- include "activemq.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/activemq-helm-chart/templates/statefulset.yaml b/activemq-helm-chart/templates/statefulset.yaml index 842533f177a..14928d5de01 100644 --- a/activemq-helm-chart/templates/statefulset.yaml +++ b/activemq-helm-chart/templates/statefulset.yaml @@ -24,16 +24,25 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: + {{- if not .Values.tls.enabled }} - name: openwire containerPort: 61616 protocol: TCP - name: webconsole containerPort: 8161 protocol: TCP + {{- else }} + - name: openwire-ssl + containerPort: {{ .Values.tls.sslPort }} + protocol: TCP + - name: webconsole-ssl + containerPort: {{ .Values.tls.webConsoleSslPort }} + protocol: TCP + {{- end }} {{- if .Values.livenessProbe.enabled }} livenessProbe: tcpSocket: - port: openwire + port: {{ if .Values.tls.enabled }}openwire-ssl{{ else }}openwire{{ end }} initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.livenessProbe.periodSeconds }} timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} @@ -43,7 +52,7 @@ spec: {{- if .Values.readinessProbe.enabled }} readinessProbe: tcpSocket: - port: openwire + port: {{ if .Values.tls.enabled }}openwire-ssl{{ else }}openwire{{ end }} initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.readinessProbe.periodSeconds }} timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} @@ -64,6 +73,16 @@ spec: mountPath: /opt/apache-activemq/conf/activemq.xml subPath: activemq.xml {{- end }} + {{- if .Values.tls.enabled }} + - name: keystore + mountPath: /opt/apache-activemq/conf/broker.ks + subPath: broker.ks + readOnly: true + - name: truststore + mountPath: /opt/apache-activemq/conf/broker.ts + subPath: broker.ts + readOnly: true + {{- end }} {{- with .Values.resources }} resources: {{- toYaml . | nindent 10 }} @@ -84,6 +103,14 @@ spec: - name: config configMap: name: {{ include "activemq.fullname" . }}-config + {{- if .Values.tls.enabled }} + - name: keystore + secret: + secretName: {{ .Values.tls.keystoreSecret }} + - name: truststore + secret: + secretName: {{ .Values.tls.truststoreSecret }} + {{- end }} {{- if not .Values.persistence.enabled }} - name: data emptyDir: {} diff --git a/activemq-helm-chart/values.yaml b/activemq-helm-chart/values.yaml index 3a8abcc677f..d3c4d6fd87f 100644 --- a/activemq-helm-chart/values.yaml +++ b/activemq-helm-chart/values.yaml @@ -67,4 +67,11 @@ ingress: paths: - path: / pathType: Prefix - tls: [] \ No newline at end of file + tls: [] + +tls: + enabled: false + keystoreSecret: "activemq-keystore" # kubectl create secret generic activemq-keystore --from-file=broker.ks= + truststoreSecret: "activemq-truststore" # kubectl create secret generic activemq-truststore --from-file=broker.ts= + sslPort: 61617 + webConsoleSslPort: 8162 \ No newline at end of file From d3ccd54da995f6ef94b2256e576e4d16a135c63d Mon Sep 17 00:00:00 2001 From: Ken Liao Date: Tue, 25 Nov 2025 15:55:24 -0800 Subject: [PATCH 3/5] correct instructions --- activemq-helm-chart/templates/NOTES.txt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/activemq-helm-chart/templates/NOTES.txt b/activemq-helm-chart/templates/NOTES.txt index 06cdaae8735..cf84715dd2d 100644 --- a/activemq-helm-chart/templates/NOTES.txt +++ b/activemq-helm-chart/templates/NOTES.txt @@ -6,19 +6,19 @@ {{- end }} {{- end }} {{- else if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[1].nodePort}" services {{ include "activemq.fullname" . }}) + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "activemq.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT + echo {{ if .Values.tls.enabled }}https{{ else }}http{{ end }}://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "activemq.fullname" . }}' export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "activemq.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") - echo http://$SERVICE_IP:{{ .Values.service.webConsolePort }} + echo {{ if .Values.tls.enabled }}https{{ else }}http{{ end }}://$SERVICE_IP:{{ if .Values.tls.enabled }}{{ .Values.tls.webConsoleSslPort }}{{ else }}{{ .Values.service.webConsolePort }}{{ end }} {{- else if contains "ClusterIP" .Values.service.type }} export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "activemq.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[1].containerPort}") - echo "Visit http://127.0.0.1:8161 to use your application" - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8161:$CONTAINER_PORT + echo "Visit {{ if .Values.tls.enabled }}https://127.0.0.1:{{ .Values.tls.webConsoleSslPort }}{{ else }}http://127.0.0.1:{{ .Values.service.webConsolePort }}{{ end }} to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME {{ if .Values.tls.enabled }}{{ .Values.tls.webConsoleSslPort }}{{ else }}{{ .Values.service.webConsolePort }}{{ end }}:$CONTAINER_PORT {{- end }} 2. Login credentials: @@ -26,9 +26,10 @@ Password: {{ .Values.auth.password }} 3. To connect to ActiveMQ from applications: - Connection URL: tcp://{{ include "activemq.fullname" . }}:{{ .Values.service.port }} {{- if .Values.tls.enabled }} - SSL Connection URL: ssl://{{ include "activemq.fullname" . }}:{{ .Values.tls.sslPort }} + Connection URL: ssl://{{ include "activemq.fullname" . }}:{{ .Values.tls.sslPort }} +{{- else }} + Connection URL: tcp://{{ include "activemq.fullname" . }}:{{ .Values.service.port }} {{- end }} {{- if .Values.tls.enabled }} From 73e85056220378403b04ad66fdcb41ea12b6498b Mon Sep 17 00:00:00 2001 From: Ken Liao Date: Tue, 25 Nov 2025 16:10:04 -0800 Subject: [PATCH 4/5] add more to README --- activemq-helm-chart/README.md | 40 ++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/activemq-helm-chart/README.md b/activemq-helm-chart/README.md index 13517582bd6..d11730c0aca 100644 --- a/activemq-helm-chart/README.md +++ b/activemq-helm-chart/README.md @@ -43,7 +43,7 @@ The following table lists the configurable parameters of the ActiveMQ chart and | `service.type` | Kubernetes service type | `ClusterIP` | | `service.port` | OpenWire service port | `61616` | | `service.webConsolePort` | Web Console port | `8161` | -| `persistence.enabled` | Enable persistence using PVC | `true` | +| `persistence.enabled` | Enable persistence using PVC | `false` | | `persistence.storageClass` | PVC Storage Class | `""` | | `persistence.accessMode` | PVC Access Mode | `ReadWriteOnce` | | `persistence.size` | PVC Storage Request | `8Gi` | @@ -55,6 +55,11 @@ The following table lists the configurable parameters of the ActiveMQ chart and | `readinessProbe.enabled` | Enable readiness probe | `true` | | `ingress.enabled` | Enable ingress | `false` | | `config.activemqXmlPath` | Path to custom activemq.xml file | `""` | +| `tls.enabled` | Enable TLS/SSL | `false` | +| `tls.keystoreSecret` | Kubernetes secret containing broker.ks | `""` | +| `tls.truststoreSecret` | Kubernetes secret containing broker.ts | `""` | +| `tls.sslPort` | OpenWire SSL port | `61617` | +| `tls.webConsoleSslPort` | Web Console SSL port | `8162` | ## Accessing ActiveMQ @@ -97,14 +102,39 @@ By default, the chart mounts a Persistent Volume at this location. The volume is ## TLS Configuration -To enable TLS, create secrets with your keystore and truststore files: +To enable TLS/SSL connections, you need to create Kubernetes secrets containing your keystore and truststore files. + +### Generate Test Certificates (for development) + +```bash +# Generate keystore +keytool -genkey -alias broker -keyalg RSA -keystore broker.ks \ + -storepass changeit -keypass changeit \ + -dname "CN=localhost, OU=Test, O=Test, L=Test, ST=Test, C=US" + +# Export certificate +keytool -export -alias broker -keystore broker.ks \ + -file broker.cert -storepass changeit + +# Create truststore +keytool -import -alias broker -keystore broker.ts \ + -file broker.cert -storepass changeit -noreply +``` + +### Create Kubernetes Secrets ```bash -kubectl create secret generic activemq-keystore --from-file=broker.ks=/path/to/broker.ks -kubectl create secret generic activemq-truststore --from-file=broker.ts=/path/to/broker.ts +kubectl create secret generic activemq-keystore --from-file=broker.ks +kubectl create secret generic activemq-truststore --from-file=broker.ts +``` + +### Install with TLS Enabled +```bash helm install my-activemq . \ --set tls.enabled=true \ --set tls.keystoreSecret=activemq-keystore \ --set tls.truststoreSecret=activemq-truststore -``` \ No newline at end of file +``` + +**Note:** When TLS is enabled, only SSL/TLS ports are exposed. Non-TLS ports are not available. \ No newline at end of file From 1cd6cb91c6838ab2e3053851143a3559c268513d Mon Sep 17 00:00:00 2001 From: Ken Liao Date: Tue, 25 Nov 2025 20:40:03 -0800 Subject: [PATCH 5/5] Added ability to configure jetty.xml --- activemq-helm-chart/README.md | 10 ++++------ activemq-helm-chart/templates/configmap.yaml | 4 ++++ activemq-helm-chart/templates/statefulset.yaml | 5 +++++ activemq-helm-chart/values.yaml | 1 + 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/activemq-helm-chart/README.md b/activemq-helm-chart/README.md index d11730c0aca..a7644172779 100644 --- a/activemq-helm-chart/README.md +++ b/activemq-helm-chart/README.md @@ -55,6 +55,7 @@ The following table lists the configurable parameters of the ActiveMQ chart and | `readinessProbe.enabled` | Enable readiness probe | `true` | | `ingress.enabled` | Enable ingress | `false` | | `config.activemqXmlPath` | Path to custom activemq.xml file | `""` | +| `config.jettyXmlPath` | Path to custom jetty.xml file | `""` | | `tls.enabled` | Enable TLS/SSL | `false` | | `tls.keystoreSecret` | Kubernetes secret containing broker.ks | `""` | | `tls.truststoreSecret` | Kubernetes secret containing broker.ts | `""` | @@ -83,15 +84,12 @@ tcp://my-activemq:61616 ## Custom Configuration -To use a custom `activemq.xml` configuration file, place your file in the chart directory and specify the path: - -```bash -cp activemq_sample.xml mq-activemq.xml -``` +To use custom configuration files, place your files in the chart directory and specify the paths: ```yaml config: activemqXmlPath: "my-activemq.xml" + jettyXmlPath: "my-jetty.xml" ``` ## Persistence @@ -118,7 +116,7 @@ keytool -export -alias broker -keystore broker.ks \ # Create truststore keytool -import -alias broker -keystore broker.ts \ - -file broker.cert -storepass changeit -noreply + -file broker.cert -storepass changeit ``` ### Create Kubernetes Secrets diff --git a/activemq-helm-chart/templates/configmap.yaml b/activemq-helm-chart/templates/configmap.yaml index 89eb203cb60..4d44407b384 100644 --- a/activemq-helm-chart/templates/configmap.yaml +++ b/activemq-helm-chart/templates/configmap.yaml @@ -12,4 +12,8 @@ data: {{- if .Values.config.activemqXmlPath }} activemq.xml: | {{ .Files.Get .Values.config.activemqXmlPath | indent 4 }} + {{- end }} + {{- if .Values.config.jettyXmlPath }} + jetty.xml: | +{{ .Files.Get .Values.config.jettyXmlPath | indent 4 }} {{- end }} \ No newline at end of file diff --git a/activemq-helm-chart/templates/statefulset.yaml b/activemq-helm-chart/templates/statefulset.yaml index 14928d5de01..60d2d292bb7 100644 --- a/activemq-helm-chart/templates/statefulset.yaml +++ b/activemq-helm-chart/templates/statefulset.yaml @@ -73,6 +73,11 @@ spec: mountPath: /opt/apache-activemq/conf/activemq.xml subPath: activemq.xml {{- end }} + {{- if .Values.config.jettyXmlPath }} + - name: config + mountPath: /opt/apache-activemq/conf/jetty.xml + subPath: jetty.xml + {{- end }} {{- if .Values.tls.enabled }} - name: keystore mountPath: /opt/apache-activemq/conf/broker.ks diff --git a/activemq-helm-chart/values.yaml b/activemq-helm-chart/values.yaml index d3c4d6fd87f..5b95b600e18 100644 --- a/activemq-helm-chart/values.yaml +++ b/activemq-helm-chart/values.yaml @@ -14,6 +14,7 @@ auth: config: activemqXmlPath: "" + jettyXmlPath: "" service: type: ClusterIP