{
  "schema_version": 2,
  "id": "operate/kubernetes/active-active/create-aa-crdb-cli",
  "title": "Create Active-Active databases with crdb-cli",
  "url": "https://redis.io/docs/latest/operate/kubernetes/8.2.0/active-active/create-aa-crdb-cli/",
  "summary": "This section shows how to set up an Active-Active Redis Enterprise database on Kubernetes using the Redis Enterprise Software operator.",
  "content": "\u003e [!NOTE]\n\u003e  Versions 6.4.2 and later support the Active-Active database controller. This controller allows you to create Redis Enterprise Active-Active databases (REAADB) and Redis Enterprise remote clusters (RERC) with custom resources. We recommend using the [REAADB method for creating Active-Active databases](https://redis.io/docs/latest/operate/kubernetes/active-active/create-reaadb).\n\nOn Kubernetes, Redis Enterprise [Active-Active](https://redis.io/docs/latest/operate/rs/databases/active-active) databases provide read-and-write access to the same dataset from different Kubernetes clusters. For more general information about Active-Active, see the [Redis Enterprise Software docs](https://redis.io/docs/latest/operate/rs/databases/active-active).\n\nCreating an Active-Active database requires routing [network access](https://redis.io/docs/latest/operate/kubernetes/networking) between two Redis Enterprise clusters residing in different Kubernetes clusters. Without the proper access configured for each cluster, syncing between the databases instances will fail.\n\nThis process consists of:\n\n1. Documenting values to be used in later steps. It's important these values are correct and consistent.\n1. Editing the Redis Enterprise cluster (REC) spec file to include the `ActiveActive` section. This will be slightly different depending on the K8s distribution you are using.\n1. Creating the database with the `crdb-cli` command. These values must match up with values in the REC resource spec.\n\n## Prerequisites\n\nBefore creating Active-Active databases, you'll need admin access to two or more working Kubernetes clusters that each have:\n\n- Routing for external access with an [ingress resources](https://redis.io/docs/latest/operate/kubernetes/networking/ingress) (or [route resources](https://redis.io/docs/latest/operate/kubernetes/networking/routes) on OpenShift).\n- A working [Redis Enterprise cluster (REC)](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_api) with a unique name.\n- Enough memory resources available for the database (see [hardware requirements](https://redis.io/docs/latest/operate/rs/installing-upgrading/install/plan-deployment/hardware-requirements)).\n\n\u003e [!NOTE]\n\u003e  The `activeActive` field and the `ingressOrRouteSpec` field cannot coexist in the same REC. If you configured your ingress via the `ingressOrRouteSpec` field in the REC, create your Active-Active database with the RedisEnterpriseActiveActiveDatabase (REAADB) custom resource.\n\n## Document required parameters\n\nThe most common mistake when setting up Active-Active databases is incorrect or inconsistent parameter values. The values listed in the resource file must match those used in the crdb-cli command.\n\n- **Database name** `\u003cdb-name\u003e`:\n  - Description: Combined with ingress suffix to create the Active-Active database hostname\n  - Format: string\n  - Example value: `myaadb`\n  - How you get it: you choose\n  - The database name requirements are:\n       - Maximum of 63 characters\n       - Only letter, number, or hyphen (-) characters\n       - Starts with a letter; ends with a letter or digit.\n       - Database name is not case-sensitive\n\nYou'll need the following information for each participating Redis Enterprise cluster (REC):\n\n\u003e [!NOTE]\n\u003e You'll need to create DNS aliases to resolve your API hostname `\u003capi-hostname\u003e`,`\u003cingress-suffix\u003e`, `\u003creplication-hostname\u003e` to the IP address for the ingress controller’s LoadBalancer (or routes in Openshift) for each database. To avoid entering multiple DNS records, you can use a wildcard in your alias (such as *.ijk.example.com).\n\n- **REC hostname** `\u003crec-hostname\u003e`:\n  - Description: Hostname used to identify your Redis Enterprise cluster in the `crdb-cli` command. This MUST be different from other participating clusters.\n  - Format: `\u003crec-name\u003e.\u003cnamespace\u003e.svc.cluster.local`\n  - Example value: `rec01.ns01.svc.cluster.local`\n  - How to get it: List all your Redis Enterprise clusters\n      ```bash\n      kubectl get rec\n      ```\n- **API hostname** `\u003capi-hostname\u003e`:\n  - Description: Hostname used to access the Redis Enterprise cluster API from outside the K8s cluster\n  - Format: string\n  - Example value: `api.ijk.example.com`\n- **Ingress suffix** `\u003cingress-suffix\u003e`:\n  - Description: Combined with database name to create the Active-Active database hostname\n  - Format: string\n  - Example value: `-cluster.ijk.example.com`\n- [**REC admin credentials**](https://redis.io/docs/latest/operate/kubernetes/security/authentication/manage-rec-credentials) `\u003cusername\u003e \u003cpassword\u003e`:\n  - Description: Admin username and password for the REC stored in a secret\n  - Format: string\n  - Example value: username: `user@example.com`, password: `something`\n  - How to get them:\n    ```sh\n    kubectl get secret \u003crec-name\u003e \\\n      -o jsonpath='{.data.username}' | base64 --decode\n    kubectl get secret \u003crec-name\u003e \\\n      -o jsonpath='{.data.password}' | base64 --decode\n    ```\n- **Replication hostname** `\u003creplication-hostname\u003e`:\n  - Description: Hostname used inside the ingress for the database\n  - Format: `\u003cdb-name\u003e\u003cingress-suffix\u003e`\n  - Example value: `myaadb-cluster.ijk.example.com`\n  - How to get it: Combine `\u003cdb-name\u003e` and `\u003cingress-suffix`\u003e values you documented above.\n- **Replication endpoint** `\u003creplication-endpoint\u003e`:\n  - Description: Endpoint used externally to contact the database\n  - Format: `\u003cdb-name\u003e\u003cingress-suffix\u003e:443`\n  - Example value: `myaadb-cluster.ijk.example.com:443`\n  - How to get it:`\u003creplication-hostname\u003e:443`\n\n## Add `activeActive` section to the REC resource file\n\nFrom inside your K8s cluster, edit your Redis Enterprise cluster (REC) resource to add the following to the `spec` section. Do this for each participating cluster.\n\n The operator uses the API hostname (`\u003capi-hostname\u003e`) to create an ingress to the Redis Enterprise cluster's API; this only happens once per cluster. Every time a new Active-Active database instance is created on this cluster, the operator creates a new ingress route to the database with the ingress suffix (`\u003cingress-suffix\u003e`). The hostname for each new database will be in the format \u003cnobr\u003e`\u003cdb-name\u003e\u003cingress-suffix\u003e`\u003c/nobr\u003e.\n\n### Using ingress controller\n\n1. If your cluster uses an [ingress controller](https://redis.io/docs/latest/operate/kubernetes/networking/ingress), add the following to the `spec` section of your REC resource file.\n\n  Nginx:\n\n  ```sh\n  activeActive:\n    apiIngressUrl: \u003capi-hostname\u003e\n    dbIngressSuffix: \u003cingress-suffix\u003e\n    ingressAnnotations:\n       kubernetes.io/ingress.class: nginx\n      nginx.ingress.kubernetes.io/backend-protocol: HTTPS\n      nginx.ingress.kubernetes.io/ssl-passthrough: \"true\"\n    method: ingress\n  ```\n\nHAproxy:\n\n  ```sh\n  activeActive:\n    apiIngressUrl: \u003capi-hostname\u003e\n    dbIngressSuffix: \u003cingress-suffix\u003e\n    ingressAnnotations:\n      kubernetes.io/ingress.class: haproxy\n       ingress.kubernetes.io/ssl-passthrough: \"true\"\n    method: ingress\n  ```\n\n2. After the changes are saved and applied, you can verify a new ingress was created for the API.\n\n    ```sh\n    $ kubectl get ingress\n    NAME   HOSTS                            ADDRESS                                 PORTS   AGE\n    rec01  api.abc.cde.example.com  225161f845b278-111450635.us.cloud.com   80      24h\n    ```\n\n3. Verify you can access the API from outside the K8s cluster.\n\n    ```sh\n   curl -k -L -i -u \u003cusername\u003e:\u003cpassword\u003e https://\u003capi-hostname\u003e/v1/cluster\n    ```\n\n    If the API call fails, create a DNS alias that resolves your API hostname (`\u003capi-hostname\u003e`) to the IP address for the ingress controller's LoadBalancer.\n\n4. Make sure you have DNS aliases for each database that resolve your API hostname `\u003capi-hostname\u003e`,`\u003cingress-suffix\u003e`, `\u003creplication-hostname\u003e` to the IP address of the ingress controller’s LoadBalancer. To avoid entering multiple DNS records, you can use a wildcard in your alias (such as `*.ijk.example.com`).\n\n#### If using Istio Gateway and VirtualService\n\nNo changes are required to the REC spec if you are using [Istio](https://redis.io/docs/latest/operate/kubernetes/networking/istio-ingress) in place of an ingress controller. The `activeActive` section added above creates ingress resources. The two custom resources used to configure Istio (Gateway and VirtualService) replace the need for ingress resources.\n\n\u003e [!WARNING]\n\u003e These custom resources are not controlled by the operator and will need to be configured and maintained manually.\n\nFor each cluster, verify the VirtualService resource has two `- match:` blocks in the `tls` section. The hostname under `sniHosts:` should match your `\u003creplication-hostname\u003e`.\n\n### Using OpenShift routes\n\n1. Make sure your Redis Enterprise cluster (REC) has a different name (`\u003crec-name.namespace\u003e`) than any other participating clusters. If not, you'll need to manually rename the REC or move it to a different namespace.\n            You can check your new REC name with:\n    ```sh\n    oc get rec -o jsonpath='{.items[0].metadata.name}'\n    ```\n\n    If the rec name was modified, reapply [scc.yaml](https://github.com/RedisLabs/redis-enterprise-k8s-docs/blob/master/openshift/scc.yaml) to the namespace to reestablish security privileges.\n    \n    ```sh\n    oc apply -f scc.yaml\n    oc adm policy add-scc-to-group redis-enterprise-scc-v2  system:serviceaccounts:\u003cnamespace\u003e\n    ```\n\n    Releases before 6.4.2-6 use the earlier version of the SCC, named `redis-enterprise-scc`.\n\n1. Make sure you have DNS aliases for each database that resolve your API hostname `\u003capi-hostname\u003e`,`\u003cingress-suffix\u003e`, `\u003creplication-hostname\u003e` to the route IP address. To avoid entering multiple DNS records, you can use a wildcard in your alias (such as `*.ijk.example.com`).\n\n1. If your cluster uses [OpenShift routes](https://redis.io/docs/latest/operate/kubernetes/networking/routes), add the following to the `spec` section of your Redis Enterprise cluster (REC) resource file.\n\n      ```sh\n      activeActive:\n        apiIngressUrl: \u003capi-hostname\u003e\n        dbIngressSuffix: \u003cingress-suffix\u003e\n        method: openShiftRoute\n      ```\n\n1. Make sure you have DNS aliases that resolve to the routes IP for both the API hostname (`\u003capi-hostname\u003e`) and the replication hostname (`\u003creplication-hostname\u003e`) for each database. To avoid entering each database individually, you can use a wildcard in your alias (such as `*.ijk.example.com`).\n\n1. After the changes are saved and applied, you can see that a new route was created for the API.\n\n    ```sh\n    $ oc get route\n    NAME    HOST/PORT                       PATH    SERVICES  PORT  TERMINATION   WILDCARD\n    rec01   api-openshift.apps.abc.example.com rec01   api             passthrough   None\n    ```\n\n## Create an Active-Active database with `crdb-cli`\n\nThe `crdb-cli` command can be run from any Redis Enterprise pod hosted on any participating K8s cluster. You'll need the values for the [required parameters](https://redis.io/docs/latest/operate/kubernetes/active-active/create-aa-crdb-cli#document-required-parameters) for each Redis Enterprise cluster.\n\n```sh\ncrdb-cli crdb create \\\n  --name \u003cdb-name\u003e \\\n  --memory-size \u003cmem-size\u003e \\\n  --encryption yes \\\n  --instance fqdn=\u003crec-hostname-01\u003e,url=https://\u003capi-hostname-01\u003e,username=\u003cusername-01\u003e,password=\u003cpassword-01\u003e,replication_endpoint=\u003creplication-endpoint-01\u003e,replication_tls_sni=\u003creplication-hostname-01\u003e \\\n  --instance fqdn=\u003crec-hostname-02\u003e,url=https://\u003capi-hostname-02\u003e,username=\u003cusername-02\u003e,password=\u003cpassword-02\u003e,replication_endpoint=\u003creplication-endpoint-02\u003e,replication_tls_sni=\u003creplication-hostname-02\u003e\n```\n\nTo create a database that syncs between more than two instances, add additional `--instance` arguments.\n\nSee the [`crdb-cli` reference](https://redis.io/docs/latest/operate/rs/references/cli-utilities/crdb-cli) for more options.\n\n## Test your database\n\nThe easiest way to test your Active-Active database is to set a key-value pair in one database and retrieve it from the other.\n\nYou can connect to your databases with the instructions in [Manage databases](https://redis.io/docs/latest/operate/kubernetes/re-databases/db-controller#connect-to-a-database). Set a test key with `SET foo bar` in the first database. If your Active-Active deployment is working properly, when connected to your second database, `GET foo` should output `bar`.\n",
  "tags": ["docs","operate","kubernetes"],
  "last_updated": "2026-10-19T14:33:15-05:00"
}
