Chapter 5. Migrating Redis to Valkey
5.1. Migration compatibility matrix Copy linkLink copied to clipboard!
Valkey is compatible with Redis OSS v7.2 and all earlier open-source Redis versions because Valkey v7.2.4 is a fork of Redis v7.2.4. Migrating from any open-source Redis version to Valkey is an effective upgrade.
Redis (CE) v7.4 and later versions are not open-source and the data files are not compatible with Valkey.
The following table provides migration options depending on the Redis version you run.
| Redis | Valkey |
|---|---|
| 6.x | 7.2.x |
| 7.2.x | 7.2.x |
| 7.2.x | 8.0.x |
| 7.4 | NA |
Upgrading an instance is irreversible. You cannot downgrade the version of a Valkey instance.
5.2. Prerequisites Copy linkLink copied to clipboard!
Before beginning the migration, ensure the following prerequisites are met.
- 3scale 2.15 or higher
- Complete the Redis migration by referring Externalizing databases for 2.16
- A working installation of Redis with access to the configuration and data files.
- A fresh installation of Valkey on your target server.
- Backup of your Redis data to prevent data loss during migration.
5.3. Best Practices Copy linkLink copied to clipboard!
5.3.1. To ensure a successful migration from Redis to Valkey, follow these best practices. Copy linkLink copied to clipboard!
- Consider your post-migration verification steps before proceeding. This requireS you to take a snapshot of data using the api or portal and define a test plan to verify a successful migration.
- Consider letting 3scale components process all the jobs in the background before fully scaling the instance.
- Consider performing the migration at the time of lowest traffic as the migration affects the service.
- Before you upgrade the version of your instance, ensure that you become familiar with the newer version to see how this version impacts your application.
- Test Valkey configurations and migration scripts in a non-production environment to identify potential issues.
5.4. Redis to Valkey: Migration Steps Copy linkLink copied to clipboard!
Export the following environments.
export REDIS_ON_CLUSTER_NAMESPACE=<namespace where the Redis pod is running>
export OPERATOR_NAMESPACE=<namespace where the 3scale operator is running>
export THREESCALE_NAMESPACE=<namespace where the 3scale instance is running>
Additionally, export the following replica counts. This is done to ensure that we are scaling the 3scale instance back to the replica values that we scaled it down from.
SYSTEM_MEMCACHE_REPLICA_COUNT=$(oc get deployment system-memcache -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
ZYNC_DATABASE_REPLICA_COUNT=$(oc get deployment zync-database -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
APICAST_PRODUCTION_REPLICA_COUNT=$(oc get deployment -n $THREESCALE_NAMESPACE apicast-production -o=jsonpath='{.spec.replicas}')
APICAST_STAGING_REPLICA_COUNT=$(oc get deployment apicast-staging -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
BACKEND_CRON_REPLICA_COUNT=$(oc get deployment backend-cron -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
BACKEND_LISTENER_REPLICA_COUNT=$(oc get deployment backend-listener -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
BACKEND_WORKER_REPLICA_COUNT=$(oc get deployment backend-worker -o=jsonpath='{.spec.replicas}')
SYSTEM_APP_REPLICA_COUNT=$(oc get deployment system-app -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
SYSTEM_SIDEKIQ_REPLICA_COUNT=$(oc get deployment system-sidekiq -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
SYSTEM_SEARCHD_REPLICA_COUNT=$(oc get deployment system-searchd -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
ZYNC_REPLICA_COUNT=$(oc get deployment zync -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
ZYNC_QUE_REPLICA_COUNT=$(oc get deployment zync-que -n $THREESCALE_NAMESPACE -o=jsonpath='{.spec.replicas}')
5.4.1. Scale 3scale Operator and 3scale instance down Copy linkLink copied to clipboard!
- Scale down the deployment of the 3scale operator controller to prevent it from interfering with the scaling down of other pods.
oc scale deployment threescale-operator-controller-manager-v2 -n $OPERATOR_NAMESPACE --replicas=0
- Scale down all the pods of the 3scale deployment, except the Redis instances:
oc scale deployment/{apicast-production,apicast-staging,backend-cron,backend-listener,backend-worker,system-app,system-memcache,system-sidekiq,system-searchd,zync,zync-database,zync-que} -n $THREESCALE_NAMESPACE --replicas=0
5.4.2. Export Redis Data Copy linkLink copied to clipboard!
- Back up data of the backend-redis deployment:
oc cp $(oc get pods -l 'deployment=backend-redis' -n $REDIS_ON_CLUSTER_NAMESPACE -o json | jq '.items[0].metadata.name' -r):/var/lib/redis/data/dump.rdb ./backend-redis-dump.rdb
- Back up data of the system-redis deployment:
oc cp $(oc get pods -l 'deployment=system-redis' -n $REDIS_ON_CLUSTER_NAMESPACE -o json | jq '.items[0].metadata.name' -r):/var/lib/redis/data/dump.rdb ./system-redis-dump.rdb
Ensure to tweak the values accordingly to where and what your backend Redis instance is.
Connect to your Redis container(s) using redis-cli, and check the number of keys, using the INFO KEYSPACE command. This will be used later to verify that the entire database has been successfully migrated. In this example, keys=6286 indicates that there are 6,286 keys in the database.
sh-5.2$ redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> INFO KEYSPACE
# Keyspace
db1:keys=6286,expires=1,avg_ttl=53682
5.4.3. Scale down the deployments backend-redis and system-redis Copy linkLink copied to clipboard!
oc scale deployment/system-redis --replicas=0
oc scale deployment/backend-redis --replicas=0
5.4.4. Prepare the required resources for the new databases Copy linkLink copied to clipboard!
Create or switch to the namespace where the Valkey databases are deployed.
Export the name of the namespace where the new Valkey databases will be installed into a variable. You can use an existing namespace, or create a new one. It is also possible to deploy the new database in the same namespace where 3scale is installed, but it is not recommended.
VALKEY_NAMESPACE=<database-target-namespace>
oc project $VALKEY_NAMESPACE
or
oc new-project $VALKEY_NAMESPACE
5.4.4.1. Backend Valkey resources Copy linkLink copied to clipboard!
Create a YAML file backend-valkey-external.yaml locally with the specification of the new deployment for Valkey instance for Backend component:
kind: Deployment
apiVersion: apps/v1
metadata:
name: backend-valkey-external
labels:
app: backend-valkey-external
spec:
replicas: 1
selector:
matchLabels:
deployment: backend-valkey-external
template:
metadata:
labels:
deployment: backend-valkey-external
spec:
restartPolicy: Always
serviceAccountName: backend-valkey-external
schedulerName: default-scheduler
terminationGracePeriodSeconds: 30
securityContext: {}
containers:
- resources:
limits:
cpu: '2'
memory: 32Gi
requests:
cpu: '1'
memory: 1Gi
readinessProbe:
exec:
command:
- container-entrypoint
- bash
- '-c'
- redis-cli set liveness-probe "`date`" | grep OK
initialDelaySeconds: 10
timeoutSeconds: 1
periodSeconds: 30
successThreshold: 1
failureThreshold: 3
terminationMessagePath: /dev/termination-log
name: backend-valkey-external
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 10
timeoutSeconds: 1
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
env:
- name: VALKEY_CONF
value: /etc/valkey/valkey.conf
imagePullPolicy: IfNotPresent
volumeMounts:
- name: backend-valkey-storage-external
mountPath: /var/lib/valkey/data
- name: valkey-config-external
mountPath: /etc/valkey/
terminationMessagePolicy: File
image: 'registry.redhat.io/rhel9/valkey-8'
serviceAccount: backend-valkey-external
volumes:
- name: backend-valkey-storage-external
persistentVolumeClaim:
claimName: backend-valkey-storage-external
- name: valkey-config-external
configMap:
name: valkey-config-external
items:
- key: valkey.conf
path: valkey.conf
defaultMode: 420
dnsPolicy: ClusterFirst
strategy:
type: Recreate
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
Consider updating the following:
- Labels, annotations and environment variables in case you had or require some custom values
- Limits and Requests in case you had or require some custom values
- Other values can be modified according to the requirements
Create a service account for the Backend Valkey instance and label it:
oc create serviceaccount backend-valkey-external
oc label serviceaccount backend-valkey-external app=backend-valkey-external
Create a YAML file backend-valkey-storage-external-pvc.yaml locally with the specification of the Persistent Volume Claim for the new Valkey instance:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: backend-valkey-storage-external
labels:
app: backend-valkey-external
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
volumeMode: Filesystem
Adjust the storage request as required.
Create a YAML file backend-valkey-service.yaml locally with the specification of the Service for the new Valkey instance:
apiVersion: v1
kind: Service
metadata:
name: backend-valkey-service
labels:
app: backend-valkey-external
spec:
type: ClusterIP
ports:
- port: 6379
targetPort: 6379
protocol: TCP
selector:
deployment: backend-valkey-external
5.4.4.2. System Valkey Resources Copy linkLink copied to clipboard!
Create a YAML file system-valkey-external.yaml locally with the specification of the new deployment for Valkey instance for System component:
kind: Deployment
apiVersion: apps/v1
metadata:
name: system-valkey-external
labels:
app: system-valkey-external
spec:
replicas: 1
selector:
matchLabels:
deployment: system-valkey-external
template:
metadata:
labels:
deployment: system-valkey-external
spec:
restartPolicy: Always
serviceAccountName: system-valkey-external
schedulerName: default-scheduler
terminationGracePeriodSeconds: 30
securityContext: {}
containers:
- resources:
limits:
cpu: '2'
memory: 32Gi
requests:
cpu: '1'
memory: 1Gi
readinessProbe:
exec:
command:
- container-entrypoint
- bash
- '-c'
- redis-cli set liveness-probe "`date`" | grep OK
initialDelaySeconds: 10
timeoutSeconds: 1
periodSeconds: 30
successThreshold: 1
failureThreshold: 3
terminationMessagePath: /dev/termination-log
name: system-valkey-external
livenessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 10
timeoutSeconds: 1
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
env:
- name: VALKEY_CONF
value: /etc/valkey/valkey.conf
imagePullPolicy: IfNotPresent
volumeMounts:
- name: system-valkey-storage-external
mountPath: /var/lib/valkey/data
- name: valkey-config-external
mountPath: /etc/valkey/
terminationMessagePolicy: File
image: 'registry.redhat.io/rhel9/valkey-8'
serviceAccount: system-valkey-external
volumes:
- name: system-valkey-storage-external
persistentVolumeClaim:
claimName: system-valkey-storage-external
- name: valkey-config-external
configMap:
name: valkey-config-external
items:
- key: valkey.conf
path: valkey.conf
defaultMode: 420
dnsPolicy: ClusterFirst
strategy:
type: Recreate
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
Consider updating the following:
- Labels, annotations and environment variables in case you had or require some custom values
- Limits and Requests in case you had or require some custom values
- Other values can be modified according to the requirements
Create a service account for the Backend Valkey instance and label it:
oc create serviceaccount system-valkey-external
oc label serviceaccount system-valkey-external app=system-valkey-external
Create a YAML file system-valkey-storage-external-pvc.yaml locally with the specification of the Persistent Volume Claim for the new Valkey instance:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: system-valkey-storage-external
labels:
app: system-valkey-external
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
volumeMode: Filesystem
Adjust the storage request as required.
Create a YAML file system-valkey-service.yaml locally with the specification of the Service for the new Valkey instance:
apiVersion: v1
kind: Service
metadata:
name: system-valkey-service
labels:
app: system-valkey-external
spec:
type: ClusterIP
ports:
- port: 6379
targetPort: 6379
protocol: TCP
selector:
deployment: system-valkey-external
Create a YAML file valkey-config-external.yaml locally with the specification of the ConfigMap for the new Valkey instances configuration.
Valkey’s configuration is similar to Redis, but you must review the valkey.conf file for any changes specific to your environment.
kind: ConfigMap
apiVersion: v1
metadata:
name: valkey-config-external
data:
valkey.conf: |
protected-mode no
port 6379
timeout 0
tcp-keepalive 300
daemonize no
supervised no
loglevel notice
databases 16
#save 900 1
#save 300 10
#save 60 10000
save ""
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-disable-tcp-nodelay no
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
activerehashing no
aof-rewrite-incremental-fsync yes
dir /var/lib/valkey/data
rename-command REPLICAOF ""
rename-command SLAVEOF ""
- The above Redis configuration closely matches the configuration provided by the 3scale Operator, with a slight difference in being prepared to restore data from the dump file.
- If you enabled AOF in your Valkey configuration, disable it on the first start. Otherwise, the copied RDB file will not be imported into Valkey.
5.4.5. Create the new Valkey resources in the namespace Copy linkLink copied to clipboard!
At this point, you must have the following files in the local working directory.
- backend-redis-dump.rdb
- backend-valkey-external.yaml
- backend-valkey-secret.yaml
- backend-valkey-service.yaml
- backend-valkey-storage-external-pvc.yaml
- valkey-config-external.yaml
- system-redis-dump.rdb
- system-valkey-external.yaml
- system-valkey-secret.yaml
- system-valkey-service.yaml
- system-valkey-storage-external-pvc.yaml
Ensure your current namespace is $VALKEY_NAMESPACE:
oc project $VALKEY_NAMESPACE
Create the resource from the YAML files created in previous steps using the oc apply:
Config map:
oc apply -f valkey-config-external.yaml
Backend:
oc apply -f backend-valkey-external.yaml
oc apply -f backend-valkey-storage-external-pvc.yaml
oc apply -f backend-valkey-service.yaml
System:
oc apply -f system-valkey-external.yaml
oc apply -f system-valkey-storage-external-pvc.yaml
oc apply -f system-valkey-service.yaml
Verify that all the resources have been created properly with the following command:
oc get deployment,pvc,svc,serviceaccount -l app=backend-valkey-external
oc get deployment,pvc,svc,serviceaccount -l app=system-valkey-external
Specifically, check that the column READY for the backend-valkey-external and system-valkey-external deployment shows 1/1.
5.4.6. Import Data into Valkey Copy linkLink copied to clipboard!
Restore the data in the new Valkey instances using the previously created dump files:
oc cp ./backend-redis-dump.rdb $(oc get pods -l 'deployment=backend-valkey-external' -o json | jq '.items[0].metadata.name' -r):/var/lib/valkey/data/dump.rdb
oc cp ./system-redis-dump.rdb $(oc get pods -l 'deployment=system-valkey-external' -o json | jq '.items[0].metadata.name' -r):/var/lib/valkey/data/dump.rdb
Restart the Valkey deployments:
oc rollout restart deployment/backend-valkey-external
oc rollout restart deployment/system-valkey-external
Once Valkey instances are in a ready state, create an append-only file:
oc rsh $(oc get pods -l 'deployment=backend-valkey-external' -o json | jq '.items[0].metadata.name' -r) bash -c 'redis-cli BGREWRITEAOF'
oc rsh $(oc get pods -l 'deployment=system-valkey-external' -o json | jq '.items[0].metadata.name' -r) bash -c 'redis-cli BGREWRITEAOF'
After a few minutes, confirm that the AOF rewrite is complete:
oc rsh $(oc get pods -l 'deployment=backend-valkey-external' -o json | jq '.items[0].metadata.name' -r) bash -c 'redis-cli info' | grep aof_rewrite_in_progress
oc rsh $(oc get pods -l 'deployment=system-valkey-external' -o json | jq '.items[0].metadata.name' -r) bash -c 'redis-cli info' | grep aof_rewrite_in_progress
While aof_rewrite_in_progress = 1, the execution is in progress. Check periodically until aof_rewrite_in_progress = 0. Zero indicates that the execution is complete.
Edit valkey-config-external ConfigMap resource using oc edit configmap/valkey-config-external and apply the following changes:
- uncomment the lines:
save 900 1
save 300 10
save 60 10000
-
remove the line
save ""and setappendonlyvalue toyes
appendonly yes
- Restart the Valkey deployments:
oc rollout restart deployment/backend-valkey-external
oc rollout restart deployment/system-valkey-external
5.4.7. Update Redis secret Copy linkLink copied to clipboard!
Before updating the 3scale secrets so that the 3scale instance starts using the new external databases, back them up:
oc get secret backend-redis -n $THREESCALE_NAMESPACE -o yaml > backend-redis-secret.yaml
oc get secret system-redis -n $THREESCALE_NAMESPACE -o yaml > system-redis-secret.yaml
Change the value of the backend-redis secret REDIS_QUEUES_URL on the cluster to:
redis://<Valkey Redis endpoint>:6379/1
Change the value of the backend-redis secret REDIS_STORAGE_URL on the cluster to:
redis://<Valkey Redis endpoint>:6379/0
Change the value of the system-redis secret URL on the cluster to:
redis://<Valkey Redis endpoint>:6379/0
5.4.8. Scale up 3scale operator and 3scale instance Copy linkLink copied to clipboard!
oc scale deployment threescale-operator-controller-manager-v2 -n $OPERATOR_NAMESPACE --replicas=1
oc scale deployment system-memcache -n $THREESCALE_NAMESPACE --replicas=$SYSTEM_MEMCACHE_REPLICA_COUNT
oc scale deployment zync-database -n $THREESCALE_NAMESPACE --replicas=$ZYNC_DATABASE_REPLICA_COUNT
oc scale deployment apicast-production -n $THREESCALE_NAMESPACE --replicas=$APICAST_PRODUCTION_REPLICA_COUNT
oc scale deployment apicast-staging -n $THREESCALE_NAMESPACE --replicas=$APICAST_STAGING_REPLICA_COUNT
oc scale deployment backend-cron -n $THREESCALE_NAMESPACE --replicas=$BACKEND_CRON_REPLICA_COUNT
oc scale deployment backend-listener -n $THREESCALE_NAMESPACE --replicas=$BACKEND_LISTENER_REPLICA_COUNT
oc scale deployment backend-worker -n $THREESCALE_NAMESPACE --replicas=$BACKEND_WORKER_REPLICA_COUNT
oc scale deployment system-app -n $THREESCALE_NAMESPACE --replicas=$SYSTEM_APP_REPLICA_COUNT
oc scale deployment system-sidekiq -n $THREESCALE_NAMESPACE --replicas=$SYSTEM_SIDEKIQ_REPLICA_COUNT
oc scale deployment system-searchd -n $THREESCALE_NAMESPACE --replicas=$SYSTEM_SEARCHD_REPLICA_COUNT
oc scale deployment zync -n $THREESCALE_NAMESPACE --replicas=$ZYNC_REPLICA_COUNT
oc scale deployment zync-que -n $THREESCALE_NAMESPACE --replicas=$ZYNC_QUE_REPLICA_COUNT
Wait for 3scale instances to fully recover and confirm that the migration data was successful.
Once the 3scale instance state is confirmed to be correct, the on-cluster Redis instances can be deleted.
5.4.9. Validate and Test Copy linkLink copied to clipboard!
After importing the data and configuring Valkey, it’s crucial to validate and test the new setup.
To verify that the data is migrated, determine the number of keys in the Valkey database. If the migration is successful, then the number of keys in the Valkey database match the number of keys in the Redis database that you obtained in previous step:
sh-5.2$ redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> INFO KEYSPACE
# Keyspace
db1:keys=6286,expires=1,avg_ttl=53682
Test all application features to verify that they work as expected with Valkey.
5.4.10. Restore in case of failure Copy linkLink copied to clipboard!
If the migration is unsuccessful and you need to revert back to the previous configuration:
- Scale entire instance down:
oc scale deployment threescale-operator-controller-manager-v2 -n $OPERATOR_NAMESPACE --replicas=0
oc scale deployment/{apicast-production,apicast-staging,backend-cron,backend-listener,backend-worker,system-app,system-memcache,system-sidekiq,system-searchd,zync,zync-database,zync-que} -n $THREESCALE_NAMESPACE --replicas=0
- Remove the backend-redis and system-redis secrets
oc delete secret system-redis -n $THREESCALE_NAMESPACE
oc delete secret backend-redis -n $THREESCALE_NAMESPACE
- Re-create secrets from the backed-up secrets
oc apply -f backend-redis-secret.yaml
oc apply -f system-redis-secret.yaml
- Scale up 3scale instance
oc scale deployment threescale-operator-controller-manager-v2 -n $OPERATOR_NAMESPACE --replicas=1
oc scale deployment system-memcache -n $THREESCALE_NAMESPACE --replicas=$SYSTEM_MEMCACHE_REPLICA_COUNT
oc scale deployment zync-database -n $THREESCALE_NAMESPACE --replicas=$ZYNC_DATABASE_REPLICA_COUNT
oc scale deployment apicast-production -n $THREESCALE_NAMESPACE --replicas=$APICAST_PRODUCTION_REPLICA_COUNT
oc scale deployment apicast-staging -n $THREESCALE_NAMESPACE --replicas=$APICAST_STAGING_REPLICA_COUNT
oc scale deployment backend-cron -n $THREESCALE_NAMESPACE --replicas=$BACKEND_CRON_REPLICA_COUNT
oc scale deployment backend-listener -n $THREESCALE_NAMESPACE --replicas=$BACKEND_LISTENER_REPLICA_COUNT
oc scale deployment backend-worker -n $THREESCALE_NAMESPACE --replicas=$BACKEND_WORKER_REPLICA_COUNT
oc scale deployment system-app -n $THREESCALE_NAMESPACE --replicas=$SYSTEM_APP_REPLICA_COUNT
oc scale deployment system-sidekiq -n $THREESCALE_NAMESPACE --replicas=$SYSTEM_SIDEKIQ_REPLICA_COUNT
oc scale deployment system-searchd -n $THREESCALE_NAMESPACE --replicas=$SYSTEM_SEARCHD_REPLICA_COUNT
oc scale deployment zync -n $THREESCALE_NAMESPACE --replicas=$ZYNC_REPLICA_COUNT
oc scale deployment zync-que -n $THREESCALE_NAMESPACE --replicas=$ZYNC_QUE_REPLICA_COUNT