diff --git a/.gitignore b/.gitignore index 485dee6..5c3bdbb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -.idea +*bundle.yaml diff --git a/README.md b/README.md index 5c4a35e..642e32e 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ The operator deploys a `RedisEnterpriseCluster` with default configurations valu Some examples [have moved](https://docs.redis.com/latest/kubernetes/reference/cluster-options/) to the Redis Enterprise doc site, [docs.redis.com](https://docs.redis.com/latest/kubernetes/). -* Cluster username (Default is demo@redislabs.com) +* Cluster username (Default is demo@redis.com) ```yaml username: "admin@acme.com" ``` diff --git a/active_active_database_readme.md b/active_active_database_readme.md index 8e25d14..b1cac08 100644 --- a/active_active_database_readme.md +++ b/active_active_database_readme.md @@ -3,14 +3,10 @@ This document describes how to deploy an Active-Active database with Redis Enterprise for Kubernetes. -**Disclaimer:** - This feature is in public preview. - **This document assumes the following:** - You have at least two running Redis Enterprise clusters that will be used as your participating clusters. - On each Kubernetes cluster you have Ingress controller or Openshift Routes deployed. - - You have admin access level for each Kubernetes cluster. ## Table of contents * [Overview](#overview) @@ -19,9 +15,11 @@ This document describes how to deploy an Active-Active database with Redis Enter * [Remove participating cluster from an existing Active-Active database](#remove-participating-cluster-from-an-existing-active-active-database) * [Set the database global configurations specifications](#set-the-database-global-configurations-specifications) * [Set global database secret](#set-global-database-secret) + * [Manage global configurations secrets](#manage-global-configurations-secrets) * [Delete an existing Active-Active database](#delete-an-existing-active-active-database) * [Update existing participating cluster (RERC) details](#update-existing-participating-cluster-rerc-details) * [Update existing participating cluster (RERC) secret](#update-existing-participating-cluster-rerc-secret) + * [Active-Active database with Redis modules](#active-active-database-with-redis-modules) * [Test your Active-Active database](#test-your-active-active-database) * [Limitations](#limitations) @@ -34,6 +32,9 @@ The new custom resources for declaring Active-Active databases in Redis Enterpri For example, an Active-Active database with two participating clusters should have two Redis Enterprise Remote Cluster (RERC) custom resources and one Redis Enterprise Active Active Database (REAADB) custom resource on each participating cluster. +### General note about Hashicorp Vault secrets +The operator supports the use of Hashicorp Vault Secrets for the Active-Active database REAADB/RERC custom resources secrets. Throughout this document there are explanations about using K8s secrets. If Hashicorp Vault is used by the REC, the secrets should be saved within the Hashicorp Vault server in the same path that is used for other REC/REDB secrets, and the name should be used appropriately with RERC/REAADB. For some explanations/examples of how to store secrets in vault, see [the Hashicorp Vault integration document.](vault/README.md) + ## Create a new Active-Active database **For each participating cluster with a namespace that hosts the Redis Enterprise operator, follow the [Participating cluster preparation setup](#participating-cluster-preparation-setup)** @@ -45,25 +46,9 @@ For example, an Active-Active database with two participating clusters should ha Note: * This part is for new participating clusters that are not already configured to use the Redis Enterprise Operator active-active databases. -1. Apply the following CRDs: -``` - kubectl apply -f crds/reaadb_crd.yaml - kubectl apply -f crds/rerc_crd.yaml -``` - -Note: - * This step requires "cluster role" permissions for applying CRD resources. +1. In case your REC is not configured with the 'spec.ingressOrRouteSpec', please configure a Ingress or Route, follow the instructions [here](setting_ingress_or_route_readme.md) -2. Add the following environment variables to enable the active active and remote cluster controllers on the Redis Enterprise operator Configmap: -``` - kubectl patch cm operator-environment-config --type merge --patch "{\"data\": \ - {\"ACTIVE_ACTIVE_DATABASE_CONTROLLER_ENABLED\":\"true\", \ - \"REMOTE_CLUSTER_CONTROLLER_ENABLED\":\"true\"}}" -``` - -3. Configure a Ingress or Route, follow the instructions [here](setting_ingress_or_route_readme.md) - -4. Configure ValidatingWebhookConfiguration, follow the instructions [here](admission/README.md) +2. Configure ValidatingWebhookConfiguration, follow the instructions [here](admission/README.md) Note: this is a must for managing Active-Active database via the operator. #### Part 2: participating cluster info preparation setup @@ -106,7 +91,7 @@ type: Opaque ``` 2. For each of the secrets you collected, generate a new secret with the credentials data and name it with the following convention: `redis-enterprise-`, replace the `` with the RERC name. -The new secret generated from the previous example of Redis Enterprise cluster named "rec1" that resides in "ns1" namespace that will be used for the RERC name: "rerc1" should look as follows: +The new secret generated from the previous example of Redis Enterprise cluster named "rec1" that resides in "ns1" namespace that will be used for the RERC name: "new-york-1" should look as follows: ``` apiVersion: v1 data: @@ -114,7 +99,7 @@ data: username: PHNvbWUgdXNlcj4 kind: Secret metadata: - name: redis-enterprise-rerc1 + name: redis-enterprise-new-york-1 type: Opaque ``` @@ -134,26 +119,26 @@ a. The example for a REC named "rec1" in the namespace "ns1": apiVersion: app.redislabs.com/v1alpha1 kind: RedisEnterpriseRemoteCluster metadata: - name: rerc1 + name: new-york-1 spec: recName: rec1 recNamespace: ns1 - apiFqdnUrl: test-example-api-rec1-ns1.redis.com - dbFqdnSuffix: -example-cluster-rec1-ns1.redis.com - secretName: redis-enterprise-rerc1 + apiFqdnUrl: test-example-api-new-york-1.redis.com + dbFqdnSuffix: -example-cluster-new-york-1.redis.com + secretName: redis-enterprise-new-york-1 ``` b. The example for a REC named "rec2" in the namespace "ns2": ``` apiVersion: app.redislabs.com/v1alpha1 kind: RedisEnterpriseRemoteCluster metadata: - name: rerc2 + name: boston-1 spec: recName: rec2 recNamespace: ns2 - apiFqdnUrl: test-example-api-rec2-ns2.redis.com - dbFqdnSuffix: -example-cluster-rec2-ns2.redis.com - secretName: redis-enterprise-rerc2 + apiFqdnUrl: test-example-api-boston-1.redis.com + dbFqdnSuffix: -example-cluster-boston-1.redis.com + secretName: redis-enterprise-boston-1 ``` Notes: @@ -168,14 +153,14 @@ To follow the statuses of the applied RERC custom resources, run the following: ``` kubectl get rerc ``` -For example to view the status of the RERC named "rerc1": +For example to view the status of the RERC named "new-york-1": ``` - kubectl get rerc rerc1 + kubectl get rerc new-york-1 ``` The output should be as below: ``` NAME STATUS SPEC STATUS LOCAL - rerc1 Active Valid true + new-york-1 Active Valid true ``` Note: @@ -190,8 +175,8 @@ metadata: name: example-aadb-1 spec: participatingClusters: - - name: rerc1 - - name: rerc2 + - name: new-york-1 + - name: boston-1 globalConfigurations: shardCount: 3 ``` @@ -350,7 +335,7 @@ For example, to get the REAADB named: "example-aadb-1" participating clusters st ``` Following is the output of the example above: ``` - [{"id":1,"name":"rerc1"},{"id":2,"name":"rerc2"},{"id":3,"name":"rerc3"}] + [{"id":1,"name":"new-york-1"},{"id":2,"name":"boston-1"},{"id":3,"name":"rerc3"}] ``` ## Remove participating cluster from an existing Active-Active database @@ -376,7 +361,7 @@ For example, to view the status of the REAADB named "example-aadb-1" after remov ``` the output should be as below: ``` - {... ,"participatingClusters":[{"id":1,"name":"rerc1"},{"id":2,"name":"rerc2"}],"redisEnterpriseCluster":"rec1","specStatus":"Valid","status":"active"} + {... ,"participatingClusters":[{"id":1,"name":"new-york-1"},{"id":2,"name":"boston-1"}],"redisEnterpriseCluster":"rec1","specStatus":"Valid","status":"active"} ``` **On the participating cluster that you removed do the following:** @@ -424,6 +409,10 @@ To get the REAADB run the following: kubectl get reaadb -o yaml ``` +For example, to view the status of the REAADB named "example-aadb-1": +``` + kubectl get reaadb example-aadb-1 -o=jsonpath='{.status.secretsStatus}' +``` ## Set global database secret Notes: @@ -480,13 +469,80 @@ To get the REAADB secrets status run the following: ``` kubectl get reaadb -o=jsonpath='{.status.secretsStatus}' ``` +``` +The output should be as below (with the secret used in previous steps): +``` + [{"name":"my-db-secret","status":"Invalid"}] +``` + Note: as the secret status is 'Invalid' it means that the secret isn't synced yet on the participating cluster. + +2. Sync the secret on the other participating clusters. +Apply the generated secret from the previous steps, replace `` with a file containing the secret you generated in the previous step. +``` + kubectl apply -f +``` + +## Manage global configurations secrets + +The secrets under the REAADBs' 'spec.globalConfigurations' sync with the correct data on all of the participating clusters is the users' responsibility. + +Notes: +* This section is regarding the secrets that are under the REAADB '.spec.globalConfigurations'. For more information and all the fields please view the [REAADB API readme](redis_enterprise_active_active_database_api.md) +* For setting the global database secret please view [Set global database secret](#set-global-database-secret). + +**On one of the participating clusters that already exists do the following:** + +1. Generate the yaml containing the secret with the relevant data. +For example a secret named 'my-secret' with the data: password 'my-pass' as base 64 encoded: +``` +apiVersion: v1 +data: + password: bXktcGFzcw +kind: Secret +metadata: + name: my-secret +type: Opaque +``` + +2. Apply the generated secret from the previous step, replace `` with a file containing the secret you generated in the previous step. +``` + kubectl apply -f +``` + +3. Set the required field under the REAADBs' 'spec.globalConfigurations' with the secret name. +For example, to patch a REAADB named 'example-aadb-1' with the field containing the secret name from the previous steps on the global configurations run the following: +``` + kubectl patch reaadb example-aadb-1 --type merge --patch '{"spec": {"globalConfigurations": {"": "my-secret"}}}' +``` + +4. Follow the statuses of the REAADB custom resource run the following: +``` + kubectl get reaadb +``` For example, to view the status of the REAADB named "example-aadb-1": ``` - kubectl get reaadb example-aadb-1 -o=jsonpath='{.status.secretsStatus}' + kubectl get reaadb example-aadb-1 +``` +The output should be as below: +``` + NAME STATUS SPEC STATUS GLOBAL CONFIGURATIONS REDB LINKED REDBS + example-aadb-1 active Valid +``` + +Note: + * As the 'STATUS' and the 'SPEC STATUS' are 'Active' and 'Valid' respectively it means the configurations are correct. In case of an error status, view the REAADB custom resource events and the Redis Enterprise operator logs. + +**On the other participating clusters that already exists do the following:** + +1. View the secret status on the REAADB (on the other participating clusters). +To get the REAADB secrets status run the following: +``` + kubectl get reaadb -o=jsonpath='{.status.secretsStatus}' +``` ``` The output should be as below (with the secret used in previous steps): ``` - [{"name":"my-db-secret","status":"Invalid"}] + [{"name":"my-secret","status":"Invalid"}] ``` Note: as the secret status is 'Invalid' it means that the secret isn't synced yet on the participating cluster. @@ -519,22 +575,22 @@ To get all the REAADB that exists run the following: **On the participating cluster you want to modify (with the local RERC) do the following:** 1. Patch the participating cluster corresponding local RERC that you want to update. -For example updating the DB FQDN suffix of an RERC named: "rerc1": +For example updating the DB FQDN suffix of an RERC named: "new-york-1": ``` - kubectl patch rerc rerc1 --type merge --patch '{"spec": {"dbFqdnSuffix": "-example2-cluster-rec1-ns1.redis.com"}}' + kubectl patch rerc new-york-1 --type merge --patch '{"spec": {"dbFqdnSuffix": "-example2-cluster-new-york-1.redis.com"}}' ``` To follow the statuses of the updated RERC custom resources run the following: ``` kubectl get rerc ``` -For example to view the status of the RERC named "rerc1": +For example to view the status of the RERC named "new-york-1": ``` - kubectl get rerc rerc1 + kubectl get rerc new-york-1 ``` The output should be as below: ``` NAME STATUS SPEC STATUS LOCAL - rerc1 Active Valid true + new-york-1 Active Valid true ``` Note: @@ -567,7 +623,7 @@ Note: **On the participating cluster that you changed the REC secret (with the local RERC) do the following:** 1. update the secret with the new credentials data and name it with the following convention: `redis-enterprise-`, replace the `` with the RERC name. -For example, a secret generated with the RERC name 'rerc1': +For example, a secret generated with the RERC name 'new-york-1': ``` apiVersion: v1 data: @@ -575,7 +631,7 @@ data: username: PHNvbWUgdXNlcj4 kind: Secret metadata: - name: redis-enterprise-rerc1 + name: redis-enterprise-new-york-1 type: Opaque ``` @@ -589,14 +645,14 @@ To follow the statuses of the updated RERC custom resources run the following: ``` kubectl get rerc ``` -For example to view the status of the RERC named "rerc1": +For example to view the status of the RERC named "new-york-1": ``` - kubectl get rerc rerc1 + kubectl get rerc new-york-1 ``` The output should be as below: ``` NAME STATUS SPEC STATUS LOCAL - rerc1 Active Valid true + new-york-1 Active Valid true ``` Note: @@ -624,7 +680,7 @@ Note: **On the other clusters that are participating in the Active-Active database do the following:** 1. update the secret with the new credentials data and name it with the following convention: `redis-enterprise-`, replace the `` with the RERC name. -For example, a secret generated with the RERC name 'rerc1': +For example, a secret generated with the RERC name 'new-york-1': ``` apiVersion: v1 data: @@ -632,7 +688,7 @@ data: username: PHNvbWUgdXNlcj4 kind: Secret metadata: - name: redis-enterprise-rerc1 + name: redis-enterprise-new-york-1 type: Opaque ``` @@ -646,19 +702,29 @@ To follow the statuses of the updated RERC custom resources run the following: ``` kubectl get rerc ``` -For example to view the status of the RERC named "rerc1": +For example to view the status of the RERC named "new-york-1": ``` - kubectl get rerc rerc1 + kubectl get rerc new-york-1 ``` The output should be as below: ``` NAME STATUS SPEC STATUS LOCAL - rerc1 Active Valid true + new-york-1 Active Valid true ``` Note: * As the 'STATUS' and the 'SPEC STATUS' are 'Active' and 'Valid' respectively it means the configurations are correct, in case of an error please view the RERC custom resource events and/ or the Redis Enterprise operator logs. +## Active-Active database with Redis modules + +Note - Modules are currently in preview for Active-Active databases. + +To use modules with Active-Active databases enable the alpha feature flag on all participating clusters: +To enable modules for Active-Active databases, set a boolean environment variable with the name "ENABLE_ALPHA_FEATURES" to True. This variable can be set via the redis-enterprise-operator pod spec, or through the operator-environment-config Config Map. + +Importent note: +upgrading modules with Active-Active databases is currently not supported via the operator, to upgrade please use the RS APIs directly and after the module has successfully upgraded update the module version on the REAADB custom resource. + ## Test your Active-Active database The easiest way to test your Active-Active database is to set a key-value pair in one database and retrieve it from the other. @@ -692,17 +758,5 @@ From the output fetch the redis 'targetPort': ### No migration from the previous AA method migrating Active-Active database with non-operator managed Active-Active database is currently not supported. -### HashiCorp Vault secret storage -Storing the secrets in HashiCorp Vault is currently not supported for operator managed Active-Active database . - ### database version is currently not supported -Setting database specific version is currently not supported for operator managed Active-Active database . - -### Modules are currently not supported -Redis modules are currently not supported for operator managed Active-Active database . - -### Backup are currently not supported -Database backups are currently not supported for operator managed Active-Active database . - -### client authentication certificates are currently not supported -client authentication certificates are currently not supported for operator managed Active-Active database . +Setting database specific version is currently not supported for operator managed Active-Active database. diff --git a/bundle.yaml b/bundle.yaml index ab9474f..c6b912b 100644 --- a/bundle.yaml +++ b/bundle.yaml @@ -363,12 +363,16 @@ spec: containerTimezone: description: Container timezone configuration. While the default timezone on all containers is UTC, this setting can be used to set the timezone - on services rigger/bootstrapper/RS containers. Currently the only - supported value is to propagate the host timezone to all containers. + on services rigger/bootstrapper/RS containers. You can either propagate + the hosts timezone to RS pods or set it manually via timezoneName. properties: propagateHost: - description: Identifies that container timezone should be in sync with the host. + description: Identifies that container timezone should be in sync with the host, this + option mounts a hostPath volume onto RS pods that could be restricted in some systems. type: object + timezoneName: + description: POSIX-style timezone name as a string to be passed as EnvVar to RE pods, e.g. "Europe/London". + type: string type: object createServiceAccount: description: Whether to create service account @@ -415,12 +419,75 @@ spec: enforceIPv4: description: Sets ENFORCE_IPV4 environment variable type: boolean + extraEnvVars: + description: 'ADVANCED USAGE: use carefully. Add environment variables + to RS StatefulSet''s containers.' + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array extraLabels: additionalProperties: type: string description: Labels that the user defines for their convenience type: object hostAliases: + description: Adds hostAliases entries to the Redis Enterprise pods items: description: HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file. @@ -437,11 +504,7 @@ spec: type: array ingressOrRouteSpec: description: Access configurations for the Redis Enterprise Cluster - and Databases. Note - this feature is currently in preview. For - this feature to take effect, set a boolean environment variable - with the name "ENABLE_ALPHA_FEATURES" to True. This variable can - be set via the redis-enterprise-operator pod spec, or through the - operator-environment-config Config Map. At most one of ingressOrRouteSpec + and Databases. At most one of ingressOrRouteSpec or activeActive fields can be set at the same time. properties: apiFqdnUrl: @@ -597,16 +660,13 @@ spec: the protocol is LDAPS or STARTTLS. type: string cacheTTLSeconds: - default: 300 description: The maximum TTL of cached entries. type: integer enabledForControlPlane: - default: false description: Whether to enable LDAP for control plane access. Disabled by default. type: boolean enabledForDataPlane: - default: false description: Whether to enable LDAP for data plane access. Disabled by default. type: boolean @@ -715,7 +775,12 @@ spec: podAnnotations: additionalProperties: type: string - description: pod annotations + description: annotations for the service rigger and redis enterprise pods + type: object + redisEnterprisePodAnnotations: + additionalProperties: + type: string + description: annotations for redis enterprise pod type: object podAntiAffinity: description: 'Override for the default anti-affinity rules of the Redis @@ -3780,6 +3845,9 @@ spec: type: object type: array serviceNaming: + description: Used to determine how to name the services created automatically when a database is created. + When bdb_name is used, the database name will be also used for the service name. + When redis-port is used, the service will be named redis-. enum: - bdb_name - redis-port @@ -6315,6 +6383,11 @@ spec: type: object type: array type: object + podAnnotations: + additionalProperties: + type: string + description: annotations for the service rigger pod + type: object type: object sideContainersSpec: items: @@ -7766,6 +7839,8 @@ spec: properties: propagateHost: type: object + timezoneName: + type: string type: object createServiceAccount: type: boolean @@ -7790,11 +7865,74 @@ spec: type: object enforceIPv4: type: boolean + extraEnvVars: + description: 'ADVANCED USAGE: use carefully. Add environment variables + to RS StatefulSet''s containers.' + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array extraLabels: additionalProperties: type: string type: object hostAliases: + description: Adds hostAliases entries to the Redis Enterprise pods items: properties: hostnames: @@ -7893,13 +8031,10 @@ spec: caCertificateSecretName: type: string cacheTTLSeconds: - default: 300 type: integer enabledForControlPlane: - default: false type: boolean enabledForDataPlane: - default: false type: boolean protocol: enum: @@ -7965,6 +8100,12 @@ spec: podAnnotations: additionalProperties: type: string + description: annotations for the service rigger and redis enterprise pods + type: object + redisEnterprisePodAnnotations: + additionalProperties: + type: string + description: annotations for redis enterprise pod type: object podAntiAffinity: properties: @@ -10910,6 +11051,9 @@ spec: type: object type: array serviceNaming: + description: Used to determine how to name the services created automatically when a database is created. + When bdb_name is used, the database name will be also used for the service name. + When redis-port is used, the service will be named redis-. enum: - bdb_name - redis-port @@ -13438,6 +13582,11 @@ spec: type: object type: array type: object + podAnnotations: + additionalProperties: + type: string + description: annotations for the service rigger pod + type: object type: object sideContainersSpec: items: @@ -15077,7 +15226,12 @@ spec: and it must not be below 1GB. type: string modulesList: - description: List of modules associated with database + description: List of modules associated with database. + Note - For Active-Active databases this feature is currently in preview. For + this feature to take effect for Active-Active databases, set a boolean environment variable + with the name "ENABLE_ALPHA_FEATURES" to True. This variable can + be set via the redis-enterprise-operator pod spec, or through the + operator-environment-config Config Map. items: description: 'Redis Enterprise Module: https://redislabs.com/redis-enterprise/modules/' properties: @@ -15423,6 +15577,840 @@ spec: type: object type: object --- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: redisenterpriseremoteclusters.app.redislabs.com + labels: + app: redis-enterprise +spec: + group: app.redislabs.com + names: + kind: RedisEnterpriseRemoteCluster + listKind: RedisEnterpriseRemoteClusterList + plural: redisenterpriseremoteclusters + singular: redisenterpriseremotecluster + shortNames: + - rerc + scope: Namespaced + versions: + - name: v1alpha1 + served: true + storage: true + additionalPrinterColumns: + - jsonPath: .status.status + name: Status + type: string + - jsonPath: .status.specStatus + name: Spec Status + type: string + - jsonPath: .status.local + name: Local + type: string + subresources: + status: {} + schema: + openAPIV3Schema: + description: RedisEntepriseRemoteCluster represents a remote participating + cluster. + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + status: + properties: + local: + description: Indicates whether this object represents a local or a + remote cluster. + type: boolean + specStatus: + description: Whether the desired specification is valid. + type: string + status: + description: The status of the remote cluster. + type: string + observedGeneration: + description: The most recent generation observed for this RERC. It corresponds to the RERC's generation, which is updated by the API Server. + type: integer + type: object + spec: + properties: + apiFqdnUrl: + description: The URL of the cluster, will be used for the active-active + database URL. + type: string + dbFqdnSuffix: + description: The database URL suffix, will be used for the active-active + database replication endpoint and replication endpoint SNI. + type: string + recNamespace: + description: The namespace of the REC that the RERC is pointing at + type: string + recName: + description: The name of the REC that the RERC is pointing at + type: string + secretName: + description: 'The name of the secret containing cluster credentials. + Must be of the following format: "redis-enterprise-"' + type: string + required: + - apiFqdnUrl + - recName + - recNamespace + type: object + type: object +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: redisenterpriseactiveactivedatabases.app.redislabs.com + labels: + app: redis-enterprise +spec: + group: app.redislabs.com + names: + kind: RedisEnterpriseActiveActiveDatabase + listKind: RedisEnterpriseActiveActiveDatabaseList + plural: redisenterpriseactiveactivedatabases + singular: redisenterpriseactiveactivedatabase + shortNames: + - reaadb + preserveUnknownFields: false + scope: Namespaced + versions: + - name: v1alpha1 + served: true + storage: true + additionalPrinterColumns: + - jsonPath: .status.status + name: Status + type: string + - jsonPath: .status.specStatus + name: Spec Status + type: string + - jsonPath: .status.linkedRedbs[*] + name: Linked REDBs + type: string + - jsonPath: .status.replicationStatus + name: Replication Status + type: string + subresources: + status: {} + schema: + openAPIV3Schema: + description: RedisEnterpriseActiveActiveDatabase is the Schema for the redisenterpriseactiveactivedatabase + API + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + status: + description: RedisEnterpriseActiveActiveDatabaseStatus defines the observed + state of RedisEnterpriseActiveActiveDatabase + properties: + status: + description: The status of the active active database. + type: string + specStatus: + description: Whether the desired specification is valid + type: string + linkedRedbs: + description: The linked REDBs. + items: + type: string + type: array + participatingClusters: + description: The list of instances/ clusters statuses. + items: + description: Status of participating cluster. + properties: + name: + description: The name of the remote cluster CR that is linked. + type: string + id: + description: The corresponding ID of the instance in the active-active database. + format: int64 + type: integer + replicationStatus: + description: The replication status of the participating cluster + enum: + - up + - down + type: string + required: + - name + type: object + type: array + guid: + description: The active-active database corresponding GUID. + type: string + lastTaskUid: + description: The last active-active database task UID. + type: string + redisEnterpriseCluster: + description: The Redis Enterprise Cluster Object this Resource is associated + with + type: string + replicationStatus: + description: The overall replication status + enum: + - up + - down + type: string + secretsStatus: + description: The status of the secrets + items: + description: Status of secrets. + properties: + name: + description: The name of the secret. + type: string + status: + description: The status of the secret. + enum: + - Valid + - Invalid + type: string + required: + - name + type: object + type: array + type: object + spec: + description: RedisEnterpriseActiveActiveDatabaseSpec defines the desired + state of RedisEnterpriseActiveActiveDatabase + properties: + redisEnterpriseCluster: + description: Connection to Redis Enterprise Cluster + properties: + name: + description: The name of the Redis Enterprise Cluster where the + database should be stored. + type: string + required: + - name + type: object + participatingClusters: + description: The list of instances/ clusters specifications and configurations. + items: + properties: + name: + description: The name of the remote cluster CR to link. + type: string + required: + - name + type: object + type: array + globalConfigurations: + description: The Active-Active database global configurations, + contains the global properties for each of the participating clusters/ instances databases within the Active-Active database. + properties: + activeActive: + description: Connection/ association to the Active-Active database. + properties: + name: + description: 'The the corresponding Active-Active database name, + Redis Enterprise Active Active Database custom resource name, + this Resource is associated with. In case this resource is + created manually at the active active database creation this + field must be filled via the user, otherwise, the operator + will assign this field automatically. Note: this feature is + currently unsupported.' + type: string + participatingClusterName: + description: 'The corresponding participating cluster name, + Redis Enterprise Remote Cluster custom resource name, in the + Active-Active database, In case this resource is created manually + at the active active database creation this field must be + filled via the user, otherwise, the operator will assign this + field automatically. Note: this feature is currently unsupported.' + type: string + required: + - name + - participatingClusterName + type: object + alertSettings: + description: Settings for database alerts + properties: + bdb_backup_delayed: + description: Periodic backup has been delayed for longer than + specified threshold value [minutes] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_crdt_src_high_syncer_lag: + description: Active-active source - sync lag is higher than + specified threshold value [seconds] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_crdt_src_syncer_connection_error: + description: Active-active source - sync has connection error + while trying to connect replica source + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_crdt_src_syncer_general_error: + description: Active-active source - sync encountered in general + error + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_high_latency: + description: Latency is higher than specified threshold value + [micro-sec] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_high_throughput: + description: Throughput is higher than specified threshold + value [requests / sec.] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_long_running_action: + description: An alert for state-machines that are running + for too long + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_low_throughput: + description: Throughput is lower than specified threshold + value [requests / sec.] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_ram_dataset_overhead: + description: Dataset RAM overhead of a shard has reached the + threshold value [% of its RAM limit] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_ram_values: + description: Percent of values kept in a shard's RAM is lower + than [% of its key count] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_replica_src_high_syncer_lag: + description: Replica-of source - sync lag is higher than specified + threshold value [seconds] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_replica_src_syncer_connection_error: + description: Replica-of source - sync has connection error + while trying to connect replica source + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_shard_num_ram_values: + description: Number of values kept in a shard's RAM is lower + than [values] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_size: + description: Dataset size has reached the threshold value + [% of the memory limit] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + type: object + backup: + description: Target for automatic database backups. + properties: + abs: + properties: + absSecretName: + description: The name of the secret that holds ABS credentials. + The secret must contain the keys "AccountName" and "AccountKey", + and these must hold the corresponding credentials + type: string + container: + description: Azure Blob Storage container name. + type: string + subdir: + description: Optional. Azure Blob Storage subdir under + container. + type: string + required: + - absSecretName + - container + type: object + ftp: + properties: + url: + description: a URI of the "ftps://[USER[:PASSWORD]@]HOST[:PORT]/PATH[/]" + format + type: string + required: + - url + type: object + gcs: + description: GoogleStorage + properties: + bucketName: + description: Google Storage bucket name. + type: string + gcsSecretName: + description: The name of the secret that holds the Google + Cloud Storage credentials. The secret must contain the + keys "CLIENT_ID", "PRIVATE_KEY", "PRIVATE_KEY_ID", "CLIENT_EMAIL" + and these must hold the corresponding credentials. The + keys should correspond to the values in the key JSON. + type: string + subdir: + description: Optional. Google Storage subdir under bucket. + type: string + required: + - bucketName + - gcsSecretName + type: object + interval: + description: Backup Interval in seconds + type: integer + mount: + description: MountPointStorage + properties: + path: + description: Path to the local mount point. You must create + the mount point on all nodes, and the redislabs:redislabs + user must have read and write permissions on the local + mount point. + type: string + required: + - path + type: object + s3: + properties: + awsSecretName: + description: The name of the secret that holds the AWS + credentials. The secret must contain the keys "AWS_ACCESS_KEY_ID" + and "AWS_SECRET_ACCESS_KEY", and these must hold the + corresponding credentials. + type: string + bucketName: + description: Amazon S3 bucket name. + type: string + subdir: + description: Optional. Amazon S3 subdir under bucket. + type: string + required: + - awsSecretName + - bucketName + type: object + sftp: + properties: + sftp_url: + description: SFTP url + type: string + sftpSecretName: + description: The name of the secret that holds SFTP credentials. + The secret must contain the "Key" key, which is the + SSH private key for connecting to the sftp server. + type: string + required: + - sftpSecretName + - sftp_url + type: object + swift: + properties: + auth_url: + description: Swift service authentication URL. + type: string + container: + description: Swift object store container for storing + the backup files. + type: string + prefix: + description: Optional. Prefix (path) of backup files in + the swift container. + type: string + swiftSecretName: + description: 'The name of the secret that holds Swift + credentials. The secret must contain the keys "Key" + and "User", and these must hold the corresponding credentials: + service access key and service user name (pattern for + the latter does not allow special characters &,<,>,")' + type: string + required: + - auth_url + - container + - swiftSecretName + type: object + type: object + clientAuthenticationCertificates: + description: The Secrets containing TLS Client Certificate to + use for Authentication + items: + type: string + type: array + dataInternodeEncryption: + description: Internode encryption (INE) setting. An optional boolean + setting, overriding a similar cluster-wide policy. If set to + False, INE is guaranteed to be turned off for this DB (regardless + of cluster-wide policy). If set to True, INE will be turned + on, unless the capability is not supported by the DB ( in such + a case we will get an error and database creation will fail). + If left unspecified, will be disabled if internode encryption + is not supported by the DB (regardless of cluster default). + Deleting this property after explicitly setting its value shall + have no effect. + type: boolean + databasePort: + description: Database port number. TCP port on which the database + is available. Will be generated automatically if omitted. can + not be changed after creation + type: integer + databaseSecretName: + description: The name of the secret that holds the password to + the database (redis databases only). If secret does not exist, + it will be created. To define the password, create an opaque + secret and set the name in the spec. The password will be taken + from the value of the 'password' key. Use an empty string as + value within the secret to disable authentication for the database. + Note - memcached databases must not be set with a value, and + a secret/password will not be automatically created for them. + Use the memcachedSaslSecretName field to set authentication + parameters for memcached databases. + type: string + defaultUser: + description: Is connecting with a default user allowed? If disabled, + the DatabaseSecret will not be created or updated + type: boolean + evictionPolicy: + description: Database eviction policy. see more https://docs.redislabs.com/latest/rs/administering/database-operations/eviction-policy/ + type: string + isRof: + description: Whether it is an RoF database or not. Applicable + only for databases of type "REDIS". Assumed to be false if left + blank. + type: boolean + memcachedSaslSecretName: + description: Credentials used for binary authentication in memcached + databases. The credentials should be saved as an opaque secret + and the name of that secret should be configured using this + field. For username, use 'username' as the key and the actual + username as the value. For password, use 'password' as the key + and the actual password as the value. Note that connections + are not encrypted. + type: string + memorySize: + description: memory size of database. use formats like 100MB, + 0.1GB. minimum value in 100MB. When redis on flash (RoF) is + enabled, this value refers to RAM+Flash memory, and it must + not be below 1GB. + type: string + modulesList: + description: List of modules associated with database. + Note - For Active-Active databases this feature is currently in preview. For + this feature to take effect for Active-Active databases, set a boolean environment variable + with the name "ENABLE_ALPHA_FEATURES" to True. This variable can + be set via the redis-enterprise-operator pod spec, or through the + operator-environment-config Config Map. + items: + description: 'Redis Enterprise Module: https://redislabs.com/redis-enterprise/modules/' + properties: + config: + description: Module command line arguments e.g. VKEY_MAX_ENTITY_COUNT + 30 + type: string + name: + description: The module's name e.g "ft" for redissearch + type: string + uid: + description: Module's uid - do not set, for system use only + nolint:staticcheck // custom json tag unknown to the linter + type: string + version: + description: Module's semantic version e.g "1.6.12" + type: string + required: + - name + - version + type: object + type: array + ossCluster: + description: OSS Cluster mode option. Note that not all client + libraries support OSS cluster mode. + type: boolean + persistence: + description: Database on-disk persistence policy + enum: + - disabled + - aofEverySecond + - aofAlways + - snapshotEvery1Hour + - snapshotEvery6Hour + - snapshotEvery12Hour + type: string + proxyPolicy: + description: 'The policy used for proxy binding to the endpoint. + Supported proxy policies are: single/all-master-shards/all-nodes + When left blank, the default value will be chosen according + to the value of ossCluster - single if disabled, all-master-shards + when enabled' + type: string + rackAware: + description: 'Whether database should be rack aware. This improves + availability - more information: https://docs.redislabs.com/latest/rs/concepts/high-availability/rack-zone-awareness/' + type: boolean + redisEnterpriseCluster: + description: Connection to Redis Enterprise Cluster + properties: + name: + description: The name of the Redis Enterprise Cluster where + the database should be stored. + type: string + required: + - name + type: object + redisVersion: + description: Redis OSS version. For existing databases - Upgrade + Redis OSS version. For new databases - the version which the + database will be created with. If set to 'major' - will always + upgrade to the most recent major Redis version. If set to 'latest' + - will always upgrade to the most recent Redis version. Depends + on 'redisUpgradePolicy' - if you want to set the value to 'latest' + for some databases, you must set redisUpgradePolicy on the cluster + before. Possible values are 'major' or 'latest' When using upgrade + - make sure to backup the database before. This value is used + only for database type 'redis' + enum: + - major + - latest + type: string + replicaSources: + description: What databases to replicate from + items: + properties: + clientKeySecret: + description: 'Secret that defines the client certificate + and key used by the syncer in the target database cluster. + The secret must have 2 keys in its map: "cert" which is + the PEM encoded certificate, and "key" which is the PEM + encoded private key.' + type: string + compression: + description: GZIP compression level (0-6) to use for replication. + type: integer + replicaSourceName: + description: The name of the resource from which the source + database URI is derived. The type of resource must match + the type specified in the ReplicaSourceType field. + type: string + replicaSourceType: + description: The type of resource from which the source + database URI is derived. If set to 'SECRET', the source + database URI is derived from the secret named in the ReplicaSourceName + field. The secret must have a key named 'uri' that defines + the URI of the source database in the form of 'redis://...'. + The type of secret (kubernetes, vault, ...) is determined + by the secret mechanism used by the underlying REC object. + If set to 'REDB', the source database URI is derived from + the RedisEnterpriseDatabase resource named in the ReplicaSourceName + field. + type: string + serverCertSecret: + description: 'Secret that defines the server certificate + used by the proxy in the source database cluster. The + secret must have 1 key in its map: "cert" which is the + PEM encoded certificate.' + type: string + tlsSniName: + description: TLS SNI name to use for the replication link. + type: string + required: + - replicaSourceName + - replicaSourceType + type: object + type: array + replication: + description: In-memory database replication. When enabled, database + will have replica shard for every master - leading to higher + availability. + type: boolean + rofRamSize: + description: The size of the RAM portion of an RoF database. Similarly + to "memorySize" use formats like 100MB, 0.1GB It must be at + least 10% of combined memory size (RAM+Flash), as specified + by "memorySize". + type: string + rolesPermissions: + description: List of Redis Enteprise ACL and Role bindings to + apply + items: + description: Redis Enterprise Role and ACL Binding + properties: + acl: + description: 'Acl Name of RolePermissionType (note: use + exact name of the ACL from the Redis Enterprise ACL list, + case sensitive)' + type: string + role: + description: 'Role Name of RolePermissionType (note: use + exact name of the role from the Redis Enterprise role + list, case sensitive)' + type: string + type: + description: Type of Redis Enterprise Database Role Permission + type: string + required: + - acl + - role + - type + type: object + type: array + shardCount: + description: Number of database server-side shards + type: integer + shardsPlacement: + description: Control the density of shards - should they reside + on as few or as many nodes as possible. Available options are + "dense" or "sparse". If left unset, defaults to "dense". + type: string + tlsMode: + description: Require SSL authenticated and encrypted connections + to the database. enabled - all incoming connections to the Database + must use SSL. disabled - no incoming connection to the Database + should use SSL. replica_ssl - databases that replicate from + this one need to use SSL. + enum: + - disabled + - enabled + - replica_ssl + type: string + type: + description: The type of the database. + enum: + - redis + - memcached + type: string + type: object + required: + - participatingClusters + type: object + type: object +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -15434,6 +16422,8 @@ spec: selector: matchLabels: name: redis-enterprise-operator + strategy: + type: Recreate template: metadata: labels: @@ -15443,9 +16433,10 @@ spec: serviceAccountName: redis-enterprise-operator containers: - name: redis-enterprise-operator - image: redislabs/operator:6.4.2-5 + image: redislabs/operator:6.4.2-6 command: - - redis-enterprise-operator + - operator-root + - operator imagePullPolicy: Always envFrom: - configMapRef: @@ -15485,9 +16476,10 @@ spec: port: 8080 scheme: HTTP - name: admission - image: redislabs/operator:6.4.2-5 + image: redislabs/operator:6.4.2-6 command: - - /usr/local/bin/admission + - operator-root + - admission imagePullPolicy: Always envFrom: - configMapRef: diff --git a/crds/reaadb_crd.yaml b/crds/reaadb_crd.yaml index 4ed6341..adb45d5 100644 --- a/crds/reaadb_crd.yaml +++ b/crds/reaadb_crd.yaml @@ -29,6 +29,9 @@ spec: - jsonPath: .status.linkedRedbs[*] name: Linked REDBs type: string + - jsonPath: .status.replicationStatus + name: Replication Status + type: string subresources: status: {} schema: @@ -69,6 +72,12 @@ spec: description: The corresponding ID of the instance in the active-active database. format: int64 type: integer + replicationStatus: + description: The replication status of the participating cluster + enum: + - up + - down + type: string required: - name type: object @@ -83,6 +92,12 @@ spec: description: The Redis Enterprise Cluster Object this Resource is associated with type: string + replicationStatus: + description: The overall replication status + enum: + - up + - down + type: string secretsStatus: description: The status of the secrets items: @@ -541,7 +556,12 @@ spec: not be below 1GB. type: string modulesList: - description: List of modules associated with database + description: List of modules associated with database. + Note - For Active-Active databases this feature is currently in preview. For + this feature to take effect for Active-Active databases, set a boolean environment variable + with the name "ENABLE_ALPHA_FEATURES" to True. This variable can + be set via the redis-enterprise-operator pod spec, or through the + operator-environment-config Config Map. items: description: 'Redis Enterprise Module: https://redislabs.com/redis-enterprise/modules/' properties: diff --git a/crds/rec_crd.yaml b/crds/rec_crd.yaml index 76f3c89..4b18ce0 100644 --- a/crds/rec_crd.yaml +++ b/crds/rec_crd.yaml @@ -268,12 +268,16 @@ spec: containerTimezone: description: Container timezone configuration. While the default timezone on all containers is UTC, this setting can be used to set the timezone - on services rigger/bootstrapper/RS containers. Currently the only - supported value is to propagate the host timezone to all containers. + on services rigger/bootstrapper/RS containers. You can either propagate + the hosts timezone to RS pods or set it manually via timezoneName. properties: propagateHost: - description: Identifies that container timezone should be in sync with the host. + description: Identifies that container timezone should be in sync with the host, this + option mounts a hostPath volume onto RS pods that could be restricted in some systems. type: object + timezoneName: + description: POSIX-style timezone name as a string to be passed as EnvVar to RE pods, e.g. "Europe/London". + type: string type: object createServiceAccount: description: Whether to create service account @@ -320,12 +324,75 @@ spec: enforceIPv4: description: Sets ENFORCE_IPV4 environment variable type: boolean + extraEnvVars: + description: 'ADVANCED USAGE: use carefully. Add environment variables + to RS StatefulSet''s containers.' + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array extraLabels: additionalProperties: type: string description: Labels that the user defines for their convenience type: object hostAliases: + description: Adds hostAliases entries to the Redis Enterprise pods items: description: HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file. @@ -342,11 +409,7 @@ spec: type: array ingressOrRouteSpec: description: Access configurations for the Redis Enterprise Cluster - and Databases. Note - this feature is currently in preview. For - this feature to take effect, set a boolean environment variable - with the name "ENABLE_ALPHA_FEATURES" to True. This variable can - be set via the redis-enterprise-operator pod spec, or through the - operator-environment-config Config Map. At most one of ingressOrRouteSpec + and Databases. At most one of ingressOrRouteSpec or activeActive fields can be set at the same time. properties: apiFqdnUrl: @@ -502,16 +565,13 @@ spec: the protocol is LDAPS or STARTTLS. type: string cacheTTLSeconds: - default: 300 description: The maximum TTL of cached entries. type: integer enabledForControlPlane: - default: false description: Whether to enable LDAP for control plane access. Disabled by default. type: boolean enabledForDataPlane: - default: false description: Whether to enable LDAP for data plane access. Disabled by default. type: boolean @@ -620,7 +680,12 @@ spec: podAnnotations: additionalProperties: type: string - description: pod annotations + description: annotations for the service rigger and redis enterprise pods + type: object + redisEnterprisePodAnnotations: + additionalProperties: + type: string + description: annotations for redis enterprise pod type: object podAntiAffinity: description: 'Override for the default anti-affinity rules of the Redis @@ -3685,6 +3750,9 @@ spec: type: object type: array serviceNaming: + description: Used to determine how to name the services created automatically when a database is created. + When bdb_name is used, the database name will be also used for the service name. + When redis-port is used, the service will be named redis-. enum: - bdb_name - redis-port @@ -6220,6 +6288,11 @@ spec: type: object type: array type: object + podAnnotations: + additionalProperties: + type: string + description: annotations for the service rigger pod + type: object type: object sideContainersSpec: items: @@ -7671,6 +7744,8 @@ spec: properties: propagateHost: type: object + timezoneName: + type: string type: object createServiceAccount: type: boolean @@ -7695,11 +7770,74 @@ spec: type: object enforceIPv4: type: boolean + extraEnvVars: + description: 'ADVANCED USAGE: use carefully. Add environment variables + to RS StatefulSet''s containers.' + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array extraLabels: additionalProperties: type: string type: object hostAliases: + description: Adds hostAliases entries to the Redis Enterprise pods items: properties: hostnames: @@ -7798,13 +7936,10 @@ spec: caCertificateSecretName: type: string cacheTTLSeconds: - default: 300 type: integer enabledForControlPlane: - default: false type: boolean enabledForDataPlane: - default: false type: boolean protocol: enum: @@ -7870,6 +8005,12 @@ spec: podAnnotations: additionalProperties: type: string + description: annotations for the service rigger and redis enterprise pods + type: object + redisEnterprisePodAnnotations: + additionalProperties: + type: string + description: annotations for redis enterprise pod type: object podAntiAffinity: properties: @@ -10815,6 +10956,9 @@ spec: type: object type: array serviceNaming: + description: Used to determine how to name the services created automatically when a database is created. + When bdb_name is used, the database name will be also used for the service name. + When redis-port is used, the service will be named redis-. enum: - bdb_name - redis-port @@ -13343,6 +13487,11 @@ spec: type: object type: array type: object + podAnnotations: + additionalProperties: + type: string + description: annotations for the service rigger pod + type: object type: object sideContainersSpec: items: diff --git a/crds/redb_crd.yaml b/crds/redb_crd.yaml index 61907cf..5b4c26d 100644 --- a/crds/redb_crd.yaml +++ b/crds/redb_crd.yaml @@ -391,7 +391,12 @@ spec: and it must not be below 1GB. type: string modulesList: - description: List of modules associated with database + description: List of modules associated with database. + Note - For Active-Active databases this feature is currently in preview. For + this feature to take effect for Active-Active databases, set a boolean environment variable + with the name "ENABLE_ALPHA_FEATURES" to True. This variable can + be set via the redis-enterprise-operator pod spec, or through the + operator-environment-config Config Map. items: description: 'Redis Enterprise Module: https://redislabs.com/redis-enterprise/modules/' properties: diff --git a/examples/v1alpha1/reaadb.yaml b/examples/v1alpha1/reaadb.yaml index fdc59bb..c96398a 100644 --- a/examples/v1alpha1/reaadb.yaml +++ b/examples/v1alpha1/reaadb.yaml @@ -5,11 +5,8 @@ metadata: labels: app: redis-enterprise spec: - # The Redis Enterprise Cluster Object this Resource is associated with - redisEnterpriseCluster: - name: rec1 participatingClusters: - # Participating cluster with RERC named 'rerc1' in 'ns1' namespace. - - name: rerc1.ns1 - # Participating cluster with RERC named 'rerc2' in 'ns2' namespace. - - name: rerc2.ns2 + # Participating cluster pointing to RERC named: 'new-york-1'. + - name: new-york-1 + # Participating cluster pointing to RERC named: 'boston-1'. + - name: boston-1 diff --git a/examples/v1alpha1/redb.yaml b/examples/v1alpha1/redb.yaml index 5ba3f85..8759b10 100644 --- a/examples/v1alpha1/redb.yaml +++ b/examples/v1alpha1/redb.yaml @@ -4,6 +4,3 @@ metadata: name: redis-enterprise-database labels: app: redis-enterprise -spec: - redisEnterpriseCluster: - name: redis-enterprise diff --git a/examples/v1alpha1/rerc.yaml b/examples/v1alpha1/rerc.yaml index 7ec97b6..78db7b7 100644 --- a/examples/v1alpha1/rerc.yaml +++ b/examples/v1alpha1/rerc.yaml @@ -1,7 +1,8 @@ apiVersion: app.redislabs.com/v1alpha1 kind: RedisEnterpriseRemoteCluster metadata: - name: rerc1 + # Your name of the RERC. + name: new-york-1 labels: app: redis-enterprise spec: @@ -10,10 +11,10 @@ spec: # The Namespace of the REC that the RERC is pointing at recNamespace: ns1 # The URL of the cluster, will be used for the active-active database URL - apiFqdnUrl: testapi-rerc1-ns1.redislabs.com + apiFqdnUrl: testapi-new-york-1-ns1.redislabs.com # The database URL suffix, will be used for the active-active # database replication endpoint and replication endpoint SNI - dbFqdnSuffix: -example-rerc1-ns1.redislabs.com + dbFqdnSuffix: -example-new-york-1-ns1.redislabs.com # The name of the secret containing cluster credentials. # Need to follow format: "redis-enterprise-"' - secretName: redis-enterprise-rerc1 + secretName: redis-enterprise-new-york-1 diff --git a/log_collector/log_collector.py b/log_collector/log_collector.py index 6e025a3..25481b4 100644 --- a/log_collector/log_collector.py +++ b/log_collector/log_collector.py @@ -25,11 +25,18 @@ MODE_ALL = "all" FIRST_VERSION_SUPPORTING_RESTRICTED = "6.2.18-3" +MIN_KUBECTL_VERSION_SUPPORT_RETRIES = "1.23" +MIN_OC_VERSION_SUPPORT_RETRIES = "4.10" +DEFAULT_KUBECTL_VERSION = "1.22" +DEFAULT_OC_VERSION = "4.9" + RS_LOG_FOLDER_PATH = "/var/opt/redislabs/log" +LOGGER_OUTPUT_FILE = "output.log" logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) -logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s') -VERSION_LOG_COLLECTOR = "6.4.2-5" +LOGGER_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' +logging.basicConfig(format=LOGGER_FORMAT) +VERSION_LOG_COLLECTOR = "6.4.2-6" TIME_FORMAT = time.strftime("%Y%m%d-%H%M%S") @@ -42,11 +49,18 @@ DEFAULT_K8S_CLI = "kubectl" OC_K8S_CLI = "oc" -RESTRICTED_MODE_API_RESOURCES = [ +OPERATOR_CUSTOM_RESOURCES = [ "RedisEnterpriseCluster", "RedisEnterpriseDatabase", "RedisEnterpriseRemoteCluster", "RedisEnterpriseActiveActiveDatabase", +] + +NON_LABELED_RESOURCES = OPERATOR_CUSTOM_RESOURCES + [ + "VolumeAttachment", +] + +RESTRICTED_MODE_API_RESOURCES = NON_LABELED_RESOURCES + [ "StatefulSet", "Deployment", "Service", @@ -68,13 +82,6 @@ "Namespace" ] -OPERATOR_CUSTOM_RESOURCES = [ - "RedisEnterpriseCluster", - "RedisEnterpriseDatabase", - "RedisEnterpriseRemoteCluster", - "RedisEnterpriseActiveActiveDatabase", -] - ALL_ONLY_API_RESOURCES = [ "Node", "ResourceQuota", @@ -89,7 +96,7 @@ "ReplicaSet", "StorageClass", "Gateway", - "VirtualService" + "VirtualService", ] SHA_DIGESTS_BEFORE_RESTRICTED_MODE_SUPPORT = [ @@ -104,6 +111,28 @@ UNRECOGNIZED_RESOURCE = "error: the server doesn't have a resource type" +def set_file_logger(output_dir): + """ + add a file handler to the logger + """ + path = os.path.join(output_dir, LOGGER_OUTPUT_FILE) + # verify handler is not exist + for handler in list(logger.handlers): + try: + if handler.__class__.__name__ == 'FileHandler': + if handler.baseFilename == path: + # handler already exist - continue + return + except NameError: + continue + except AttributeError: + continue + logger_file_handler = logging.FileHandler(path) + logger_file_handler.setLevel(logging.INFO) + logger_file_handler.setFormatter(logging.Formatter(LOGGER_FORMAT)) + logger.addHandler(logger_file_handler) + + def make_dir(directory): """ Create an directory if not exists @@ -164,9 +193,11 @@ def _get_namespace_from_config(): # pylint: disable=R0913 def collect_from_ns(namespace, output_dir, api_resources, logs_from_all_pods=False, k8s_cli_input="", - mode=MODE_RESTRICTED): + mode=MODE_RESTRICTED, skip_support_package=False, collect_empty_files=False): "Collect the context of a specific namespace. Typically runs in parallel processes." + set_file_logger(output_dir) k8s_cli = detect_k8s_cli(k8s_cli_input) + k8s_cli_version = detect_k8s_cli_version(k8s_cli) logger.info("Started collecting from namespace '%s'", namespace) ns_output_dir = os.path.join(output_dir, namespace) make_dir(ns_output_dir) @@ -176,12 +207,12 @@ def collect_from_ns(namespace, output_dir, api_resources, logs_from_all_pods=Fal selector = '--selector="{}"'.format(OPERATOR_LABEL) collect_connectivity_check(namespace, ns_output_dir, k8s_cli) - get_redis_enterprise_debug_info(namespace, ns_output_dir, k8s_cli, mode) + get_redis_enterprise_debug_info(namespace, ns_output_dir, k8s_cli, mode, skip_support_package, k8s_cli_version) collect_pod_rs_logs(namespace, ns_output_dir, k8s_cli, mode) collect_resources_list(namespace, ns_output_dir, k8s_cli, mode) collect_events(namespace, ns_output_dir, k8s_cli, mode) - collect_api_resources(namespace, ns_output_dir, k8s_cli, api_resources, selector) - collect_api_resources_description(namespace, ns_output_dir, k8s_cli, api_resources, selector) + collect_api_resources(namespace, ns_output_dir, k8s_cli, api_resources, selector, collect_empty_files) + collect_api_resources_description(namespace, ns_output_dir, k8s_cli, api_resources, selector, collect_empty_files) collect_pods_logs(namespace, ns_output_dir, k8s_cli, logs_from_all_pods) @@ -190,6 +221,7 @@ def collect_resources(namespace, output_dir, api_resources, k8s_cli_input="", se """ Collect specific resources from specific namespace. Not meant to be used to collect RS pod logs. """ + set_file_logger(output_dir) k8s_cli = detect_k8s_cli(k8s_cli_input) ns_output_dir = os.path.join(output_dir, namespace) make_dir(ns_output_dir) @@ -230,6 +262,39 @@ def detect_k8s_cli(k8s_cli_input=""): return DEFAULT_K8S_CLI +def detect_k8s_cli_version(k8s_cli): # noqa: C901 + """ + detect kubectl/oc version + """ + get_k8s_cli_version_cmd = "{} version -o json".format(k8s_cli) + + is_oc = k8s_cli.endswith(OC_K8S_CLI) + + version = DEFAULT_OC_VERSION if is_oc else DEFAULT_KUBECTL_VERSION + + # in some k8s cli versions there is a warning msg that need to be ignored, so we redirect stderr to null . + try: + with open(os.devnull, 'wb') as dev_null: + output = subprocess.check_output(get_k8s_cli_version_cmd, + shell=True, + stderr=dev_null) + except subprocess.CalledProcessError as ex: + logger.warning("Failed in shell command: %s, output: %s", + get_k8s_cli_version_cmd, ex.output) + return version + + output = native_string(output) + + if output: + try: + version = get_cli_version(output, is_oc) + # pylint: disable=W0703 + except Exception: + logger.exception("Failed to detect k8s cli version") + return version + return version + + def parse_operator_deployment(k8s_cli, namespaces): """ Compare operator version with the current log_collector version. @@ -310,6 +375,27 @@ def check_if_version_supports_restricted(operator_version): return True +def compare_versions(current_version, supported_version): + """ + Compare between the current version and the version that is supported + check if the current version is supported (current >= supported) + the versions convention is x.y + """ + try: + current = current_version.split(".") + supported = supported_version.split(".") + + if int(current[0]) < int(supported[0]): + return False + if int(current[0]) > int(supported[0]): + return True + return int(current[1]) >= int(supported[1]) + # pylint: disable=W0703 + except Exception: + logger.info("issues parsing version") + return False + + def determine_default_mode(operator_tag, is_sha_digest): """ determine the default mode based on the version/sha digest @@ -325,8 +411,18 @@ def run(results): """ Collect logs """ - logger.info("Started Redis Enterprise k8s log collector") + output_file_name = "redis_enterprise_k8s_debug_info_{}".format(TIME_FORMAT) + output_dir = results.output_dir + if not output_dir: + output_dir = os.getcwd() + output_dir = os.path.join(output_dir, output_file_name) + make_dir(output_dir) + with open(os.path.join(output_dir, LOGGER_OUTPUT_FILE), "x"): + pass + + set_file_logger(output_dir) + logger.info("Started Redis Enterprise k8s log collector") start_time = time.time() k8s_cli = detect_k8s_cli(results.k8s_cli) namespace_input = results.namespace @@ -350,18 +446,13 @@ def run(results): if mode == MODE_ALL: api_resources = api_resources + ALL_ONLY_API_RESOURCES - output_file_name = "redis_enterprise_k8s_debug_info_{}".format(TIME_FORMAT) - output_dir = results.output_dir - if not output_dir: - output_dir = os.getcwd() - output_dir = os.path.join(output_dir, output_file_name) - make_dir(output_dir) collect_cluster_info(output_dir, k8s_cli) processes = [] for namespace in namespaces: proc = Process(target=collect_from_ns, - args=[namespace, output_dir, api_resources, logs_from_all_pods, k8s_cli, mode]) + args=[namespace, output_dir, api_resources, logs_from_all_pods, + k8s_cli, mode, results.skip_support_package, results.collect_empty_files]) proc.start() processes.append(proc) @@ -511,19 +602,22 @@ def create_debug_info_package_on_pod(namespace, pod_name, attempt, k8s_cli): def download_debug_info_package_from_pod( # pylint: disable=R0913 - namespace, output_dir, pod_name, attempt, k8s_cli, debug_file_path, debug_file_name + namespace, output_dir, pod_name, attempt, k8s_cli, debug_file_path, debug_file_name, k8s_cli_version ): """ This function attempt to download debug info package from a given pod. It should only be called once the package is created. """ - cmd = "cd \"{}\" && {} -n {} cp {}:{} ./{} --retries={}".format(output_dir, - k8s_cli, - namespace, - pod_name, - debug_file_path, - debug_file_name, - attempt) + cmd = "cd \"{}\" && {} -n {} cp {}:{} ./{}".format(output_dir, + k8s_cli, + namespace, + pod_name, + debug_file_path, + debug_file_name, + ) + if compare_versions(k8s_cli_version, get_min_cli_version(k8s_cli)): + cmd = "{} --retries={}".format(cmd, attempt) + return_code, out = run_shell_command(cmd) if return_code: logger.info("Unable to copy debug info from pod %s" @@ -535,8 +629,32 @@ def download_debug_info_package_from_pod( # pylint: disable=R0913 return True +def get_min_cli_version(k8s_cli): + """ + Get the minimum kubectl/oc version + """ + return MIN_OC_VERSION_SUPPORT_RETRIES if (k8s_cli and k8s_cli.endswith(OC_K8S_CLI))\ + else MIN_KUBECTL_VERSION_SUPPORT_RETRIES + + +def get_cli_version(output, is_oc): + """ + Get the client version from the version output command + """ + parsed = json.loads("".join(output)) + if is_oc: + client_version = parsed['releaseClientVersion'] + logger.info("OC Client Version: %s", client_version) + return client_version + major = parsed['clientVersion']['major'] + minor = parsed['clientVersion']['minor'] + client_version = "{}.{}".format(major, minor) + logger.info("Kubectl version found: %s", client_version) + return client_version + + def create_and_download_debug_info_package_from_pod( - namespace, pod_name, output_dir, k8s_cli + namespace, pod_name, output_dir, k8s_cli, k8s_cli_version ): """ This function attempts to create a debug info package on a pod and if debug @@ -558,7 +676,8 @@ def create_and_download_debug_info_package_from_pod( (debug_info_path, debug_info_file_name) = debug_info_path_and_name for attempt in range(DEBUG_INFO_PACKAGE_RETRIES): if download_debug_info_package_from_pod( - namespace, output_dir, pod_name, attempt + 1, k8s_cli, debug_info_path, debug_info_file_name + namespace, output_dir, pod_name, attempt + 1, k8s_cli, debug_info_path, debug_info_file_name, + k8s_cli_version ): logger.info( "Namespace '%s': Collected Redis Enterprise cluster debug package from pod: %s", @@ -581,7 +700,7 @@ def create_and_download_debug_info_package_from_pod( return False -def get_redis_enterprise_debug_info(namespace, output_dir, k8s_cli, mode): +def get_redis_enterprise_debug_info(namespace, output_dir, k8s_cli, mode, skip_support_package, k8s_cli_version): """ Connects to an RS cluster node, creates and copies debug info package from a pod, preferably one that passes readiness probe @@ -601,10 +720,12 @@ def get_redis_enterprise_debug_info(namespace, output_dir, k8s_cli, mode): logger.warning("Cannot find a ready redis enterprise pod, will use a non-ready pod") pod_names = [pod['metadata']['name'] for pod in rs_pods] - logger.info("Trying to extract debug info from RS pods: {%s}", pod_names) - for pod_name in pod_names: - if create_and_download_debug_info_package_from_pod(namespace, pod_name, output_dir, k8s_cli): - break + if not skip_support_package: + logger.info("Trying to extract debug info from RS pods: {%s}", pod_names) + for pod_name in pod_names: + if create_and_download_debug_info_package_from_pod(namespace, pod_name, output_dir, + k8s_cli, k8s_cli_version): + break def collect_resources_list(namespace, output_dir, k8s_cli, mode): @@ -648,59 +769,96 @@ def collect_events(namespace, output_dir, k8s_cli, mode=MODE_RESTRICTED): # We get the events in YAML format as well since in YAML format they are a bit more informative. output = run_get_resource_yaml(namespace, "Event", k8s_cli) - with open(os.path.join(output_dir, "Event.yaml"), "w+") as file_handle: + with open(os.path.join(output_dir, "Event.yaml"), "w+", encoding='UTF-8') as file_handle: file_handle.write(output) -def collect_api_resources(namespace, output_dir, k8s_cli, api_resources, selector=""): +def check_empty_yaml_file(out): + """ + given an output of kubectl get command in yaml format, checks whether the items list is empty + """ + for line in out.split("\n"): + if line.startswith("items"): + return line.split(":")[1].strip() == '[]' + return False + + +def collect_api_resources(namespace, output_dir, k8s_cli, api_resources, selector="", collect_empty_files=False): """ Creates file for each of the API resources with the output of kubectl get -o yaml """ logger.info("Namespace '%s': Collecting API resources", namespace) resources_out = OrderedDict() + message = f"Namespace '{namespace}': no resources of type %s is found" if not selector else \ + f"Namespace '{namespace}': no {extract_label(selector)} labeled resources of type %s is found" + + message = f"{message}, skip collecting empty log file" for resource in api_resources: if resource == "Namespace": output = run_get_resource_yaml(namespace, resource, k8s_cli, resource_name=namespace) - elif resource in OPERATOR_CUSTOM_RESOURCES: + elif resource in NON_LABELED_RESOURCES: output = run_get_resource_yaml(namespace, resource, k8s_cli) else: output = run_get_resource_yaml(namespace, resource, k8s_cli, selector) if output: - resources_out[resource] = output - logger.info("Namespace '%s': + Collected %s", namespace, resource) + if check_empty_yaml_file(output) and not collect_empty_files: + logger.info(message, resource) + else: + resources_out[resource] = output + logger.info("Namespace '%s': + Collected %s", namespace, resource) if selector: # collect PV resource collect_persistent_volume(namespace, k8s_cli, resources_out, "get", KUBCTL_GET_YAML_RETRIES) for entry, out in resources_out.items(): with open(os.path.join(output_dir, - "{}.yaml".format(entry)), "w+") as file_handle: + "{}.yaml".format(entry)), "w+", encoding='UTF-8') as file_handle: file_handle.write(out) -def collect_api_resources_description(namespace, output_dir, k8s_cli, api_resources, selector=""): +def check_empty_desc_file(out): + """ + check if output of kubectl describe resource is empty + """ + return MISSING_RESOURCE in out.lower() + + +def extract_label(selector): + """given a selector, extract the label itself""" + return selector.split('=')[-1][:-1] + + +def collect_api_resources_description(namespace, output_dir, k8s_cli, api_resources, selector="", + collect_empty_files=False): """ Creates file for each of the API resources with the output of kubectl describe """ logger.info("Namespace '%s': Collecting API resources description", namespace) resources_out = OrderedDict() + message = f"Namespace '{namespace}': no resources of type %s is found" if not selector else \ + f"Namespace '{namespace}': no {extract_label(selector)} labeled resources of type %s is found" + + message = f"{message}, skip collecting empty log file" for resource in api_resources: if resource == "Namespace": output = describe_resource(namespace, resource, k8s_cli, resource_name=namespace) - elif resource in OPERATOR_CUSTOM_RESOURCES: + elif resource in NON_LABELED_RESOURCES: output = describe_resource(namespace, resource, k8s_cli) else: output = describe_resource(namespace, resource, k8s_cli, selector) if output: - resources_out[resource] = output - logger.info("Namespace: '%s' + Collected %s", namespace, resource) + if check_empty_desc_file(output) and not collect_empty_files: + logger.info(message, resource) + else: + resources_out[resource] = output + logger.info("Namespace: '%s' + Collected %s", namespace, resource) if selector: # collect PV resource collect_persistent_volume_description(namespace, k8s_cli, resources_out, KUBCTL_DESCRIBE_RETRIES) for entry, out in resources_out.items(): with open(os.path.join(output_dir, - "{}.txt".format(entry)), "w+") as file_handle: + "{}.txt".format(entry)), "w+", encoding='UTF-8') as file_handle: file_handle.write(out) @@ -837,6 +995,7 @@ def archive_files(output_dir, output_dir_name): file_name = output_dir + ".tar.gz" + logger.info("Archiving files into %s", file_name) with tarfile.open(file_name, "w|gz") as tar: tar.add(output_dir, arcname=output_dir_name) logger.info("Archived files into %s", file_name) @@ -900,7 +1059,7 @@ def collect_logs_from_pod(namespace, pod, logs_dir, k8s_cli): cmd = "{} logs -c {} -n {} {}" \ .format(k8s_cli, container, namespace, pod) with open(os.path.join(logs_dir, "{}-{}.log".format(pod, container)), - "w+") as file_handle: + "w+", encoding='UTF-8') as file_handle: _, output = run_shell_command(cmd) file_handle.write(output) @@ -912,7 +1071,7 @@ def collect_logs_from_pod(namespace, pod, logs_dir, k8s_cli): container_log_before_restart_file = os.path.join(logs_dir, '{}-{}-instance-before-restart.log'.format(pod, container)) if err_code == 0: # Previous container instance found; did restart. - with open(container_log_before_restart_file, "w+") as file_handle: + with open(container_log_before_restart_file, "w+", encoding='UTF-8') as file_handle: file_handle.write(output) logger.info("Namespace '%s': + %s-%s", namespace, pod, container) @@ -960,7 +1119,7 @@ def collect_helper(output_dir, cmd, file_name, resource_name, namespace=None): logger.warning("Error when running %s: %s", cmd, out) return path = os.path.join(output_dir, file_name) - with open(path, "w+") as file_handle: + with open(path, "w+", encoding='UTF-8') as file_handle: file_handle.write(out) logger.info("Namespace '%s': Collected %s", namespace, resource_name) @@ -1149,5 +1308,9 @@ def check_not_negative(value): parser.add_argument('--collect_istio', action="store_true", help="collect data from istio-system namespace to debug potential " "problems related to istio ingress method") + parser.add_argument('--skip_support_package', action="store_true", + help="not collect RS support package") + parser.add_argument('--collect_empty_files', action="store_true", + help='collect empty log files for missing resources') parser.set_defaults(collect_istio=False) run(parser.parse_args()) diff --git a/multi-namespace-redb/README.md b/multi-namespace-redb/README.md index 2b02c75..a2287c7 100644 --- a/multi-namespace-redb/README.md +++ b/multi-namespace-redb/README.md @@ -22,7 +22,11 @@ rules: - apiGroups: - app.redislabs.com resources: ["redisenterpriseclusters", "redisenterpriseclusters/status", "redisenterpriseclusters/finalizers", - "redisenterprisedatabases", "redisenterprisedatabases/status", "redisenterprisedatabases/finalizers"] + "redisenterprisedatabases", "redisenterprisedatabases/status", "redisenterprisedatabases/finalizers", + "redisenterpriseremoteclusters", "redisenterpriseremoteclusters/status", + "redisenterpriseremoteclusters/finalizers", + "redisenterpriseactiveactivedatabases", "redisenterpriseactiveactivedatabases/status", + "redisenterpriseactiveactivedatabases/finalizers"] verbs: ["delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"] - apiGroups: [""] resources: ["secrets"] diff --git a/multi-namespace-redb/operator.yaml b/multi-namespace-redb/operator.yaml index 9738dc0..6baf047 100644 --- a/multi-namespace-redb/operator.yaml +++ b/multi-namespace-redb/operator.yaml @@ -9,6 +9,8 @@ spec: selector: matchLabels: name: redis-enterprise-operator + strategy: + type: Recreate template: metadata: labels: @@ -18,9 +20,10 @@ spec: serviceAccountName: redis-enterprise-operator containers: - name: redis-enterprise-operator - image: redislabs/operator:6.4.2-5 + image: redislabs/operator:6.4.2-6 command: - - redis-enterprise-operator + - operator-root + - operator imagePullPolicy: Always envFrom: - configMapRef: @@ -60,9 +63,10 @@ spec: port: 8080 scheme: HTTP - name: admission - image: redislabs/operator:6.4.2-5 + image: redislabs/operator:6.4.2-6 command: - - /usr/local/bin/admission + - operator-root + - admission imagePullPolicy: Always envFrom: - configMapRef: diff --git a/multi-namespace-redb/operator_cluster_role.yaml b/multi-namespace-redb/operator_cluster_role.yaml index f9014ac..5465574 100644 --- a/multi-namespace-redb/operator_cluster_role.yaml +++ b/multi-namespace-redb/operator_cluster_role.yaml @@ -1,7 +1,7 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: redis-enterprise-operator + name: redis-enterprise-operator-consumer-ns rules: - apiGroups: [""] resources: ["namespaces"] diff --git a/multi-namespace-redb/operator_cluster_role_binding.yaml b/multi-namespace-redb/operator_cluster_role_binding.yaml index 4a399a9..3b372c6 100644 --- a/multi-namespace-redb/operator_cluster_role_binding.yaml +++ b/multi-namespace-redb/operator_cluster_role_binding.yaml @@ -1,12 +1,12 @@ kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: redis-enterprise-operator + name: redis-enterprise-operator-consumer-ns subjects: - kind: ServiceAccount name: redis-enterprise-operator namespace: NAMESPACE_OF_SERVICE_ACCOUNT roleRef: kind: ClusterRole - name: redis-enterprise-operator + name: redis-enterprise-operator-consumer-ns apiGroup: rbac.authorization.k8s.io diff --git a/multi-namespace-redb/role.yaml b/multi-namespace-redb/role.yaml index 12e8da4..c223534 100644 --- a/multi-namespace-redb/role.yaml +++ b/multi-namespace-redb/role.yaml @@ -8,7 +8,11 @@ rules: - apiGroups: - app.redislabs.com resources: ["redisenterpriseclusters", "redisenterpriseclusters/status", "redisenterpriseclusters/finalizers", - "redisenterprisedatabases", "redisenterprisedatabases/status", "redisenterprisedatabases/finalizers"] + "redisenterprisedatabases", "redisenterprisedatabases/status", "redisenterprisedatabases/finalizers", + "redisenterpriseremoteclusters", "redisenterpriseremoteclusters/status", + "redisenterpriseremoteclusters/finalizers", + "redisenterpriseactiveactivedatabases", "redisenterpriseactiveactivedatabases/status", + "redisenterpriseactiveactivedatabases/finalizers"] verbs: ["delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"] - apiGroups: [""] resources: ["secrets"] diff --git a/openshift.bundle.yaml b/openshift.bundle.yaml index 9e42ecf..6b909fe 100644 --- a/openshift.bundle.yaml +++ b/openshift.bundle.yaml @@ -2,7 +2,7 @@ apiVersion: security.openshift.io/v1 kind: SecurityContextConstraints metadata: - name: redis-enterprise-scc + name: redis-enterprise-scc-v2 annotations: kubernetes.io/description: redis-enterprise-scc is the minimal SCC needed to run Redis Enterprise nodes on Kubernetes. It provides the same features as restricted-v2 SCC, but allows pods to enable the SYS_RESOURCE capability, @@ -405,12 +405,16 @@ spec: containerTimezone: description: Container timezone configuration. While the default timezone on all containers is UTC, this setting can be used to set the timezone - on services rigger/bootstrapper/RS containers. Currently the only - supported value is to propagate the host timezone to all containers. + on services rigger/bootstrapper/RS containers. You can either propagate + the hosts timezone to RS pods or set it manually via timezoneName. properties: propagateHost: - description: Identifies that container timezone should be in sync with the host. + description: Identifies that container timezone should be in sync with the host, this + option mounts a hostPath volume onto RS pods that could be restricted in some systems. type: object + timezoneName: + description: POSIX-style timezone name as a string to be passed as EnvVar to RE pods, e.g. "Europe/London". + type: string type: object createServiceAccount: description: Whether to create service account @@ -457,12 +461,75 @@ spec: enforceIPv4: description: Sets ENFORCE_IPV4 environment variable type: boolean + extraEnvVars: + description: 'ADVANCED USAGE: use carefully. Add environment variables + to RS StatefulSet''s containers.' + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array extraLabels: additionalProperties: type: string description: Labels that the user defines for their convenience type: object hostAliases: + description: Adds hostAliases entries to the Redis Enterprise pods items: description: HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file. @@ -479,11 +546,7 @@ spec: type: array ingressOrRouteSpec: description: Access configurations for the Redis Enterprise Cluster - and Databases. Note - this feature is currently in preview. For - this feature to take effect, set a boolean environment variable - with the name "ENABLE_ALPHA_FEATURES" to True. This variable can - be set via the redis-enterprise-operator pod spec, or through the - operator-environment-config Config Map. At most one of ingressOrRouteSpec + and Databases. At most one of ingressOrRouteSpec or activeActive fields can be set at the same time. properties: apiFqdnUrl: @@ -639,16 +702,13 @@ spec: the protocol is LDAPS or STARTTLS. type: string cacheTTLSeconds: - default: 300 description: The maximum TTL of cached entries. type: integer enabledForControlPlane: - default: false description: Whether to enable LDAP for control plane access. Disabled by default. type: boolean enabledForDataPlane: - default: false description: Whether to enable LDAP for data plane access. Disabled by default. type: boolean @@ -757,7 +817,12 @@ spec: podAnnotations: additionalProperties: type: string - description: pod annotations + description: annotations for the service rigger and redis enterprise pods + type: object + redisEnterprisePodAnnotations: + additionalProperties: + type: string + description: annotations for redis enterprise pod type: object podAntiAffinity: description: 'Override for the default anti-affinity rules of the Redis @@ -3822,6 +3887,9 @@ spec: type: object type: array serviceNaming: + description: Used to determine how to name the services created automatically when a database is created. + When bdb_name is used, the database name will be also used for the service name. + When redis-port is used, the service will be named redis-. enum: - bdb_name - redis-port @@ -6357,6 +6425,11 @@ spec: type: object type: array type: object + podAnnotations: + additionalProperties: + type: string + description: annotations for the service rigger pod + type: object type: object sideContainersSpec: items: @@ -7808,6 +7881,8 @@ spec: properties: propagateHost: type: object + timezoneName: + type: string type: object createServiceAccount: type: boolean @@ -7832,11 +7907,74 @@ spec: type: object enforceIPv4: type: boolean + extraEnvVars: + description: 'ADVANCED USAGE: use carefully. Add environment variables + to RS StatefulSet''s containers.' + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + optional: + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array extraLabels: additionalProperties: type: string type: object hostAliases: + description: Adds hostAliases entries to the Redis Enterprise pods items: properties: hostnames: @@ -7935,13 +8073,10 @@ spec: caCertificateSecretName: type: string cacheTTLSeconds: - default: 300 type: integer enabledForControlPlane: - default: false type: boolean enabledForDataPlane: - default: false type: boolean protocol: enum: @@ -8007,6 +8142,12 @@ spec: podAnnotations: additionalProperties: type: string + description: annotations for the service rigger and redis enterprise pods + type: object + redisEnterprisePodAnnotations: + additionalProperties: + type: string + description: annotations for redis enterprise pod type: object podAntiAffinity: properties: @@ -10952,6 +11093,9 @@ spec: type: object type: array serviceNaming: + description: Used to determine how to name the services created automatically when a database is created. + When bdb_name is used, the database name will be also used for the service name. + When redis-port is used, the service will be named redis-. enum: - bdb_name - redis-port @@ -13480,6 +13624,11 @@ spec: type: object type: array type: object + podAnnotations: + additionalProperties: + type: string + description: annotations for the service rigger pod + type: object type: object sideContainersSpec: items: @@ -15119,7 +15268,12 @@ spec: and it must not be below 1GB. type: string modulesList: - description: List of modules associated with database + description: List of modules associated with database. + Note - For Active-Active databases this feature is currently in preview. For + this feature to take effect for Active-Active databases, set a boolean environment variable + with the name "ENABLE_ALPHA_FEATURES" to True. This variable can + be set via the redis-enterprise-operator pod spec, or through the + operator-environment-config Config Map. items: description: 'Redis Enterprise Module: https://redislabs.com/redis-enterprise/modules/' properties: @@ -15465,6 +15619,840 @@ spec: type: object type: object --- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: redisenterpriseremoteclusters.app.redislabs.com + labels: + app: redis-enterprise +spec: + group: app.redislabs.com + names: + kind: RedisEnterpriseRemoteCluster + listKind: RedisEnterpriseRemoteClusterList + plural: redisenterpriseremoteclusters + singular: redisenterpriseremotecluster + shortNames: + - rerc + scope: Namespaced + versions: + - name: v1alpha1 + served: true + storage: true + additionalPrinterColumns: + - jsonPath: .status.status + name: Status + type: string + - jsonPath: .status.specStatus + name: Spec Status + type: string + - jsonPath: .status.local + name: Local + type: string + subresources: + status: {} + schema: + openAPIV3Schema: + description: RedisEntepriseRemoteCluster represents a remote participating + cluster. + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + status: + properties: + local: + description: Indicates whether this object represents a local or a + remote cluster. + type: boolean + specStatus: + description: Whether the desired specification is valid. + type: string + status: + description: The status of the remote cluster. + type: string + observedGeneration: + description: The most recent generation observed for this RERC. It corresponds to the RERC's generation, which is updated by the API Server. + type: integer + type: object + spec: + properties: + apiFqdnUrl: + description: The URL of the cluster, will be used for the active-active + database URL. + type: string + dbFqdnSuffix: + description: The database URL suffix, will be used for the active-active + database replication endpoint and replication endpoint SNI. + type: string + recNamespace: + description: The namespace of the REC that the RERC is pointing at + type: string + recName: + description: The name of the REC that the RERC is pointing at + type: string + secretName: + description: 'The name of the secret containing cluster credentials. + Must be of the following format: "redis-enterprise-"' + type: string + required: + - apiFqdnUrl + - recName + - recNamespace + type: object + type: object +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: redisenterpriseactiveactivedatabases.app.redislabs.com + labels: + app: redis-enterprise +spec: + group: app.redislabs.com + names: + kind: RedisEnterpriseActiveActiveDatabase + listKind: RedisEnterpriseActiveActiveDatabaseList + plural: redisenterpriseactiveactivedatabases + singular: redisenterpriseactiveactivedatabase + shortNames: + - reaadb + preserveUnknownFields: false + scope: Namespaced + versions: + - name: v1alpha1 + served: true + storage: true + additionalPrinterColumns: + - jsonPath: .status.status + name: Status + type: string + - jsonPath: .status.specStatus + name: Spec Status + type: string + - jsonPath: .status.linkedRedbs[*] + name: Linked REDBs + type: string + - jsonPath: .status.replicationStatus + name: Replication Status + type: string + subresources: + status: {} + schema: + openAPIV3Schema: + description: RedisEnterpriseActiveActiveDatabase is the Schema for the redisenterpriseactiveactivedatabase + API + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + status: + description: RedisEnterpriseActiveActiveDatabaseStatus defines the observed + state of RedisEnterpriseActiveActiveDatabase + properties: + status: + description: The status of the active active database. + type: string + specStatus: + description: Whether the desired specification is valid + type: string + linkedRedbs: + description: The linked REDBs. + items: + type: string + type: array + participatingClusters: + description: The list of instances/ clusters statuses. + items: + description: Status of participating cluster. + properties: + name: + description: The name of the remote cluster CR that is linked. + type: string + id: + description: The corresponding ID of the instance in the active-active database. + format: int64 + type: integer + replicationStatus: + description: The replication status of the participating cluster + enum: + - up + - down + type: string + required: + - name + type: object + type: array + guid: + description: The active-active database corresponding GUID. + type: string + lastTaskUid: + description: The last active-active database task UID. + type: string + redisEnterpriseCluster: + description: The Redis Enterprise Cluster Object this Resource is associated + with + type: string + replicationStatus: + description: The overall replication status + enum: + - up + - down + type: string + secretsStatus: + description: The status of the secrets + items: + description: Status of secrets. + properties: + name: + description: The name of the secret. + type: string + status: + description: The status of the secret. + enum: + - Valid + - Invalid + type: string + required: + - name + type: object + type: array + type: object + spec: + description: RedisEnterpriseActiveActiveDatabaseSpec defines the desired + state of RedisEnterpriseActiveActiveDatabase + properties: + redisEnterpriseCluster: + description: Connection to Redis Enterprise Cluster + properties: + name: + description: The name of the Redis Enterprise Cluster where the + database should be stored. + type: string + required: + - name + type: object + participatingClusters: + description: The list of instances/ clusters specifications and configurations. + items: + properties: + name: + description: The name of the remote cluster CR to link. + type: string + required: + - name + type: object + type: array + globalConfigurations: + description: The Active-Active database global configurations, + contains the global properties for each of the participating clusters/ instances databases within the Active-Active database. + properties: + activeActive: + description: Connection/ association to the Active-Active database. + properties: + name: + description: 'The the corresponding Active-Active database name, + Redis Enterprise Active Active Database custom resource name, + this Resource is associated with. In case this resource is + created manually at the active active database creation this + field must be filled via the user, otherwise, the operator + will assign this field automatically. Note: this feature is + currently unsupported.' + type: string + participatingClusterName: + description: 'The corresponding participating cluster name, + Redis Enterprise Remote Cluster custom resource name, in the + Active-Active database, In case this resource is created manually + at the active active database creation this field must be + filled via the user, otherwise, the operator will assign this + field automatically. Note: this feature is currently unsupported.' + type: string + required: + - name + - participatingClusterName + type: object + alertSettings: + description: Settings for database alerts + properties: + bdb_backup_delayed: + description: Periodic backup has been delayed for longer than + specified threshold value [minutes] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_crdt_src_high_syncer_lag: + description: Active-active source - sync lag is higher than + specified threshold value [seconds] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_crdt_src_syncer_connection_error: + description: Active-active source - sync has connection error + while trying to connect replica source + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_crdt_src_syncer_general_error: + description: Active-active source - sync encountered in general + error + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_high_latency: + description: Latency is higher than specified threshold value + [micro-sec] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_high_throughput: + description: Throughput is higher than specified threshold + value [requests / sec.] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_long_running_action: + description: An alert for state-machines that are running + for too long + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_low_throughput: + description: Throughput is lower than specified threshold + value [requests / sec.] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_ram_dataset_overhead: + description: Dataset RAM overhead of a shard has reached the + threshold value [% of its RAM limit] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_ram_values: + description: Percent of values kept in a shard's RAM is lower + than [% of its key count] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_replica_src_high_syncer_lag: + description: Replica-of source - sync lag is higher than specified + threshold value [seconds] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_replica_src_syncer_connection_error: + description: Replica-of source - sync has connection error + while trying to connect replica source + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_shard_num_ram_values: + description: Number of values kept in a shard's RAM is lower + than [values] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + bdb_size: + description: Dataset size has reached the threshold value + [% of the memory limit] + properties: + enabled: + description: Alert enabled or disabled + type: boolean + threshold: + description: Threshold for alert going on/off + type: string + required: + - enabled + - threshold + type: object + type: object + backup: + description: Target for automatic database backups. + properties: + abs: + properties: + absSecretName: + description: The name of the secret that holds ABS credentials. + The secret must contain the keys "AccountName" and "AccountKey", + and these must hold the corresponding credentials + type: string + container: + description: Azure Blob Storage container name. + type: string + subdir: + description: Optional. Azure Blob Storage subdir under + container. + type: string + required: + - absSecretName + - container + type: object + ftp: + properties: + url: + description: a URI of the "ftps://[USER[:PASSWORD]@]HOST[:PORT]/PATH[/]" + format + type: string + required: + - url + type: object + gcs: + description: GoogleStorage + properties: + bucketName: + description: Google Storage bucket name. + type: string + gcsSecretName: + description: The name of the secret that holds the Google + Cloud Storage credentials. The secret must contain the + keys "CLIENT_ID", "PRIVATE_KEY", "PRIVATE_KEY_ID", "CLIENT_EMAIL" + and these must hold the corresponding credentials. The + keys should correspond to the values in the key JSON. + type: string + subdir: + description: Optional. Google Storage subdir under bucket. + type: string + required: + - bucketName + - gcsSecretName + type: object + interval: + description: Backup Interval in seconds + type: integer + mount: + description: MountPointStorage + properties: + path: + description: Path to the local mount point. You must create + the mount point on all nodes, and the redislabs:redislabs + user must have read and write permissions on the local + mount point. + type: string + required: + - path + type: object + s3: + properties: + awsSecretName: + description: The name of the secret that holds the AWS + credentials. The secret must contain the keys "AWS_ACCESS_KEY_ID" + and "AWS_SECRET_ACCESS_KEY", and these must hold the + corresponding credentials. + type: string + bucketName: + description: Amazon S3 bucket name. + type: string + subdir: + description: Optional. Amazon S3 subdir under bucket. + type: string + required: + - awsSecretName + - bucketName + type: object + sftp: + properties: + sftp_url: + description: SFTP url + type: string + sftpSecretName: + description: The name of the secret that holds SFTP credentials. + The secret must contain the "Key" key, which is the + SSH private key for connecting to the sftp server. + type: string + required: + - sftpSecretName + - sftp_url + type: object + swift: + properties: + auth_url: + description: Swift service authentication URL. + type: string + container: + description: Swift object store container for storing + the backup files. + type: string + prefix: + description: Optional. Prefix (path) of backup files in + the swift container. + type: string + swiftSecretName: + description: 'The name of the secret that holds Swift + credentials. The secret must contain the keys "Key" + and "User", and these must hold the corresponding credentials: + service access key and service user name (pattern for + the latter does not allow special characters &,<,>,")' + type: string + required: + - auth_url + - container + - swiftSecretName + type: object + type: object + clientAuthenticationCertificates: + description: The Secrets containing TLS Client Certificate to + use for Authentication + items: + type: string + type: array + dataInternodeEncryption: + description: Internode encryption (INE) setting. An optional boolean + setting, overriding a similar cluster-wide policy. If set to + False, INE is guaranteed to be turned off for this DB (regardless + of cluster-wide policy). If set to True, INE will be turned + on, unless the capability is not supported by the DB ( in such + a case we will get an error and database creation will fail). + If left unspecified, will be disabled if internode encryption + is not supported by the DB (regardless of cluster default). + Deleting this property after explicitly setting its value shall + have no effect. + type: boolean + databasePort: + description: Database port number. TCP port on which the database + is available. Will be generated automatically if omitted. can + not be changed after creation + type: integer + databaseSecretName: + description: The name of the secret that holds the password to + the database (redis databases only). If secret does not exist, + it will be created. To define the password, create an opaque + secret and set the name in the spec. The password will be taken + from the value of the 'password' key. Use an empty string as + value within the secret to disable authentication for the database. + Note - memcached databases must not be set with a value, and + a secret/password will not be automatically created for them. + Use the memcachedSaslSecretName field to set authentication + parameters for memcached databases. + type: string + defaultUser: + description: Is connecting with a default user allowed? If disabled, + the DatabaseSecret will not be created or updated + type: boolean + evictionPolicy: + description: Database eviction policy. see more https://docs.redislabs.com/latest/rs/administering/database-operations/eviction-policy/ + type: string + isRof: + description: Whether it is an RoF database or not. Applicable + only for databases of type "REDIS". Assumed to be false if left + blank. + type: boolean + memcachedSaslSecretName: + description: Credentials used for binary authentication in memcached + databases. The credentials should be saved as an opaque secret + and the name of that secret should be configured using this + field. For username, use 'username' as the key and the actual + username as the value. For password, use 'password' as the key + and the actual password as the value. Note that connections + are not encrypted. + type: string + memorySize: + description: memory size of database. use formats like 100MB, + 0.1GB. minimum value in 100MB. When redis on flash (RoF) is + enabled, this value refers to RAM+Flash memory, and it must + not be below 1GB. + type: string + modulesList: + description: List of modules associated with database. + Note - For Active-Active databases this feature is currently in preview. For + this feature to take effect for Active-Active databases, set a boolean environment variable + with the name "ENABLE_ALPHA_FEATURES" to True. This variable can + be set via the redis-enterprise-operator pod spec, or through the + operator-environment-config Config Map. + items: + description: 'Redis Enterprise Module: https://redislabs.com/redis-enterprise/modules/' + properties: + config: + description: Module command line arguments e.g. VKEY_MAX_ENTITY_COUNT + 30 + type: string + name: + description: The module's name e.g "ft" for redissearch + type: string + uid: + description: Module's uid - do not set, for system use only + nolint:staticcheck // custom json tag unknown to the linter + type: string + version: + description: Module's semantic version e.g "1.6.12" + type: string + required: + - name + - version + type: object + type: array + ossCluster: + description: OSS Cluster mode option. Note that not all client + libraries support OSS cluster mode. + type: boolean + persistence: + description: Database on-disk persistence policy + enum: + - disabled + - aofEverySecond + - aofAlways + - snapshotEvery1Hour + - snapshotEvery6Hour + - snapshotEvery12Hour + type: string + proxyPolicy: + description: 'The policy used for proxy binding to the endpoint. + Supported proxy policies are: single/all-master-shards/all-nodes + When left blank, the default value will be chosen according + to the value of ossCluster - single if disabled, all-master-shards + when enabled' + type: string + rackAware: + description: 'Whether database should be rack aware. This improves + availability - more information: https://docs.redislabs.com/latest/rs/concepts/high-availability/rack-zone-awareness/' + type: boolean + redisEnterpriseCluster: + description: Connection to Redis Enterprise Cluster + properties: + name: + description: The name of the Redis Enterprise Cluster where + the database should be stored. + type: string + required: + - name + type: object + redisVersion: + description: Redis OSS version. For existing databases - Upgrade + Redis OSS version. For new databases - the version which the + database will be created with. If set to 'major' - will always + upgrade to the most recent major Redis version. If set to 'latest' + - will always upgrade to the most recent Redis version. Depends + on 'redisUpgradePolicy' - if you want to set the value to 'latest' + for some databases, you must set redisUpgradePolicy on the cluster + before. Possible values are 'major' or 'latest' When using upgrade + - make sure to backup the database before. This value is used + only for database type 'redis' + enum: + - major + - latest + type: string + replicaSources: + description: What databases to replicate from + items: + properties: + clientKeySecret: + description: 'Secret that defines the client certificate + and key used by the syncer in the target database cluster. + The secret must have 2 keys in its map: "cert" which is + the PEM encoded certificate, and "key" which is the PEM + encoded private key.' + type: string + compression: + description: GZIP compression level (0-6) to use for replication. + type: integer + replicaSourceName: + description: The name of the resource from which the source + database URI is derived. The type of resource must match + the type specified in the ReplicaSourceType field. + type: string + replicaSourceType: + description: The type of resource from which the source + database URI is derived. If set to 'SECRET', the source + database URI is derived from the secret named in the ReplicaSourceName + field. The secret must have a key named 'uri' that defines + the URI of the source database in the form of 'redis://...'. + The type of secret (kubernetes, vault, ...) is determined + by the secret mechanism used by the underlying REC object. + If set to 'REDB', the source database URI is derived from + the RedisEnterpriseDatabase resource named in the ReplicaSourceName + field. + type: string + serverCertSecret: + description: 'Secret that defines the server certificate + used by the proxy in the source database cluster. The + secret must have 1 key in its map: "cert" which is the + PEM encoded certificate.' + type: string + tlsSniName: + description: TLS SNI name to use for the replication link. + type: string + required: + - replicaSourceName + - replicaSourceType + type: object + type: array + replication: + description: In-memory database replication. When enabled, database + will have replica shard for every master - leading to higher + availability. + type: boolean + rofRamSize: + description: The size of the RAM portion of an RoF database. Similarly + to "memorySize" use formats like 100MB, 0.1GB It must be at + least 10% of combined memory size (RAM+Flash), as specified + by "memorySize". + type: string + rolesPermissions: + description: List of Redis Enteprise ACL and Role bindings to + apply + items: + description: Redis Enterprise Role and ACL Binding + properties: + acl: + description: 'Acl Name of RolePermissionType (note: use + exact name of the ACL from the Redis Enterprise ACL list, + case sensitive)' + type: string + role: + description: 'Role Name of RolePermissionType (note: use + exact name of the role from the Redis Enterprise role + list, case sensitive)' + type: string + type: + description: Type of Redis Enterprise Database Role Permission + type: string + required: + - acl + - role + - type + type: object + type: array + shardCount: + description: Number of database server-side shards + type: integer + shardsPlacement: + description: Control the density of shards - should they reside + on as few or as many nodes as possible. Available options are + "dense" or "sparse". If left unset, defaults to "dense". + type: string + tlsMode: + description: Require SSL authenticated and encrypted connections + to the database. enabled - all incoming connections to the Database + must use SSL. disabled - no incoming connection to the Database + should use SSL. replica_ssl - databases that replicate from + this one need to use SSL. + enum: + - disabled + - enabled + - replica_ssl + type: string + type: + description: The type of the database. + enum: + - redis + - memcached + type: string + type: object + required: + - participatingClusters + type: object + type: object +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -15476,6 +16464,8 @@ spec: selector: matchLabels: name: redis-enterprise-operator + strategy: + type: Recreate template: metadata: labels: @@ -15485,11 +16475,12 @@ spec: serviceAccountName: redis-enterprise-operator containers: - name: redis-enterprise-operator - image: registry.connect.redhat.com/redislabs/redis-enterprise-operator:6.4.2-5 + image: registry.connect.redhat.com/redislabs/redis-enterprise-operator:6.4.2-6 securityContext: runAsUser: 1001 command: - - redis-enterprise-operator + - operator-root + - operator imagePullPolicy: Always envFrom: - configMapRef: @@ -15531,9 +16522,10 @@ spec: port: 8080 scheme: HTTP - name: admission - image: registry.connect.redhat.com/redislabs/redis-enterprise-operator:6.4.2-5 + image: registry.connect.redhat.com/redislabs/redis-enterprise-operator:6.4.2-6 command: - - /usr/local/bin/admission + - operator-root + - admission imagePullPolicy: Always envFrom: - configMapRef: diff --git a/openshift/operator_rhel.yaml b/openshift/operator_rhel.yaml index 2cb0f66..5595eaa 100644 --- a/openshift/operator_rhel.yaml +++ b/openshift/operator_rhel.yaml @@ -9,6 +9,8 @@ spec: selector: matchLabels: name: redis-enterprise-operator + strategy: + type: Recreate template: metadata: labels: @@ -18,11 +20,12 @@ spec: serviceAccountName: redis-enterprise-operator containers: - name: redis-enterprise-operator - image: registry.connect.redhat.com/redislabs/redis-enterprise-operator:6.4.2-5 + image: registry.connect.redhat.com/redislabs/redis-enterprise-operator:6.4.2-6 securityContext: runAsUser: 1001 command: - - redis-enterprise-operator + - operator-root + - operator imagePullPolicy: Always envFrom: - configMapRef: @@ -64,9 +67,10 @@ spec: port: 8080 scheme: HTTP - name: admission - image: registry.connect.redhat.com/redislabs/redis-enterprise-operator:6.4.2-5 + image: registry.connect.redhat.com/redislabs/redis-enterprise-operator:6.4.2-6 command: - - /usr/local/bin/admission + - operator-root + - admission imagePullPolicy: Always envFrom: - configMapRef: diff --git a/openshift/rec_rhel.yaml b/openshift/rec_rhel.yaml index 35391ef..d22f73a 100644 --- a/openshift/rec_rhel.yaml +++ b/openshift/rec_rhel.yaml @@ -9,7 +9,7 @@ spec: nodes: 3 redisEnterpriseImageSpec: repository: registry.connect.redhat.com/redislabs/redis-enterprise - versionTag: 6.4.2-61.rhel8-openshift + versionTag: 6.4.2-81.rhel8-openshift redisEnterpriseServicesRiggerImageSpec: repository: registry.connect.redhat.com/redislabs/services-manager bootstrapperImageSpec: diff --git a/openshift/scc.yaml b/openshift/scc.yaml index eb0e802..828e819 100644 --- a/openshift/scc.yaml +++ b/openshift/scc.yaml @@ -1,7 +1,7 @@ apiVersion: security.openshift.io/v1 kind: SecurityContextConstraints metadata: - name: redis-enterprise-scc + name: redis-enterprise-scc-v2 annotations: kubernetes.io/description: redis-enterprise-scc is the minimal SCC needed to run Redis Enterprise nodes on Kubernetes. It provides the same features as restricted-v2 SCC, but allows pods to enable the SYS_RESOURCE capability, diff --git a/operator.yaml b/operator.yaml index 9738dc0..6baf047 100644 --- a/operator.yaml +++ b/operator.yaml @@ -9,6 +9,8 @@ spec: selector: matchLabels: name: redis-enterprise-operator + strategy: + type: Recreate template: metadata: labels: @@ -18,9 +20,10 @@ spec: serviceAccountName: redis-enterprise-operator containers: - name: redis-enterprise-operator - image: redislabs/operator:6.4.2-5 + image: redislabs/operator:6.4.2-6 command: - - redis-enterprise-operator + - operator-root + - operator imagePullPolicy: Always envFrom: - configMapRef: @@ -60,9 +63,10 @@ spec: port: 8080 scheme: HTTP - name: admission - image: redislabs/operator:6.4.2-5 + image: redislabs/operator:6.4.2-6 command: - - /usr/local/bin/admission + - operator-root + - admission imagePullPolicy: Always envFrom: - configMapRef: diff --git a/redis_enterprise_active_active_database_api.md b/redis_enterprise_active_active_database_api.md index 06307fb..7e208b1 100644 --- a/redis_enterprise_active_active_database_api.md +++ b/redis_enterprise_active_active_database_api.md @@ -13,6 +13,7 @@ This document describes the parameters for the Redis Enterprise Active Active Da * [Enums](#enums) * [ActiveActiveDatabaseSecretStatus](#activeactivedatabasesecretstatus) * [ActiveActiveDatabaseStatus](#activeactivedatabasestatus) + * [ReplicationStatus](#replicationstatus) ## Objects ### ParticipatingCluster @@ -30,6 +31,7 @@ Status of participating cluster. | ----- | ----------- | ------ | -------- | -------- | | name | The name of the remote cluster CR that is linked. | string | | true | | id | The corresponding ID of the instance in the active-active database. | *int64 | | false | +| replicationStatus | The replication status of the participating cluster | [ReplicationStatus](#replicationstatus) | | false | [Back to Table of Contents](#table-of-contents) ### RedisEnterpriseActiveActiveDatabase @@ -67,7 +69,7 @@ RedisEnterpriseActiveActiveDatabaseStatus defines the observed state of RedisEnt | Field | Description | Scheme | Default Value | Required | | ----- | ----------- | ------ | -------- | -------- | | specStatus | Whether the desired specification is valid | [SpecStatusName](#specstatusname) | | false | -| status | The status of the active active database. | [ActiveActiveDatabaseStatus](#activeactivedatabasestatus) | | false | +| status | The status of the active active database. This status does not include the replication link (data-path) status For the replication link status please view the 'Replication Status' or the 'status.replicationStatus' on the custom resource. | [ActiveActiveDatabaseStatus](#activeactivedatabasestatus) | | false | | participatingClusters | The list of instances/ clusters statuses. | []*[ParticipatingClusterStatus](#participatingclusterstatus) | | false | | globalConfigurations | The active-active default global configurations linked REDB | string | | false | | linkedRedbs | The linked REDBs. | []string | | false | @@ -75,6 +77,7 @@ RedisEnterpriseActiveActiveDatabaseStatus defines the observed state of RedisEnt | lastTaskUid | The last active-active database task UID. | string | | false | | redisEnterpriseCluster | The Redis Enterprise Cluster Object this Resource is associated with | string | | false | | secretsStatus | The status of the secrets | []*[SecretStatus](#secretstatus) | | false | +| replicationStatus | The overall replication status | [ReplicationStatus](#replicationstatus) | | false | [Back to Table of Contents](#table-of-contents) ### SecretStatus @@ -107,3 +110,11 @@ Status of secrets. | "error" | Active-active database is in recovery. ActiveActiveDatabaseStatusRecovery ActiveActiveDatabaseStatus = "recovery" Active-active database status error. | | "" | Active-active database status unknown. | [Back to Table of Contents](#table-of-contents) + +### ReplicationStatus + +| Value | Description | +| ----- | ----------- | +| "up" | | +| "down" | | +[Back to Table of Contents](#table-of-contents) diff --git a/redis_enterprise_cluster_api.md b/redis_enterprise_cluster_api.md index 503c7ce..3160a92 100644 --- a/redis_enterprise_cluster_api.md +++ b/redis_enterprise_cluster_api.md @@ -108,11 +108,12 @@ Customization options for the REC API service. [Back to Table of Contents](#table-of-contents) ### ContainerTimezoneSpec -Used to set the timezone across all redis enterprise containers. +Used to set the timezone across all redis enterprise containers - You can either propagate the hosts timezone to RS pods or set it manually via timezoneName. | Field | Description | Scheme | Default Value | Required | | ----- | ----------- | ------ | -------- | -------- | -| propagateHost | Identifies that container timezone should be in sync with the host. | *[PropagateHost](#propagatehost) | | false | +| propagateHost | Identifies that container timezone should be in sync with the host, this option mounts a hostPath volume onto RS pods that could be restricted in some systems. | *[PropagateHost](#propagatehost) | | false | +| timezoneName | POSIX-style timezone name as a string to be passed as EnvVar to RE pods, e.g. "Europe/London". | string | | false | [Back to Table of Contents](#table-of-contents) ### CrdbCoordinator @@ -339,7 +340,7 @@ RedisEnterpriseClusterSpec defines the desired state of RedisEnterpriseCluster | redisEnterpriseAdditionalPodSpecAttributes | ADVANCED USAGE USE AT YOUR OWN RISK - specify pod attributes that are required for the statefulset - Redis Enterprise pods. Pod attributes managed by the operator might override these settings. Also make sure the attributes are supported by the K8s version running on the cluster - the operator does not validate that. | *[v1.PodSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#podspec-v1-core) | | false | | license | Redis Enterprise License | string | Empty string which is a [Trial Mode licesne](https://docs.redislabs.com/latest/rs/administering/cluster-operations/settings/license-keys/#trial-mode) | false | | licenseSecretName | K8s secret or Vault Secret Name/Path to use for Cluster License. When left blank, the license is read from the "license" field. Note that you can't specify non-empty values in both "license" and "licenseSecretName", only one of these fields can be used to pass the license string. The license needs to be stored under the key "license". | string | Empty string | false | -| username | Username for the admin user of Redis Enterprise | string | demo@redislabs.com | false | +| username | Username for the admin user of Redis Enterprise | string | demo@redis.com | false | | nodeSelector | Selector for nodes that could fit Redis Enterprise pod | *map[string]string | | false | | redisEnterpriseImageSpec | Specification for Redis Enterprise container image | *[ImageSpec](#imagespec) | the default Redis Enterprise image for this version | false | | redisEnterpriseServicesRiggerImageSpec | Specification for Services Rigger container image | *[ImageSpec](#imagespec) | the default Services Rigger image for this version | false | @@ -360,9 +361,11 @@ RedisEnterpriseClusterSpec defines the desired state of RedisEnterpriseCluster | clusterRecovery | ClusterRecovery initiates cluster recovery when set to true. Note that this field is cleared automatically after the cluster is recovered | *bool | | false | | rackAwarenessNodeLabel | Node label that specifies rack ID - if specified, will create rack aware cluster. Rack awareness requires node label must exist on all nodes. Additionally, operator needs a special cluster role with permission to list nodes. | string | | false | | priorityClassName | Adds the priority class to pods managed by the operator | string | | false | +| hostAliases | Adds hostAliases entries to the Redis Enterprise pods | []v1.HostAlias | | false | | volumes | additional volumes | [][v1.Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#volume-v1-core) | | false | | redisEnterpriseVolumeMounts | additional volume mounts within the redis enterprise containers | [][v1.VolumeMount](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#volumemount-v1-core) | | false | -| podAnnotations | pod annotations | map[string]string | | false | +| podAnnotations | annotations for the service rigger and redis enterprise pods | map[string]string | | false | +| redisEnterprisePodAnnotations | annotations for redis enterprise pod | map[string]string | | false | | podTolerations | Tolerations that are added to all managed pods. for more information: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ | [][v1.Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#toleration-v1-core) | empty | false | | slaveHA | Slave high availability mechanism configuration. | *[SlaveHA](#slaveha) | | false | | clusterCredentialSecretName | Secret Name/Path to use for Cluster Credentials. To be used only if ClusterCredentialSecretType is vault. If left blank, will use cluster name. | string | | false | @@ -379,9 +382,10 @@ RedisEnterpriseClusterSpec defines the desired state of RedisEnterpriseCluster | ocspConfiguration | An API object that represents the cluster's OCSP configuration. To enable OCSP, the cluster's proxy certificate should contain the OCSP responder URL. | *[OcspConfiguration](#ocspconfiguration) | | false | | encryptPkeys | Private key encryption Possible values: true/false | *bool | | false | | containerTimezone | Container timezone configuration. While the default timezone on all containers is UTC, this setting can be used to set the timezone on services rigger/bootstrapper/RS containers. Currently the only supported value is to propagate the host timezone to all containers. | *[ContainerTimezoneSpec](#containertimezonespec) | | false | -| ingressOrRouteSpec | Access configurations for the Redis Enterprise Cluster and Databases. Note - this feature is currently in preview. For this feature to take effect, set a boolean environment variable with the name "ENABLE_ALPHA_FEATURES" to True. This variable can be set via the redis-enterprise-operator pod spec, or through the operator-environment-config Config Map. At most one of ingressOrRouteSpec or activeActive fields can be set at the same time. | *[IngressOrRouteSpec](#ingressorroutespec) | | false | +| ingressOrRouteSpec | Access configurations for the Redis Enterprise Cluster and Databases. At most one of ingressOrRouteSpec or activeActive fields can be set at the same time. | *[IngressOrRouteSpec](#ingressorroutespec) | | false | | services | Customization options for operator-managed service resources created for Redis Enterprise clusters and databases | *[Services](#services) | | false | | ldap | Cluster-level LDAP configuration, such as server addresses, protocol, authentication and query settings. | *[LDAPSpec](#ldapspec) | | false | +| extraEnvVars | ADVANCED USAGE: use carefully. Add environment variables to RS StatefulSet's containers. | []v1.EnvVar | | false | [Back to Table of Contents](#table-of-contents) ### RedisEnterpriseClusterStatus @@ -446,9 +450,10 @@ Specification for service rigger | Field | Description | Scheme | Default Value | Required | | ----- | ----------- | ------ | -------- | -------- | | databaseServiceType | Service types for access to databases. should be a comma separated list. The possible values are cluster_ip, headless and load_balancer. | string | cluster_ip,headless | true | -| serviceNaming | | string | | true | +| serviceNaming | Used to determine how to name the services created automatically when a database is created. When bdb_name is used, the database name will be also used for the service name. When redis-port is used, the service will be named redis- | string | bdb_name | true | | extraEnvVars | | []v1.EnvVar | | false | | servicesRiggerAdditionalPodSpecAttributes | ADVANCED USAGE USE AT YOUR OWN RISK - specify pod attributes that are required for the rigger deployment pod. Pod attributes managed by the operator might override these settings (Containers, serviceAccountName, podTolerations, ImagePullSecrets, nodeSelector, PriorityClassName, PodSecurityContext). Also make sure the attributes are supported by the K8s version running on the cluster - the operator does not validate that. | *[v1.PodSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#podspec-v1-core) | | false | +| podAnnotations | annotations for the service rigger pod | map[string]string | | false | [Back to Table of Contents](#table-of-contents) ### SlaveHA diff --git a/redis_enterprise_database_api.md b/redis_enterprise_database_api.md index d827709..56708db 100644 --- a/redis_enterprise_database_api.md +++ b/redis_enterprise_database_api.md @@ -201,7 +201,7 @@ RedisEnterpriseDatabaseSpec defines the desired state of RedisEnterpriseDatabase | replicaSources | What databases to replicate from | [][ReplicaSource](#replicasource) | | false | | alertSettings | Settings for database alerts | *[DbAlertsSettings](#dbalertssettings) | | false | | backup | Target for automatic database backups. | *[BackupSpec](#backupspec) | | false | -| modulesList | List of modules associated with database | *[][DbModule](#dbmodule) | | false | +| modulesList | List of modules associated with database. Note - For Active-Active databases this feature is currently in preview. For this feature to take effect for Active-Active databases, set a boolean environment variable with the name "ENABLE_ALPHA_FEATURES" to True. This variable can be set via the redis-enterprise-operator pod spec, or through the operator-environment-config Config Map. | *[][DbModule](#dbmodule) | | false | | rolesPermissions | List of Redis Enteprise ACL and Role bindings to apply | [][RolePermission](#rolepermission) | | false | | defaultUser | Is connecting with a default user allowed? If disabled, the DatabaseSecret will not be created or updated | *bool | true | false | | ossCluster | OSS Cluster mode option. Note that not all client libraries support OSS cluster mode. | *bool | false | false | diff --git a/setting_ingress_or_route_readme.md b/setting_ingress_or_route_readme.md index b3876a6..9037a36 100644 --- a/setting_ingress_or_route_readme.md +++ b/setting_ingress_or_route_readme.md @@ -72,13 +72,7 @@ For example, wildcard DB FQDN suffix DNS of a REC named "rec1", with the namespa On the namespace where the REC resides, do the following: -1. Add the following environment variables to enable alpha features on the Redis Enterprise operator Configmap: -``` - kubectl patch cm operator-environment-config --type merge --patch "{\"data\": \ - {\"ENABLE_ALPHA_FEATURES\":\"true\"}}" -``` - -2. Configure the Ingress controller or Openshift Routes configurations via the 'ingressOrRouteSpec' field on the REC spec. +Please configure the Ingress controller or Openshift Routes configurations via the 'ingressOrRouteSpec' field on the REC spec. For example, configuring a Nginx ingress via the above configurations on a REC named "rec1" with the namespace "ns1": ``` kubectl patch rec rec1 --type merge --patch "{\"spec\": \ diff --git a/vault/README.md b/vault/README.md index 85f1d57..bb5ddfe 100644 --- a/vault/README.md +++ b/vault/README.md @@ -19,6 +19,9 @@ How to use Hashicorp Vault as a source for secrets: 6. [ Deploy REDB admission Controller ](#redb-admission) 7. [ Creating an REDB](#deployment_redb) 8. [ REDB secrets ](#redb_secrets) +9. [ RERC secrets ](#rerc_secrets) +10. [ REAADB secrets ](#reaadb_secrets) + > Note: when using Openshift it might be recommended to use oc instead of kubectl @@ -264,3 +267,10 @@ An REDB has several secrets associate with it as detailed here.
4. [Client Auth](../redis_enterprise_database_api.md#redisenterprisedatabasespec) (optional) - The Secrets containing TLS Client Certificate to use for Authentication > The full and detailed REDB fields documentation can be found [here](../redis_enterprise_database_api.md#redisenterprisedatabasespec) + +### RERC secrets +The secretName field is supported and should be stored in Hashicorp Vault if the Redis Enterprise Cluster uses Hashicorp Vault as a secret source. + + +### REAADB secrets +A REDB specification is built into REAADB (the globalConfigurations field). All secret names specified there are supported and should be stored in Hashicorp Vault if the Redis Enterprise Cluster uses Hashicorp Vault as a secret source. \ No newline at end of file