Over the past few years, the container ecosystem has been evolving rapidly, affecting how teams build, distribute, and operate applications. Changes in image availability, maintenance models, and long-term support expectations have encouraged many organizations to pause and reassess their container strategies – especially for critical infrastructure components running in production.

In this context, many teams are returning to well-established open-source solutions and community-driven projects as a reliable and transparent foundation. Of course, there is no single “right” approach: the choice of images, vendors, or support models should always depend on your specific requirements, constraints, and risk tolerance. You are free to use the tools and solutions that best fit your situation.

For teams that choose to follow this open-source–first approach, we have prepared a practical guide that demonstrates how to migrate safely using a real-world example. In this article, we focus on Apache ZooKeeper and show how to migrate ZooKeeper data when moving away from Bitnami-based Docker deployments or when rebuilding ZooKeeper clusters using alternative images, platforms, or orchestration models.

Migration Overview

ZooKeeper stores critical coordination and metadata information, making data migration a sensitive operation. Below are three proven methods to migrate ZooKeeper data between Docker-based or containerized ZooKeeper deployments:

1. Migration using the ZooKeeper Admin REST API (recommended)

2. Migration via direct data directory copy

3. Migration in Kubernetes environments using StatefulSets

Each method applies to different deployment models and operational constraints.

Method 1: Migration Using ZooKeeper Admin REST API (Recommended)

This is the safest and recommended approach for migrating data between ZooKeeper clusters, provided that the Admin REST API is enabled.

Key Characteristics

  • Uses ZooKeeper’s built-in snapshot and restore mechanism
  • Preserves data consistency across the cluster
  • Works well for Dockerized and distributed environments
  • Snapshot and restore operations are rate-limited to once every 5 minutes by default Snapshot Creation

Important: The snapshot must be taken from a single node in the source cluster.

 curl -H 'Authorization: digest root:root_passwd' \
  http://hostname:adminPort/commands/snapshot?streaming=true \
  --output snapshotFileName

This command streams a snapshot of the ZooKeeper data to a local file.

Restore Procedure

All cluster members must restore from the same snapshot file.

Recommended Restore Steps

1. Block traffic on the ZooKeeper client port (or secure client port) before starting the restore

2. For each ZooKeeper server:

  • Ensure the cluster contains no existing data
  • Move the files in dataDir and dataLogDir to different location, or delete the data inside these directories to prevent the restored database from being overwritten when server restarts after restore
  • Restore the server using restore admin server command
  • Unblock traffic on the client port or client secure port after restore is complete
 curl -H 'Content-Type:application/octet-stream' \
 -H 'Authorization: digest root:root_passwd' \
 -POST http://hostname:adminPort/commands/restore \
 --data-binary "@snapshotFileName"

Notes

  • Ideal for cluster-to-cluster migrations
  • All nodes must restore from the same snapshot
  • Admin REST API must be explicitly enabled

Method 2: Direct File Copy (Data Directory Migration)

This method involves copying ZooKeeper’s on-disk data directly between nodes. It is best suited for:

  • Standalone ZooKeeper installations
  • ZooKeeper running on dedicated servers or virtual machines
  • Scenarios where Admin REST API is unavailable

Assumptions

  • A 3-node ZooKeeper cluster
  • Access to ZooKeeper dataDir on each node

Step 1: Copy $DATADIR/Version-*  from each of the nodes locally

 mkdir -p /tmp/zk-migrate/{1,2,3}
 rsync -vzal $OLD_NODE1:$DATADIR/Version-*  /tmp/zk-migrate/1
 rsync -vzal $OLD_NODE2:$DATADIR/Version-*  /tmp/zk-migrate/2
 rsync -vzal $OLD_NODE3:$DATADIR/Version-*  /tmp/zk-migrate/3

Step 2: Prepare Destination Nodes

  • Stop ZooKeeper on all destination nodes
  • Delete $DATADIR/Version-* from each of nodes

Step 3: Copy Local Data To New Nodes

rsync -vzal /tmp/zk-migrate/1/* $OLD_NODE1:$DATADIR/
rsync -vzal /tmp/zk-migrate/2/* $OLD_NODE2:$DATADIR/
rsync -vzal /tmp/zk-migrate/3/* $OLD_NODE3:$DATADIR/

Step 4: Update ownership of the data directories on the destination nodes

Change the ownership of the newly copied data directories to the user and group running the ZooKeeper service:

chown -R $ZK_USER:$ZK_GROUP $DATADIR/*

Step 5: Start ZooKeeper

Start ZooKeeper services on all nodes and verify cluster health.

Notes

  • Incorrect ownership or mismatched data may prevent startup
  • Ensure node-to-node data mapping remains consistent

Method 3: Kubernetes Migration Using StatefulSets

In Kubernetes environments, ZooKeeper should ideally be deployed using StatefulSets, which provide stable identities and persistent storage.

Recommended Approach
  • Detach the persistent volume from the source ZooKeeper pod
  • Attach it to the destination ZooKeeper pod
  • This effectively moves the entire ZooKeeper data directory

If the Existing Deployment Is Not Stateful

If the original ZooKeeper pods were deployed:

  • Without StatefulSets, or
  • Using ephemeral storage

Then:

  • Deploy new ZooKeeper nodes using StatefulSets (highly recommended)
  • Follow Method 2 to migrate data into the new persistent volumes

Benefits of StatefulSets

  • Stable network identities
  • Predictable storage mapping
  • Safer rolling restarts and upgrades

Final Recommendations

  • Avoid running production ZooKeeper clusters on unsupported or unmaintained Docker images
  • Prefer Admin REST API–based migration whenever possible
  • For Kubernetes, always use StatefulSets with persistent volumes
  • Validate backups and snapshots before performing destructive operations

Migrating away from deprecated Bitnami ZooKeeper images is not only a maintenance task. It is a critical step toward the long-term stability, security, and supportability of your infrastructure.