Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

How to use message migration with AMQ Broker Operator

December 5, 2023
Howard Gao
Related topics:
KubernetesOperators
Related products:
AMQ BrokerRed Hat OpenShift

Share:

    This article covers the message migration feature of AMQ Broker Operator. Enterprise messaging is of vital importance for mission critical businesses like financial and telecom firms. Important transaction information often rely on reliable messaging brokers like Red Hat's AMQ broker as the backbone for messaging processing. With the help of AMQ Broker Operator, users can easily deploy their AMQ broker-based application to a cloud environment like Red Hat OpenShift.

    The AMQ Broker Operator makes it easy to scale your broker deployment up and down according to your business requirement. When you scale up the broker deployment, more broker pods are available to handle messages. When you scale down, you get less broker processing power but you can free up cloud resources that you do not need.

    The message migration solution

    However, there is one concern that needs to be addressed. How do you deal with the important messages in the brokers that are going to be scaled down? If you simply let the broker pod down, those messages will be taken offline and stay in the persistent store of the scaled down broker and will never get processed any more—a situation unacceptable for any serious businesses. Here is where message migration comes to the rescue.

    For each of its broker deployment the AMQ Broker Operator watches all the pods it deploys. When a user scales down a broker deployment and some of the pods go down the operator detects the event and will immediately performs message migration.

    When a broker pod is scaled down, the operator will start a new broker pod in its place, mount the same Persistent Volume Claim (PVC) as its persistent store. When the new pod (called drainer pod) is started, it launches a special process where it finds a living broker pod and sends a scaleDown command via the jolokia endpoint to the drainer pod. The drainer pod then sends all its persistent messages to the living broker.

    If all messages are migrated without error, the drainer pod will terminate itself with a 0 exit code from the process. If the migration fails, the drainer pod will return with a non-zero code. The operator sees the non-zero code and will launch a new pod again and repeat the migration process until all the messages are migrated. The operator deletes the PVC only if the message migration is successful.

    The diagram in Figure 1 illustrates how the message migration works.

    message migration
    Figure 1: Scale down work flow
    License under MIT License.

    Messeage migration can be enabled in a Broker custom resource. It also requires persistence to be enabled as only persistent messages are migrated during a scale-down.

    Note that the operator only performs message migration on a normal scale down. It does not handle pod crashes.

    Let’s take an example to show how to set up a broker deployment and do message migration.

    Prerequisites

    • a Kubernetes cluster

    • admin access to the cluster

    Step 1: Create a new namespace

    Create a new namespace called message-migration-example:

    $ kubectl create namespace message-migration-example
    namespace/message-migration-example created

    Change the context to use it as current namespace:

    $ kubectl config set-context --current --namespace=message-migration-example
    Context "minikube" modified.

    We will deploy all the resources to this namespace.

    Step 2: Install AMQ Broker operator

    We will be using upstream operator. With the current namespace message-migration-example:

    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/crds/broker_activemqartemis_crd.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/crds/broker_activemqartemissecurity_crd.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/crds/broker_activemqartemisaddress_crd.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/crds/broker_activemqartemisscaledown_crd.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/service_account.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/role.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/role_binding.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/election_role.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/election_role_binding.yaml
    $ kubectl create -f https://raw.githubusercontent.com/artemiscloud/activemq-artemis-operator/v1.0.15/deploy/operator.yaml

    Check that the operator pod is running:

    $ kubectl get pod
    NAME                                                   READY   STATUS    RESTARTS   AGE
    activemq-artemis-controller-manager-7465974d85-z94dr   1/1     Running   0          30m

    Step 3: Deploy a broker deployment

    With the operator up and running, we can deploy two broker pods using the following CR:

    broker.yaml:

    apiVersion: broker.amq.io/v1beta1
    kind: ActiveMQArtemis
    metadata:
      name: amq
    spec:
      deploymentPlan:
        size: 2
        persistenceEnabled: true
        messageMigration: true
    
    $ kubectl create -f broker.yaml
    activemqartemis.broker.amq.io/amq created

    Note by default if spec.persistenceEnabled is set to true, the spec.messageMigration is also set to true.

    After the CR is deployed, a StatefulSet (amq-ss) is created by the operator with replica 2 and each broker gets a PVC volume mounted for storing persistent messages. You will see 2 broker pods created in namespace message-migration-example, along with the operator pod.

    $ kubectl get pod
    NAME                                                   READY   STATUS    RESTARTS   AGE
    activemq-artemis-controller-manager-7465974d85-z94dr   1/1     Running   0          76m
    amq-ss-0                                               1/1     Running   0          14m
    amq-ss-1                                               1/1     Running   0          4m31s
    
    

    Step 4: Send messages to pod 1

    When doing scale down, it is always the pods whose name has the largest ordinal number get deleted. In this example there are 2 pods whose names are amq-ss-0, amq-ss-1. If we scale down from 2 to 1 pod, the pod amq-ss-1 will get deleted.

    We will send a few messages to broker pod amq-ss-1 in order to see scale down in action.

    $ kubectl exec amq-ss-1 -- amq-broker/bin/artemis producer --url tcp://amq-ss-1:61616 --message-count 10 --destination test
    Defaulted container "amq-container" out of: amq-container, amq-container-init (init)
    Connection brokerURL = tcp://amq-ss-1:61616
    Producer ActiveMQQueue[test], thread=0 Started to calculate elapsed time ...
    
    Producer ActiveMQQueue[test], thread=0 Produced: 10 messages
    Producer ActiveMQQueue[test], thread=0 Elapsed time in second : 0 s
    Producer ActiveMQQueue[test], thread=0 Elapsed time in milli second : 74 milli seconds

    The above command uses the AMQ broker’s built-in command line tool artemis to send 10 messages to a queue test in each broker. We can use the command line tool to check the messages on each broker:

    $ kubectl exec amq-ss-1 -- amq-broker/bin/artemis queue stat --url tcp://amq-ss-1:61616
    Defaulted container "amq-container" out of: amq-container, amq-container-init (init)
    Connection brokerURL = tcp://amq-ss-1: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.67...|activemq.management.67...|1             |0            |0             |0               |0             |0              |MULTICAST   |
    |test                     |test                     |0             |10           |10            |0               |0             |0              |ANYCAST     |
    

    Step 5: Scale down the broker pods

    Edit the custom resource to change the spec.deploymentPlan.size to 1.

    apiVersion: broker.amq.io/v1beta1
    kind: ActiveMQArtemis
    metadata:
      name: amq
    spec:
      deploymentPlan:
        size: 1
        persistenceEnabled: true
        messageMigration: true
    

    Apply the change:

    $ kubectl apply -f broker.yaml
    activemqartemis.broker.amq.io/amq configured
    

    When the change is applied, broker pod amq-ss-1 will be terminated and a new pod will be created to perform message migration. When the message migration is completed, the new pod will be terminated.

    Now the scale down is done and there is only one living broker pod:

    $ kubectl get pod
    NAME                                                   READY   STATUS    RESTARTS   AGE
    activemq-artemis-controller-manager-7465974d85-z94dr   1/1     Running   0          4h50m
    amq-ss-0                                               1/1     Running   0          3h47m
    

    Checking the messages you will see the messages are now migrated to the living pod:

    $ kubectl exec amq-ss-0 -- amq-broker/bin/artemis queue stat --url tcp://amq-ss-0:61616
    Defaulted container "amq-container" out of: amq-container, amq-container-init (init)
    Connection brokerURL = tcp://amq-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.66...|activemq.management.66...|1             |0            |0             |0               |0             |0              |MULTICAST   |
    |test                     |test                     |0             |10           |10            |0               |0             |0              |ANYCAST     |
    

    Troubleshooting

    If the message migration failed, the drainer pod (the pod created to do message migration) won’t exit immediately. Instead it will sleep for 30 seconds, during which time users can get the pod’s log to find details of the message migration for debug.

    You can also check out the operator's log to find more details about the message migration.

    The persistent volume of the scaled down pod will not be deleted in case of a message migration failure. You will be able to manually recover the messages from it in case of a failed message migration.

    Related Posts

    • Manage Kafka clusters with AKHQ and AMQ streams

    • Connecting external clients to Red Hat AMQ Broker on Red Hat OpenShift

    • Hello World for AMQ Broker on OpenShift

    • Setting up RBAC on Red Hat AMQ Broker

    • Logging incoming and outgoing messages for Red Hat AMQ 7

    • How to run Kafka on Openshift, the enterprise Kubernetes, with AMQ Streams

    Recent Posts

    • Ollama or vLLM? How to choose the right LLM serving tool for your use case

    • How to build a Model-as-a-Service platform

    • How Quarkus works with OpenTelemetry on OpenShift

    • Our top 10 articles of 2025 (so far)

    • The benefits of auto-merging GitHub and GitLab repositories

    What’s up next?

    Gitops Cookbook e-book tile card

    GitOps has become a standard in deploying applications to Kubernetes, and many companies are adopting the methodology for their DevOps and cloud-native strategy. Download the GitOps Cookbook for useful recipes and examples for successful hands-on applications development and deployment with GitOps.

    Get the e-book
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue