Customized Artemis Broker Configuration With Init Containers on Kubernetes or Openshift
In this article, we will discuss and explore options on how we can customize the configuration for Artemis Broker on Kubernetes or OpenShift.
Join the DZone community and get the full member experience.
Join For FreeApache ActiveMQ Artemis is a powerful open-source multi-protocol message broker. Red Hat AMQ 7 is the enterprise distribution of Apache ActiveMQ Artemis. Also, there is artemiscloud.io available for Kubernetes and OpenShift.
In this article, we will discuss how we can customize the configuration for Artemis Broker on Kubernetes. This could be helpful for those who are migrating from the Standalone version of AMQ 7 or Artemis to AMQ 7 on OpenShift. For beginners, the using_operator article would be helpful. In this article too, I am referring to this article for basic setup.
I am using minikube version: v1.19.0 for testing this setup on my laptop.
By default, broker configuration doesn't have to divert configuration. A divert just route messages from one address to another address in the same broker. Thus there is no need for an external connector to move messages from one destination to another, simple broker configuration using divert will move the messages. Following the configuration we will make here exclusive is set as false which means a copy of the message will be routed or forwarded from priceUpdates address/destination to priceForwarding address/destination.
x
<divert name="prices-divert">
<address>priceUpdates</address>
<forwarding-address>priceForwarding</forwarding-address>
<exclusive>false</exclusive>
</divert>
So, let's start now
1. Deploy Artemis Operator
xxxxxxxxxx
$ minikube start -p artemis-operator-1
$ mkdir artemis_cloud
$ cd artemis_cloud/
$ git clone https://github.com/artemiscloud/activemq-artemis-operator.git
$ kubectl create namespace myproject
$ kubectl config set-context --current --namespace=myproject
$ cd activemq-artemis-operator/
$ kubectl create -f deploy/service_account.yaml
$ kubectl create -f deploy/role.yaml
$ kubectl create -f deploy/role_binding.yaml
$ kubectl create -f deploy/crds/broker_activemqartemis_crd.yaml
$ kubectl create -f deploy/crds/broker_activemqartemisaddress_crd.yaml
$ kubectl create -f deploy/crds/broker_activemqartemisscaledown_crd.yaml
$ kubectl create -f deploy/operator.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
activemq-artemis-operator-85dddc589d-kqbvl 1/1 Running 0 2m22s
2. Configurations for Artemis init container: We need config/post-config.sh file and Dockerfile. Dockerfile refers to artemis-broker-init image, also config folder with post-config.sh file.
x
$ mkdir init_image
$ cd init_image
$ tree
.
├── config
│ └── post-config.sh
└── Dockerfile
1 directory, 2 files
$ cat Dockerfile
FROM quay.io/artemiscloud/activemq-artemis-broker-init:0.2.4
ADD config /amq/scripts
3. Content of post-config.sh file: Here we are adding divert and address configurations. At the end of the post-config.sh with sed command we are appending these configuration to default broker.xml. Here We don't have to set this CONFIG_INSTANCE_DIR
environment variable; it is resolved itself by init container and broker.
x
$ cat config/post-config.sh
echo "#### Custom config start. ####"
diverts=""
diverts=" ${diverts}<diverts>\n"
diverts=" ${diverts} <divert name=\"prices-divert\">\n"
diverts=" ${diverts} <address>priceUpdates</address>\n"
diverts=" ${diverts} <forwarding-address>priceForwarding</forwarding-address>\n"
diverts=" ${diverts} <exclusive>false</exclusive>\n"
diverts=" ${diverts} </divert>\n"
diverts=" ${diverts}</diverts>\n\n"
address=""
address=" ${address}<address name=\"priceForwarding\">\n"
address=" ${address} <anycast>\n"
address=" ${address} <queue name=\"priceForwarding\" />\n"
address=" ${address} </anycast>\n"
address=" ${address}</address>\n\n"
address=" ${address}<address name=\"priceUpdates\">\n"
address=" ${address} <anycast>\n"
address=" ${address} <queue name=\"priceUpdates\" />\n"
address=" ${address} </anycast>\n"
address=" ${address}</address>\n\n"
sed -i "s| <addresses>|${diverts} <addresses> ${address}|g" ${CONFIG_INSTANCE_DIR}/etc/broker.xml
echo "#### Custom config done. ####"
$
4. Create a customized init Docker Image.
x
# set docker context to minikube profile artemis-operator-1.
$ eval $(minikube -p artemis-operator-1 docker-env)
# check if docker context is set for minikube profile artemis-operator-1.
$ minikube profile list|grep artemis-operator-1
| artemis-operator-1 | kvm2 | docker | 192.168.50.67 | 8443 | v1.20.2 | Running | 1 |
$ docker context ls
NAME DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default * Current DOCKER_HOST based configuration tcp://192.168.50.67:2376 https://192.168.50.67:8443 (myproject) swarm
# Finally create docker image.
$ docker build -t init-custom:v1 .
$ docker images|grep init
REPOSITORY TAG IMAGE ID CREATED SIZE
init-custom v1 c57643837947 16 seconds ago 726MB
quay.io/artemiscloud/activemq-artemis-broker-init 0.2.4 636a02126ffc 2 months ago 726MB
$
5. Deploy Artemis broker instance using init image we just created: Within the git repository we cloned in first step, we can find examples activemq-artemis-operator/deploy/examples. We can create a artemis-basic-deployment-init.yaml with same content of artemis-basic-deployment.yaml. Than we can modify artemis-basic-deployment-init.yaml with image as broker image and initImage with the image we created.
x
$ cp artemis-basic-deployment.yaml artemis-basic-deployment-init.yaml
$ cat artemis-basic-deployment-init.yaml
apiVersion: broker.amq.io/v2alpha4
kind: ActiveMQArtemis
metadata:
name: ex-aao
spec:
deploymentPlan:
size: 1
image: quay.io/artemiscloud/activemq-artemis-broker-kubernetes:0.2.1
initImage: init-custom:v1
# finally create broker instance
$ kubectl apply -f artemis-basic-deployment-init.yaml
activemqartemis.broker.amq.io/ex-aao created
$ kubectl get pods -w
NAME READY STATUS RESTARTS AGE
activemq-artemis-operator-85dddc589d-kqbvl 1/1 Running 0 73m
ex-aao-ss-0 0/1 PodInitializing 0 20s
# In a minute or two
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
activemq-artemis-operator-85dddc589d-kqbvl 1/1 Running 0 94m
ex-aao-ss-0 1/1 Running 0 21m
$
6. Now send some messages to test Divert functionality.
x
# Send some messages to priceUpdates destination
$ kubectl exec ex-aao-ss-0 -n myproject -- /bin/bash /home/jboss/amq-broker/bin/artemis producer --user admin --password admin --url tcp://ex-aao-ss-0:61616 --destination priceUpdates --message-count 5
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Connection brokerURL = tcp://ex-aao-ss-0:61616
Producer ActiveMQQueue[priceUpdates], thread=0 Started to calculate elapsed time ...
Producer ActiveMQQueue[priceUpdates], thread=0 Produced: 5 messages
Producer ActiveMQQueue[priceUpdates], thread=0 Elapsed time in second : 1 s
Producer ActiveMQQueue[priceUpdates], thread=0 Elapsed time in milli second : 1328 milli seconds
# check queue stats
$ kubectl exec ex-aao-ss-0 -n myproject -- /bin/bash /home/jboss/amq-broker/bin/artemis queue stat --user admin --password admin --url tcp://ex-aao-ss-0:61616
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Connection brokerURL = tcp://ex-aao-ss-0:61616
|NAME |ADDRESS |CONSUMER_COUNT |MESSAGE_COUNT |MESSAGES_ADDED |DELIVERING_COUNT |MESSAGES_ACKED |SCHEDULED_COUNT |ROUTING_TYPE |
|DLQ |DLQ |0 |0 |0 |0 |0 |0 |ANYCAST |
|ExpiryQueue |ExpiryQueue |0 |0 |0 |0 |0 |0 |ANYCAST |
|activemq.management.1b865d33-fa08-4340-852e-b10d458fb1b9|activemq.management.1b865d33-fa08-4340-852e-b10d458fb1b9|1 |0 |0 |0 |0 |0 |MULTICAST |
|priceForwarding |priceForwarding |0 |5 |5 |0 |0 |0 |ANYCAST |
|priceUpdates |priceUpdates |0 |5 |5 |0 |0 |0 |ANYCAST |
$
7. Check If broker.xml has divert and address configuration set.
xxxxxxxxxx
$ kubectl exec --stdin --tty ex-aao-ss-0 -- /bin/bash
[jboss@ex-aao-ss-0 ~]$ pwd
/home/jboss
[jboss@ex-aao-ss-0 ~]$ cd amq-broker/etc/
[jboss@ex-aao-ss-0 etc]$ cat broker.xml
# to keep this short, removing other content
<diverts>
<divert name="prices-divert">
<address>priceUpdates</address>
<forwarding-address>priceForwarding</forwarding-address>
<exclusive>false</exclusive>
</divert>
</diverts>
<addresses> <address name="priceForwarding">
<anycast>
<queue name="priceForwarding" />
</anycast>
</address>
<address name="priceUpdates">
<anycast>
<queue name="priceUpdates" />
</anycast>
</address>
# to keep this short, removing other content
[jboss@ex-aao-ss-0 etc]$ exit
That's it, guys. I hope you will find this article helpful. When containers are immutable, it means any changes at runtime will not persist after pod restart, but with init containers, we can have our own customized image and this will persist during and after restart too.
Opinions expressed by DZone contributors are their own.
Comments