How to create and automate database replicas using the database controller
| Redis Enterprise for Kubernetes |
|---|
You can configure a replica of a database by creating an item in
the replicaSources section of the RedisEnterpriseDatabase (REDB) custom resource.
A secret must be created with the stringData section containing the replica source URI as follows:
Create a secret with the replica source URI listed in the stringData field as follows:
apiVersion:v1kind:Secretmetadata:name:my-replica-sourcestringData:uri:<replica-source-uri-goes-here>The replica source URL can be retrieved by going to "UI > database > configuration > Press the button Get Replica of source URL" in the administrative UI. But, this information can also be retrieved directly from the REST API as well.
A replica of database CR simply uses the secret in the replicaSources section:
apiVersion:app.redislabs.com/v1alpha1kind:RedisEnterpriseDatabasemetadata:name:name-of-replicaspec:redisEnterpriseCluster:name:name-of-clusterreplicaSources:- replicaSourceType:SECRETreplicaSourceName:my-replica-sourceIn the above, name-of-replica database will be created as a replica of the
source database as long as the source database exists on the source cluster
and the secret contains the correct replica source URL for that database.
You will need kubectl, curl, and jq installed for this procedure.
Set your metadata:
CLUSTER_NAME=test
SOURCE_DB=db1
TARGET_DB=db2
TARGET_CLUSTER_NAME=test
Retrieve the cluster authentication:
CLUSTER_USER=`kubectl get secret/${CLUSTER_NAME} -o json | jq -r .data.username | base64 -d`
CLUSTER_PASSWORD=`kubectl get secret/${CLUSTER_NAME} -o json | jq -r .data.password | base64 -d`
Forward the port of the REST API service for your source cluster:
kubectl port-forward pod/${CLUSTER_NAME}-0 9443
Request the information from the REST API:
JQ='.[] | select(.name=="'
JQ+="${SOURCE_DB}"
JQ+='") | ("redis://admin:" + .authentication_admin_pass + "@"+.name+":"+(.endpoints[0].port|tostring))'
URI=`curl -sf -k -u "$CLUSTER_USER:$CLUSTER_PASSWORD" "https://localhost:9443/v1/bdbs?fields=uid,name,endpoints,authentication_admin_pass" | jq "$JQ" | sed 's/"//g'`
Note: URI now contains the replica source URI.
Construct the secret for the replica:
cat << EOF > secret.yamlapiVersion:v1kind:Secretmetadata:name:${SOURCE_DB}-urlstringData:uri:${URI}EOFkubectl apply -f secret.yamlCreate the replica database:
cat << EOF > target.yamlapiVersion:app.redislabs.com/v1alpha1kind:RedisEnterpriseDatabasemetadata:name:${TARGET_DB}spec:redisEnterpriseCluster:name:${TARGET_CLUSTER_NAME}replicaSources:- replicaSourceType:SECRETreplicaSourceName:${SOURCE_DB}-urlEOFkubectl apply -f target.yamlThe following procedure uses a ConfigMap and a Job to construct the replica source URL secret from the source database and configure the target database.
There are four parameters:
source - the name of the source databasecluster - the name of the cluster for the source databasetarget - the name of the target databasetargetCluster - the name of the cluster for the target databaseThese parameters can be set by:
kubectl create configmap replica-of-database-parameters \
--from-literal=source=name-of-source \
--from-literal=cluster=name-of-cluster \
--from-literal=target=name-of-target \
--from-literal=targetCluster=name-of-cluster
where "name-of-..." is replaced with the database source, source cluster, database target, and target cluster names.
The Job and ConfigMap below, when submitted, will create the secret and replica database:
apiVersion:batch/v1kind:Jobmetadata:name:replica-of-databasespec:backoffLimit:4template:spec:serviceAccountName:redis-enterprise-operatorrestartPolicy:Nevervolumes:- name:scriptsconfigMap:name:replica-of-databasecontainers:- name:createdbimage:debian:stable-slimenv:- name:MY_NAMESPACEvalueFrom:fieldRef:fieldPath:metadata.namespace- name:SCRIPTvalue:create.sh- name:SOURCE_DBvalueFrom:configMapKeyRef:name:replica-of-database-parameterskey:source- name:TARGET_DBvalueFrom:configMapKeyRef:name:replica-of-database-parameterskey:target- name:CLUSTER_SERVICEvalue:.svc.cluster.local- name:CLUSTER_NAMEvalueFrom:configMapKeyRef:name:replica-of-database-parameterskey:cluster- name:CLUSTER_PORTvalue:"9443"- name:TARGET_CLUSTER_NAMEvalueFrom:configMapKeyRef:name:replica-of-database-parameterskey:targetClustervolumeMounts:- mountPath:/opt/scripts/name:scriptscommand:- /bin/bash- -c- | apt-get update; apt-get install -y curl jq apt-transport-https gnupg2
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6A030B21BA07F4FB
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-get install -y kubectl
bash /opt/scripts/$SCRIPT---apiVersion:v1kind:ConfigMapmetadata:name:replica-of-databasedata:create.sh:| CLUSTER_USER=`kubectl get secret/${CLUSTER_NAME} -o json | jq -r .data.username | base64 -d`
CLUSTER_PASSWORD=`kubectl get secret/${CLUSTER_NAME} -o json | jq -r .data.password | base64 -d`
CLUSTER_HOST=${CLUSTER_NAME}.${MY_NAMESPACE}${CLUSTER_SERVICE}
JQ='.[] | select(.name=="'
JQ+="${SOURCE_DB}"
JQ+='") | ("redis://admin:" + .authentication_admin_pass + "@"+.endpoints[0].dns_name+":"+(.endpoints[0].port|tostring))'
URI=`curl -sf -k -u "$CLUSTER_USER:$CLUSTER_PASSWORD" "https://${CLUSTER_HOST}:${CLUSTER_PORT}/v1/bdbs?fields=uid,name,endpoints,authentication_admin_pass" | jq "$JQ" | sed 's/"//g'`
echo "URL: ${URL}"
echo ""
cat << EOF > /tmp/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: ${SOURCE_DB}-url
stringData:
uri: ${URI}
EOF
cat /tmp/secret.yaml
cat << EOF > /tmp/target.yaml
apiVersion: app.redislabs.com/v1alpha1
kind: RedisEnterpriseDatabase
metadata:
name: ${TARGET_DB}
spec:
redisEnterpriseCluster:
name: ${TARGET_CLUSTER_NAME}
replicaSources:
- replicaSourceType: SECRET
replicaSourceName: ${SOURCE_DB}-url
EOF
echo "---"
cat /tmp/target.yaml
echo ""
kubectl -n ${MY_NAMESPACE} apply -f /tmp/secret.yaml
kubectl -n ${MY_NAMESPACE} apply -f /tmp/target.yaml