From b038b9df6a355d0ce8bae3211829d123e0182837 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Mon, 1 Jun 2026 14:54:37 +0200 Subject: [PATCH 01/22] K8SPSMDB-1533 Documented naming conventions for Helm install (#330) * K8SPSMDB-1533 Documented naming conventions for Helm install modified: docs/custom-install.md modified: docs/helm.md --- docs/custom-install.md | 117 ++++++++++++++++++++++++++++------------- docs/helm.md | 18 +++++-- 2 files changed, 95 insertions(+), 40 deletions(-) diff --git a/docs/custom-install.md b/docs/custom-install.md index c9993594..fc36d473 100644 --- a/docs/custom-install.md +++ b/docs/custom-install.md @@ -1,4 +1,4 @@ -# Install Percona Server for MongoDB with customized parameters +# Install Percona Operator for MongoDB with customized parameters You can customize the configuration of Percona Server for MongoDB and install it with customized parameters. @@ -22,53 +22,96 @@ To check available configuration options, see [`deploy/cr.yaml` :octicons-link- === "Helm" - To install Percona Server for MongoDB with custom parameters, use the following command: + You can install the Operator deployment and Percona Server for MongoDB clusters with custom parameters using Helm. You can review the available configuration options for the [Operator chart :octicons-link-external-16:](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-operator#installing-the-chart) and the [Database chart :octicons-link-external-16:](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-db#installing-the-chart). + + You can provide custom parameters to Helm using either the `--set` flag or a `values.yaml` file. The `--set` flag is suitable for overriding a small number of parameters directly from the command line, while a `values.yaml` file is ideal when you want to manage many custom settings together. Both methods are fully supported by Helm and can be used as preferred for your deployment. + **Using `--set` flags** + + To pass a custom parameter to Helm, use the `--set key=value` flag with the `helm install` command. + + For example, to enable [Percona Monitoring and Management (PMM) :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/index.html) for the database cluster, run: + ```bash - helm install --set key=value + helm install my-db percona/psmdb-db --version {{ release }} --namespace my-namespace \ + --set pmm.enabled=true ``` - You can pass any of the Operator’s [Custom Resource options :octicons-link-external-16:](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-db#installing-the-chart) as a - `--set key=value[,key=value]` argument. + **Using a `values.yaml` file** - The following example deploys a Percona Server for MongoDB Cluster in the - `psmdb` namespace, with disabled backups and 20 Gi storage: + Create a `values.yaml` file with your custom parameters and pass it to `helm install` with the `-f` or `--values` flag: - === "Command line" + ```bash + helm install my-db percona/psmdb-db --version {{ release }} --namespace my-namespace -f values.yaml + ``` - ```bash - helm install my-db percona/psmdb-db --version {{ release }} --namespace psmdb \ - --set "replsets.rs0.name=rs0" --set "replsets.rs0.size=3" \ - --set "replsets.rs0.volumeSpec.pvc.resources.requests.storage=20Gi" \ - --set backup.enabled=false --set sharding.enabled=false - ``` + Example `values.yaml`: - === "YAML file" + ```yaml + pmm: + enabled: false + image: + repository: percona/pmm-client + tag: {{ pmm3recommended }} + ``` - You can specify customized options in a YAML file instead of using separate command line parameters. The resulting - file similar to the following example looks as follows: + ## Naming conventions for Helm resources - ``` yaml title="values.yaml" - allowUnsafeConfigurations: true - sharding: - enabled: false - replsets: - - name: rs0 - size: 3 - volumeSpec: - pvc: - resources: - requests: - storage: 2Gi - backup: - enabled: false - ``` - - Apply the resulting YAML file as follows: + When you install a chart, Helm creates a release and uses the release name and chart name to generate resource names. By default, resources are named `release-name-chart-name`. - ```bash - helm install my-db percona/psmdb-db --namespace psmdb -f values.yaml - ``` + You can override the default naming with the `nameOverride` or `fullnameOverride` options. Pass them using the `--set` flag or in your `values.yaml` file. + + | Option | Effect | Example | + | ------ | ------ | ------- | + | `nameOverride` | Replaces the chart name but keeps the release name in the generated name | `release-name-name-override` | + | `fullnameOverride` | Replaces the entire generated name with the specified value | `fullname-override` | + + *Using `nameOverride`* — replaces the chart name but keeps the release name: + + ```bash + helm install my-operator percona/psmdb-operator --namespace my-namespace \ + --set nameOverride=mongo-operator + ``` + + Deployment name: `my-operator-mongo-operator`. + + ```bash + helm install cluster1 percona/psmdb-db -n my-namespace \ + --set nameOverride=mongodb + ``` + + Cluster name: `cluster1-mongodb`. + + *Using `fullnameOverride`* — replaces the full resource name: + + ```bash + helm install my-operator percona/psmdb-operator --namespace my-namespace \ + --set fullnameOverride=percona-mongodb-operator + ``` + + Deployment name: `percona-mongodb-operator`. + + ```bash + helm install cluster1 percona/psmdb-db -n my-namespace \ + --set fullnameOverride=my-db + ``` + + Cluster name: `my-db`. + + !!! note "Cluster name length" + + For the psmdb-db chart, keep release names and overrides short enough to satisfy Kubernetes resource name limits (for example, many DNS-label resource names such as Services are limited to 63 characters). + + ## Common Helm values reference + + The following table lists commonly used values for the Operator and database charts. For the full list of options, see the chart values files. + + | Value | Charts | Description | + | ----- | ------ | ----------- | + | `nameOverride` | [psmdb-operator](https://github.com/percona/percona-helm-charts/blob/main/charts/psmdb-operator/values.yaml), [psmdb-db](https://github.com/percona/percona-helm-charts/blob/main/charts/psmdb-db/values.yaml) | Replaces the chart name in generated resource names | + | `fullnameOverride` | [psmdb-operator](https://github.com/percona/percona-helm-charts/blob/main/charts/psmdb-operator/values.yaml), [psmdb-db](https://github.com/percona/percona-helm-charts/blob/main/charts/psmdb-db/values.yaml) | Replaces the entire generated resource name | + | `watchAllNamespaces` | [psmdb-operator](https://github.com/percona/percona-helm-charts/blob/main/charts/psmdb-operator/values.yaml) | Deploy the Operator in cluster-wide mode to watch all namespaces | + | `disableTelemetry` | [psmdb-operator](https://github.com/percona/percona-helm-charts/blob/main/charts/psmdb-operator/values.yaml) | Disable telemetry collection. See [Telemetry](telemetry.md) for details | ## Configure ports for MongoDB cluster components diff --git a/docs/helm.md b/docs/helm.md index 8fa87afc..a472a5df 100644 --- a/docs/helm.md +++ b/docs/helm.md @@ -5,11 +5,23 @@ A Helm [chart :octicons-link-external-16:](https://helm.sh/docs/topics/charts/) You can find Percona Helm charts in [percona/percona-helm-charts :octicons-link-external-16:](https://github.com/percona/percona-helm-charts) repository in GitHub. +Helm charts for Percona Server for MongoDB include: + +* [Percona Server for MongoDB Operator CRDs :octicons-link-external-16:](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-operator-crds) +* [Percona Server for MongoDB Operator Deployment :octicons-link-external-16:](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-operator) +* [Percona Server for MongoDB Database :octicons-link-external-16:](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-db) + +For a typical installation, you first install the Operator CRDs, then the Operator Deployment, and finally you use the Operator to deploy a Percona Server for MongoDB cluster. + +This guide walks you through installing the Percona Server for MongoDB Operator with default parameters and names. + +To install the Operator with custom parameters or resource names, refer to [Install Percona Operator for MongoDB with customized parameters](custom-install.md). + ## Prerequisites To install and deploy the Operator, you need the following: -1. [Helm v3 :octicons-link-external-16:](https://docs.helm.sh/using_helm/#installing-helm). +1. [Helm v3 :octicons-link-external-16:](https://docs.helm.sh/using_helm/#installing-helm). Run `helm version` to check the version. 2. [kubectl :octicons-link-external-16:](https://kubernetes.io/docs/tasks/tools/) command line utility. 3. A Kubernetes environment. You can deploy it locally on [Minikube :octicons-link-external-16:](https://github.com/kubernetes/minikube) for testing purposes or using any cloud provider of your choice. Check the list of our [officially supported platforms](System-Requirements.md#officially-supported-platforms). @@ -20,6 +32,7 @@ To install and deploy the Operator, you need the following: * [Set up Amazon Elastic Kubernetes Service](eks.md#prerequisites) * [Create and configure the AKS cluster](aks.md#create-and-configure-the-aks-cluster) +4. Privileges to create Custom Resource Definitions (CRDs), RBAC resources, and deploy the Operator. --8<-- "what-you-install.md" ## Installation @@ -117,8 +130,7 @@ Here's a sequence of steps to follow: You have successfully installed and deployed the Operator with default parameters. -You can find in the documentation for the charts which [Operator :octicons-link-external-16:](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-operator#installing-the-chart) and [database :octicons-link-external-16:](https://github.com/percona/percona-helm-charts/tree/main/charts/psmdb-db#installing-the-chart) parameters can be customized during installation. -Also, you can check the rest of the Operator's parameters in the [Custom Resource options reference](operator.md). + ## Next steps From 62650873a095343d3263dc708e584ce668a7e566 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Tue, 2 Jun 2026 12:23:18 +0200 Subject: [PATCH 02/22] K8SPSMDB-680 Documented disabling localhost authentication bypass (#327) * K8SPSMDB-680 Added new document on disabling localhost authentication bypass for Percona Server for MongoDB. - Updated options.md to reference the new localhost authentication bypass documentation. - Enhanced users.md to include a link to the new bypass documentation. new file: docs/auth-bypass-localhost.md modified: docs/options.md modified: docs/users.md modified: mkdocs-base.yml --- docs/auth-bypass-localhost.md | 77 +++++++++++++++++++++++++++++++++++ docs/options.md | 4 +- docs/users.md | 2 + mkdocs-base.yml | 6 ++- 4 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 docs/auth-bypass-localhost.md diff --git a/docs/auth-bypass-localhost.md b/docs/auth-bypass-localhost.md new file mode 100644 index 00000000..a6ac6509 --- /dev/null +++ b/docs/auth-bypass-localhost.md @@ -0,0 +1,77 @@ +# Disabling the Percona Server for MongoDB localhost exception + +By default, you can connect to Percona Server for MongoDB from `localhost` without authentication to perform administrative actions such as creating the first user. This is called the **localhost exception**. The Operator relies on this exception to bootstrap the cluster. + +After the Operator sets up the cluster and creates the system users, Percona Server for MongoDB itself closes the localhost exception. You can make the closure permanent, protecting against scenarios where the exception could otherwise re-open. + +The Percona Server for MongoDB parameter `enableLocalhostAuthBypass` controls whether the localhost exception is available. It is `true` by default. To disable it, set it in the `setParameter` block within the custom `configuration` section of the Custom Resource. + +## Considerations + +Here's what you need to know before disabling the localhost exception: + +1. Never disable the localhost exception when you create a new cluster. Setting `enableLocalhostAuthBypass: false` **before** the Operator creates system users prevents it from initializing the replica set. You will see repeated failures logged in the Operator. +2. Disabling localhost exception means you can no longer use it as a recovery mechanism if you lost all your admin credentials. Therefore, ensure you have working backups of the cluster data and the Kubernetes Secrets containing the cluster credentials. See [About backups](backups.md) and [System users](system-users.md). + +## Disable localhost authentication bypass on running clusters + +Perform the following steps on your **running** cluster. Review the [Considerations](#considerations) section for important information. + +1. Confirm that your cluster is running: + + ```bash + kubectl -n get psmdb -o jsonpath='{.status.state}' + ``` + + The command should return `ready`. See [Custom resource statuses](cr-statuses.md) for other possible values. + +2. Edit the `deploy/cr.yaml` Custom Resource manifest and add the `setParameter` block to the `configuration` section for each replica set: + + === "Non-sharded cluster" + + ```yaml + ... + spec: + ... + replsets: + - name: rs0 + configuration: | + setParameter: + enableLocalhostAuthBypass: false + ... + ``` + + === "Sharded cluster" + + For sharded clusters, apply the same block to every shard replica set and to the config server replica set: + + ```yaml + ... + spec: + ... + replsets: + - name: rs0 + configuration: | + setParameter: + enableLocalhostAuthBypass: false + sharding: + configsvrReplSet: + configuration: | + setParameter: + enableLocalhostAuthBypass: false + ... + ``` + +3. Apply the configuration: + + ```bash + kubectl apply -f deploy/cr.yaml -n + ``` + +4. Wait for the Operator to perform a rolling restart. Check the cluster status: + + ```bash + kubectl get psmdb -n + ``` + +For more information about Percona Server for MongoDB configuration options, see [Changing MongoDB options](options.md). diff --git a/docs/options.md b/docs/options.md index c0979635..ad4dd540 100644 --- a/docs/options.md +++ b/docs/options.md @@ -8,7 +8,9 @@ Then you pass these options to MongoDB instances in the cluster in one of the fo - [Use a ConfigMap](#use-a-configmap) - [Use a Secret object](#use-a-secret-object) -Note that you can't change options that may break the behavior of the Operator. For example, TLS/SSL options. If you try changing such options, your changes will be ignored. +Note that you can't change options that may break the behavior of the Operator. For example, TLS/SSL options. If you try changing such options, your changes will be ignored. + +Some options, such as `enableLocalhostAuthBypass`, can be set via `replsets.configuration` and, for sharded clusters, `sharding.configsvrReplSet.configuration`, but only on running clusters. Setting them before the cluster has bootstrapped prevents initialization. See [Disable localhost authentication bypass](auth-bypass-localhost.md) for details. ## Edit the `deploy/cr.yaml` file diff --git a/docs/users.md b/docs/users.md index d0a6635f..562570c8 100644 --- a/docs/users.md +++ b/docs/users.md @@ -22,6 +22,8 @@ For system users, the Operator creates the required Secret automatically when it Authentication is enabled in Percona Server for MongoDB clusters by default. If you need to disable authentication for development, testing, or migration purposes, see [Disable authentication](auth-disable.md). +Percona Server for MongoDB allows bypassing authentication by connecting from `localhost` to create the first user. To permanently disable the MongoDB localhost authentication bypass on a running cluster, see [Disable localhost authentication bypass](auth-bypass-localhost.md). + ### MongoDB internal authentication key (optional) *Default Secret name:* `my-cluster-name-mongodb-keyfile` diff --git a/mkdocs-base.yml b/mkdocs-base.yml index 629768ab..17589169 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -228,7 +228,10 @@ nav: - Manage system users with Vault: - "Overview": system-users-vault.md - "Configuration": system-users-vault-setup.md - - "Disable authentication": auth-disable.md + - Authentication: + - OpenLDAP integration: ldap.md + - "Disable authentication": auth-disable.md + - "Disable localhost authentication bypass": auth-bypass-localhost.md - "Changing MongoDB options": options.md - options-pbm.md - hookscript.md @@ -312,7 +315,6 @@ nav: - HOWTOs: - Install the database with customized parameters: custom-install.md - - "OpenLDAP integration": ldap.md - "How to use private registry": custom-registry.md - "Creating a private S3-compatible cloud for backups": private.md - "How to use backups to move the external database to Kubernetes": backups-move-from-external-db.md From 08c639a0578763dfd4b5a9deb9edb9899d8127f2 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Mon, 22 Jun 2026 11:30:05 +0200 Subject: [PATCH 03/22] K8SPSMDB-1635 Documented the option to configure PMM auth mechanism (#338) * K8SPSMDB-1635 Documented the option to configure PMM auth mechanism --- docs/operator.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/operator.md b/docs/operator.md index afe282da..a7f65b55 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -1883,6 +1883,14 @@ Address of the PMM Server to collect data from the Cluster. | ----------- | ---------- | | :material-code-string: string | `monitoring-service` | +### `pmm.authenticationMechanism` + +The authentication mechanism to use when establishing a connection to MongoDB for monitoring with PMM. Supported values are `SCRAM-SHA-256` and `SCRAM-SHA-1`. Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `SCRAM-SHA-256` | + ### `pmm.containerSecurityContext` A custom [Kubernetes Security Context for a Container :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) to be used instead of the default one. From 1e6df8b7b2352bbc563255ee86ff114d08ee5735 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Mon, 22 Jun 2026 15:58:57 +0200 Subject: [PATCH 04/22] K8SPSMDB-1669 IRSA doc improvements (#329) * K8SPSMDB-1669 IRSA doc improvements --- ...ckups-storage-s3-instance-profile-draft.md | 281 +++++++++ docs/backups-storage-s3.md | 536 ++++++++++++++++-- 2 files changed, 760 insertions(+), 57 deletions(-) create mode 100644 docs/backups-storage-s3-instance-profile-draft.md diff --git a/docs/backups-storage-s3-instance-profile-draft.md b/docs/backups-storage-s3-instance-profile-draft.md new file mode 100644 index 00000000..676a5378 --- /dev/null +++ b/docs/backups-storage-s3-instance-profile-draft.md @@ -0,0 +1,281 @@ +# Draft: IAM instance profile section for backups-storage-s3.md + +This file contains the proposed **Automate access to Amazon S3 using IAM instance profile** section. Replace lines 465–473 in `backups-storage-s3.md` with the content below (from `## Automate access` through the end of the instance profile section). + +--- + +## Automate access to Amazon S3 using IAM instance profile + +An [IAM instance profile :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) attaches an IAM role to EC2 instances. When your Kubernetes worker nodes run on EC2, Pods obtain AWS credentials through the [EC2 instance metadata service (IMDS) :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html). You do not store AWS access keys in a Kubernetes Secret. Instead, Percona Backup for MongoDB uses the AWS default credential provider chain and receives credentials from the worker node automatically. + +Use this method when your cluster runs on EC2 worker nodes and IRSA is not configured—for example, in self-managed Kubernetes clusters on EC2. All Pods on the same worker node share the node's IAM permissions. + +### Prerequisites + +Before you start, make sure you have the following: + +* A Kubernetes cluster whose worker nodes run on EC2 +* The [Operator and database deployed](kubectl.md), or ready to deploy +* An S3 bucket for backups +* The [AWS CLI :octicons-link-external-16:](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) and [kubectl :octicons-link-external-16:](https://kubernetes.io/docs/tasks/tools/) installed and configured +* Your AWS account ID. You can get it with: + + ```bash + aws sts get-caller-identity --query Account --output text + ``` + +Set environment variables for the commands below. Replace the placeholders with your values: + +```bash +export aws_region= +export s3_bucket= +export policy_name= +export role_name= +export instance_profile_name= +export namespace= +export account_id=$(aws sts get-caller-identity --query Account --output text) +``` + +### Configure the IAM role and instance profile +{.power-number} + +1. Create an IAM policy that grants access to your S3 bucket. Replace `` with your bucket name: + + ```json title="s3-bucket-policy.json" + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:*" + ], + "Resource": [ + "arn:aws:s3:::", + "arn:aws:s3:::/*" + ] + } + ] + } + ``` + + !!! tip + + The example uses broad `s3:*` permissions for simplicity. In production, restrict the policy to the specific S3 actions your backup and restore workflows require. Refer to the [Amazon S3 permissions documentation :octicons-link-external-16:](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html) and tailor the policy to follow the principle of least privilege. + +2. Create the IAM policy: + + ```bash + aws iam create-policy \ + --policy-name $policy_name \ + --policy-document file://s3-bucket-policy.json + ``` + +3. Create a trust policy that allows EC2 instances to assume the role: + + ```json title="ec2-trust-policy.json" + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + } + ``` + +4. Create the IAM role: + + ```bash + aws iam create-role \ + --role-name $role_name \ + --assume-role-policy-document file://ec2-trust-policy.json \ + --description "Allow EC2 worker nodes to access S3 backups" + ``` + +5. Attach the S3 policy to the role: + + ```bash + aws iam attach-role-policy \ + --role-name $role_name \ + --policy-arn arn:aws:iam::${account_id}:policy/${policy_name} + ``` + +6. Create an instance profile and add the role to it: + + ```bash + aws iam create-instance-profile \ + --instance-profile-name $instance_profile_name + + aws iam add-role-to-instance-profile \ + --instance-profile-name $instance_profile_name \ + --role-name $role_name + ``` + + !!! note "EKS clusters without IRSA" + + Amazon EKS worker nodes already have an instance profile through the node group IAM role. Instead of creating a new instance profile, attach the S3 policy from step 2 to the existing node group role. Skip steps 6–7 in the next section and apply the policy to that role. + +### Attach the instance profile to worker nodes +{.power-number} + +1. Attach the instance profile to each EC2 worker node in your cluster. The exact steps depend on how you manage your nodes: + + * **Self-managed clusters:** Attach the profile when you launch instances, or associate it with running instances: + + ```bash + aws ec2 associate-iam-instance-profile \ + --instance-id \ + --iam-instance-profile Name=$instance_profile_name + ``` + + * **Auto Scaling groups:** Update the launch template or Auto Scaling group to use `$instance_profile_name`. + +2. If you changed the instance profile on running nodes, restart the Operator and database Pods so backup agents pick up the new credentials: + + ```bash + kubectl rollout restart deployment/percona-server-mongodb-operator -n $namespace + kubectl rollout status deployment/percona-server-mongodb-operator -n $namespace + ``` + +3. Verify that worker nodes expose IAM credentials through IMDS. Run this command from a database Pod: + + ```bash + kubectl exec -it -n $namespace -- \ + curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + my-ec2-role + ``` + + The output should show the IAM role name attached to the worker node. + +### Configure Percona Server for MongoDB cluster + +Now you are ready to configure Percona Server for MongoDB to use the instance profile for backups. + +=== "A new cluster deployment" + + 1. Edit the `backup.storages` subsection in `deploy/cr.yaml` Custom Resource manifest. Give your storage a name (default name is `s3-us-west`) and set the following keys: + + * `type` - make sure the type is `s3` + * `bucket` - where the data will be stored + * `region` - location of the bucket + * `prefix` (optional) - a path (sub-folder) inside the S3 bucket where backups will be stored. If you don't set a prefix, backups are stored in the root directory. + * Omit `s3.credentialsSecret` so that PBM uses the worker node's instance profile to access the S3 storage. + + Here's the example configuration: + + ```yaml + ... + backup: + enabled: true + ... + storages: + aws-s3: + type: s3 + s3: + bucket: + region: + prefix: data/pbm + ... + ``` + + For more storage options, see the [Operator Custom Resource options](operator.md#operator-backup-section). + + 2. Apply the configuration and deploy the cluster: + + ```bash + kubectl apply -f deploy/cr.yaml -n $namespace + ``` + + 3. Wait for the cluster to report the `ready` status: + + ```bash + kubectl get psmdb -n $namespace + ``` + +=== "Existing cluster" + + If your running Percona Server for MongoDB cluster is currently using a Kubernetes Secret with S3 credentials for backups, you can switch to an instance profile by following these steps: + + 1. [Attach the instance profile to worker nodes](#attach-the-instance-profile-to-worker-nodes), if you have not done so already. + + 2. Make a rolling restart of the database Pods. + + * Export the cluster name as an environment variable: + + ```bash + export DBCLUSTER=my-cluster-name + ``` + + * Use the following for loop: + + ```bash + for i in 0 1 2; do + kubectl delete pod $DBCLUSTER-rs0-$i -n $namespace + done + ``` + + 3. Restart the Operator Deployment: + + ```bash + kubectl rollout restart deployment/percona-server-mongodb-operator -n $namespace + ``` + + 4. Remove the credentials Secret by patching the cluster. The storage name in the following command is `aws-s3`. Replace it with your value if you use another name: + + ```bash + kubectl -n $namespace patch psmdb $DBCLUSTER --type=json \ + -p '[{"op":"remove","path":"/spec/backup/storages/aws-s3/s3/credentialsSecret"}]' + sleep 30 + ``` + +### Verify access to S3 using IAM instance profile + +1. Run an on-demand backup to confirm that the cluster can write to the S3 bucket. Here's the example of the backup object configuration: + + ```yaml title="deploy/backup/backup.yaml" + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBBackup + metadata: + name: backup1 + finalizers: + - percona.com/delete-backup + spec: + clusterName: my-cluster-name + storageName: aws-s3 + ``` + +2. Apply the configuration to start the backup: + + ```bash + kubectl apply -f deploy/backup/backup.yaml -n $namespace + ``` + +3. Check the backup progress: + + ```bash + kubectl get psmdb-backup -n $namespace + ``` + + When the backup reaches the `ready` status, the instance profile configuration is working. + +### Troubleshooting + +#### Backup fails with access denied + +* Confirm that the IAM policy is attached to the role associated with the worker node's instance profile. +* Make sure `s3.credentialsSecret` is not set in the Custom Resource. Secret-based credentials override instance profile credentials. +* Verify that Pods can reach IMDS. Some environments block the metadata endpoint or require [IMDSv2 :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configured-instance-metadata-service.html). + +#### All Pods on the node share the same permissions + +This is expected behavior for instance profiles. If you need per-Pod S3 permissions, use [IRSA](#automate-access-to-amazon-s3-using-irsa) on EKS instead. diff --git a/docs/backups-storage-s3.md b/docs/backups-storage-s3.md index c550968b..59a209b4 100644 --- a/docs/backups-storage-s3.md +++ b/docs/backups-storage-s3.md @@ -1,52 +1,83 @@ # Amazon S3 storage -To use Amazon S3 storage service, create a Secret object with your access credentials. Use the [deploy/backup-s3.yaml :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/v{{release}}/deploy/backup-s3.yaml) file as an example. You must specify the following information: +To use Amazon S3 storage service for backups, you need the following: -* `metadata.name` is the name of the Kubernetes secret which you will reference in the Custom Resource -* `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are base64-encoded keys to access S3 storage +* A bucket name +* A region where the bucket is located +* Authentication to the bucket. See [Choose the authentication method](#choose-the-authentication-method) for available options. -Use the following command to encode the keys: +## Storage considerations -=== ":simple-linux: in Linux" +Make sure your storage has enough free space for backups, especially for large databases. - ```bash - echo -n 'plain-text-string' | base64 --wrap=0 - ``` +Also, note that S3 has an upload limit of 10,000 parts per file. If your backup is very large, you may hit this limit, which increases the size of each chunk. Large chunk sizes can use a lot of memory on the S3 server. To avoid issues: -=== ":simple-apple: in macOS" +1. Check your storage free space before backing up. +2. Be aware of the 10,000 part limit for S3 uploads. +3. Adjust your backup chunk size and memory settings in the Custom Resource if necessary for large backups. - ```bash - echo -n 'plain-text-string' | base64 - ``` +## Choose the authentication method -Here's the example configuration of the Secret file: +You can use one of the following options to authenticate to S3: + +* **S3 access keys**. Store your AWS S3 access key and secret key in a Kubernetes Secret and reference it in your cluster configuration. This method **works on any Kubernetes platform** and requires that you manage the credentials yourself. +* **IAM role for service accounts (IRSA)**. Assign an IAM role to the Kubernetes Service Account used by the Operator. With IRSA, you don’t need to manage static secrets since AWS automatically provides temporary credentials to the Pod, following best practices for security and rotation. This is the recommended approach on Amazon Elastic Kubernetes Service (EKS), because you can map S3 permissions to specific Kubernetes service accounts instead of sharing them across all pods on a node. +* **IAM instance profile**. Attach an IAM role with S3 permissions to your EC2 worker nodes. Pods that run backup agents obtain credentials through the instance metadata service, so you don't need to manage static secrets. Use this method when your cluster runs on EC2 instances and IRSA is not configured. All pods on the same node share the node's permissions. -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: my-cluster-name-backup-s3 -type: Opaque -data: - AWS_ACCESS_KEY_ID: UkVQTEFDRS1XSVRILUFXUy1BQ0NFU1MtS0VZ - AWS_SECRET_ACCESS_KEY: UkVQTEFDRS1XSVRILUFXUy1TRUNSRVQtS0VZ -``` +### How the Operator chooses S3 authentication + +* If a Secret with s3 credentials exists and is defined in the Custom Resource, it has the highest precedence. The Operator always uses S3 credentials in a Kubernetes Secret if they are present. +* If a Secret with S3 credentials is not defined, but IRSA-related credentials are configured, then the Operator will use IRSA. In this case, IRSA credentials take precedence over any IAM instance profile on the worker nodes. + +## Set up AWS S3 access with S3 credentials + +Follow these steps to authenticate using an AWS S3 access key and secret key. This method works on any Kubernetes environment. + +1. Encode your `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` keys using base64: + + === ":simple-linux: in Linux" + + ```bash + echo -n 'plain-text-string' | base64 --wrap=0 + ``` + + === ":simple-apple: in macOS" + + ```bash + echo -n 'plain-text-string' | base64 + ``` + +2. Create a Secret manifest with your access credentials. Use the [deploy/backup-s3.yaml :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/v{{release}}/deploy/backup-s3.yaml) file as an example. You must specify the following information: -1. Create the Kubernetes Secret object with this file: + * `metadata.name` is the name of the Kubernetes secret which you will reference in the Custom Resource + * Base64-encoded credentials to access S3 storage. + + Here's the example configuration of the Secret file: + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: my-cluster-name-backup-s3 + type: Opaque + data: + AWS_ACCESS_KEY_ID: + AWS_SECRET_ACCESS_KEY: + ``` + +3. Create the Kubernetes Secret object with this file: ```bash kubectl apply -f deploy/backup-s3.yaml -n ``` -2. Configure the storage in the Custom Resource. Modify the `backup.storages` subsection of the `deploy/cr.yaml` file. Give your storage a name (the default name is `s3-us-west`) and define the following information: +4. Configure the storage in the Custom Resource. Modify the `backup.storages` subsection of the `deploy/cr.yaml` file. Give your storage a name (the default name is `s3-us-west`) and define the following information: * `type` - make sure the type is `s3` * `bucket` - where the data will be stored * `region` - location of the bucket * `credentialsSecret` - the name of the Secret you created previously - !!! tip "Organizing backups" - - You can use the [prefix](operator.md#backupstoragesstorage-names3prefix) option to specify a path (sub-folder) inside the S3 bucket where backups will be stored. If you don't set a prefix, backups are stored in the root directory. + * `prefix` (optional) - a path (sub-folder) inside the S3 bucket where backups will be stored. If you don't set a prefix, backups are stored in the root directory. Here's the example: @@ -66,57 +97,448 @@ data: For more configuration options, see the [Operator Custom Resource options](operator.md#operator-backup-section). - !!! note "Plan for large backups" - Make sure your storage has enough free space for backups, especially for large databases. +5. Apply the configuration: + + ```bash + kubectl apply -f deploy/cr.yaml -n + ``` + +## Automate access to Amazon S3 using IRSA + +[IAM Roles for Service Accounts (IRSA) :octicons-link-external-16:](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) lets Pods on Amazon EKS assume an IAM role through the cluster's OpenID Connect (OIDC) provider. You do not store AWS access keys in a Kubernetes Secret. Instead, Percona Backup for MongoDB uses the AWS default credential provider chain and receives temporary credentials automatically. - Also, note that S3 has an upload limit of 10,000 parts per file. If your backup is very large, you may hit this limit, which increases the size of each chunk. Large chunk sizes can use a lot of memory on the S3 server. To avoid issues: +### Prerequisites - 1. Check your storage free space before backing up. - 2. Be aware of the 10,000 part limit for S3 uploads. - 3. Adjust your backup chunk size and memory settings in the Custom Resource if necessary for large backups. +Before you start, make sure you have the following: -3. Apply the configuration: +* An [EKS cluster with the Operator and database deployed](eks.md) +* An S3 bucket for backups +* The [AWS CLI :octicons-link-external-16:](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html), [eksctl :octicons-link-external-16:](https://github.com/weaveworks/eksctl#installation), and [kubectl :octicons-link-external-16:](https://kubernetes.io/docs/tasks/tools/) installed and configured +* Your AWS account ID. You can get it with: ```bash - kubectl apply -f deploy/cr.yaml -n + aws sts get-caller-identity --query Account --output text + ``` + +Set environment variables for the commands below. Replace the placeholders with your values: + +```bash +export cluster_name= +export aws_region= +export s3_bucket= +export policy_name= +export role_name= +export account_id=$(aws sts get-caller-identity --query Account --output text) +export namespace= +``` + +### Configure the IAM role {.power-number} + +1. Check whether your EKS cluster has an [OIDC issuer URL :octicons-link-external-16:](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) enabled: + + ```bash + aws eks describe-cluster --name $cluster_name --region $aws_region \ + --query "cluster.identity.oidc.issuer" --output text + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + https://oidc.eks.us-west-2.amazonaws.com/id/4B2D5F8C1A2B3C4D5E6F7A8B9C0D1E2F + ``` + + Save the OIDC ID from the URL (the part after `/id/`) and export it as an environment variable: + + ```bash + export oidc_id= + ``` + + For example, if the issuer URL is `https://oidc.eks.us-west-2.amazonaws.com/id/4B2D5F8C1A2B3C4D5E6F7A8B9C0D1E2F`, set `oidc_id` to `4B2D5F8C1A2B3C4D5E6F7A8B9C0D1E2F`. + + If the command returns no issuer URL, create the OIDC provider: + + ```bash + eksctl utils associate-iam-oidc-provider \ + --region $aws_region --cluster $cluster_name --approve + ``` + +2. Create an IAM policy that grants access to your S3 bucket. Replace `` with your bucket name: + + ```json title="s3-bucket-policy.json" + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:*" + ], + "Resource": [ + "arn:aws:s3:::", + "arn:aws:s3:::/*" + ] + } + ] + } + ``` + + !!! tip + + The example uses broad `s3:*` permissions for simplicity. In production, restrict the policy to the specific S3 actions your backup and restore workflows require. Refer to the [Amazon S3 permissions documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html) and tailor the policy to follow the principle of least privilege. + + +3. Create the IAM policy and save its Amazon Resource Name (ARN): + + ```bash + aws iam create-policy \ + --policy-name $policy_name \ + --policy-document file://s3-bucket-policy.json ``` -## Automating access to Amazon S3 based on IAM roles + ??? example "Sample output" + + ```{.json .no-copy} + { + "Policy": { + "PolicyName": "s3-access", + "PolicyId": "ANPARXP3OARBBRX6TZXTI", + "Arn": "arn:aws:iam:::policy/s3-access", + "Path": "/", + "DefaultVersionId": "v1", + "AttachmentCount": 0, + "PermissionsBoundaryUsageCount": 0, + "IsAttachable": true, + "CreateDate": "2026-05-26T12:52:57+00:00", + "UpdateDate": "2026-05-26T12:52:57+00:00" + } + } + ``` + -Using AWS EC2 instances for backups makes it possible to automate access to AWS S3 buckets based on [Identity Access Management (IAM) roles :octicons-link-external-16:](https://kubernetes-on-aws.readthedocs.io/en/latest/user-guide/iam-roles.html) for Service Accounts with *no need to specify the S3 credentials explicitly*. + Note the `PolicyArn` value from the command output. You will need it later in this setup. + +4. Create a trust policy that allows your EKS OIDC provider to assume the role. Replace ``, ``, and `` in the file with your `$account_id`, `$aws_region`, and `$oidc_id` values: + + ```json title="role-trust-policy.json" + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam:::oidc-provider/oidc.eks..amazonaws.com/id/" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "oidc.eks..amazonaws.com/id/:aud": "sts.amazonaws.com" + } + } + } + ] + } + ``` -You can either use the *IAM instance profile* or configure *IAM roles for Service Accounts*. Both approaches are AWS-specific so you should follow the official Amazon documentation. +5. Create the IAM role: -=== "Using IAM instance profile" + ```bash + aws iam create-role \ + --role-name $role_name \ + --assume-role-policy-document file://role-trust-policy.json \ + --description "Allow Percona Operator for MongoDB to access S3 backups" + ``` - Follow these steps: + ??? example "Sample output" + + ```{.json .no-copy} + { + "Role": { + "Path": "/", + "RoleName": "s3-access-role", + "RoleId": "AROARXP3OARBHYAIOYMKD", + "Arn": "arn:aws:iam:::role/s3-access-role", + "CreateDate": "2026-05-26T12:53:29+00:00", + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam:::oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/4B2D5F8C1A2B3C4D5E6F7A8B9C0D1E2F" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "oidc.eks.eu-west-1.amazonaws.com/id/4B2D5F8C1A2B3C4D5E6F7A8B9C0D1E2F:aud": "sts.amazonaws.com" + } + } + } + ] + } + } + } + ``` - 1. Create the [IAM instance profile :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) and the permission policy within where you specify the access level that grants the access to S3 buckets. - 2. Attach the IAM profile to an EC2 instance. - 3. Configure an S3 storage bucket in the Custom Resource and verify the connection from the EC2 instance to it. - 4. *Do not provide* `s3.credentialsSecret` for the storage in `deploy/cr.yaml`. +6. Attach the S3 policy to the role. Replace `` with the policy name from step 3 if you did not export `$policy_name`: -=== "Using IAM role for service account" + ```bash + aws iam attach-role-policy \ + --role-name $role_name \ + --policy-arn arn:aws:iam::${account_id}:policy/${policy_name} + ``` - [IRSA :octicons-link-external-16:](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) is the native way for the cluster [running on Amazon Elastic Kubernetes Service (AWS EKS)](eks.md) to access the AWS API using permissions configured in AWS IAM roles. + ??? example "Sample output" + + ```{.json .no-copy} + { + "AttachedPolicies": [ + { + "PolicyName": "s3-access", + "PolicyArn": "arn:aws:iam:::policy/s3-access" + } + ] + } + ``` - Assuming that you have [deployed the Operator and the database cluster on EKS](eks.md), and your EKS cluster has [OpenID Connect issuer URL (OIDC) :octicons-link-external-16:](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) enabled, the high-level steps to configure it are the following: +7. Get the IAM role ARN. You will use it when you annotate the Kubernetes Service Accounts: - 1. Create an IAM role for your OIDC, and attach to the created role the policy that defines the access to an S3 bucket. See [official Amazon documentation :octicons-link-external-16:](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) for details. + ```bash + role_arn=$(aws iam get-role --role-name $role_name --query "Role.Arn" --output text) + ``` - 2. Find the service accounts used for the Operator and the database cluster. Service account for the Operator is `percona-server-mongodb-operator` (it is set by the `serviceAccountName` key in the `deploy/operator.yaml` or `deploy/bundle.yaml` manifest). The cluster's default account is `default` (it can be set with the `serviceAccountName` Custom Resource option in the `replsets`, `sharding.configsvrReplSet`, and `sharding.mongos` subsections of the `deploy/cr.yaml` manifest). - 3. Annotate both service accounts with the needed IAM roles. The commands should look as follows: +### Assign the IAM role to the Service accounts +1. Deploy the Operator if you haven't done so yet: + + ```bash + kubectl apply --server-side -f https://raw.githubusercontent.com/percona/percona-server-mongodb-operator/v{{ release }}/deploy/bundle.yaml -n $namespace + ``` + +2. Find service accounts used by the Operator and the database cluster: + + ```bash + kubectl get serviceaccounts -n $namespace + ``` + + ??? example "Expected output" + + ```{.text .no-copy} + default 0 15m + percona-server-mongodb-operator 0 15m + ``` + + `percona-server-mongodb-operator` is the Operator service account defined by the `serviceAccountName` key in the `deploy/operator.yaml` or `deploy/bundle.yaml` manifest. + `default` is cluster's default service account. You can override it with the `serviceAccountName` Custom Resource option in the `replsets`, `sharding.configsvrReplSet`, and `sharding.mongos` subsections of the `deploy/cr.yaml` manifest, if needed. + +3. Annotate both service accounts with the needed IAM role ARN: + + ```bash + kubectl -n $namespace annotate serviceaccount default eks.amazonaws.com/role-arn=$role_arn --overwrite + kubectl -n $namespace annotate serviceaccount percona-server-mongodb-operator eks.amazonaws.com/role-arn=$role-arn --overwrite + ``` + +4. Annotating a Service Account does not restart existing Pods automatically. Restart the Operator and database Pods so they pick up the new `AWS_ROLE_ARN` environment variable: + + ```bash + kubectl rollout restart deployment/percona-server-mongodb-operator -n $namespace + kubectl rollout status deployment/percona-server-mongodb-operator -n $namespace + ``` + +5. Verify that IRSA is configured correctly: + + * Check the annotation on both Service Accounts: + + ```bash + kubectl -n $namespace get sa default -o yaml + kubectl -n $namespace get sa percona-server-mongodb-operator -o yaml + ``` + + * Confirm that `AWS_ROLE_ARN` is set inside the Operator Pods: + + ```bash + kubectl -n $namespace exec -it deploy/percona-server-mongodb-operator -- printenv | grep AWS_ROLE_ARN + ``` + + ??? example "Sample output" + + ```text + AWS_ROLE_ARN=arn:aws:iam:::role/s3-access-role + ``` + +### Configure Percona Server for MongoDB cluster + +Now you are ready to configure Percona Server for MongoDB to use IRSA for backups. + +=== "A new cluster deployment" + + 1. Edit the `backup.storages` subsection in `deploy/cr.yaml` Custom Resource manifest. Give your storage a name (default name is `s3-us-west`) and set the following keys: + + * `type` - make sure the type is `s3` + * `bucket` - where the data will be stored + * `region` - location of the bucket + * `prefix` (optional) - a path (sub-folder) inside the S3 bucket where backups will be stored. If you don't set a prefix, backups are stored in the root directory. + * Omit `s3.credentialsSecret` so that PBM uses IRSA to access the S3 storage. + + Here's the example configuration: + + ```yaml + ... + backup: + enabled: true + ... + storages: + aws-s3: + type: s3 + s3: + bucket: + region: + prefix: data/pbm + ... + ``` + + For more storage options, see the [Operator Custom Resource options](operator.md#operator-backup-section). + + 2. Apply the configuration and deploy the cluster: + + ```bash + kubectl apply -f deploy/cr.yaml -n $namespace + ``` + + 3. Wait for the cluster to report the "Ready" status: + ```bash - kubectl -n annotate serviceaccount default eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role --overwrite - kubectl -n annotate serviceaccount percona-server-mongodb-operator eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role --overwrite + kubectl get psmdb -n $namespace ``` - Don't forget to substitute the `` and `` placeholders with the real namespaces, and use your IAM role instead of the `eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/my-role` example. + 4. Confirm that `AWS_ROLE_ARN` is set inside the database Pods. Replace the `` with the name of your cluster (corresponds to the `metadata.name` value in your Custom Resource): + + ```bash + kubectl exec -it -rs0-1 -- printenv | grep AWS_ROLE_ARN + ``` + + ??? example "Sample output" + + ```text + AWS_ROLE_ARN=arn:aws:iam:::role/s3-access-role + ``` + + +=== "Existing cluster" + + If your running Percona Server for MongoDB cluster is currently using a Kubernetes Secret with S3 credentials for backups, you can switch to IRSA authentication by following these steps: + + 1. [Assign the IAM role to service accounts](#assign-the-iam-role-to-the-service-accounts), if you haven't done it before + 2. Make a rolling restart of the database Pods. + + * Export the cluster name as an environment variable: + + ```bash + export DBCLUSTER=my-cluster-name + ``` + + * Use the following for loop: + + ```bash + for i in 0 1 2; do + kubectl delete pod $DBCLUSTER-rs0-$i -n $namespace + done + ``` + + 3. Restart the Operator Deployment: + + ```bash + kubectl rollout restart deployment percona-server-mongodb-operator -n $namespace + ``` + + 4. Confirm that AWS_ROLE_ARN is set inside the Operator and database Pods: + + ```bash + kubectl -n $namespace exec -it deploy/percona-server-mongodb-operator -- printenv | grep AWS_ROLE_ARN + kubectl exec -it $DBCLUSTER-rs0-0 -- printenv | grep AWS_ROLE_ARN + ``` + + ??? example "Sample output" + + ```text + AWS_ROLE_ARN=arn:aws:iam:::role/s3-access-role + ``` + + 5. Remove the credentials Secret by patching the cluster. The storage name in the following command is `aws-s3`. Replace it with your value if you use another name: + + ```bash + kubectl -n $namespace patch psmdb $DBCLUSTER --type=json \ + -p '[{"op":"remove","path":"/spec/backup/storages/aws-s3/s3/credentialsSecret"}]' + sleep 30 + ``` + +### Verify access to S3 using IRSA + +1. Run an on-demand backup to confirm that the cluster can write to the S3 bucket. Here's the example of the backup object configuration: + + ```yaml title="deploy/backup/backup.yaml" + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBBackup + metadata: + name: backup1 + finalizers: + - percona.com/delete-backup + spec: + clusterName: my-cluster-name + storageName: aws-s3 #Must match the name in your cluster configuration + ``` + +2. Apply the configuration to start the backup: + + ```bash + kubectl apply -f deploy/backup/backup.yaml -n $namespace + ``` + +3. Check the backup progress: + + ```bash + kubectl get psmdb-backup -n $namespace + ``` + +### Troubleshooting + +#### Pods stuck in Pending state + +If your Pods are stuck in the `Pending` state, it may be because the `storageClass` specified in your Custom Resource does not match the one available in your EKS cluster. Review your Custom Resource configuration and ensure that it uses the correct storage class for your environment. + +#### PBM reports "Request ARN is invalid" + +This error usually indicates a problem with your IRSA (IAM Roles for Service Accounts) configuration. To resolve it: + +1. **Verify the OIDC Provider:** + + Confirm that your EKS cluster has the correct OIDC provider set up. In your trust policy, the URL must exactly match your cluster's OIDC provider URL and should follow the format: + + ``` + https://oidc.eks..amazonaws.com/id/ + ``` + + Even minor mismatches (such as missing trailing slashes or extra characters) can cause this error. + +2. **Check Service Account Annotations:** + Ensure that the Kubernetes service account used by the Operator has the correct `eks.amazonaws.com/role-arn` annotation. The annotation key should be present, and the value should be the full ARN of the IAM role you created for S3 access. + +3. **Review Trust Policy Conditions:** + Make sure the IAM role's trust policy references the correct service account namespace and name, and that any conditions (such as `StringEquals`) are accurate. + +4. **Restart Pods:** + After correcting any issues, restart both the database and Operator pods to ensure the new IAM credentials are picked up. + +By following these steps, you should be able to resolve the "Request ARN is invalid" error when using IRSA. + + +## Automate access to Amazon S3 using IAM instance profile + +Follow these steps: - 4. Configure an S3 storage bucket in the Custom Resource and verify the connection from the EC2 instance to it. *Do not provide* `s3.credentialsSecret` for the storage in `deploy/cr.yaml`. +1. Create the [IAM instance profile :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) and the permission policy within. In this policy you specify the access level that grants the access to S3 buckets. +2. Attach the IAM profile to your EC2 worker nodes. +3. Configure an S3 storage bucket in the Custom Resource and verify the connection from the EC2 instance to it. +4. Create or update the Percona Server for MongoDB cluster. *Do not provide* `s3.credentialsSecret` for the storage in `deploy/cr.yaml`. -!!! note - If IRSA-related credentials are defined, they have the priority over any IAM instance profile. S3 credentials in a secret, if present, override any IRSA/IAM instance profile related credentials and are used for authentication instead. From b66aa352f612b6d7e508f9e10047d3a74e80ca26 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Mon, 6 Jul 2026 15:15:41 +0300 Subject: [PATCH 05/22] =?UTF-8?q?K8SPSMDB-1571=20Documented=20the=20abilit?= =?UTF-8?q?y=20to=20configure=20reconciliation=20inte=E2=80=A6=20(#334)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit K8SPSMDB-1571 Documented the ability to configure reconciliation interval --- docs/env-vars-operator.md | 24 +++++++++- docs/reconciliation-concurrency.md | 73 +++++++++++++++++++++++++++++- docs/users.md | 2 +- 3 files changed, 95 insertions(+), 4 deletions(-) diff --git a/docs/env-vars-operator.md b/docs/env-vars-operator.md index 1fd34914..dfb227f1 100644 --- a/docs/env-vars-operator.md +++ b/docs/env-vars-operator.md @@ -1,6 +1,6 @@ # Configure Operator environment variables -You can configure the Percona Operator for MongoDB by setting environment variables in the Operator Deployment. This lets you tune logging, scope the namespaces that are watched, and adjust reconciliation concurrency without rebuilding images. +You can configure the Percona Operator for MongoDB by setting environment variables in the Operator Deployment. This lets you tune logging, scope the namespaces that are watched, and adjust reconciliation behavior without rebuilding images. You can set environment variables in the following ways: @@ -86,6 +86,28 @@ env: value: "true" ``` +### `RECONCILE_INTERVAL` + +Controls how long the Operator waits before re-queuing reconciliation for a cluster after a reconcile loop completes (available since Operator 1.23.0). + +|Value type|Default|Example| +|---|---|---| +|duration string|`"5s"`|`"30s"` or `"1m"`| + +**Notes:** + +- The value must be a Go duration string (for example, `30s`, `1m`, `5m`). +- The minimum allowed value is `5s`. Values below `5s`, zero, negative, or unparseable values fall back to `5s`. The Operator logs a message when it rejects a value. +- Increasing the interval reduces the number of Kubernetes API requests the Operator generates. The default of `5s` can produce a high request rate in large deployments. + +**Example configuration:** + +```yaml +env: + - name: RECONCILE_INTERVAL + value: "30s" +``` + ### `MAX_CONCURRENT_RECONCILES` Controls the maximum number of concurrent reconciliation operations. diff --git a/docs/reconciliation-concurrency.md b/docs/reconciliation-concurrency.md index 6cee7d8c..74eef82a 100644 --- a/docs/reconciliation-concurrency.md +++ b/docs/reconciliation-concurrency.md @@ -10,15 +10,24 @@ Reconciliation is triggered by a variety of events, including: - Changes to the cluster state - Changes to the cluster resources +You can tune reconciliation behavior with two environment variables in the `percona-server-mongodb-operator` Deployment: + +- `MAX_CONCURRENT_RECONCILES` — how many clusters the Operator can reconcile in parallel +- `RECONCILE_INTERVAL` — how long the Operator waits before re-queuing reconciliation for each cluster + +See [Configure Operator environment variables](env-vars-operator.md) for the full list of supported values and defaults. + +## Configure concurrent reconciliation workers + By default, the Operator has one reconciliation worker. This means that if you deploy or update 2 clusters at the same time, the Operator will reconcile them sequentially. -The `MAX_CONCURRENT_RECONCILES` environment variable in the `percona-server-mongodb-operator` deployment controls the number of concurrent workers that can reconcile resources in Percona Server for MongoDB clusters in parallel. +The `MAX_CONCURRENT_RECONCILES` environment variable controls the number of concurrent workers that can reconcile resources in Percona Server for MongoDB clusters in parallel. Thus, to extend the previous example, if you set the number of reconciliation workers to `2`, the Operator will reconcile both clusters in parallel. This also helps you with benchmarking the Operator performance. The general recommendation is to set the number of concurrent workers equal to the number of Percona Server for MongoDB clusters. When the number of workers is greater, the excessive workers will remain idle. -## Set the number of reconciliation workers +### Set the number of reconciliation workers 1. Check the index of the `MAX_CONCURRENT_RECONCILES` environment variable using the following command: @@ -72,4 +81,64 @@ You can set the value to any number greater than 0. ```{.text .no-copy} 2 + ``` + +## Configure the reconciliation interval + +After each reconcile loop, the Operator schedules the next one using the `RECONCILE_INTERVAL` environment variable. The default is `5s`. + +Increasing this value reduces Kubernetes API traffic from the Operator. This can be useful in large environments where the default interval generates more requests than needed. Values below `5s`, zero, negative, or invalid duration strings fall back to `5s`. + +### Set the reconciliation interval + +1. Check the current value: + + ```bash + kubectl -n get deployment percona-server-mongodb-operator -o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="RECONCILE_INTERVAL")].value}' + ``` + + ??? example "Sample output" + + ```{.json .no-copy} + 5s + ``` + +2. To set a new value and verify it's been updated, run the following command: + + ```bash + kubectl -n patch deployment percona-server-mongodb-operator \ + --type='strategic' \ + -o yaml \ + -p='{ + "spec": { + "template": { + "spec": { + "containers": [ + { + "name": "percona-server-mongodb-operator", + "env": [ + { + "name": "RECONCILE_INTERVAL", + "value": "30s" + } + ] + } + ] + } + } + } + }'\ + -o jsonpath='{.spec.template.spec.containers[0].env[?(@.name=="RECONCILE_INTERVAL")].value}' + ``` + +The command does the following: + +- Patches the deployment to update the `RECONCILE_INTERVAL` environment variable +- Sets the value to `30s` +- Outputs the result + +??? example "Sample output" + + ```{.text .no-copy} + 30s ``` \ No newline at end of file diff --git a/docs/users.md b/docs/users.md index 562570c8..2470840d 100644 --- a/docs/users.md +++ b/docs/users.md @@ -16,7 +16,7 @@ The Operator stores user credentials in the Secret objects. When the Operator creates application-level (unprivileged) users, it uses the username you specify in the Custom Resource (CR). The Operator either generates a password for this user and creates a corresponding Secret, or uses the credentials of a user you have manually created in MongoDB and creates a Secret with that data. -For system users, the Operator creates the required Secret automatically when it creates the cluster. If a Secret with the expected name already exists (as specified in the CR), the Operator will reuse it. Starting with version 1.22.0, you can also [store and manage system user credentials in HashiCorp Vault]. In this case, the Operator retrieves the passwords from Vault and creates or updates the relevant Secrets based on the Vault-stored credentials. +For system users, the Operator creates the required Secret automatically when it creates the cluster. If a Secret with the expected name already exists (as specified in the CR), the Operator will reuse it. Starting with version 1.22.0, you can also [store and manage system user credentials in HashiCorp Vault](system-users-vault.md). In this case, the Operator retrieves the passwords from Vault and creates or updates the relevant Secrets based on the Vault-stored credentials. ## Authentication From 709fe8c015cc1f0fc42a85ca94f0d7bc45113617 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Fri, 10 Jul 2026 13:35:10 +0300 Subject: [PATCH 06/22] K8SPSMDB-1458 Added TLS certificate management policy documentation and examples (#345) K8SPSMDB-1458 Added TLS certificate management policy documentation and examples modified: docs/TLS.md modified: docs/cr-statuses.md modified: docs/operator.md new file: docs/tls-cert-management-policy.md modified: mkdocs-base.yml --- _resource/overrides/main.html | 4 +- _resourcepdf/overrides/main.html | 4 +- docs/TLS.md | 52 ++++++---- docs/cr-statuses.md | 19 +++- docs/operator.md | 19 ++++ docs/tls-cert-management-policy.md | 158 +++++++++++++++++++++++++++++ docs/volume-attributes-class.md | 2 +- mkdocs-base.yml | 1 + 8 files changed, 232 insertions(+), 27 deletions(-) create mode 100644 docs/tls-cert-management-policy.md diff --git a/_resource/overrides/main.html b/_resource/overrides/main.html index ff52b731..603c5da2 100644 --- a/_resource/overrides/main.html +++ b/_resource/overrides/main.html @@ -10,11 +10,11 @@ {% block announce %}
Where the open source database community meets: - Use code PERCONA75 and secure your spot for Percona Live. + Secure your spot for Percona Live. Where the open source database community meets: - Use code PERCONA75 and secure your spot for Percona Live. + Secure your spot for Percona Live. -ssl` / `-ssl-internal` Secrets | `userProvidedOnly` | +| You own rotation and must avoid surprise CA changes on Secret loss | `userProvidedOnly` | + +The following table explains how the Operator responds under each policy when it cannot access TLS Secrets. + +| Situation | `auto` | `userProvidedOnly` | +|-----------|--------|-------------------| +| Cluster created without TLS Secrets | Operator creates Secrets and starts the cluster | Cluster stays in `initializing` until you create Secrets | +| TLS Secret deleted while cluster is running | Operator may create new Secrets and roll Pods | Pods keep running; Operator logs an error; `TLSSecretsReady=False` | +| TLS Secrets restored | Normal operation | `TLSSecretsReady=True`; no forced restart from this policy alone | + +## Configuration + +### Prerequisites + +Ensure you have: + +1. Created both TLS Secrets in the cluster namespace, or that your sync tool created them before the database Pods must start. See [Generate TLS certificates manually](tls-manual.md). +2. Referenced the Secret names in the Custom Resource: + + ```yaml + spec: + secrets: + ssl: my-cluster-name-ssl + sslInternal: my-cluster-name-ssl-internal + ``` + +3. Run Percona Operator for MongoDB version 1.23.0 or later. + +### Configure the certificate management policy + +1. Edit the `deploy/cr.yaml` Custom Resource manifest and configure the `spec.tls.certManagementPolicy` option: + + ```yaml + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDB + metadata: + name: my-cluster-name + spec: + tls: + mode: preferTLS + certManagementPolicy: userProvidedOnly + secrets: + ssl: my-cluster-name-ssl + sslInternal: my-cluster-name-ssl-internal + replsets: + - name: rs0 + size: 3 + ``` + +2. Apply the manifest: + + ```bash + kubectl apply -f deploy/cr.yaml -n + ``` + +For Helm installations, set the equivalent value in your Helm values file for `tls.certManagementPolicy`. + +!!! note + + Do not set the `userProvidedOnly` value if you expect the Operator to bootstrap TLS for you. With this policy, missing Secrets at deploy time leave the cluster in the `initializing` state until the Secrets exist. + + +## Monitor the cluster state + +If a TLS Secret is missing and `spec.tls.certManagementPolicy` is set to `userProvidedOnly`, the Operator updates the `TLSSecretsReady` cluster condition to `False` and sets the reason to `TLSSecretNotFound`. + +To check the condition, run: + +```bash +kubectl -n get psmdb my-cluster-name -o jsonpath='{range .status.conditions[?(@.type=="TLSSecretsReady")]}{.status}{"\n"}{.reason}{"\n"}{.message}{"\n"}{end}' +``` + +??? example "Sample output when a Secret is missing" + + ```{.text .no-copy} + False + TLSSecretNotFound + TLS secret my-cluster-name-ssl is missing, certManagementPolicy is userProvidedOnly + ``` + +The cluster may still show Pods as running while `TLSSecretsReady` is `False`. Treat this as a **degraded** state: MongoDB continues with certificates already mounted in Pods, but you should restore the Secrets promptly. + +Check Operator logs for errors mentioning `certManagementPolicy is userProvidedOnly`. + +See [Custom resource statuses](cr-statuses.md#conditions) for more on cluster conditions. + +## Restore TLS Secrets + +1. Confirm which Secret is missing: + + ```bash + kubectl -n get secret my-cluster-name-ssl my-cluster-name-ssl-internal + ``` + +2. Recreate or re-sync the Secret (from backup, External Secrets, or your certificate pipeline). + +3. Wait for the next reconciliation cycle, then verify: + + ```bash + kubectl -n get psmdb my-cluster-name -o jsonpath='{.status.conditions[?(@.type=="TLSSecretsReady")].status}' + ``` + + The output should be `True`. + +Under `userProvidedOnly`, restoring Secrets does not by itself force a rolling restart. Pods continue using the certificates already loaded until you [update certificates](tls-update.md) intentionally. + +## Switch between policies + +### Change to userProvidedOnly + +Safe when TLS Secrets already exist and you want to prevent automatic regeneration if they are lost later. Apply the updated Custom Resource; no immediate Pod restart is required solely for this change. + +### Change to auto + +If TLS Secrets are **missing** when you switch to `auto`, the Operator creates new certificates. That may change the CA and trigger a rolling restart. Only switch back to `auto` if you intentionally want the Operator to take over certificate creation again. + +There is no Operator guardrail that blocks `userProvidedOnly` → `auto` when Secrets are absent. Plan the switch and client CA trust accordingly. + +## Rotate certificates with userProvidedOnly + +Certificate rotation remains your responsibility: + +1. Update the TLS Secrets with new certificate material (same Secret names). +2. Follow the steps in [Update certificates](tls-update.md) for your certificate source. +3. Confirm `TLSSecretsReady=True` after both Secrets are valid. + +The Operator picks up new Secret content and reconciles Pods according to its normal TLS update flow. diff --git a/docs/volume-attributes-class.md b/docs/volume-attributes-class.md index d903fa24..979d8990 100644 --- a/docs/volume-attributes-class.md +++ b/docs/volume-attributes-class.md @@ -128,4 +128,4 @@ To configure a VolumeAttributesClass, you need to create a `VolumeAttributesClas storageClassName: standard-rwo volumeAttributesClassName: silver volumeMode: Filesystem - ``` + ``` diff --git a/mkdocs-base.yml b/mkdocs-base.yml index 17589169..0887e7be 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -246,6 +246,7 @@ nav: - Configure TLS using cert-manager: tls-cert-manager.md - Generate certificates manually: tls-manual.md - Update certificates: tls-update.md + - "Configure the TLS certificate management policy": tls-cert-management-policy.md - Disable TLS: tls-disable.md - Data at rest encryption: - About data-at-rest encryption: encryption.md From 908f1c3482506ad2dbbb9dfcd1efc3ab5b0b1770 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Fri, 10 Jul 2026 13:36:22 +0300 Subject: [PATCH 07/22] K8SPSMDB-1546 Documented the query data source for PMM (#351) * K8SPSMDB-1546 Documented the query data source for PMM Updated monitoring doc Added the new option to CR reference --- docs/monitoring.md | 110 +++++++++++++++++++++++++++++++++++---------- docs/operator.md | 14 ++++++ 2 files changed, 100 insertions(+), 24 deletions(-) diff --git a/docs/monitoring.md b/docs/monitoring.md index 48ee7fc4..67f89442 100644 --- a/docs/monitoring.md +++ b/docs/monitoring.md @@ -2,30 +2,92 @@ {% include 'assets/fragments/monitor-db.txt' %} -## Enable profiling - -Starting from the Operator version 1.12.0, MongoDB operation profiling is -disabled by default. To analyze query execution on the [PMM Query Analytics :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/use/qan/index.html) dashboard, you -[should enable profiling :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/install-pmm/install-pmm-client/connect-database/mongodb.html#compare-query-source-methods) explicitly. You can pass options to MongoDB [in several ways](options.md). - -This example shows how to pass the configuration via the `configuration` subsection of the `deploy/cr.yaml` manifest. - - ```yaml - spec: - ... - replsets: - - name: rs0 - size: 3 - configuration: | - operationProfiling: - slowOpThresholdMs: 200 - mode: slowOp - rateLimit: 100 - ``` - -Optionally, you can specify additional parameters for the [`pmm-admin add mongodb` :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/use/commands/pmm-admin.html?h=pmm+admin#__tabbed_1_1) command in the `pmm.mongodParams` and `pmm.mongosParams` keys for `mongod` and `mongos` Pods respectively. - -:material-information: Info: Note that the Operator automatically manages common MongoDB Service Monitoring parameters such as username, password, service-name, host, etc. Assigning values to these parameters is not recommended and can negatively affect the functionality of the PMM setup carried out by the Operator. +## Configure Query Analytics + +To analyze query execution on the [PMM Query Analytics (QAN) :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/use/qan/index.html) dashboard, you must configure how PMM collects query data. Starting with Operator version 1.23.0, use the [`pmm.querySource`](operator.md#pmmquerysource) option to choose the collection method: + +* `profiler` (default) — PMM reads query performance data from each database's `system.profile` collection. This method requires you to [enable profiling :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/install-pmm/install-pmm-client/connect-database/mongodb.html#compare-query-source-methods) explicitly. +* `mongolog` — PMM reads slow-query data directly from mongod log files. This method has minimal impact on the database and scales better in clusters with many databases. It requires [PMM 3.3.0 or newer :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/install-pmm/install-pmm-client/connect-database/mongodb.html#compare-query-source-methods) and the [log collector](persistent-logging.md) enabled so that logs are written to `/data/db/logs/`. + +See the [PMM documentation on query source methods :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/install-pmm/install-pmm-client/connect-database/mongodb.html#compare-query-source-methods) for a detailed comparison. + +### Configure the profiler query source + +To use the default `profiler` query source, do the following: + +* [enable profiling in PMM :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/install-pmm/install-pmm-client/connect-database/mongodb.html#compare-query-source-methods) +* Configure the Operator: + + * set the `pmm.querySource` option to `profiler` + * enable profiling in the Percona Server for MongoDB, so PMM can collect query data. You can pass MongoDB options in several ways: edit the Custom Resource, via the ConfigMap or a Secret. Read more about [changing MongoDB options](options.md). + +This example shows how to configure `profiler` and pass the configuration via the `configuration` subsection of the `deploy/cr.yaml` manifest: + +```yaml +spec: + pmm: + enabled: true + querySource: profiler + replsets: + - name: rs0 + size: 3 + configuration: | + operationProfiling: + slowOpThresholdMs: 200 + mode: slowOp + rateLimit: 100 +``` + +Apply the configuration: + +```bash +kubectl apply -f deploy/cr.yaml -n +``` + +### Configure the mongolog query source + +!!! note "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +To use `mongolog`, do the following: + +* Enable [log collector](persistent-logging.md) so that mongod logs are available at `/data/db/logs/` for the PMM Client + + When using mongolog, configure [log rotation](logrotate.md) carefully. Avoid moving or renaming active log files during rotation, as this can interrupt mongolog collection. + +* Set `pmm.querySource` to `mongolog` +* Configure MongoDB to write slow operations to the mongod log. + +Here's the example configuration: + +```yaml +spec: + pmm: + enabled: true + querySource: mongolog + logcollector: + enabled: true + replsets: + - name: rs0 + size: 3 + configuration: | + operationProfiling: + mode: off + slowOpThresholdMs: 200 +``` + +Apply the configuration: + +```bash +kubectl apply -f deploy/cr.yaml -n +``` + +### Additional PMM Client parameters + +Optionally, you can specify additional parameters for the [`pmm-admin add mongodb` :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/use/commands/pmm-admin.html?h=pmm+admin#__tabbed_1_1) command in the `pmm.mongodParams` and `pmm.mongosParams` keys for `mongod` and `mongos` Pods respectively. + +!!! warning + + Do not pass username, password, service name, host, or query source in `pmm.mongodParams` or `pmm.mongosParams`. The Operator automatically manages these settings for you. Overriding them can break PMM monitoring. When done, apply the edited `deploy/cr.yaml` file: diff --git a/docs/operator.md b/docs/operator.md index 75ddbd12..c7ae0257 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -1926,6 +1926,20 @@ A custom name to define for a cluster. PMM Server uses this name to properly par | ----------- | ---------- | | :material-code-string: string | `mongo-cluster` | +### `pmm.querySource` + +Defines the source for Query Analytics (QAN) data collection. The Operator passes this value to PMM Client as the `--query-source` flag when adding the MongoDB service. Available starting with Operator version 1.23.0. + +Supported values: + +* `profiler` — collect queries via the MongoDB profiler (default). Requires profiling to be enabled in PMM and in MongoDB. See [Configure the profiler query source](monitoring.md#configure-the-profiler-query-source). +* `mongolog` — collect queries from mongod log files. Requires [log collector](persistent-logging.md) to be enabled so that logs are written to `/data/db/logs/`. See [Configure the mongolog query source](monitoring.md#configure-the-mongolog-query-source). + +If omitted, the Operator does not pass the `--query-source` flag and PMM uses the profiler method. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `mongolog` | ### `pmm.mongodParams` From e91debb45625deb809133a5cbb44275c0219bfe0 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Fri, 10 Jul 2026 15:55:38 +0300 Subject: [PATCH 08/22] K8SPSMDB-1572 Documented the revisionHistoryLimit option, added a section to the upgrade overview (#337) --- docs/operator.md | 8 ++++++++ docs/update.md | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/operator.md b/docs/operator.md index c7ae0257..a6d0cd83 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -221,6 +221,14 @@ A strategy the Operator uses for [upgrades](update.md). Possible values are [Sma | ----------- | ---------- | | :material-code-string: string | `SmartUpdate` | +### `revisionHistoryLimit` + +The maximum number of [revisions :octicons-link-external-16:](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#revision-history-limit) the Operator keeps for Percona Server for MongoDB StatefulSets (replica set members, config servers, and `mongos` Pods). Kubernetes uses this history when you roll a StatefulSet back to a previous Pod template. Lower values reduce the number of retained revisions and help keep the cluster namespace tidy; higher values keep more rollback points. When unset, the default number of revisions is `10`. Available since Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `10` | + ### `ignoreAnnotations` The list of annotations [to be ignored](annotations.md#specifying-labels-and-annotations-ignored-by-the-operator) by the Operator. diff --git a/docs/update.md b/docs/update.md index c99e5426..16415640 100644 --- a/docs/update.md +++ b/docs/update.md @@ -50,7 +50,19 @@ To select an update strategy, set the `updateStrategy` key in the [Custom Resour * `OnDelete` For a manual update of your database cluster using the `RollingUpdate` or `OnDelete` strategies, refer to [the low-level Kubernetes way of database upgrades](update_manually.md) guide. - + +## Revision history limit + +Each time the Operator updates a StatefulSet Pod template, Kubernetes stores a revision in the StatefulSet history. You can control how many of these revisions are kept by setting [`spec.revisionHistoryLimit`](operator.md#revisionhistorylimit) in the Custom Resource. This is useful when you want fewer stale revisions in the namespace, or when you need to keep more rollback points after frequent configuration changes. + +```yaml +spec: + updateStrategy: SmartUpdate + revisionHistoryLimit: 10 +``` + +When you omit this option, Kubernetes keeps the default of 10 revisions. + ## Update on OpenShift -If you run the Operator on [Red Hat Marketplace :octicons-link-external-16:](https://marketplace.redhat.com) or you run Red Hat certified Operators on [OpenShift :octicons-link-external-16:](https://www.redhat.com/en/technologies/cloud-computing/openshift), you need to do additional steps during the upgrade. See [Upgrade Percona Server for MongoDB on OpenShift](update_openshift.md) for details. +If you run the Operator on [OpenShift :octicons-link-external-16:](https://www.redhat.com/en/technologies/cloud-computing/openshift), you need to do additional steps during the upgrade. See [Upgrade Percona Server for MongoDB on OpenShift](update_openshift.md) for details. \ No newline at end of file From 5bb9eacf419a5a75c4f6674c7bfee145dc74720c Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Mon, 13 Jul 2026 16:16:54 +0300 Subject: [PATCH 09/22] K8SPSMDB-1608 Documented the ExternalDNS configuration (#340) * K8SPSMDB-1608 Documented the ExternalDNS configuration modified: docs/expose.md modified: docs/operator.md --- docs/annotations.md | 5 +- docs/expose.md | 109 +++++++++++++++++++++++++++++++++++++++++++- docs/operator.md | 84 ++++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+), 2 deletions(-) diff --git a/docs/annotations.md b/docs/annotations.md index 5cb77b94..87e92f6e 100644 --- a/docs/annotations.md +++ b/docs/annotations.md @@ -78,6 +78,7 @@ Use **Annotations** when: | `percona.com/ssl-hash` | Pods | Stores the hash of the most recent TLS configuration | | `percona.com/ssl-internal-hash` | Pods | Stores the hash of the most recent TLS configuration for internal communication | | `percona.com/passwords-updated`| Secrets | Indicates when passwords were last updated in the Secret | +| `percona.com/external-dns-managed` | Services | Set by the Operator when External DNS `/hostname` and `/ttl` annotations are generated from values defined in `expose.externalDNS`. Marks ownership of those annotations. Do not set or remove it manually. See [How the Operator manages External DNS annotations](expose.md#how-the-operator-manages-external-dns-annotations). | `"true"` | | `kubectl.kubernetes.io/restartedAt` | PVC | Records the most recent timestamp when the associated resource was intentionally restarted. This annotation is typically used to trigger rolling restarts of StatefulSets, ensuring Pods or PVCs are refreshed according to Kubernetes best practices. | `2026-02-01T12:34:56Z` | ## Setting labels and annotations in the Custom Resource @@ -182,4 +183,6 @@ spec: ... ``` -The label and annotation values must exactly match the ones defined for the Service to be kept. \ No newline at end of file +The label and annotation values must exactly match the ones defined for the Service to be kept. + +External DNS annotations follow separate ownership rules. The Operator manages `external-dns.alpha.kubernetes.io/hostname` and `/ttl` only on Services marked with `percona.com/external-dns-managed`. Manual External DNS annotations on unmarked Services, and other External DNS keys such as `/target` or `/alias`, are preserved and do not need to be listed in `ignoreAnnotations`. See [How the Operator manages External DNS annotations](expose.md#how-the-operator-manages-external-dns-annotations) for details. \ No newline at end of file diff --git a/docs/expose.md b/docs/expose.md index 7b865f83..b3fec92a 100644 --- a/docs/expose.md +++ b/docs/expose.md @@ -103,12 +103,119 @@ To expose Pods externally, configure the following option in the Custom Resource * **`LoadBalancer`**: Exposes the Pod externally using a cloud provider’s load balancer. Both [ClusterIP and NodePort Services are automatically created :octicons-link-external-16:](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) in this variant. + Cloud load balancers often assign long, auto-generated hostnames (for example, `a1b2c3d4e5.elb.amazonaws.com`). To publish stable, human-readable hostnames, configure [External DNS](expose.md#automatic-dns-records-with-external-dns), available in the Operator 1.23.0 and later. To learn more, see [Automatic DNS records with External DNS](#automatic-dns-records-with-external-dns). + If the NodePort type is used, the URI looks like this: -```mongodb://databaseAdmin:databaseAdminPassword@:,:,:/admin?replicaSet=rs0&ssl=false``` +``` +mongodb://databaseAdmin:databaseAdminPassword@:,:,:/admin?replicaSet=rs0&ssl=false +``` All Node addresses should be *directly* reachable by the application. +## Automatic DNS records with External DNS + +Starting from Operator version 1.23.0, you can configure the Operator and [External DNS :octicons-link-external-16:](https://github.com/kubernetes-sigs/external-dns) to work together. + +In the cluster Custom Resource, define how External DNS should create records: specify your `domain` (required) and optionally `prefix` and `ttl` under `expose.externalDNS`. The Operator then adds the `external-dns.alpha.kubernetes.io/hostname` annotation to each exposed per-Pod Service with a unique value in the format `--.`. External DNS reads this annotation and automatically creates a DNS record in your external DNS server: Amazon Route53, Cloud DNS, Azure DNS, or others. + +If you set `ttl`, the Operator also adds `external-dns.alpha.kubernetes.io/ttl` on each Service. The value is the DNS record lifetime in **seconds**. External DNS passes this TTL to your DNS provider when it creates or updates records. Omit `ttl` to let External DNS and the provider use their defaults. + +External DNS continuously watches for resource changes and updates the DNS records automatically when a new Service is created or its configuration or state changes. This automation simplifies connectivity for applications that must reach Percona Server for MongoDB from outside Kubernetes, reduces the risk of misconfiguration and supports environments that scale or change frequently. With `prefix`, you can enforce consistent DNS naming across clusters and environments. + +You can use External DNS for both replica sets and sharded clusters. By assigning DNS hostnames to each `mongod`, `mongos`, and `configsvrReplSet` Pod, you enable applications to connect to any node using simple, human-readable domain names. + +### Prerequisites + +To use External DNS, ensure you have: + +- Services exposed with the type `LoadBalancer`. Check your configuration to have `expose.enabled: true` with `expose.type: LoadBalancer` for replica sets and config servers +- A DNS zone that External DNS can manage for the `domain` you specify + +### Configuration example + +=== "Replica set" + + ```yaml + replsets: + - name: rs0 + size: 3 + expose: + enabled: true + type: LoadBalancer + externalDNS: + prefix: db-prod # optional; defaults to the CR metadata.name + domain: mongo.example.com # required + ttl: 300 # optional; seconds, passed to External DNS + ``` + + After you apply the configuration, the Operator annotates each per-Pod Service for the cluster named `my-cluster-name` like this: + + | Service (example) | `external-dns.alpha.kubernetes.io/hostname` (example) | + | ----------------- | ----------------------------------------------------- | + | `my-cluster-name-rs0-0` | `db-prod-rs0-0.mongo.example.com` | + | `my-cluster-name-rs0-1` | `db-prod-rs0-1.mongo.example.com` | + | `my-cluster-name-rs0-2` | `db-prod-rs0-2.mongo.example.com` | + +=== "Sharded cluster" + + ```yaml + replsets: + - name: rs0 + size: 3 + expose: + enabled: true + type: LoadBalancer + externalDNS: + prefix: db-prod # optional; defaults to the CR metadata.name + domain: mongo.example.com # required + ttl: 300 # optional; DNS TTL in seconds + sharding: + enabled: true + configsvrReplSet: + size: 3 + expose: + enabled: true + type: LoadBalancer + externalDNS: + prefix: shard-prod # optional; defaults to the CR metadata.name + domain: mongo.example.com # required + ttl: 300 # optional; DNS TTL in seconds + mongos: + expose: + enabled: true + type: LoadBalancer + servicePerPod: true # optional, enables service for each mongos pod + externalDNS: + prefix: mongos-prod # optional; defaults to the CR metadata.name + domain: mongo.example.com # required + ttl: 300 # optional; DNS TTL in seconds + ``` + + You can set `expose.externalDNS` under [`sharding.configsvrReplSet`](operator.md#shardingconfigsvrreplsetexposeexternaldnsprefix) and [`sharding.mongos`](operator.md#shardingmongosexposeexternaldnsprefix). Hostname patterns depend on the component: + + | Component | Hostname pattern | + | --------- | ---------------- | + | Replica sets | `{prefix}-{replsetName}-{podIndex}.{domain}` | + | Config servers | `{prefix}-cfgsvr-{podIndex}.{domain}` | + | Mongos with [`servicePerPod`](operator.md#shardingmongosexposeserviceperpod) enabled | `{prefix}-mongos-{podIndex}.{domain}` | + | Mongos with `servicePerPod` disabled | `{prefix}-mongos.{domain}` | + +If you omit `prefix`, the Operator uses `metadata.name` from the custom resource instead. With `metadata.name: my-cluster-name` and no `prefix` field, the hostname for the first Pod would be `my-cluster-name-rs0-0.mongo.example.com`. + +With `ttl: 300`, each Service also gets `external-dns.alpha.kubernetes.io/ttl: "300"`. External DNS uses that value when publishing the record; check your DNS provider for allowed TTL ranges and minimums. + +### How the Operator manages External DNS annotations + +The Operator owns the External DNS annotations it generates. The rules are: + +- When the Operator annotates the Service with the `external-dns.alpha.kubernetes.io/hostname` (and `/ttl`, if set) annotations defined via the Custom Resource, it also adds the `percona.com/external-dns-managed: "true"` annotation to this Service. The Operator uses this marker to track its ownership over the Service. Do not set or remove the `percona.com/external-dns-managed: "true"` annotation manually. +- For the Service annotated with `percona.com/external-dns-managed: "true"`, the `/hostname` and `/ttl` always follow the Custom Resource. The Operator overwrites manual edits of these two annotations on the next reconcile. To customize them, use the `externalDNS` section of the Custom Resource. +* If you edit or remove the `expose.externalDNS` configuration in the Custom Resource, the operator-written `/hostname` and `/ttl` annotations on the Services are edited or removed accordingly. External DNS then deletes the DNS records for the disabled or changed configuration. +* External DNS annotations that you add manually on Services without the `percona.com/external-dns-managed: "true"` marker, and any other External DNS keys (for example `/target` or `/alias`) on any Service, are never modified by the Operator. The manual per-Service annotation workflow keeps working. +* If `expose.annotations` already contains `external-dns.alpha.kubernetes.io/hostname`, the Operator replaces it with the hostname from `expose.externalDNS`. +* If `externalDNS` is set while `expose.enabled` is `false` (replica sets and config servers), the Operator does not add DNS annotations. + ## Service per Pod To make all database Pods accessible, Percona Operator for MongoDB can assign a [Kubernetes Service :octicons-link-external-16:](https://kubernetes.io/docs/concepts/services-networking/service/) to each Pod. This Service per Pod option allows your application to handle Cursor tracking instead of relying on a single Service. This solves the problem of `CursorNotFound` errors that occur when a Service transparently cycles between mongos instances while your client is still iterating a cursor on a large collection. diff --git a/docs/operator.md b/docs/operator.md index a6d0cd83..56327e8c 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -1168,6 +1168,34 @@ Specifies whether Service for MongoDB instances [should route external traffic : Starting from Operator version 1.22.0, the Operator automatically sets `appProtocol: mongo` on Service ports for replica sets. This is required for service mesh implementations (such as Istio) because MongoDB uses a server-first protocol, which breaks mTLS without explicit protocol specification. The `appProtocol` field is set automatically and cannot be configured manually. +### `replsets.expose.externalDNS.prefix` + +DNS label prefix for automatically generated hostnames for each per-Pod Service using the External DNS controller. The hostnames are generated in the form `{prefix}-{replsetName}-{podIndex}.{domain}`. + +!!! note + + The Operator owns `external-dns.alpha.kubernetes.io/hostname` and `/ttl` on Services marked with `percona.com/external-dns-managed: "true"`. Customize those values through this section; do not edit the annotations on the Service directly. See [How the Operator manages External DNS annotations](expose.md#how-the-operator-manages-external-dns-annotations). + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `my-cluster` | + +### `replsets.expose.externalDNS.domain` + +Base domain for automatically generated hostnames by the External DNS Controller. Must be a valid domain name. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `mongo.example.com` | + +### `replsets.expose.externalDNS.ttl` + +Optional TTL in seconds for the `external-dns.alpha.kubernetes.io/ttl` annotation on each per-Pod Service. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `300` | + ### `replsets.nonvoting.enabled` Enable or disable creation of [Replica Set non-voting instances](arbiter.md#non-voting-nodes) within the cluster. @@ -2417,6 +2445,34 @@ Specifies whether Service for config servers [should route external traffic :oct Starting from Operator version 1.22.0, the Operator automatically sets `appProtocol: mongo` on Service ports for config servers. This is required for service mesh implementations (such as Istio) because MongoDB uses a server-first protocol, which breaks mTLS without explicit protocol specification. The `appProtocol` field is set automatically and cannot be configured manually. +### `sharding.configsvrReplSet.expose.externalDNS.prefix` + +DNS label prefix for automatically generated hostnames for each per-Pod Service for the config servers using the External DNS controller. The hostnames are generated in the form `{prefix}-cfgsvr-{podIndex}.{domain}`. + +!!! note + + The Operator owns `external-dns.alpha.kubernetes.io/hostname` and `/ttl` on Services marked with `percona.com/external-dns-managed: "true"`. Customize those values through this section; do not edit the annotations on the Service directly. See [How the Operator manages External DNS annotations](expose.md#how-the-operator-manages-external-dns-annotations). + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `my-cluster` | + +### `sharding.configsvrReplSet.expose.externalDNS.domain` + +Base domain for automatically generated hostnames by the External DNS controller for config servers. Must be a valid domain name. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `mongo.example.com` | + +### `sharding.configsvrReplSet.expose.externalDNS.ttl` + +Optional TTL in seconds for the `external-dns.alpha.kubernetes.io/ttl` annotation on each per-Pod Service. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `300` | + ### `sharding.configsvrReplSet.volumeSpec.emptyDir` The [Kubernetes emptyDir volume :octicons-link-external-16:](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir), i.e. the directory which will be created on a node, and will be accessible to the Config Server Pod containers. @@ -2957,6 +3013,34 @@ Specifies whether Service for the mongos instances [should route external traffi Starting from Operator version 1.22.0, the Operator automatically sets `appProtocol: mongo` on Service ports for mongos instances. This is required for service mesh implementations (such as Istio) because MongoDB uses a server-first protocol, which breaks mTLS without explicit protocol specification. The `appProtocol` field is set automatically and cannot be configured manually. +### `sharding.mongos.expose.externalDNS.prefix` + +DNS label prefix for automatically generated hostnames for each per-Pod Service for the mongos using the External DNS controller. The hostnames are generated in the form `{prefix}-mongos-{podIndex}.{domain}`. + +!!! note + + The Operator owns `external-dns.alpha.kubernetes.io/hostname` and `/ttl` on Services marked with `percona.com/external-dns-managed: "true"`. Customize those values through this section; do not edit the annotations on the Service directly. See [How the Operator manages External DNS annotations](expose.md#how-the-operator-manages-external-dns-annotations). + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `my-cluster` | + +### `sharding.mongos.expose.externalDNS.domain` + +Base domain for automatically generated hostnames by the External DNS controller for mongos. Must be a valid domain name. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `mongo.example.com` | + +### `sharding.mongos.expose.externalDNS.ttl` + +Optional TTL in seconds for the `external-dns.alpha.kubernetes.io/ttl` annotation on each per-Pod Service. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `300` | + ### `sharding.mongos.hostAliases.ip` The IP address for [Kubernetes host aliases :octicons-link-external-16:](https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/) for mongos Pods. From 2d8b8f25552323c5b86050485e50896c8d6a79ab Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Mon, 20 Jul 2026 09:32:46 +0300 Subject: [PATCH 10/22] K8SPSMDB-1543 Documented user deletion policy (#365) * K8SPSMDB-1543 Documented user deletion policy --- docs/app-users.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/app-users.md b/docs/app-users.md index 95b767e0..5681605b 100644 --- a/docs/app-users.md +++ b/docs/app-users.md @@ -12,7 +12,6 @@ Regardless of how you create users, their usernames must be unique. ## Create users via Custom Resource Starting from Operator version 1.17.0, you can create users in Percona Server for MongoDB via the `users` subsection in the Custom Resource. This is called declarative user management. -{.power-number} You can modify the `users` section in the `deploy/cr.yaml` configuration file either at cluster creation time or adjust it over time. @@ -40,11 +39,18 @@ users: After you apply the configuration, the Operator creates a Secret named `-custom-user-secret`, generates a password for the user, and sets it by the key named after the user name. +!!! note "External database users" + + The Operator doesn't generate passwords for users created in the **`$external`** database. You can't set the `passwordSecretRef` for these users either. + + Such users are used for authentication via an external authentication source, such as an LDAP server. The user credentials are stored in an external authentication source, and their usernames are mapped to those in the `$external` database during authentication. + ### Generate user passwords manually If you don't want the Operator to generate a user password automatically, you can create a Secret resource that contains the user password. Then specify a reference to this Secret resource in the `passwordSecretRef` key. You can find a detailed description of the corresponding options in the [Custom Resource reference](operator.md#operator-users-section). Here's how to do it: +{.power-number} 1. Create a Secret configuration file: @@ -87,12 +93,6 @@ Here's how to do it: kubectl apply -f deploy/cr.yaml ``` -!!! note "External database users" - - The Operator doesn't generate passwords for users created in the **`$external`** database. You can't set the `passwordSecretRef` for these users either. - - Such users are used for authentication via an external authentication source, such as an LDAP server. The user credentials are stored in an external authentication source, and their usernames are mapped to those in the `$external` database during authentication. - The Operator tracks password changes in the Secret object and updates the user password in the database. This applies to [manually created users](#create-users-manually) as well: if a user was created manually in the database before creating the user via Custom Resource, the existing user is updated. However, manual password updates in the database are not tracked: the Operator doesn't overwrite changed passwords with the old ones from the users Secret. @@ -141,6 +141,14 @@ roles: Find more information about available options and their accepted values in the [roles subsection of the Custom Resource reference](operator.md#roles-section). +### Delete users and roles + +You can unassign a role from a user by updating the Custom Resource. Upon reconciliation, the Operator updates the user record in the database. + +However, the Operator does not delete users when they are removed from the Custom Resource. This prevents accidental removal of pre-existing users. + +To delete a user or a role, remove its entry from the Custom Resource and delete it from the database. + ## Create users manually You can create application-level users manually. Run the commands below, substituting the `` placeholder with the real namespace of your database cluster: From 71d418f1c3f40d6a473e00f8a2b9b95bc8bc925a Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 10:51:37 +0300 Subject: [PATCH 11/22] K8SPSMDB-1519 Documented the support of Alibaba OSS (#358) * K8SPSMDB-1519 Documented the support of Alibaba OSS modified: docs/backups-storage.md modified: docs/backups.md modified: docs/operator.md modified: mkdocs-base.yml new file:docs/backups-storage-oss.md --- docs/backups-storage-oss.md | 179 +++++++++++ ...ckups-storage-s3-instance-profile-draft.md | 281 ------------------ docs/backups-storage.md | 2 + docs/backups.md | 1 + docs/operator.md | 122 +++++++- mkdocs-base.yml | 1 + 6 files changed, 304 insertions(+), 282 deletions(-) create mode 100644 docs/backups-storage-oss.md delete mode 100644 docs/backups-storage-s3-instance-profile-draft.md diff --git a/docs/backups-storage-oss.md b/docs/backups-storage-oss.md new file mode 100644 index 00000000..9a4ec55b --- /dev/null +++ b/docs/backups-storage-oss.md @@ -0,0 +1,179 @@ +# Alibaba Cloud Object Storage Service (OSS) + +!!! note "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +If you operate in the Asia-Pacific or China region, or already run workloads on Alibaba Cloud, you can use Alibaba Cloud Object Storage Service (OSS) as the remote backup storage. This way you can keep backup traffic in the same cloud, which helps reduce latency and simplifies compliance. + +To use [Alibaba Cloud Object Storage Service (OSS) :octicons-link-external-16:](https://www.alibabacloud.com/product/object-storage-service) as a remote store for backups, you need the following: + +* An Alibaba Cloud account with the Object Storage Service (OSS) enabled for it +* An OSS bucket. Refer to the [bucket naming conventions :octicons-link-external-16:](https://www.alibabacloud.com/help/en/oss/user-guide/bucket-naming-conventions) for requirements +* Access to the Resource Access Management (RAM) console and sufficient permissions to create and manage access policies and users. Read more about using RAM with Alibaba Cloud OSS in the [official documentation :octicons-link-external-16:](https://www.alibabacloud.com/help/en/oss/user-guide/how-oss-works-with-ram). + +**Configuration steps** +{.power-number} + +1. Create an OSS bucket in the [Alibaba Cloud Management Console :octicons-link-external-16:](https://www.alibabacloud.com/help/en/oss/user-guide/create-buckets-4/), or with the [`ossutil` :octicons-link-external-16:](https://www.alibabacloud.com/help/en/oss/developer-reference/ossutil-overview) CLI. Note the bucket name, region, and endpoint URL (for example, `https://oss-eu-central-1.aliyuncs.com`). + +2. Create a RAM user and grant it permissions to access the bucket. Create an AccessKey pair for that user. See [Configure access to Alibaba Cloud OSS for PBM :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/details/oss.html#configure-access-to-alibaba-cloud-oss-for-pbm) for permission guidance. + +3. Encode your AccessKey ID and AccessKey secret with base64: + + === ":simple-linux: in Linux" + + ```bash + echo -n 'plain-text-string' | base64 --wrap=0 + ``` + + === ":simple-apple: in macOS" + + ```bash + echo -n 'plain-text-string' | base64 + ``` + +4. Create a Kubernetes Secret manifest with the encoded credentials: + + ```yaml title="backup-oss-secret.yaml" + apiVersion: v1 + kind: Secret + metadata: + name: my-cluster-name-backup-oss + type: Opaque + data: + ALIBABA_ACCESS_KEY_ID: + ALIBABA_ACCESS_KEY_SECRET: + ``` + +5. Create the Secret in your cluster. Replace the `` placeholder with your value: + + ```bash + kubectl apply -f backup-oss-secret.yaml -n + ``` + +6. Configure the OSS storage in the `deploy/cr.yaml` Custom Resource. Specify the following information: + + * Set `storages.NAME.type` to `oss`. Substitute the `NAME` part with a name you will later use to refer to this storage when making backups and restores. + * Specify the bucket name for the `storages.NAME.oss.bucket` option + * Specify the Secret name for the `storages.NAME.oss.credentialsSecret` option + * Specify the OSS endpoint for the `storages.NAME.oss.endpointUrl` option + * Specify the bucket region for the `storages.NAME.oss.region` option + * Optionally, set `storages.NAME.oss.prefix` to store backups in a sub-folder. If you don't set a prefix, backups are stored in the root of the bucket + + ```yaml + backup: + storages: + alibaba-oss: + type: oss + oss: + bucket: OSS-BACKUP-BUCKET-NAME-HERE + prefix: "some-prefix" + credentialsSecret: my-cluster-name-backup-oss + endpointUrl: https://oss-eu-central-1.aliyuncs.com + region: eu-central-1 + ``` + + These and other options within the `storages.NAME.oss` subsection are further described in the [Operator Custom Resource options](operator.md#operator-backup-section). + +7. Apply the configuration: + + ```bash + kubectl apply -f deploy/cr.yaml -n + ``` + +## Optional settings + +You can fine-tune OSS uploads and encryption in the same `oss` block. + +### Upload retries and multipart settings + +Use these options to improve reliability on unstable networks and to control multipart uploads: + +```yaml +backup: + storages: + alibaba-oss: + type: oss + oss: + bucket: OSS-BACKUP-BUCKET-NAME-HERE + credentialsSecret: my-cluster-name-backup-oss + endpointUrl: https://oss-eu-central-1.aliyuncs.com + region: eu-central-1 + connectTimeout: 10s + uploadPartSize: 10485760 + maxUploadParts: 10000 + retryer: + maxAttempts: 3 + maxBackoff: 5m + baseDelay: 1s +``` + +### Server-side encryption + +OSS supports server-side encryption with OSS-managed keys (SSE-OSS) or with customer master keys in Alibaba Cloud Key Management Service (SSE-KMS). Configure encryption under `serverSideEncryption`. + +Provide the encryption key either directly in the Custom +Resource with `encryptionKeyId`, or in a dedicated Secret +referenced by `secretName`. When you use a Secret, it must +contain the `SSE_CUSTOMER_KEY` key. + +=== "With encryptionKeyId in a Secret" + + To keep the key out of the Custom Resource, create a Kubernetes Secret that includes the `SSE_CUSTOMER_KEY` value and reference it with `secretName`. + + 1. Create the Secret manifest. For example: + + ```yaml title="oss-sse-key.yaml" + apiVersion: v1 + kind: Secret + metadata: + name: my-cluster-name-backup-oss-sse + type: Opaque + stringData: + SSE_CUSTOMER_KEY: "OSS-KMS-KEY-ID-HERE" + ``` + + 2. Create the Secret object: + + ```bash + kubectl apply -f oss-sse-key.yaml -n + ``` + + 3. Reference this Secret in your storage configuration: + + ```yaml + backup: + storages: + alibaba-oss: + type: oss + oss: + bucket: OSS-BACKUP-BUCKET-NAME-HERE + credentialsSecret: my-cluster-name-backup-oss + endpointUrl: https://oss-eu-central-1.aliyuncs.com + region: eu-central-1 + serverSideEncryption: + secretName: my-cluster-name-backup-oss-sse + encryptionMethod: sse + encryptionAlgorithm: KMS + ``` + +=== "With encryptionKeyId in the Custom Resource" + + Provide the encryption key directly in the Custom Resource with `encryptionKeyId`: + + ```yaml + backup: + storages: + alibaba-oss: + type: oss + oss: + bucket: OSS-BACKUP-BUCKET-NAME-HERE + credentialsSecret: my-cluster-name-backup-oss + endpointUrl: https://oss-eu-central-1.aliyuncs.com + region: eu-central-1 + serverSideEncryption: + encryptionMethod: sse + encryptionAlgorithm: KMS + encryptionKeyId: OSS-KMS-KEY-ID-HERE + ``` + +For encryption types, RAM permissions, and PBM-side details, see [Server-side encryption in PBM :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/details/oss.html#server-side-encryption). diff --git a/docs/backups-storage-s3-instance-profile-draft.md b/docs/backups-storage-s3-instance-profile-draft.md deleted file mode 100644 index 676a5378..00000000 --- a/docs/backups-storage-s3-instance-profile-draft.md +++ /dev/null @@ -1,281 +0,0 @@ -# Draft: IAM instance profile section for backups-storage-s3.md - -This file contains the proposed **Automate access to Amazon S3 using IAM instance profile** section. Replace lines 465–473 in `backups-storage-s3.md` with the content below (from `## Automate access` through the end of the instance profile section). - ---- - -## Automate access to Amazon S3 using IAM instance profile - -An [IAM instance profile :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) attaches an IAM role to EC2 instances. When your Kubernetes worker nodes run on EC2, Pods obtain AWS credentials through the [EC2 instance metadata service (IMDS) :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html). You do not store AWS access keys in a Kubernetes Secret. Instead, Percona Backup for MongoDB uses the AWS default credential provider chain and receives credentials from the worker node automatically. - -Use this method when your cluster runs on EC2 worker nodes and IRSA is not configured—for example, in self-managed Kubernetes clusters on EC2. All Pods on the same worker node share the node's IAM permissions. - -### Prerequisites - -Before you start, make sure you have the following: - -* A Kubernetes cluster whose worker nodes run on EC2 -* The [Operator and database deployed](kubectl.md), or ready to deploy -* An S3 bucket for backups -* The [AWS CLI :octicons-link-external-16:](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) and [kubectl :octicons-link-external-16:](https://kubernetes.io/docs/tasks/tools/) installed and configured -* Your AWS account ID. You can get it with: - - ```bash - aws sts get-caller-identity --query Account --output text - ``` - -Set environment variables for the commands below. Replace the placeholders with your values: - -```bash -export aws_region= -export s3_bucket= -export policy_name= -export role_name= -export instance_profile_name= -export namespace= -export account_id=$(aws sts get-caller-identity --query Account --output text) -``` - -### Configure the IAM role and instance profile -{.power-number} - -1. Create an IAM policy that grants access to your S3 bucket. Replace `` with your bucket name: - - ```json title="s3-bucket-policy.json" - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:*" - ], - "Resource": [ - "arn:aws:s3:::", - "arn:aws:s3:::/*" - ] - } - ] - } - ``` - - !!! tip - - The example uses broad `s3:*` permissions for simplicity. In production, restrict the policy to the specific S3 actions your backup and restore workflows require. Refer to the [Amazon S3 permissions documentation :octicons-link-external-16:](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html) and tailor the policy to follow the principle of least privilege. - -2. Create the IAM policy: - - ```bash - aws iam create-policy \ - --policy-name $policy_name \ - --policy-document file://s3-bucket-policy.json - ``` - -3. Create a trust policy that allows EC2 instances to assume the role: - - ```json title="ec2-trust-policy.json" - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": "ec2.amazonaws.com" - }, - "Action": "sts:AssumeRole" - } - ] - } - ``` - -4. Create the IAM role: - - ```bash - aws iam create-role \ - --role-name $role_name \ - --assume-role-policy-document file://ec2-trust-policy.json \ - --description "Allow EC2 worker nodes to access S3 backups" - ``` - -5. Attach the S3 policy to the role: - - ```bash - aws iam attach-role-policy \ - --role-name $role_name \ - --policy-arn arn:aws:iam::${account_id}:policy/${policy_name} - ``` - -6. Create an instance profile and add the role to it: - - ```bash - aws iam create-instance-profile \ - --instance-profile-name $instance_profile_name - - aws iam add-role-to-instance-profile \ - --instance-profile-name $instance_profile_name \ - --role-name $role_name - ``` - - !!! note "EKS clusters without IRSA" - - Amazon EKS worker nodes already have an instance profile through the node group IAM role. Instead of creating a new instance profile, attach the S3 policy from step 2 to the existing node group role. Skip steps 6–7 in the next section and apply the policy to that role. - -### Attach the instance profile to worker nodes -{.power-number} - -1. Attach the instance profile to each EC2 worker node in your cluster. The exact steps depend on how you manage your nodes: - - * **Self-managed clusters:** Attach the profile when you launch instances, or associate it with running instances: - - ```bash - aws ec2 associate-iam-instance-profile \ - --instance-id \ - --iam-instance-profile Name=$instance_profile_name - ``` - - * **Auto Scaling groups:** Update the launch template or Auto Scaling group to use `$instance_profile_name`. - -2. If you changed the instance profile on running nodes, restart the Operator and database Pods so backup agents pick up the new credentials: - - ```bash - kubectl rollout restart deployment/percona-server-mongodb-operator -n $namespace - kubectl rollout status deployment/percona-server-mongodb-operator -n $namespace - ``` - -3. Verify that worker nodes expose IAM credentials through IMDS. Run this command from a database Pod: - - ```bash - kubectl exec -it -n $namespace -- \ - curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ - ``` - - ??? example "Sample output" - - ```{.text .no-copy} - my-ec2-role - ``` - - The output should show the IAM role name attached to the worker node. - -### Configure Percona Server for MongoDB cluster - -Now you are ready to configure Percona Server for MongoDB to use the instance profile for backups. - -=== "A new cluster deployment" - - 1. Edit the `backup.storages` subsection in `deploy/cr.yaml` Custom Resource manifest. Give your storage a name (default name is `s3-us-west`) and set the following keys: - - * `type` - make sure the type is `s3` - * `bucket` - where the data will be stored - * `region` - location of the bucket - * `prefix` (optional) - a path (sub-folder) inside the S3 bucket where backups will be stored. If you don't set a prefix, backups are stored in the root directory. - * Omit `s3.credentialsSecret` so that PBM uses the worker node's instance profile to access the S3 storage. - - Here's the example configuration: - - ```yaml - ... - backup: - enabled: true - ... - storages: - aws-s3: - type: s3 - s3: - bucket: - region: - prefix: data/pbm - ... - ``` - - For more storage options, see the [Operator Custom Resource options](operator.md#operator-backup-section). - - 2. Apply the configuration and deploy the cluster: - - ```bash - kubectl apply -f deploy/cr.yaml -n $namespace - ``` - - 3. Wait for the cluster to report the `ready` status: - - ```bash - kubectl get psmdb -n $namespace - ``` - -=== "Existing cluster" - - If your running Percona Server for MongoDB cluster is currently using a Kubernetes Secret with S3 credentials for backups, you can switch to an instance profile by following these steps: - - 1. [Attach the instance profile to worker nodes](#attach-the-instance-profile-to-worker-nodes), if you have not done so already. - - 2. Make a rolling restart of the database Pods. - - * Export the cluster name as an environment variable: - - ```bash - export DBCLUSTER=my-cluster-name - ``` - - * Use the following for loop: - - ```bash - for i in 0 1 2; do - kubectl delete pod $DBCLUSTER-rs0-$i -n $namespace - done - ``` - - 3. Restart the Operator Deployment: - - ```bash - kubectl rollout restart deployment/percona-server-mongodb-operator -n $namespace - ``` - - 4. Remove the credentials Secret by patching the cluster. The storage name in the following command is `aws-s3`. Replace it with your value if you use another name: - - ```bash - kubectl -n $namespace patch psmdb $DBCLUSTER --type=json \ - -p '[{"op":"remove","path":"/spec/backup/storages/aws-s3/s3/credentialsSecret"}]' - sleep 30 - ``` - -### Verify access to S3 using IAM instance profile - -1. Run an on-demand backup to confirm that the cluster can write to the S3 bucket. Here's the example of the backup object configuration: - - ```yaml title="deploy/backup/backup.yaml" - apiVersion: psmdb.percona.com/v1 - kind: PerconaServerMongoDBBackup - metadata: - name: backup1 - finalizers: - - percona.com/delete-backup - spec: - clusterName: my-cluster-name - storageName: aws-s3 - ``` - -2. Apply the configuration to start the backup: - - ```bash - kubectl apply -f deploy/backup/backup.yaml -n $namespace - ``` - -3. Check the backup progress: - - ```bash - kubectl get psmdb-backup -n $namespace - ``` - - When the backup reaches the `ready` status, the instance profile configuration is working. - -### Troubleshooting - -#### Backup fails with access denied - -* Confirm that the IAM policy is attached to the role associated with the worker node's instance profile. -* Make sure `s3.credentialsSecret` is not set in the Custom Resource. Secret-based credentials override instance profile credentials. -* Verify that Pods can reach IMDS. Some environments block the metadata endpoint or require [IMDSv2 :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configured-instance-metadata-service.html). - -#### All Pods on the node share the same permissions - -This is expected behavior for instance profiles. If you need per-Pod S3 permissions, use [IRSA](#automate-access-to-amazon-s3-using-irsa) on EKS instead. diff --git a/docs/backups-storage.md b/docs/backups-storage.md index 9fa5484d..fe678432 100644 --- a/docs/backups-storage.md +++ b/docs/backups-storage.md @@ -10,6 +10,7 @@ The Operator provides several storage types for different storages. To help you * **minio** - Use this storage type for MinIO and other S3-compatible services that don't support SigV4 or require endpoint configuration that works better with the `minio` storage type. * **gcp** - Use this storage type for Google Cloud Storage. * **azure** - Use this storage type for Microsoft Azure Blob storage. +* **oss** - Use this storage type for Alibaba Cloud Object Storage Service (OSS). * **filesystem** - Use this storage type for uploading backups to a remote file server. For each backup storage, create a [Kubernetes Secret :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/secret/) object with credentials and reference it in the Custom Resource. @@ -22,4 +23,5 @@ Use the page for your storage type: * [MinIO and S3-compatible storages](backups-storage-minio.md) * [Google Cloud storage](backups-storage-gcp.md) * [Microsoft Azure Blob storage](backups-storage-azure.md) +* [Alibaba Cloud OSS storage](backups-storage-oss.md) * [Remote file server](backups-storage-filesystem.md) diff --git a/docs/backups.md b/docs/backups.md index d49597a1..094e15f8 100644 --- a/docs/backups.md +++ b/docs/backups.md @@ -78,6 +78,7 @@ cluster using the following remote backup storages: * [Google Cloud storage](backups-storage-gcp.md) * [MinIO and S3-compatible storages](backups-storage-minio.md) * [Microsoft Azure Blob storage](backups-storage-azure.md) +* [Alibaba Cloud OSS storage](backups-storage-oss.md) * [Remote file server](backups-storage-filesystem.md) ![image](assets/images/backup-cloud.svg) diff --git a/docs/operator.md b/docs/operator.md index 56327e8c..be2ba431 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -3304,7 +3304,7 @@ Marks the storage as main. All other storages you define are added as profiles. ### `backup.storages.STORAGE-NAME.type` -The cloud storage type used for backups. Only `s3`, `gcs`, `minio`, `azure`, and `filesystem` types are supported. +The cloud storage type used for backups. Supported types are: `s3`, `gcs`, `minio`, `azure`, `oss`, and `filesystem`. | Value type | Example | | ----------- | ---------- | @@ -3599,6 +3599,126 @@ The [private endpoint URL :octicons-link-external-16:](https://learn.microsoft.c | ----------- | ---------- | | :material-code-string: string | `https://accountName.blob.core.windows.net` | +### `backup.storages.STORAGE-NAME.oss.credentialsSecret` + +The [Kubernetes secret :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/secret/) for backups. It should contain `ALIBABA_ACCESS_KEY_ID` and `ALIBABA_ACCESS_KEY_SECRET` keys. See [Alibaba Cloud OSS storage](backups-storage-oss.md) for setup steps. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `my-cluster-name-backup-oss` | + +### `backup.storages.STORAGE-NAME.oss.bucket` + +The [Alibaba Cloud OSS bucket :octicons-link-external-16:](https://www.alibabacloud.com/help/en/oss/user-guide/bucket-overview) name for backups. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | | + +### `backup.storages.STORAGE-NAME.oss.prefix` + +The path (sub-folder) to the backups inside the bucket. If undefined, backups are stored in the bucket's root directory. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `""` | + +### `backup.storages.STORAGE-NAME.oss.endpointUrl` + +The endpoint URL of the Alibaba Cloud OSS service for the selected region. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `https://oss-eu-central-1.aliyuncs.com` | + +### `backup.storages.STORAGE-NAME.oss.region` + +The [Alibaba Cloud OSS region :octicons-link-external-16:](https://www.alibabacloud.com/help/en/oss/user-guide/regions-and-endpoints) where the bucket is located. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `eu-central-1` | + +### `backup.storages.STORAGE-NAME.oss.connectTimeout` + +The timeout for establishing a connection to Alibaba Cloud OSS. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `10s` | + +### `backup.storages.STORAGE-NAME.oss.uploadPartSize` + +The size of data chunks in bytes to be uploaded to the storage bucket (10 MiB by default). + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `10485760` | + +### `backup.storages.STORAGE-NAME.oss.maxUploadParts` + +The maximum number of data chunks to be uploaded to the storage bucket (10000 by default). + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `10000` | + +### `backup.storages.STORAGE-NAME.oss.retryer.maxAttempts` + +The maximum number of retries to upload data to Alibaba Cloud OSS. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `3` | + +### `backup.storages.STORAGE-NAME.oss.retryer.maxBackoff` + +The maximum time to wait until the next retry. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `5m` | + +### `backup.storages.STORAGE-NAME.oss.retryer.baseDelay` + +The base delay before the first retry. Later retries use exponential backoff up to `maxBackoff`. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `1s` | + +### `backup.storages.STORAGE-NAME.oss.serverSideEncryption.secretName` + +The [Kubernetes secret :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/secret/) that stores the encryption key for [OSS server-side encryption](backups-storage-oss.md#server-side-encryption). It must contain the `SSE_CUSTOMER_KEY` key. Use either `secretName` or [`encryptionKeyId`](#backupstoragesstorage-nameossserversideencryptionencryptionkeyid). + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `my-cluster-name-backup-oss-sse` | + +### `backup.storages.STORAGE-NAME.oss.serverSideEncryption.encryptionMethod` + +The encryption method used for [OSS server-side encryption](backups-storage-oss.md#server-side-encryption). Supported value: `sse`. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `sse` | + +### `backup.storages.STORAGE-NAME.oss.serverSideEncryption.encryptionAlgorithm` + +The encryption algorithm used for [OSS server-side encryption](backups-storage-oss.md#server-side-encryption). Use `AES256` for OSS-managed keys (SSE-OSS) or `KMS` for Alibaba Cloud Key Management Service (SSE-KMS). + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `KMS` | + +### `backup.storages.STORAGE-NAME.oss.serverSideEncryption.encryptionKeyId` + +The ID of the customer master key in [Alibaba Cloud Key Management Service :octicons-link-external-16:](https://www.alibabacloud.com/help/en/kms/product-overview/what-is-key-management-service) used for [OSS server-side encryption](backups-storage-oss.md#server-side-encryption). Use either `encryptionKeyId` or [`secretName`](#backupstoragesstorage-nameossserversideencryptionsecretname). + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `""` | + ### `backup.storages.STORAGE-NAME.filesystem.path` The mount point for a remote filesystem configured to store backups. diff --git a/mkdocs-base.yml b/mkdocs-base.yml index 0887e7be..bd460b9c 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -272,6 +272,7 @@ nav: - "MinIO and S3-compatible storages": backups-storage-minio.md - "Google Cloud storage": backups-storage-gcp.md - "Microsoft Azure Blob storage": backups-storage-azure.md + - "Alibaba Cloud OSS storage": backups-storage-oss.md - "Remote file server": backups-storage-filesystem.md - multi-storage.md - "Store operations logs for point-in-time recovery": backups-pitr.md From 7355e81d9d26c6360a16d112f91a97aa2b3e98d1 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 10:52:12 +0300 Subject: [PATCH 12/22] K8SPSMDB-1530 Updated the API doc to address requested use cases (#367) K8SPSMDB-1530 Updated the API doc to address requested use cases * Added clarification reg adding/removing rs * Converted commands to tabs --- docs/api.md | 852 +++++++++++++++++++++++++++++----------------------- 1 file changed, 472 insertions(+), 380 deletions(-) diff --git a/docs/api.md b/docs/api.md index 9c1b37d9..2d22464f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,513 +1,605 @@ -# Percona Operator for MongoDB API Documentation +# Manage clusters with the Kubernetes API -Percona Operator for MongoDB provides an [aggregation-layer extension for the Kubernetes API :octicons-link-external-16:](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/). Please refer to the -[official Kubernetes API documentation :octicons-link-external-16:](https://kubernetes.io/docs/reference/) on the API access and usage details. -The following subsections describe the Percona XtraDB Cluster API provided by the Operator. +Percona Operator for MongoDB extends the [Kubernetes API :octicons-link-external-16:](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) with Custom Resources (CRs). You manage database clusters the same way you manage other Kubernetes objects: -## Prerequisites +* with `kubectl` +* with Kubernetes client libraries in your programming language +* with HTTPS requests to the Kubernetes API server. For example, with `curl`. +This page shows common `kubectl` and `curl` examples for these Custom Resources: -1. Create the namespace name you will use, if not exist: +| Kind | Short name | Purpose | +| --- | --- | --- | +| `PerconaServerMongoDB` | `psmdb` | Database cluster definition and desired state | +| `PerconaServerMongoDBBackup` | `psmdb-backup` | On-demand backup request and backup status | +| `PerconaServerMongoDBRestore` | `psmdb-restore` | Restore request and restore status | - ```bash - kubectl create namespace my-namespace-name - ``` +For every field and option, see: - Trying to create an already-existing namespace will show you a - self-explanatory error message. Also, you can use the `default` namespace. +* [Custom Resource options](operator.md) +* [Backup Resource options](backup-resource-options.md) +* [Restore options](restore-options.md) +* [Custom resource statuses](cr-statuses.md) - !!! note +For general Kubernetes API access and authentication, see the [official Kubernetes API documentation :octicons-link-external-16:](https://kubernetes.io/docs/reference/). - In this document `default` namespace is used in all examples. - Substitute `default` with your namespace name if you use a different - one. +## Prerequisites -2. Prepare: +1. Deploy the Operator and install the CRDs in your cluster. See [Install on Kubernetes](kubectl.md). + +2. Create a namespace (or use an existing one) and export it: + + ```bash + export NAMESPACE=my-namespace-name + kubectl create namespace $NAMESPACE + ``` + +3. Set the API server address: ```bash # set correct API address KUBE_CLUSTER=$(kubectl config view --minify -o jsonpath='{.clusters[0].name}') API_SERVER=$(kubectl config view -o jsonpath="{.clusters[?(@.name==\"$KUBE_CLUSTER\")].cluster.server}" | sed -e 's#https://##') - - # create service account and get token - kubectl apply --server-side -f deploy/crd.yaml -f deploy/rbac.yaml -n default - KUBE_TOKEN=$(kubectl get secret $(kubectl get serviceaccount percona-server-mongodb-operator -o jsonpath='{.secrets[0].name}' -n default) -o jsonpath='{.data.token}' -n default | base64 --decode ) ``` -## Create new Percona Server for MongoDB cluster - -**Description:** - -```text -The command to create a new Percona Server for MongoDB cluster -``` - -**Kubectl Command:** - -```bash -kubectl apply -f percona-server-mongodb-operator/deploy/cr.yaml -``` - -**URL:** - -```text -https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/default/perconaservermongodbs -``` - -**Authentication:** - -```text -Authorization: Bearer $KUBE_TOKEN -``` - -**cURL Request:** - -```bash -curl -k -v -XPOST "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/default/perconaservermongodbs" \ - -H "Content-Type: application/json" \ - -H "Accept: application/json" \ - -H "Authorization: Bearer $KUBE_TOKEN" \ - -d "@cluster.json" -``` - -**Request Body (cluster.json):** - -??? example - - --8<-- "cli/api-create-cluster-request-json.md" - -**Inputs:** - -> **Metadata**: - - -> 1. Name (String, min-length: 1) : `contains name of cluster` - -> **Spec**: - - -> 1. secrets[users] (String, min-length: 1) : `contains name of secret for the users` - - -> 2. allowUnsafeConfigurations (Boolean, Default: false) : `allow unsafe configurations to run` - - -> 3. image (String, min-length: 1) : `name of the Percona Server for MongoDB cluster image` - -> replsets: - - -> 1. name (String, min-length: 1) : `name of monogo replicaset` - - -> 2. size (Integer, min-value: 1) : `contains size of MongoDB replicaset` - - -> 3. expose[exposeType] (Integer, min-value: 1) : `type of service to expose replicaset` - - -> 4. arbiter (Object) : `configuration for mongo arbiter` - -> mongod: - - -> 1. net: - - -> 1. port (Integer, min-value: 0) : `contains mongod container port` - - -> 2. hostPort (Integer, min-value: 0) : `host port to expose mongod on` - - -> 2. security: - - -> 1. enableEncryption (Boolean, Default: true) : `enable encrypting mongod storage` - - -> 2. encryptionKeySecret (String, min-length: 1) : `name of encryption key secret` - - -> 3. encryptionCipherMode (String, min-length: 1) : `type of encryption cipher to use` - - -> 3. setParameter (Object): `configure mongod engineer parameters` - - -> 4. storage: - - -> 1. engine (String, min-length: 1, default “wiredTiger”): `name of mongod storage engine` - - -> 2. inMemory (Object) : `wiredTiger engine configuration` - - -> 3. wiredTiger (Object) : `wiredTiger engine configuration` - -> pmm: - - -> 1. serverHost (String, min-length: 1) : `service name for monitoring` - - -> 2. image (String, min-length: 1) : `name of pmm image` - -> backup: - - -> 1. image (String, min-length: 1) : `name of MngoDB backup docker image` - - -> 2. serviceAccountName (String, min-length: 1) `name of service account to use for backup` - - -> 3. storages (Object) : `storage configuration object for backup` - -**Response:** - -??? example - - --8<-- "cli/api-create-cluster-response-json.md" - -## List Percona Server for MongoDB clusters +4. Get the token: + + ```bash + export KUBE_TOKEN=$(kubectl create token percona-server-mongodb-operator -n $NAMESPACE) -**Description:** + ``` -```text -Lists all Percona Server for MongoDB clusters that exist in your kubernetes cluster -``` + The `curl` examples below use `https://$API_SERVER` and `Authorization: Bearer $KUBE_TOKEN`. In production, use a dedicated ServiceAccount with the RBAC you need. -**Kubectl Command:** +!!! warning -```bash -kubectl get psmdb -``` + The `-k` flag in the `curl` examples skips TLS certificate verification. Prefer proper trust configuration for production use. -**URL:** +## Cluster lifecycle -```text -https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbs?limit=500 -``` +### Create a cluster -**Authentication:** +Create a `PerconaServerMongoDB` object. The usual path is to maintain `deploy/cr.yaml` and apply it. The same object can be posted as JSON to the API. -```text -Authorization: Bearer $KUBE_TOKEN -``` +=== "kubectl" -**cURL Request:** + ```bash + kubectl apply -f deploy/cr.yaml -n $NAMESPACE + ``` -```bash -curl -k -v -XGET "https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbs?limit=500" \ - -H "Accept: application/json;as=Table;v=v1;g=meta.k8s.io,application/json;as=Table;v=v1beta1;g=meta.k8s.io,application/json" \ - -H "Authorization: Bearer $KUBE_TOKEN" -``` +=== "curl" -**Request Body:** + ```bash + curl -k -XPOST \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d @cluster.json + ``` -```text -None -``` + Minimal `cluster.json` shape (expand with the options you need from [Custom Resource options](operator.md)). Update the `"namespace"` field with your value: + + ```json + { + "apiVersion": "psmdb.percona.com/v{{ apiversion }}", + "kind": "PerconaServerMongoDB", + "metadata": { + "name": "my-cluster-name", + "namespace": "my-namespace-name" + }, + "spec": { + "image": "percona/percona-server-mongodb:{{ mongodb80recommended }}", + "replsets": [ + { + "name": "rs0", + "size": 3, + "volumeSpec": { + "persistentVolumeClaim": { + "resources": { + "requests": { + "storage": "3Gi" + } + } + } + } + } + ], + "sharding": { + "enabled": true, + "configsvrReplSet": { + "size": 3, + "volumeSpec": { + "persistentVolumeClaim": { + "resources": { + "requests": { + "storage": "3Gi" + } + } + } + } + }, + "mongos": { + "size": 3 + } + }, + "backup": { + "enabled": true, + "image": "percona/percona-backup-mongodb:{{ pbmrecommended }}" + } + } + } + ``` -**Response:** +### List clusters -??? example +=== "kubectl" - --8<-- "cli/api-list-cluster-response-json.md" + ```bash + kubectl get psmdb -n $NAMESPACE + ``` -## Get status of Percona Server for MongoDB cluster +=== "curl" -**Description:** + ```bash + curl -k -XGET \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs?limit=100" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Accept: application/json" + ``` -```text -Gets all information about specified Percona Server for MongoDB cluster -``` + Kubernetes list responses can include a `metadata.continue` token when more results remain. Pass it on the next request: -**Kubectl Command:** + ```bash + curl -k -XGET \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs?limit=100&continue=$CONTINUE_TOKEN" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Accept: application/json" + ``` -```bash -kubectl get psmdb/my-cluster-name -o json -``` + See [Kubernetes paginated lists :octicons-link-external-16:](https://kubernetes.io/docs/reference/using-api/api-concepts/#retrieving-large-results-sets-in-chunks) for details. -**URL:** -```text -https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbs/my-cluster-name -``` +### Get cluster details and status -**Authentication:** +=== "kubectl" -```text -Authorization: Bearer $KUBE_TOKEN -``` + ```bash + kubectl get psmdb my-cluster-name -n $NAMESPACE -o json + kubectl get psmdb my-cluster-name -n $NAMESPACE -o jsonpath='{.status.state}{"\n"}{.status.host}{"\n"}' + ``` -**cURL Request:** +=== "curl" -```bash -curl -k -v -XGET "https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbs/my-cluster-name" \ - -H "Accept: application/json" \ - -H "Authorization: Bearer $KUBE_TOKEN" -``` + ```bash + curl -k -XGET \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs/my-cluster-name" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Accept: application/json" + ``` -**Request Body:** +Useful fields in the response: -```text -None -``` +* `status.state` — overall state (`initializing`, `ready`, `error`, `paused`, and others) +* `status.host` — connection endpoint hostname +* `status.ready` / `status.size` — ready Pods versus desired size +* `status.replsets` — per replica set status -**Response:** +Full state values and conditions are documented in [Custom resource statuses](cr-statuses.md). -??? example +### Scale a replica set - --8<-- "cli/api-get-status-of-cluster-response-json.md" +Prefer a JSON Patch that changes only `size`, so you do not overwrite the rest of the replica set spec. -## Scale up/down Percona Server for MongoDB cluster +=== "kubectl" -**Description:** + ```bash + kubectl patch psmdb my-cluster-name -n $NAMESPACE --type=json -p='[ + {"op": "replace", "path": "/spec/replsets/0/size", "value": 5} + ]' + ``` -```text -Increase or decrease the size of the Percona Server for MongoDB cluster nodes to fit the current high availability needs -``` +=== "curl" -**Kubectl Command:** + ```bash + curl -k -XPATCH \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs/my-cluster-name" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Content-Type: application/json-patch+json" \ + -H "Accept: application/json" \ + -d '[ + {"op": "replace", "path": "/spec/replsets/0/size", "value": 5} + ]' + ``` -```bash -kubectl patch psmdb my-cluster-name --type=merge --patch '{ -"spec": {"replsets":{ "size": "5" } -}}' -``` +Replace `/spec/replsets/0` with the index of the replica set you want to change. -**URL:** +#### Scale to zero -```text -https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbs/my-cluster-name -``` +Setting `replsets[].size` to `0` scales that replica set down. It does **not** delete the `PerconaServerMongoDB` object, and data on Persistent Volume Claims remains unless you delete those volumes separately. -**Authentication:** +To use a size below the Operator’s safe defaults (including `0`), enable the corresponding unsafe flag, for example `spec.unsafeFlags.replsetSize: true`. See [unsafeFlags](operator.md#operator-unsafeflags-section). -```text -Authorization: Bearer $KUBE_TOKEN -``` +To remove the cluster itself, [delete the Custom Resource](#delete-a-cluster). -**cURL Request:** +### Add a replica set -```bash -curl -k -v -XPATCH "https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbs/my-cluster-name" \ - -H "Authorization: Bearer $KUBE_TOKEN" \ - -H "Content-Type: application/merge-patch+json" - -H "Accept: application/json" \ - -d '{ - "spec": {"replsets":{ "size": "5" } - }}' -``` +The following command adds a new shard (deployed as the replica set) to the sharded cluster. This command is available only for sharded clusters. To expand the replica set deployment, see [Scale a replica set](#scale-a-replica-set). -**Request Body:** +=== "kubectl" -??? example + ```bash + kubectl patch psmdb my-cluster-name -n $NAMESPACE --type=json -p='[ + { + "op": "add", + "path": "/spec/replsets/-", + "value": { + "name": "rs1", + "size": 3, + "volumeSpec": { + "persistentVolumeClaim": { + "resources": { + "requests": { + "storage": "3Gi" + } + } + } + } + } + } + ]' + ``` - --8<-- "cli/api-scale-cluster-request-json.md" +=== "curl" -**Input:** + ```bash + curl -k -XPATCH \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs/my-cluster-name" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Content-Type: application/json-patch+json" \ + -H "Accept: application/json" \ + -d '[ + { + "op": "add", + "path": "/spec/replsets/-", + "value": { + "name": "rs1", + "size": 3, + "volumeSpec": { + "persistentVolumeClaim": { + "resources": { + "requests": { + "storage": "3Gi" + } + } + } + } + } + } + ]' + ``` -> **spec**: +### Remove a replica set -> replsets +To remove a shard (deployed as a replica set) from a sharded cluster, you must first drain the shard of all data. Follow this process: +1. **Drain the shard:** Use [MongoDB's drain procedure](https://www.mongodb.com/docs/manual/tutorial/remove-shards-from-cluster/) to remove all data and move chunks from the shard you want to remove. Wait until MongoDB reports that the shard is fully drained and safe for removal. -> 1. size (Int or String, Defaults: 3): `Specify the sie of the replsets cluster to scale up or down to` +2. **Remove the shard from the cluster:** After the shard is fully drained, remove the replica set from the cluster specification. -**Response:** +Remove by array index (check the current order with `kubectl get psmdb my-cluster-name -o json` first): -??? example +=== "kubectl" - --8<-- "cli/api-scale-cluster-response-json.md" + ```bash + kubectl patch psmdb my-cluster-name -n $NAMESPACE --type=json -p='[ + {"op": "remove", "path": "/spec/replsets/1"} + ]' + ``` -## Update Percona Server for MongoDB cluster image +=== "curl" -**Description:** + ```bash + curl -k -XPATCH \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs/my-cluster-name" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Content-Type: application/json-patch+json" \ + -H "Accept: application/json" \ + -d '[ + {"op": "remove", "path": "/spec/replsets/1"} + ]' + ``` -```text -Change the image of Percona Server for MongoDB containers inside the cluster -``` +### Update the MongoDB image -**Kubectl Command:** +=== "kubectl" -```bash -kubectl patch psmdb my-cluster-name --type=merge --patch '{ -"spec": {"psmdb":{ "image": "percona/percona-server-mongodb-operator:1.4.0-mongod4.2" } -}}' -``` + ```bash + kubectl patch psmdb my-cluster-name -n $NAMESPACE --type=json -p='[ + {"op": "replace", "path": "/spec/image", "value": "percona/percona-server-mongodb:{{ mongodb80recommended }}"} + ]' + ``` -**URL:** +=== "curl" -```text -https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbs/my-cluster-name -``` + ```bash + curl -k -XPATCH \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs/my-cluster-name" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Content-Type: application/json-patch+json" \ + -H "Accept: application/json" \ + -d '[ + {"op": "replace", "path": "/spec/image", "value": "percona/percona-server-mongodb:{{ mongodb80recommended }}"} + ]' + ``` -**Authentication:** +### Delete a cluster -```text -Authorization: Bearer $KUBE_TOKEN -``` +Deleting the `PerconaServerMongoDB` Custom Resource deletes the cluster. Finalizers control whether PVCs and related objects are removed. By default, PVCs are kept so you can recreate the cluster without losing data. See [Delete the database cluster](delete.md#delete-the-database-cluster). -**cURL Request:** +=== "kubectl" -```bash -curl -k -v -XPATCH "https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbs/my-cluster-name" \ - -H "Authorization: Bearer $KUBE_TOKEN" \ - -H "Accept: application/json" \ - -H "Content-Type: application/merge-patch+json" - -d '{ - "spec": {"psmdb":{ "image": "percona/percona-server-mongodb-operator:1.4.0-mongod4.2" } - }}' -``` + ```bash + kubectl delete psmdb my-cluster-name -n $NAMESPACE + ``` -**Request Body:** +=== "curl" -??? example + ```bash + curl -k -XDELETE \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbs/my-cluster-name" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Accept: application/json" + ``` - --8<-- "cli/api-update-cluster-image-request-json.md" +### Connection details -**Input:** +Starting with Operator version 1.23.0, the Operator creates a Kubernetes Secret with ready-to-use MongoDB connection strings. For the default `databaseAdmin` user, the Secret is named `-databaseadmin-conn-str`. -> **spec**: +Example for a sharded cluster: -> psmdb: +=== "kubectl" + ```bash + kubectl get secret my-cluster-name-databaseadmin-conn-str -n $NAMESPACE \ + -o jsonpath='{.data.databaseAdmin_mongos_connectionString}' | base64 --decode && echo + ``` -> 1. image (String, min-length: 1) : `name of the image to update for Percona Server for MongoDB` +=== "curl" -**Response:** + ```bash + curl -k -XGET \ + "https://$API_SERVER/api/v1/namespaces/$NAMESPACE/secrets/my-cluster-name-databaseadmin-conn-str" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Accept: application/json" \ + | grep '"databaseAdmin_mongos_connectionString"' \ + | awk -F '"' '{print $4}' \ + | base64 --decode && echo + ``` -??? example +For a non-sharded replica set, use the `databaseAdmin_rs0_connectionStringSrv` key instead. See [Connection secrets](connection-secrets.md) for all available keys. - --8<-- "cli/api-update-cluster-image-response-json.md" +## Backup lifecycle -## Backup Percona Server for MongoDB cluster +Backup storage, schedules, and retention live on the cluster Custom Resource under `spec.backup`. On-demand backups are separate `PerconaServerMongoDBBackup` objects. See [Backup and restore](backups.md). -**Description:** +To manage backups, you must configure the backup storage. See [Configure storage for backups](backups-storage.md) for details. -```text -Takes a backup of the Percona Server for MongoDB cluster containers data to be able to recover from disasters or make a roll-back later -``` +### Configure backup settings and retention -**Kubectl Command:** +Patch `spec.backup` on the cluster. Example: enable backups, set a schedule, and keep the last 3 successful backups: ```bash -kubectl apply -f percona-server-mongodb-operator/deploy/backup/backup.yaml -``` - -**URL:** - -```text -https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbbackups -``` - -**Authentication:** +kubectl patch psmdb my-cluster-name -n $NAMESPACE --type=merge -p '{ + "spec": { + "backup": { + "enabled": true, + "storages": { + "s3-us-west": { + "type": "s3", + "s3": { + "bucket": "my-bucket", + "region": "us-west-2", + "credentialsSecret": "my-cluster-name-backup-s3" + } + } + }, + "tasks": [ + { + "name": "daily-s3", + "enabled": true, + "schedule": "0 0 * * *", + "storageName": "s3-us-west", + "retention": { + "type": "count", + "count": 3, + "deleteFromStorage": true + } + } + ] + } + } +}' +``` + +For every backup option, see [Custom Resource options](operator.md#operator-backup-section) and [Make scheduled backups](backups-scheduled.md). + +!!! note + + A merge patch that replaces `storages` or `tasks` overwrites those objects/arrays. Prefer editing your maintained `deploy/cr.yaml` and applying it when you manage complex backup configuration. + +### Create a backup + +=== "kubectl" -```text -Authorization: Bearer $KUBE_TOKEN -``` - -**cURL Request:** + ```bash + kubectl apply -f deploy/backup/backup.yaml -n $NAMESPACE + ``` -```bash -curl -k -v -XPOST "https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbbackups" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - -d "@backup.json" -H "Authorization: Bearer $KUBE_TOKEN" -``` + Example Backup object: + + ```yaml + apiVersion: psmdb.percona.com/v{{ apiversion }} + kind: PerconaServerMongoDBBackup + metadata: + name: backup1 + finalizers: + - percona.com/delete-backup + spec: + clusterName: my-cluster-name + storageName: s3-us-west + type: logical + ``` -**Request Body (backup.json):** +=== "curl" -??? example + ```bash + curl -k -XPOST \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbbackups" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d @backup.json + ``` - --8<-- "cli/api-backup-cluster-request-json.md" + `backup.json`: + + ```json + { + "apiVersion": "psmdb.percona.com/v{{ apiversion }}", + "kind": "PerconaServerMongoDBBackup", + "metadata": { + "name": "backup1", + "finalizers": [ + "percona.com/delete-backup" + ] + }, + "spec": { + "clusterName": "my-cluster-name", + "storageName": "s3-us-west", + "type": "logical" + } + } + ``` -**Input:** +### List backups and check status +=== "kubectl" -1. **metadata**: + ```bash + kubectl get psmdb-backup -n $NAMESPACE + kubectl get psmdb-backup backup1 -n $NAMESPACE -o jsonpath='{.status.state}{"\n"}{.status.size}{"\n"}{.status.destination}{"\n"}' + ``` -> name(String, min-length:1) : `name of backup to create` +=== "curl" + ```bash + curl -k -XGET \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbbackups/backup1" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Accept: application/json" + ``` -2. **spec**: +Useful status fields: `status.state` (`waiting`, `running`, `ready`, `error`, …), `status.size`, `status.destination`, `status.type`, `status.completed`. See [Backup status](cr-statuses.md#perconaservermongodbbackup-status). -> -> 1. psmdbCluster(String, min-length:1) : `name of Percona Server for MongoDB cluster` +## Restore lifecycle +Restores are `PerconaServerMongoDBRestore` objects. You can restore onto the same cluster, onto a new cluster, run point-in-time recovery, or restore selected namespaces (databases/collections). Details and limitations: -> 2. storageName(String, min-length:1) : `name of storage claim to use` +* [Restore on the same cluster](backups-restore.md) +* [Restore to a new cluster](backups-restore-to-new-cluster.md) +* [Selective restore](backups-restore.md#selective-restore) -**Response:** +### Restore to the same cluster -??? example +=== "kubectl" - --8<-- "cli/api-backup-cluster-response-json.md" + ```bash + kubectl apply -f deploy/backup/restore.yaml -n $NAMESPACE + ``` -## Restore Percona Server for MongoDB cluster + Example Restore object: -**Description:** + ```yaml + apiVersion: psmdb.percona.com/v{{ apiversion }} + kind: PerconaServerMongoDBRestore + metadata: + name: restore1 + spec: + clusterName: my-cluster-name + backupName: backup1 + ``` -```text -Restores Percona Server for MongoDB cluster data to an earlier version to recover from a problem or to make a roll-back -``` +=== "curl" -**Kubectl Command:** + ```bash + curl -k -XPOST \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbrestores" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json" \ + -d @restore.json + ``` -```bash -kubectl apply -f percona-server-mongodb-operator/deploy/backup/restore.yaml -``` + `restore.json`: + + ```json + { + "apiVersion": "psmdb.percona.com/v{{ apiversion }}", + "kind": "PerconaServerMongoDBRestore", + "metadata": { + "name": "restore1" + }, + "spec": { + "clusterName": "my-cluster-name", + "backupName": "backup1" + } + } + ``` -**URL:** +### Restore to a new cluster -```text -https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbrestores -``` +1. Create the target `PerconaServerMongoDB` cluster (create flow above). +2. Create a `PerconaServerMongoDBRestore` that points at that cluster and at the backup source (often via `spec.backupSource` when the backup object does not exist in the new environment). -**Authentication:** +See [Restore to a new cluster](backups-restore-to-new-cluster.md) for storage, Secrets, and `backupSource` examples. -```text -Authorization: Bearer $KUBE_TOKEN -``` +### Selective (partial) restore -**cURL Request:** +For a logical backup, you can restore specific databases or collections with `spec.selective`: -```bash -curl -k -v -XPOST "https://$API_SERVER/apis/psmdb.percona.com/v1/namespaces/default/perconaservermongodbrestores" \ - -H "Accept: application/json" \ - -H "Content-Type: application/json" \ - -d "@restore.json" \ - -H "Authorization: Bearer $KUBE_TOKEN" +```yaml +apiVersion: psmdb.percona.com/v{{ apiversion }} +kind: PerconaServerMongoDBRestore +metadata: + name: restore-selective +spec: + clusterName: my-cluster-name + backupName: backup1 + selective: + withUsersAndRoles: true + namespaces: + - "db1.collection1" + - "db2.*" ``` -**Request Body (restore.json):** +### Check restore status -??? example - - --8<-- "cli/api-restore-cluster-request-json.md" - -**Input:** - - -1. **metadata**: - -> name(String, min-length:1): `name of restore to create` - - -2. **spec**: - -> -> 1. clusterName(String, min-length:1) : `name of Percona Server for MongoDB cluster` +=== "kubectl" + ```bash + kubectl get psmdb-restore -n $NAMESPACE + kubectl get psmdb-restore restore1 -n $NAMESPACE -o jsonpath='{.status.state}{"\n"}' + ``` -> 2. backupName(String, min-length:1) : `name of backup to restore from` +=== "curl" -**Response:** + ```bash + curl -k -XGET \ + "https://$API_SERVER/apis/psmdb.percona.com/v{{ apiversion }}/namespaces/$NAMESPACE/perconaservermongodbrestores/restore1" \ + -H "Authorization: Bearer $KUBE_TOKEN" \ + -H "Accept: application/json" + ``` -??? example +See [Restore status](cr-statuses.md#perconaservermongodbrestore-status). - --8<-- "cli/api-restore-cluster-response-json.md" From f07460f8913f4a28f241a851abb87a231c62b350 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 10:53:00 +0300 Subject: [PATCH 13/22] K8SPSMDB-1363 Documented the support of PVC snapshots (#333) * K8SPSMDB-1363 Documented the support of PVC snapshots docs/backups-pvc-setup.md docs/backups-pvc-snapshots.md docs/backups-pvc-usage.md modified: docs/backup-resource-options.md modified: docs/backups-ondemand.md modified: docs/backups-restore.md modified: docs/backups-scheduled.md modified: docs/backups.md modified: docs/cr-statuses.md modified: docs/operator.md modified: docs/restore-options.md modified: mkdocs-base.yml --- docs/backup-resource-options.md | 15 +- docs/backups-ondemand.md | 21 +++ docs/backups-pvc-setup.md | 214 +++++++++++++++++++++++ docs/backups-pvc-snapshots.md | 96 +++++++++++ docs/backups-pvc-usage.md | 289 ++++++++++++++++++++++++++++++++ docs/backups-restore.md | 3 +- docs/backups-scheduled.md | 32 +++- docs/backups.md | 28 +++- docs/cr-statuses.md | 27 ++- docs/operator.md | 10 +- docs/restore-options.md | 29 +++- mkdocs-base.yml | 4 + 12 files changed, 760 insertions(+), 8 deletions(-) create mode 100644 docs/backups-pvc-setup.md create mode 100644 docs/backups-pvc-snapshots.md create mode 100644 docs/backups-pvc-usage.md diff --git a/docs/backup-resource-options.md b/docs/backup-resource-options.md index 25668f5e..9cad143f 100644 --- a/docs/backup-resource-options.md +++ b/docs/backup-resource-options.md @@ -39,18 +39,30 @@ Specifies the name of the MongoDB cluster to back up. Specifies the name of the storage where to save a backup. It must match the name you specified in the `spec.backup.storages` subsection of the `deploy/cr.yaml` file. +Not required when `type` is `external` (PVC snapshot backups). PBM still uses the cluster backup configuration for metadata. + | Value type | Example | | ----------- | ---------- | | :material-code-string: string | `s3-us-west` | ### `type` -Specifies the backup type. Supported types are: `logical`, `physical`, `incremental-base`, `incremental`. +Specifies the backup type. Supported types are: `logical`, `physical`, `incremental-base`, `incremental`, `external`. + +Use `external` for [PVC snapshot backups](backups-pvc-snapshots.md). | Value type | Example | | ----------- | ---------- | | :material-code-string: string | `physical` | +### `volumeSnapshotClass` + +The name of the Kubernetes `VolumeSnapshotClass` to use when creating [PVC snapshot backups](backups-pvc-snapshots.md). **Required** when the `type` is `external`. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `gke-snapshot-class` | + ### `compressionType` Specifies the compression algorithm for backups. Supported values are: `gzip`, `pgzip`, `zstd`, `snappy`. Read more about compression types in the [Configure backup compression :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/usage/compression.html#configure-backup-compression) section of PBM documentation. @@ -76,3 +88,4 @@ If undefined, the Operator uses the value specified in the Custom Resource, or d | Value type | Example | | ----------- | ---------- | | :material-numeric-1-box: int | `300` | + diff --git a/docs/backups-ondemand.md b/docs/backups-ondemand.md index 11a7063e..6f7a7b09 100644 --- a/docs/backups-ondemand.md +++ b/docs/backups-ondemand.md @@ -36,6 +36,8 @@ To create a Backup resource, you need a special custom resource manifest. The [d * `spec.type` is the [backup type](backups.md#backup-types). If you leave it empty, the Operator makes a logical backup by default. + * `spec.volumeSnapshotClass` is the Kubernetes `VolumeSnapshotClass` name. You must specify it when you [make an on-demand PVC snapshot backup](backups-pvc-usage.md#make-an-on-demand-backup-from-a-pvc-snapshot). + **Examples** === "Logical" @@ -108,6 +110,25 @@ To create a Backup resource, you need a special custom resource manifest. The [d type: incremental ``` + === "PVC snapshot (external)" + + As a precondition, you must ensure at least one `VolumeSnapshotClass` exists in your Kubernetes cluster and is compatible with the storage class used by your MongoDB data volumes. See [Configure PVC snapshots](backups-pvc-setup.md) for steps. + + ```yaml + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBBackup + metadata: + finalizers: + - percona.com/delete-backup + name: my-snapshot-backup + spec: + clusterName: my-cluster-name + type: external + volumeSnapshotClass: gke-snapshot-class + ``` + + See [Make an on-demand PVC snapshot backup](backups-pvc-usage.md#make-an-on-demand-backup-from-a-pvc-snapshot) for prerequisites and monitoring. + 2. Apply the `backup.yaml` manifest to start a backup: diff --git a/docs/backups-pvc-setup.md b/docs/backups-pvc-setup.md new file mode 100644 index 00000000..13312350 --- /dev/null +++ b/docs/backups-pvc-setup.md @@ -0,0 +1,214 @@ +# Configure PVC snapshots + +This guide provides step-by-step instructions for configuring and using Persistent Volume Claim (PVC) Snapshots with Percona Operator for MongoDB. + +For a high-level explanation of PVC snapshots, see [PVC snapshot support](backups-pvc-snapshots.md). + +!!! note "Amazon EKS users" + + If you run your cluster on Amazon EKS, refer to the [Add a VolumeSnapshotClass on EKS](#add-a-volumesnapshotclass-on-eks) section. EKS requires specific addons, a `gp3` storage class, and a matching `VolumeSnapshotClass` before you can use PVC snapshots. + +## Prerequisites + +Before you use PVC snapshots, verify the following: + +1. Your Kubernetes cluster must run a CSI driver that supports Volume Snapshots. Examples: + + * Google Kubernetes Engine (GKE): `pd.csi.storage.gke.io` + * Amazon EKS: `ebs.csi.aws.com` + * Azure Kubernetes Service (AKS): `disk.csi.azure.com` + + Check what driver you have: + + ```bash + kubectl get csidriver + ``` + +2. Your Kubernetes cluster must have VolumeSnapshot CRDs installed. Most managed Kubernetes providers include these by default. Verify by running: + + ```bash + kubectl get crd | grep volumesnapshot + ``` + + ??? example "Expected output" + + ```text + volumesnapshotclasses.snapshot.storage.k8s.io + ``` + +3. At least one VolumeSnapshotClass must exist and be compatible with the storage class used by your MongoDB data volumes. Check it with: + + ```bash + kubectl get volumesnapshotclasses + ``` + + If you don't have one, you can add it yourself. Refer to the [Add a VolumeSnapshotClass](#add-a-volumesnapshotclass) section. + +4. To use PVC snapshots, you must run the Operator version 1.23.0 or later. + +## Before you start + +1. Clone the Operator repository to be able to edit manifests: + + ```bash + git clone -b v{{ release }} https://github.com/percona/percona-server-mongodb-operator + cd percona-server-mongodb-operator + ``` + +2. Export your cluster namespace: + + ```bash + export NAMESPACE= + ``` + +## Add a VolumeSnapshotClass + +If your cluster has no suitable `VolumeSnapshotClass`, create one for your platform. + +1. Create a VolumeSnapshotClass configuration file with the following configuration: + + === "Google Kubernetes Engine (GKE)" + + ```yaml title="volume-snapshot-class.yaml" + apiVersion: snapshot.storage.k8s.io/v1 + kind: VolumeSnapshotClass + metadata: + name: gke-snapshot-class + driver: pd.csi.storage.gke.io + deletionPolicy: Delete + ``` + + === "Azure Kubernetes Service (AKS)" + + ```yaml title="volume-snapshot-class.yaml" + apiVersion: snapshot.storage.k8s.io/v1 + kind: VolumeSnapshotClass + metadata: + name: aks-snapshot-class + driver: disk.csi.azure.com + deletionPolicy: Delete + ``` + + === "OpenShift" + + ```yaml title="volume-snapshot-class.yaml" + apiVersion: snapshot.storage.k8s.io/v1 + kind: VolumeSnapshotClass + metadata: + name: openshift-snapshot-class + driver: ebs.csi.aws.com # use the driver that matches your storage class + deletionPolicy: Delete + ``` + +2. Create the VolumeSnapshotClass resource: + + ```bash + kubectl apply -f volume-snapshot-class.yaml + ``` + +3. Verify that the VolumeSnapshotClass resource is created: + + ```bash + kubectl get volumesnapshotclasses + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + NAME DRIVER DELETIONPOLICY AGE + gke-snapshot-class pd.csi.storage.gke.io Delete 42s + ``` + +### Add a VolumeSnapshotClass on EKS + +1. Before you start, ensure you have the following: + + * An EKS cluster (or plan to create one) + * kubectl configured to access your cluster + * The AWS CLI installed and configured + +2. Enable required EKS addons. EKS requires two addons for volume snapshots: the Amazon EBS CSI driver and the snapshot controller. You can enable them when you create the cluster or add them to an existing cluster. + + === "At cluster creation" + + If you deploy the cluster with `eksctl` or a similar tool, include these addons in your cluster configuration: + + ```yaml + addons: + - name: aws-ebs-csi-driver + wellKnownPolicies: + ebsCSIController: true + - name: snapshot-controller + nodeGroups: + - name: ng-1 + desiredCapacity: 3 + minSize: 3 + maxSize: 3 + ``` + + === "On existing cluster" + + If your cluster already exists, enable the addons with the AWS CLI. Replace with the name of your EKS cluster in the following commands: + + ```bash + aws eks create-addon \ + --cluster-name \ + --addon-name aws-ebs-csi-driver \ + --resolve-conflicts OVERWRITE + + aws eks create-addon \ + --cluster-name \ + --addon-name snapshot-controller + ``` + +3. Create a `gp3` storage class. Since the default `gp2` storage class on EKS doesn't support volume snapshots, you must use `gp3` instead. + + * Create the storage class configuration file: + + ```yaml title="ebs-gp3-storage-class.yaml" + apiVersion: storage.k8s.io/v1 + kind: StorageClass + metadata: + name: ebs-csi-gp3 + provisioner: ebs.csi.aws.com + volumeBindingMode: WaitForFirstConsumer + allowVolumeExpansion: true + parameters: + type: gp3 + ``` + + * Apply the configuration to create the StorageClass: + + ```bash + kubectl apply -f ebs-gp3-storage-class.yaml + ``` + +4. Now you are ready to create the VolumeSnapshotClass. + + Here's the example configuration file: + + ```yaml title="ebs-gp3-snapshot-class.yaml" + apiVersion: snapshot.storage.k8s.io/v1 + kind: VolumeSnapshotClass + metadata: + name: ebs-csi-gp3 + driver: ebs.csi.aws.com + deletionPolicy: Delete + ``` + + Apply it with: + + ```bash + kubectl apply -f ebs-gp3-snapshot-class.yaml + ``` + + ??? example "Expected output" + + ```{.text .no-copy} + volumesnapshotclass.snapshot.storage.k8s.io/ebs-csi-gp3 created + ``` + +## Next steps + +[Use PVC snapshots for backups and restores](backups-pvc-usage.md){.md-button} + diff --git a/docs/backups-pvc-snapshots.md b/docs/backups-pvc-snapshots.md new file mode 100644 index 00000000..9f148900 --- /dev/null +++ b/docs/backups-pvc-snapshots.md @@ -0,0 +1,96 @@ +# PVC snapshots + +Starting with version 1.23.0, you can make **PVC snapshot backups and restores** using the Operator. + +This document provides an overview of PVC snapshots. If you are familiar with the concept and want to try it out, jump to the Configure and use PVC snapshots tutorial. If you run on Amazon EKS, start with Set up PVC snapshots on EKS. + +A PVC snapshot is a point-in-time copy of a Persistent Volume Claim (PVC) created by your storage provider through the Kubernetes [Volume Snapshot API :octicons-link-external-16:](https://kubernetes.io/docs/concepts/storage/volume-snapshots/). The storage layer captures volume contents at a specific moment without streaming data block by block to remote object storage. + +Compared with logical or physical backups that upload data to S3, Azure, or [another supported remote storage](backups-storage.md#storage-setup-guides), PVC snapshots are typically much faster for large datasets because data stays on the storage backend. + +However, PBM still requires access to the remote backup storage to store **backup metadata**, including encryption-related information, and oplogs. Therefore, your cluster configuration must include at least one entry in `backup.storages` so PBM agents can run and persist metadata. Snapshot backups do not upload database files to that storage. + +## How PVC snapshots differ from other backup types + +| Aspect | Logical / physical / incremental | PVC snapshot (`external`) | +| --- | --- | --- | +| Data location | Remote backup storage (S3, Azure, etc.) | CSI `VolumeSnapshot` objects in the cluster | +| `storageName` on Backup / scheduled task | Required | Not required | +| `volumeSnapshotClass` | Not used | Required | +| Point-in-time recovery | Supported | Not supported | +| Selective restore | Supported for logical backups | Not supported | + +## Why to use PVC snapshots + +PVC snapshots speed up backups and restores, which is especially beneficial for large data sets. With this feature, you get: + +* Much faster backups – Snapshot creation is typically seconds to minutes, regardless of database size. Time it takes to run traditional full backups increases as the size of your database grows. +* Fully compatible with data-at-rest encryption and TLS, allowing you to use PVC snapshots when encryption and secure connections are enabled. +* Much faster restores – Restoring from a snapshot is significantly faster than restoring from cloud storage. Both in-place restores and restores to a new cluster are supported. +* Lower resource usage – Snapshots avoid the CPU and network overhead of streaming data to a remote storage. + + +## Workflows + +PBM supports snapshot-based backups and restores as `external` type. The Operator integrates this feature and uses the same type. + +### Backup flow + +When a backup object with the type `external` is created either by you on demand or by the Operator according to the schedule, the Operator and PBM work together as follows: + +1. The Operator uses PBM to **prepare the database**. PBM opens a [`$backupCursor` :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/usage/backup-external.html#procedure), prepares files for copying, stores backup metadata on the remote storage, and waits until nodes reach the **`copyReady`** status. +2. For each replica set member that is `copyReady`, the Operator creates a `VolumeSnapshot` of the `mongod-data` PVC. +3. After all snapshots are `readyToUse`, the Operator uses PBM to finalize the backup. PBM closes the `$backupCursor` and marks the backup complete. + +The Backup resource `status.snapshots` field lists each replica set and the corresponding `VolumeSnapshot` name. + +### Restore flow + +Restore from a PVC snapshot backup also uses PBM’s [external restore :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/usage/restore-external-agent-restart.html) workflow. The Operator automates steps that you would otherwise run manually or using a custom script with the PBM CLI. + +When you create a restore object with the type `external`, the Operator and PBM perform the following steps: + +1. The Operator instructs PBM to **prepare the database**. PBM shuts down `mongos` nodes in sharded clusters, stops `mongod` nodes, wipes the data directory, leaves nodes in the `copyReady` stage waiting for data files, and exits. +2. The Operator scales database StatefulSets to zero and restarts the `pbm-agent` on every node with the information it requires: + + * PBM configuration file for the access to the remote storage, + * replica set name, + * node name, + * (when needed) MongoDB `db` config for encryption at rest. + +3. The Operator recreates each data PVC from the `VolumeSnapshot` either recorded in the backup or provided in the `backupSource` configuration, one PVC at a time. +4. After PVCs are restored and agents are waiting, the Operator instructs PBM to finish the restore. PBM applies metadata and brings the cluster back to a consistent state. + +Track progress in the Restore resource `status.conditions` field. See [PVC snapshot restore conditions](cr-statuses.md#pvc-snapshot-restore-conditions) for the list of condition types and meanings. + +## Requirements + +1. Your Kubernetes cluster must have the CSI driver that supports `VolumeSnapshot` API. An example of such driver for GKE is `pd.csi.storage.gke.io`, for EKS - `ebs.csi.aws.com`. +2. Your Kubernetes cluster must have the `VolumeSnapshot` CRDs installed. Verify if they are installed with this command: + + ```bash + kubectl get crd | grep volumesnapshot + ``` + + ??? example "Expected output" + + ```text + volumesnapshotclasses.snapshot.storage.k8s.iovolumesnapshotcontents.snapshot.storage.k8s.io volumesnapshots.snapshot.storage.k8s.io + ``` + +3. At least one `VolumeSnapshotClass` must exist and be compatible with the storage class used by your Percona Server for MongoDB data volumes. Check it with: + + ```bash + kubectl get volumesnapshotclasses + ``` + +See how to add it in the [Add a VolumeSnapshotClass](backups-pvc-setup.md#add-a-volumesnapshotclass) section. + + +## Limitations + +* Point-in-time recovery and selective restore are not available for `external` backups. + +## Next steps + +[Add a VolumeSnapshotClass](backups-pvc-setup.md){.md-button} diff --git a/docs/backups-pvc-usage.md b/docs/backups-pvc-usage.md new file mode 100644 index 00000000..1a042923 --- /dev/null +++ b/docs/backups-pvc-usage.md @@ -0,0 +1,289 @@ +# Use PVC snapshots for backups and restores + +Once you [configure PVC snapshots](backups-pvc-setup.md), you can use them for backups and restores. + +## Configure remote backup storage in the cluster + +PBM requires access to remote backup storage to store backup metadata and oplog files. Therefore, you must configure at least one backup storage and define it in your cluster resource. Refer to the [storage setup guides](backups-storage.md#storage-setup-guides) to find the corresponding tutorial for your storage service. + +Here's the example configuration for the S3 storage: + +```yaml +spec: + backup: + enabled: true + storages: + s3-us-west: + type: s3 + s3: + bucket: my-bucket + credentialsSecret: backup-s3 +``` + +## Make an on-demand backup from a PVC snapshot + +1. Configure the `PerconaServerMongoDBBackup` object. Edit the `deploy/backup/backup.yaml` manifest and specify the following keys: + + * `metadata.name` - the name of the backup + * `spec.clusterName` - the name of your cluster. Run `kubectl get psmdb -n ` to find out the cluster name. + * `spec.type` - is the type. Set it to `external` + * `spec.volumeSnapshotClass` - Specify the name of the `VolumeSnapshotClass` resource that your cluster has or [you have configured](backups-pvc-setup.md) + + Here's the example configuration: + + ```yaml + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBBackup + metadata: + name: my-snapshot-backup + spec: + type: external + clusterName: my-cluster + volumeSnapshotClass: csi-gce-pd-snapshot-class # The name from kubectl get volumesnapshotclasses + ``` + +2. Start the backup: + + ```bash + kubectl apply -f deploy/backup/backup.yaml -n + ``` + +3. Monitor the backup progress: + + ```bash + kubectl get psmdb-backup -n + kubectl describe psmdb-backup my-snapshot-backup -n + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + NAME CLUSTER STORAGE DESTINATION TYPE SIZE STATUS COMPLETED AGE + my-snapshot-backup my-cluster-name external ready 5m 5m + ``` + + The Backup `status.snapshots` field lists each replica set and snapshot name: + + ```yaml + status: + type: external + state: ready + pbmName: "2026-05-29T10:15:00Z" + snapshots: + - replsetName: rs0 + snapshotName: my-snapshot-backup-rs0-0 + - replsetName: rs0 + snapshotName: my-snapshot-backup-rs0-1 + - replsetName: rs0 + snapshotName: my-snapshot-backup-rs0-2 + ``` + +4. List created snapshots: + + ```bash + kubectl get volumesnapshot -n + ``` + + ??? example "Sample output" + + ```text + backup-snapshot-rs0 true mongod-data-my-cluster-name-rs0-1 3Gi gke-snapshot-class snapcontent-405dfe0c-c90c-4030-9c9a-c2040f8aca4a 4h58m 4h58m + ``` + +## Make a scheduled snapshot-based backup + +1. Configure the backup schedule in your cluster Custom Resource. Add a task under `backup.tasks`: + * Set the schedule, + * Specify the `type` as `external` + * Reference the VolumeSnapshot Class for the `volumeSnapshotClass` + * Configure the [retention policy](backups-scheduled.md#configure-retention) + + ```yaml + backup: + enabled: true + storages: + s3-us-west: + type: s3 + s3: + bucket: my-backup-bucket + region: us-west-2 + credentialsSecret: my-cluster-name-backup-s3 + tasks: + - name: daily-snapshot + enabled: true + schedule: "0 2 * * *" + type: external + volumeSnapshotClass: gke-snapshot-class + retention: + count: 7 + type: count + deleteFromStorage: true + ``` + +2. Start the backup: + + ```bash + kubectl apply -f deploy/cr.yaml -n + ``` + +The Operator creates a `PerconaServerMongoDBBackup` resource for each scheduled run. Retention with `deleteFromStorage: true` removes old `VolumeSnapshot` objects and PBM metadata when backups age out. + +See [Making scheduled backups](backups-scheduled.md) for general scheduling and retention concepts. + +## Make an in-place restore from a PVC snapshot backup + +An in-place restore is a restore to the same cluster where the backup was taken. + +You can only restore the data in the PVC snapshot up to the time when the backup was taken. Point-in-time recovery is not supported. + +--8<-- "backups-restore.md:backup-prepare" + + +To make an in-place restore, do the following: + +1. Create a Restore resource. Edit the [deploy/backup/restore.yaml :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/main/deploy/backup/restore.yaml) manifest and specify the following information: + + * `metadata.name` - the name of the restore object + * `spec.clusterName` - the name of your cluster + * `spec.backupName` - the name of the external backup to restore from + + ```yaml + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBRestore + metadata: + name: my-snapshot-restore + spec: + clusterName: my-cluster-name + backupName: my-snapshot-backup + ``` + +2. Apply the restore: + + ```bash + kubectl apply -f deploy/backup/restore.yaml -n $NAMESPACE + ``` + +3. Monitor the restore state: + + ```bash + kubectl get psmdb-restore -n $NAMESPACE + kubectl describe psmdb-restore my-snapshot-restore -n $NAMESPACE + ``` + + Typical restore states are: + + | State | What happens | + | --- | --- | + | `waiting` | Operator prepares PBM config and cluster for physical-style restore | + | `requested` | `pbm restore --external` started; waiting for **`copyReady`** | + | `running` | PVCs recreated from snapshots; `pbm-agent restore-finish` and `pbm restore-finish` run | + | `ready` | Restore completed | + +4. Inspect restore conditions: + + ```bash + kubectl get psmdb-restore my-snapshot-restore -n $NAMESPACE -o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\n"}{end}' + ``` + + Expected conditions when finished include `ReplsetPVCsRestoredFromSnapshot` and `PBMRestoreFinished`. + +## Make a restore to a new cluster + +You can use a PVC snapshot to restore data to a **different cluster** or when you have `VolumeSnapshot` objects but no `PerconaServerMongoDBBackup` in the target namespace. In this scenario you configure the Restore object using the `spec.backupSource`. + +### Preconditions + +1. When restoring to a new cluster, make sure it has a Secrets object with the same user passwords as in the original cluster. +2. When using data-at-rest encryption, set the corresponding encryption key of the target cluster. Find more details about encryption in [Data-at-rest encryption](encryption.md). The name of the required Secrets object can be found out from the spec.secrets key in the `deploy/cr.yaml` (`my-cluster-name-secrets` by default). +3. Enable backups and configure the remote backup storage on the target cluster before starting the restore. + +To make a restore to a new cluster, do the following: + +1. Configure the restore object, Edit the `deploy/backup/restore.yaml` manifest and provide the following details: + + * `metadata.name` - the name of the restore object + * `spec.clusterName` - the name of the target cluster on which you make a restore + * For the `spec.backupSource` subsection, specify the following: + + * `type` - set to `external` + * `spec.backupSource` - define the source of your backup. Fill in these fields: + + * `type` - set to `external`. + * `snapshots` - provide a list including: + * The name of each snapshot. + * The replica set (`replsetName`) each snapshot corresponds to. + + For sharded clusters, include snapshots for the config server replica set and every shard replica set listed in the source backup. + + Here's the example configuration: + + ```yaml + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBRestore + metadata: + name: my-snapshot-restore + spec: + clusterName: my-new-cluster + backupSource: + type: external + snapshots: + - replsetName: rs0 + snapshotName: my-snapshot-backup-rs0-0 + - replsetName: rs0 + snapshotName: my-snapshot-backup-rs0-1 + - replsetName: rs0 + snapshotName: my-snapshot-backup-rs0-2 + ``` + +2. Apply the configuration to start the restore: + + ```bash + kubectl apply -f deploy/backup/restore.yaml -n $NAMESPACE + ``` + +3. Monitor the restore state: + + ```bash + kubectl get psmdb-restore -n $NAMESPACE + kubectl describe psmdb-restore my-snapshot-restore -n $NAMESPACE + ``` + + Typical restore states are: + + | State | What happens | + | --- | --- | + | `waiting` | Operator prepares PBM config and cluster for physical-style restore | + | `requested` | `pbm restore --external` started; waiting for **`copyReady`** | + | `running` | PVCs recreated from snapshots; `pbm-agent restore-finish` and `pbm restore-finish` run | + | `ready` | Restore completed | + +4. Inspect restore conditions: + + ```bash + kubectl get psmdb-restore my-snapshot-restore -n $NAMESPACE -o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\n"}{end}' + ``` + + Expected conditions when finished include `ReplsetPVCsRestoredFromSnapshot` and `PBMRestoreFinished`. + +## Post-restore steps + +1. Verify cluster health: + + ```bash + kubectl get psmdb -n $NAMESPACE + kubectl get pods -n $NAMESPACE + ``` + +2. Make a **new** base backup (logical, physical, or snapshot) before relying on this cluster for disaster recovery again. + +## Troubleshooting + +| Symptom | What to check | +| --- | --- | +| Restore stuck in `requested` | PBM restore status: `pbm describe-restore` in a database Pod; nodes must reach `copyReady` | +| Restore stuck in `running` | `kubectl get pvc`; snapshot names in `backupSource` / backup status; `kubectl describe psmdb-restore` conditions | +| PVC not recreated | Source `VolumeSnapshot` exists and is `readyToUse`; name matches `status.snapshots` | +| Encryption errors | For PBM-assisted backups, Operator supplies `db` config; verify encryption settings match the backup source cluster | + +For logical and physical restore procedures, see [Restore the cluster from a previously saved backup](backups-restore.md). + diff --git a/docs/backups-restore.md b/docs/backups-restore.md index f76cf2a9..cc801899 100644 --- a/docs/backups-restore.md +++ b/docs/backups-restore.md @@ -14,6 +14,7 @@ You can make the following restores: * [Restore to a specific point in time](#make-a-point-in-time-recovery). A precondition for this restore is to [enable saving oplog operations](backups-pitr.md) * [Restore from a backup](#restore-from-a-backup) +* [Restore from a PVC snapshot backup](backups-pvc-usage.md#make-an-in-place-restore-from-a-pvc-snapshot-backup) * [Selective restore from a full logical backup](#selective-restore) For either type of a restore you need to create a Restore object using the [`deploy/backup/restore.yaml` :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/main/deploy/backup/restore.yaml) manifest. @@ -22,7 +23,7 @@ You can specify the backup to restore from in two ways: using the `backupName` o * Use the **`backupName`** option when backup objects exist in the cluster, such as for restoring to the same cluster where the backup was created. When you specify the `backupName`, PBM automatically determines the backup type and performs the corresponding restore procedure. -* Use the **`backupSource`** option when there are no backup objects in the cluster, such as [when restoring to a new cluster](backups-restore-to-new-cluster.md). You can also use the `backupSource` for restores to the same cluster, instead of the `backupName`. If you specify the `backupSource`, you must manually specify the backup type (`logical`, `physical` or `incremental`) in the configuration. +* Use the **`backupSource`** option when there are no backup objects in the cluster, such as [when restoring to a new cluster](backups-restore-to-new-cluster.md). You can also use the `backupSource` for restores to the same cluster, instead of the `backupName`. If you specify the `backupSource`, you must manually specify the backup type (`logical`, `physical`, `incremental`, or `external`) in the configuration. ## Considerations diff --git a/docs/backups-scheduled.md b/docs/backups-scheduled.md index 44e0ba74..a69a90c5 100644 --- a/docs/backups-scheduled.md +++ b/docs/backups-scheduled.md @@ -17,7 +17,8 @@ To configure scheduled backups, modify the `backups` section of the [deploy/cr.y * `name` - specify a backup name. You will need this name when you [restore from this backup](backups-restore.md). * `schedule` - specify the desired backup schedule in [crontab format :octicons-link-external-16:](https://en.wikipedia.org/wiki/Cron). * `enabled` - set this key to `true`. This enables making the `` backup along with the specified schedule. - * `storageName` - specify the name of your [already configured storage](backups-storage.md). + * `storageName` - specify the name of your [already configured storage](backups-storage.md). Omit for PVC snapshot (`external`) tasks. + * `volumeSnapshotClass` - specify the `VolumeSnapshotClass` name when `type` is `external`. See [Configure PVC snapshots](backups-pvc-setup.md) how to check if `VolumeSnapshotClass` exists in your cluster and how to add it if it doesn't. * `retention` - configure the retention policy: how many backups to keep in the storage. This setting is optional. It applies to base incremental backups but is ignored for increments. Read more about it in the [Configure retention](#configure-retention) section. * `type` - specify what [type of backup](backups.md#backup-types) to make. If you leave it empty, the Operator makes a **logical** backup by default. @@ -131,4 +132,33 @@ Use the `backup.tasks.retention` subsection to configure the retention policy fo ... ``` +=== "PVC snapshot (external)" + + This example runs a daily PVC snapshot at 2:00 a.m. and keeps the seven most recent snapshots: + + ```yaml + ... + backup: + enabled: true + storages: + s3-us-west: + type: s3 + s3: + bucket: S3-BACKUP-BUCKET-NAME-HERE + region: us-west-2 + credentialsSecret: my-cluster-name-backup-s3 + tasks: + - name: daily-snapshot + enabled: true + schedule: "0 2 * * *" + type: external + volumeSnapshotClass: gke-snapshot-class + retention: + count: 7 + type: count + deleteFromStorage: true + ``` + + See [Make a scheduled snapshot-based backup](backups-pvc-usage.md#make-a-scheduled-snapshot-based-backup). + --8<-- "restore-new-k8s-env.md" diff --git a/docs/backups.md b/docs/backups.md index 094e15f8..08c3d29a 100644 --- a/docs/backups.md +++ b/docs/backups.md @@ -1,9 +1,10 @@ # About backups -You can back up your data in two ways: +You can back up your data in several ways: * *On-demand*. You can do them manually at any moment. * *Scheduled backups*. Configure backups and their schedule in the [deploy/cr.yaml :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/main/deploy/cr.yaml). The Operator makes them automatically according to the specified schedule. +* *PVC snapshot backups*. Starting with Operator version 1.23.0, you can use Kubernetes volume snapshots for fast, storage-level copies without uploading data to object storage. See [PVC snapshot backups](backups-pvc-snapshots.md). To make backups and restores, the Operator uses the [Percona Backup for MongoDB (PBM) :octicons-link-external-16:](https://github.com/percona/percona-backup-mongodb) tool. The Operator runs PBM as [a sidecar container](sidecar.md) to the database Pods. It configures PBM in the following cases: @@ -25,6 +26,7 @@ The `pbm-agent` reads the backup type from the document, copies data based on th * Logical backup: PBM reads database data and uploads it. * Physical backup: PBM copies data files from `dbPath` and uploads them. + * External (PVC snapshot) backup: PBM prepares the database for a consistent copy; the Operator creates CSI `VolumeSnapshot` objects for each data PVC. See [PVC snapshot backups](backups-pvc-snapshots.md#backup-flow). ### Restore flow @@ -56,6 +58,29 @@ To restore the database from a physical backup, a `pbm-agent` requires the acces 4. During the restore, PBM restarts the `mongod` process several times as it switches between restore phases and starts `mongod` with the newly restored data files. 5. After a successful restore, the Operator recreates the StatefulSet with the regular configuration so PBM runs as a sidecar again. All database Pods are terminated and recreated. The Operator also restarts arbiter nodes and `mongos` Pods. +**From PVC snapshot (`external`) backup** + +Snapshot restores use PBM’s [external restore :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/usage/restore-external-agent-restart.html) workflow. At **`copyReady`**, `mongod` is stopped and data directories are empty, so the Operator recreates PVCs from volume snapshots and runs `pbm-agent restore-finish` before PBM can complete the restore. + +When you create the Restore object, the following occurs: + +1. The Operator prepares the cluster: + + * It terminates `mongos` Pods (for sharded clusters) and arbiter nodes to prevent clients from accessing the database during the restore. + * It prepares StatefulSets for restore (as for a physical backup) and starts the restore with `pbm restore --external`. + +2. PBM shuts down `mongod`, wipes the `dbPath` on each data-bearing node, and exits, leaving nodes in **`copyReady`** state waiting for data files. + +3. The Operator scales database StatefulSets to zero and runs `pbm-agent restore-finish` on every node, passing the PBM config, replica set name, node name, and (when needed) MongoDB `db` config for encryption at rest. + +4. The Operator recreates each data PVC from the `VolumeSnapshot` recorded in the backup or listed in `backupSource.snapshots`, one PVC at a time. + +5. The Operator scales StatefulSets back up and runs `pbm restore-finish` so PBM applies backup metadata and brings the cluster to a consistent state. + +6. After a successful restore, the Operator cleans up temporary restore configuration and returns the cluster to normal operation. + +For step-by-step instructions, see [Restore from a PVC snapshot backup](backups-pvc-usage.md#make-an-in-place-restore-from-a-pvc-snapshot-backup). + **Point-in-time recovery from a physical backup** 1. The Operator follows the same preparation steps as for a physical restore. @@ -97,4 +122,5 @@ Find more information in the [Multiple storages for backups](multi-storage.md) c | Full logical | Initial | GA | Queries Percona Server for MongoDB for database data and writes this data to the remote storage | - Uses less storage but is slower than physical backups
- Supports selective restore since [1.18.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.18.0.md)
- Supports point-in-time recovery
- Incompatible for restores with backups made with Operator versions before 1.9.0. Make a new backup after the upgrade to the Operator 1.9.0. | | Full physical | [1.14.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.14.0.md) | GA ([1.16.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.16.0.md)) | Copies physical files from MongoDB `dbPath` data directory to remote storage | - Faster backup/restore than logical
- Better for large datasets
- Supports point-in-time recovery since [1.15.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.15.0.md)| | Physical incremental | [1.20.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.20.0.md) | Tech preview | Copies only data changed after the previous backup | - Speeds up backup/restore
- Reduces network load and storage consumption
- Requires a base incremental backup to start the incremental chain
- Base backup and increments must bet taken from the same node
- New base backup is needed if a node is down or if the cluster was restored from a backup| +| PVC snapshot (`external`) | 1.23.0 | GA | PBM prepares the database; the Operator creates CSI volume snapshots of data PVCs | - Fast for large datasets; no data upload to object storage
- Requires Volume Snapshot API and `VolumeSnapshotClass` per backup
- No point-in-time recovery or selective restore
- See [PVC snapshot backups](backups-pvc-snapshots.md) | diff --git a/docs/cr-statuses.md b/docs/cr-statuses.md index 8cf01892..0f67249d 100644 --- a/docs/cr-statuses.md +++ b/docs/cr-statuses.md @@ -150,7 +150,8 @@ Backup progress and results are in `status.state`. You also get destination and Common fields: - `status.state` – backup job state -- `status.type` – backup type (`logical`, `physical`, `incremental`, `incremental-base`) +- `status.type` – backup type (`logical`, `physical`, `incremental`, `incremental-base`, `external`) +- `status.snapshots` – for `external` backups, list of `VolumeSnapshot` names per replica set (`replsetName`, `snapshotName`) - `status.destination` – backup path or URL - `status.size` – backup size - `status.start` / `status.completed` – start and completion timestamps @@ -181,6 +182,7 @@ Common fields: - `status.pitrTarget` – PITR target time (if set) - `status.completed` – completion timestamp - `status.error` – error details when the restore fails +- `status.conditions` – restore progress for PVC snapshot restores. See [PVC snapshot restore conditions](#pvc-snapshot-restore-conditions) ### Restore state values @@ -195,3 +197,26 @@ Common fields: | `running` | Restore is in progress. | | `ready` | Restore completed successfully. | | `error` | Restore failed. | + +### PVC snapshot restore conditions + +For restores from PVC snapshot backups, the Operator sets `status.conditions` as each phase completes. These conditions appear only for snapshot restores of the type `external`. Use them with `status.state` to see where a long-running restore is stuck. + +Each condition uses the standard Kubernetes fields (`type`, `status`, `reason`, `message`, `lastTransitionTime`). When a phase succeeds, the Operator sets the matching condition to `status: "True"`. + +| Condition | Meaning | +| --- | --- | +| `PBMAgentConfiguredForSnapshot` | Database StatefulSets are scaled to zero. Pods are configured to run `pbm-agent restore-finish` with the PBM config, replica set name, node name, and (if needed) encryption-related MongoDB config. | +| `ReplsetPVCsRestoredFromSnapshot` | All data PVCs are recreated from the `VolumeSnapshot` objects in the backup or in `backupSource.snapshots`. PVCs are rolled out one at a time. | +| `PBMAgentAwaitingRestoreFinish` | StatefulSets are scaled back up. `pbm-agent` processes on every node are running and waiting at PBM **`copyReady`** for the restore to finish. | +| `PBMRestoreFinishing` | The Operator started `pbm restore-finish` to apply backup metadata. | +| `PBMRestoreFinished` | PBM completed the external restore. The Operator can clean up temporary restore configuration. | + +Example: list restore conditions: + +```bash +kubectl get psmdb-restore -n \ + -o jsonpath='{range .status.conditions[*]}{.type}{"\t"}{.status}{"\t"}{.reason}{"\n"}{end}' +``` + +For the full restore workflow, see [PVC snapshot backups — Restore flow](backups-pvc-snapshots.md#restore-flow). diff --git a/docs/operator.md b/docs/operator.md index be2ba431..bafd8885 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -3947,12 +3947,20 @@ The backup compression level ([higher values result in better but slower compres ### `backup.tasks.type` -The backup type: (can be either `logical` (default) or `physical`; see [the Operator backups official documentation](backups.md#backup-types) for details. +The backup type. Can be `logical` (default), `physical`, `incremental`, `incremental-base`, or `external` (PVC snapshot). See [backup types](backups.md#backup-types). | Value type | Example | | ----------- | ---------- | | :material-code-string: string | `physical` | +### `backup.tasks.volumeSnapshotClass` + +The name of the Kubernetes `VolumeSnapshotClass` for scheduled PVC snapshot backups. **Required** when `backup.tasks.type` is `external`. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `gke-snapshot-class` | + ##
Log Collector section The `logcollector` section contains configuration options for [Fluent Bit Log Collector :octicons-link-external-16:](https://fluentbit.io). diff --git a/docs/restore-options.md b/docs/restore-options.md index d73dc83f..1f9f1049 100644 --- a/docs/restore-options.md +++ b/docs/restore-options.md @@ -107,15 +107,40 @@ Contains the configuration options to restore from a backup made in a different ### `backupSource.type` -Specifies the backup type. Available options: physical, logical, incremental +Specifies the backup type. Available options: `logical`, `physical`, `incremental`, `external`. + +Use `external` when restoring from [PVC snapshot backups](backups-pvc-usage.md#make-a-restore-to-a-new-cluster). | Value type | Example | | ----------- | ---------- | | :material-code-string: string | `physical` | +### `backupSource.snapshots` + +Lists `VolumeSnapshot` objects to restore from when `backupSource.type` is `external`. Required for cross-cluster or manual snapshot restores when no `PerconaServerMongoDBBackup` exists in the target namespace. + +Each item includes: + +| Field | Description | +| --- | --- | +| `replsetName` | Replica set name. | +| `snapshotName` | `VolumeSnapshot` name in the restore namespace. | + +Example: + +```yaml +backupSource: + type: external + snapshots: + - replsetName: rs0 + snapshotName: my-snapshot-backup-rs0-0 +``` + +When you use `spec.backupName` instead, the Operator reads snapshots from the Backup resource `status.snapshots`. + ### `backupSource.destination` -Specifies the path to the backup on the storage +Specifies the path to the backup on the storage. | Value type | Example | | ----------- | ---------- | diff --git a/mkdocs-base.yml b/mkdocs-base.yml index bd460b9c..8c3c1764 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -276,6 +276,10 @@ nav: - "Remote file server": backups-storage-filesystem.md - multi-storage.md - "Store operations logs for point-in-time recovery": backups-pitr.md + - "PVC snapshot backups": + - Overview: backups-pvc-snapshots.md + - "Configure PVC snapshots": backups-pvc-setup.md + - "Use PVC snapshots": backups-pvc-usage.md - Make a backup: - Scheduled backup: backups-scheduled.md - On-demand backup: backups-ondemand.md From 0eff8fa36d6d5cb00c6ada437dfd3ecf05bebe95 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 11:48:42 +0300 Subject: [PATCH 14/22] K8SPSMDB-1413 Documented the use of ClusterIssuer (#349) modified: docs/TLS.md modified: docs/env-vars-operator.md modified: docs/operator.md modified: docs/tls-cert-manager.md modified: docs/tls-update.md --- docs/TLS.md | 31 ++++- docs/env-vars-operator.md | 28 +++++ docs/operator.md | 31 ++++- docs/tls-cert-manager.md | 235 +++++++++++++++++++++++++++++++++----- docs/tls-update.md | 205 ++++++++++++++++++++++++--------- 5 files changed, 437 insertions(+), 93 deletions(-) diff --git a/docs/TLS.md b/docs/TLS.md index 8689c3d1..2e11ca5c 100644 --- a/docs/TLS.md +++ b/docs/TLS.md @@ -5,6 +5,8 @@ Percona Operator for MongoDB uses Transport Layer Security (TLS) cryptographic p * External - to enable client applications communicate with the cluster * Internal - for communication between Percona Server for MongoDB instances in the cluster. The internal certificate is also used as an authorization method. +These certificates are stored in Secrets. Default Secret names are `-ssl` and `-ssl-internal`. These Secrets are referenced in the `secrets.ssl` and `secrets.sslInternal` Custom Resource options. + You control TLS usage with the `tls.mode` option in the Custom Resource. This setting defines how Percona Server for MongoDB cluster handles TLS for both internal and external connections. You can choose from the following modes: - `allowTLS`: The cluster accepts both TLS and non-TLS incoming connections, but does not use TLS for internal communication. @@ -24,16 +26,33 @@ spec: ## TLS Certificates -TLS security can be configured in several ways: +You can configure TLS security in several ways: + +| Approach | Best for | Renewal | +| -------- | -------- | ------- | +| Operator-generated certificates (default) | Quick start, development | Manual | +| cert-manager with Operator-managed issuers | Automated TLS without external PKI | Automatic (cert-manager) | +| cert-manager with your existing `Issuer` or `ClusterIssuer` | Production clusters that use the organization's PKI (Smallstep, ACME, etc.) | Automatic (cert-manager) | +| Manual Secrets | Full control, air-gapped or custom PKI workflows | Manual | + +* By default, the Operator generates long-term certificates automatically during the cluster creation if there are no +certificate secrets available and no cert-manager is installed. When generating certificates, the Operator creates two Secrets objects named `-ssl` and `-ssl-internal`. These Secrets are referenced in the `secrets.ssl` and `secrets.sslInternal` options in the Custom Resource. -* The Operator generates long-term certificates automatically during cluster creation if no TLS Secrets are available. It creates two Secret objects named `-ssl` and `-ssl-internal`, referenced by `secrets.ssl` and `secrets.sslInternal` in the Custom Resource. This is the default behavior. The Operator doesn't rotate the certificates as long as it has access to the Secrets. Learn more about it in the [Certificate management policy](#certificate-management-policy) section. + Operator-generated certificates are not renewed automatically. You must renew them manually if you need new certificates. - To use Operator-generated self-signed certificates, leave [tls.allowInvalidCertificates](operator.md#tlsallowinvalidcertificates) at `true` (default). Set it to `false` when you use other certificate generation methods, such as cert-manager or your own CA. + To allow certificates automatically generated by the Operator, the [tls.allowInvalidCertificates](operator.md#tlsallowinvalidcertificates) + Custom Resource option is set to `true` by default. You can set it to `false` when using other certificate generation methods, such as cert-manager with a trusted CA. -* The Operator can use a specifically installed *cert-manager*, which will automatically generate and renew short-term TLS certificates. -* You can [generate TLS certificates manually](tls-manual.md). +* The Operator can use an installed *cert-manager* to automatically generate and + renew short-term TLS certificates. By default it creates namespace-scoped issuers + in the database namespace. Starting with Operator 1.23.0, you can also point it + at an existing cluster-wide [`ClusterIssuer`](tls-cert-manager.md#use-an-existing-clusterissuer) + so MongoDB certificates are signed by your organization's CA. +* You can [generate TLS certificates manually](tls-manual.md) and pass them to the Operator as Kubernetes Secrets. - **For testing purposes**, you can use pre-generated certificates available in the `deploy/ssl-secrets.yaml` file. We strongly recommend **not** using them in production. +**For testing purposes**, you can use pre-generated certificates available in the +`deploy/ssl-secrets.yaml` file. But we strongly recommend +**to not use them on any production system**! ### Certificate management policy diff --git a/docs/env-vars-operator.md b/docs/env-vars-operator.md index dfb227f1..8596053b 100644 --- a/docs/env-vars-operator.md +++ b/docs/env-vars-operator.md @@ -124,6 +124,34 @@ env: value: "3" ``` +### `CERTMANAGER_NAMESPACE` + +Specifies the namespace where the Operator creates the intermediate CA +`Certificate` when [`tls.issuerConf.kind`](operator.md#tlsissuerconfkind) is +`ClusterIssuer` and the Operator manages the CA chain. + +|Value type|Default|Example| +|---|---|---| +|string|`cert-manager`|`my-cert-manager`| + +**Notes:** + +- This variable applies only when the Operator creates cert-manager resources for + a `ClusterIssuer`-based CA chain. It does not affect database Pods or TLS Secrets, + which remain in the database namespace. +- Change this value only if cert-manager is installed in a non-default namespace. +- When you use an existing organizational `ClusterIssuer`, you typically do not + need to change this variable. See + [Use an existing ClusterIssuer](tls-cert-manager.md#use-an-existing-clusterissuer). + +**Example configuration:** + +```yaml +env: + - name: CERTMANAGER_NAMESPACE + value: "cert-manager" +``` + ## Automatic environment variables The following values are set by Kubernetes or the deployment manifest and should not be changed: diff --git a/docs/operator.md b/docs/operator.md index bafd8885..f70eb4cb 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -311,6 +311,10 @@ Prevents running backup on a cluster with [failed health checks :octicons-link-e The `tls` section in the [deploy/cr.yaml :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/main/deploy/cr.yaml) file contains various configuration options for additional customization of the [Transport Layer Security](TLS.md). +The [`tls.issuerConf`](#operator-issuerconf-section) options below control which cert-manager issuer +signs MongoDB TLS certificates. See [Configure TLS using cert-manager](tls-cert-manager.md) +for setup examples. + ### `tls.mode` Controls if the [TLS encryption](TLS.md) should be used and/or enforced. Can be @@ -332,7 +336,7 @@ The validity duration of the external certificate for cert manager (90 days by d ### `tls.allowInvalidCertificates` If `true`, the mongo shell will not attempt to validate the server certificates. -**Should be true (default variant) to use self-signed certificates generated by the Operator when there is no cert-manager.** +**Should be `true` (the default) to use self-signed certificates generated by the Operator when there is no cert-manager.** Set to `false` when using cert-manager with a trusted organizational CA (for example, an existing `ClusterIssuer`). | Value type | Example | | ----------- | ---------- | @@ -351,24 +355,41 @@ Controls how the Operator manages TLS certificates when it loses access to the S ### `tls.issuerConf.name` -A [cert-manager issuer name :octicons-link-external-16:](https://cert-manager.io/docs/concepts/issuer/). +The name of the cert-manager [Issuer :octicons-link-external-16:](https://cert-manager.io/docs/concepts/issuer/) resource that signs MongoDB TLS certificates. + +When set, the Operator creates `Certificate` resources that reference this issuer +and does not create its own CA chain. Use this to integrate with an existing +organizational PKI. See [Use an existing ClusterIssuer](tls-cert-manager.md#use-an-existing-clusterissuer) +for setup steps. | Value type | Example | | ----------- | ---------- | -| :material-code-string: string | `special-selfsigned-issuer` | +| :material-code-string: string | `my-org-issuer` | ### `tls.issuerConf.kind` -A [cert-manager issuer type :octicons-link-external-16:](https://cert-manager.io/docs/configuration/). +The cert-manager [issuer type :octicons-link-external-16:](https://cert-manager.io/docs/configuration/) referenced by MongoDB `Certificate` resources. + +Supported values: + +* `Issuer` (default) — namespace-scoped issuer in the database namespace. +* `ClusterIssuer` — cluster-scoped issuer. Available starting with Operator 1.23.0. + Use this when your platform team manages a cluster-wide issuer (for example, Smallstep or ACME). Read more in [Use an existing ClusterIssuer](tls-cert-manager.md#use-an-existing-clusterissuer) + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `ClusterIssuer` | + ### `tls.issuerConf.group` -A [cert-manager issuer group :octicons-link-external-16:](https://cert-manager.io/docs/configuration/). Should be `cert-manager.io` for built-in cert-manager certificate issuers. +The cert-manager API group for the issuer referenced in `issuerConf`. Use the `cert-manager.io` for built-in cert-manager certificate issuers | Value type | Example | | ----------- | ---------- | | :material-code-string: string | `cert-manager.io` | + ## Upgrade Options Section The `upgradeOptions` section in the [deploy/cr.yaml :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/main/deploy/cr.yaml) file contains various configuration options to control Percona Server for MongoDB upgrades. diff --git a/docs/tls-cert-manager.md b/docs/tls-cert-manager.md index 159614d4..5fe99927 100644 --- a/docs/tls-cert-manager.md +++ b/docs/tls-cert-manager.md @@ -2,50 +2,227 @@ ## About the *cert-manager* -The [cert-manager :octicons-link-external-16:](https://cert-manager.io/docs/) is a Kubernetes certificate +The [cert-manager :octicons-link-external-16:](https://cert-manager.io/docs/) is a Kubernetes certificate management controller which is widely used to automate the management and issuance -of TLS certificates. It is community-driven, and open source. +of TLS certificates. It is community-driven and open source. -When you have already installed *cert-manager* and deploy the operator, the -operator requests a certificate from the *cert-manager*. The *cert-manager* acts -as a self-signed issuer and generates certificates. The Percona Operator -self-signed issuer is local to the operator namespace. This self-signed issuer -is created because Percona Server for MongoDB requires all certificates issued -by the same CA (Certificate authority). +When the Operator creates a database cluster, it checks if the [cert-manager is installed](#install-the-cert-manager) and if you haven't provided custom TLS secrets. If these conditions are met, the Operator creates the self-signed `Issuer` or `ClusterIssuer` resource within the cert-manager and requests a certificate from it. The cert-manager generates certificates and stores them in Kubernetes Secrets. The Operator uses these Secrets for TLS in the cluster. The cert-manager manages the certificate lifecycle. -Self-signed issuer allows you to deploy and use the Percona Operator without -creating a cluster issuer separately. +You can use cert-manager in two ways: + +* **Operator-managed issuers (default)** — By default, the Operator creates a Kubernetes `Issuer` resource, which is namespace-scoped, along with a local self-signed Certificate Authority (CA) in the same database namespace. The `Issuer` is used for clusters that are deployed within a single namespace and handles certificate generation for that specific namespace. + + For deployments spanning multiple namespaces, the Operator can instead use a `ClusterIssuer` resource, which is cluster-scoped and can issue certificates across any namespace. Use a `ClusterIssuer` for [multi-namespace](cluster-wide.md) setups. Both approaches are automated by the Operator and require no additional PKI configuration from you. + +* **Your existing issuer** — you point the Operator at a cert-manager `Issuer` or + `ClusterIssuer` that your platform team already manages (for example, Smallstep, + ACME, or a corporate CA). Percona Server for MongoDB certificates are then signed and renewed under + your organization's PKI policies. + +See [Transport Layer Security (TLS)](TLS.md) for a comparison of cert-manager integration +with manual certificate generation. ## Install the *cert-manager* -The steps to install the *cert-manager* are the following: +The cert-manager requires its own namespace. By default, this is the `cert-manager` namespace. -* create a namespace, -* disable resource validations on the cert-manager namespace, -* install the cert-manager. +1. Run the following command to install cert-manager: -The following commands perform all the needed actions: + ```bash + kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v{{ certmanagerrecommended }}/cert-manager.yaml + ``` + + This creates the dedicated namespace cert-manager and installs cert-manager Deployments, Pods and Services in this namespace. It also creates cluster-wide resources such as Custom Resource Definitions and RBAC to enable the use of cert-manager in any namespace in the Kubernetes cluster. -```bash -kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v{{ certmanagerrecommended }}/cert-manager.yaml --validate=false +2. Verify the cert-manager by running the +following command: + + ```bash + kubectl get pods -n cert-manager + ``` + + The result should display the cert-manager and webhook active and running: + + ``` {.text .no-copy} + NAME READY STATUS RESTARTS AGE + cert-manager-7d59dd4888-tmjqq 1/1 Running 0 3m8s + cert-manager-cainjector-85899d45d9-8ncw9 1/1 Running 0 3m8s + cert-manager-webhook-84fcdcd5d-697k4 1/1 Running 0 3m8s + ``` + +At this point you are ready [to install the Operator and deploy Percona Server for MongoDB cluster](kubectl.md). + +See the sections below for how you can fine-tune the Operator and cert-manager to better meet your security requirements when managing TLS for your cluster: + +- [Customize certificate duration for cert-manager](#customize-certificate-duration-for-cert-manager) +* [Configure TLS certificate management policy](tls-cert-management-policy.md) +- [Operator-managed namespace-scoped issuers (default)](#operator-managed-namespace-scoped-issuers-default) +- [Operator-managed issuers with ClusterIssuer scope](#operator-managed-issuers-with-clusterissuer-scope) +- [Use an existing ClusterIssuer](#use-an-existing-clusterissuer) +- [Use an existing namespace-scoped Issuer](#use-an-existing-namespace-scoped-issuer) + +## Customize certificate duration for cert-manager + +When you deploy the cluster using the default configuration, the Operator triggers the cert-manager to create certificates +with default duration of 90 days. + +You can customize the certificate duration. For example, to align certificate lifetimes with your organization’s security and compliance policies. + +### Rules and limitations + +Check the following rules and limitations for setting up the certificate duration: + +1. You can set the duration **only when you create a new cluster**. Updating it in a running cluster is not supported. +2. The TLS certificate duration is subject to the following requirements: + + * The minimum accepted value is 1 hour. Durations below 1 hour are rejected. + * Do **not** set the duration to exactly 1 hour; the Operator will fail to generate the correct certificate object if you do. + * By default, cert-manager starts the renewal process when a certificate has one-third of its lifetime remaining, ensuring renewal before expiration. For example, if a certificate is valid for 1 hour, renewal will begin after approximately 40 minutes. + +3. Minimum CA certificate duration is 730 hours (approximately 30 days). Do not set the duration to exactly 730 hours; the Operator will fail to generate the correct certificate object if you do. + +### Configuration + +To set the custom duration, specify the `.spec.tls.certValidityDuration` option in the Custom Resource. This option defines the validity period for TLS certificates + +Here's the example configuration: + +```yaml + tls: + mode: preferTLS + certValidityDuration: 2160h + allowInvalidCertificates: true ``` -After the installation, you can verify the *cert-manager* by running the -following command: +Create a new cluster with this configuration: ```bash -kubectl get pods -n cert-manager +kubectl apply -f deploy/cr.yaml -n +``` + +To verify the duration, you can [check certificates for expiration](tls-update.md#check-your-certificates-for-expiration) at any time. This ensures your certificates are valid and helps you plan for renewals before they expire. + +## Operator-managed namespace-scoped issuers (default) + +Once you create the database with the Operator and cert-manager is running, the +Operator automatically creates: + +* a self-signed CA `Issuer` and CA `Certificate` in the database namespace, +* a signing `Issuer` that references the CA, +* external and internal TLS `Certificate` resources (`-ssl` and + `-ssl-internal`). + +cert-manager issues short-lived certificates (90 days by default) and renews them +on schedule. Set [`tls.allowInvalidCertificates`](operator.md#tlsallowinvalidcertificates) +to `true` (the default) for this self-signed setup. + + +## Operator-managed issuers with ClusterIssuer scope + +!!! note "Version availability: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +If you want the Operator to manage the CA chain and issue certificates across all namespaces, use the +`ClusterIssuer` resource rather than namespace-scoped `Issuer` resources. + +Configure the Custom Resource as follows: + +```yaml +spec: + tls: + allowInvalidCertificates: false + issuerConf: + kind: ClusterIssuer + group: cert-manager.io ``` -The result should display the *cert-manager* and webhook active and running: +Set the `tls.issuerConf.kind` option to `ClusterIssuer` without pre-creating issuers yourself. +The Operator creates the CA `Certificate` and the `ClusterIssuer` resource in the cert-manager namespace (`cert-manager` by default). The cert-manager generates signed certificates using the ClusterIssuer. -``` {.text .no-copy} -NAME READY STATUS RESTARTS AGE -cert-manager-7d59dd4888-tmjqq 1/1 Running 0 3m8s -cert-manager-cainjector-85899d45d9-8ncw9 1/1 Running 0 3m8s -cert-manager-webhook-84fcdcd5d-697k4 1/1 Running 0 3m8s +If you installed cert-manager in a custom namespace, you must explicitly define it in the `CERTMANAGER_NAMESPACE` environment variable for the Operator deployment. + +## Use an existing ClusterIssuer + +!!! note "Version availability: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +If your cluster already runs cert-manager with a cluster-wide issuer, such as +Smallstep, Let's Encrypt, or an internal CA, you can configure the Operator to +request Percona Server for MongoDB certificates from that issuer instead of creating its own CA chain. + +Configure the Custom Resource as follows: + +```yaml +spec: + tls: + allowInvalidCertificates: false + issuerConf: + name: my-org-issuer # name of your existing ClusterIssuer + kind: ClusterIssuer + group: cert-manager.io ``` -Once you create the database with the Operator, it will automatically trigger the -cert-manager to create certificates. Whenever you check certificates for expiration, -you will find that they are valid and short-term. +Replace `my-org-issuer` with the name of your existing `ClusterIssuer`. Set +[`tls.allowInvalidCertificates`](operator.md#tlsallowinvalidcertificates) to +`false` so MongoDB validates certificates against your trusted CA. + +When you deploy the cluster, the Operator creates `Certificate` resources that +reference your `ClusterIssuer`. cert-manager signs the resulting Secrets; the +Operator does not create a parallel CA or overwrite your issuer. + +!!! note + + The Operator's default RBAC does not grant access to cluster-scoped + `ClusterIssuer` resources. This is expected: cert-manager resolves the issuer + when processing `Certificate` objects. You do not need to add extra Operator + permissions to use an existing `ClusterIssuer`. + +## Use an existing namespace-scoped Issuer + +To use a cert-manager `Issuer` that already exists in the database namespace, +set [`tls.issuerConf.name`](operator.md#tlsissuerconfname) to that issuer's name. +You can leave `kind` at the default value (`Issuer`). + +```yaml +spec: + tls: + allowInvalidCertificates: false + issuerConf: + name: my-org-issuer # name of your existing Issuer + kind: Issuer + group: cert-manager.io +``` + +When the issuer name refers to an existing resource, the Operator creates TLS +`Certificate` resources that cert-manager signs through your issuer. It does not +recreate the issuer or its CA chain. + +## Pre-create certificates before deployment + +If your platform team manages cert-manager objects directly, you can create +`Certificate` (and optionally `ClusterIssuer`) resources before deploying the +cluster. When the Operator starts reconciliation, it preserves user-created +cert-manager resources that are not owned by the Operator. + +To use this approach: + +1. Create the `Certificate` resources (and issuers, if needed) in the database + namespace with the names the Operator expects: `-ssl` and + `-ssl-internal`. +2. Configure [`tls.issuerConf`](operator.md#operator-issuerconf-section) in the + Custom Resource if your certificates are signed by a specific issuer. +3. Deploy the cluster with the Operator. + +Alternatively, you can supply TLS material as Kubernetes Secrets and reference +them in [`secrets.ssl` and `secrets.sslInternal`](tls-manual.md#configure-your-cluster) +without using cert-manager at all. + +## Operator environment variable + +When the Operator manages a CA chain with `tls.issuerConf.kind: ClusterIssuer`, +it stores the intermediate CA `Certificate` in the cert-manager namespace. +By default this namespace is `cert-manager`. If you installed cert-manager +elsewhere, set the [`CERTMANAGER_NAMESPACE`](env-vars-operator.md#certmanager_namespace) +environment variable on the Operator Deployment. + +For more details on all cert-manager-related Custom Resource options, see the +[`tls.issuerConf` section](operator.md#operator-issuerconf-section) in the +Operator spec reference. diff --git a/docs/tls-update.md b/docs/tls-update.md index 15d9a9bc..4a151965 100644 --- a/docs/tls-update.md +++ b/docs/tls-update.md @@ -4,7 +4,7 @@ How your TLS certificates are updated depends on how they were created: * Certificates generated by the Operator are long-term. If you need to rotate them, you must do it manually. -* Certificates issued by the cert-manager are short-term. They are valid for 3 months. The cert-manager automatically reissues the certificates on schedule and without downtime. +* Certificates issued by the cert-manager are short-term. They are valid for 3 months by default. The cert-manager automatically reissues the certificates on schedule and without downtime. ![image](assets/images/certificates.svg) @@ -31,28 +31,50 @@ How your TLS certificates are updated depends on how they were created: 2. Optionally you can also check that the certificates issuer is up and running: - ```bash - kubectl get issuer - ``` + === "Namespace-scoped Issuer (default)" - The response should be as follows: + ```bash + kubectl get issuer + ``` - ``` {.text .no-copy} - NAME READY AGE - my-cluster-name-psmdb-issuer True 61m - my-cluster-name-psmdb-ca-issuer True 61m - ``` - - Again, this command is provided by cert-manager; if you don't have it installed, you can still use `kubectl get secrets`. + The response should be as follows: - !!! note + ``` {.text .no-copy} + NAME READY AGE + my-cluster-name-psmdb-issuer True 61m + my-cluster-name-psmdb-ca-issuer True 61m + ``` + + !!! note + + The presence of two issuers has the following meaning. The + `my-cluster-name-psmdb-ca-issuer` issuer is used to create a self signed + CA certificate (`my-cluster-name-ca-cert`), and then the + `my-cluster-name-psmdb-issuer` issuer is used to create SSL certificates + (`my-cluster-name-ssl` and `my-cluster-name-ssl-internal`) signed by + the `my-cluster-name-ca-cert` CA certificate. + + === "ClusterIssuer" - The presence of two issuers has the following meaning. The - `my-cluster-name-psmdb-ca-issuer` issuer is used to create a self signed - CA certificate (`my-cluster-name-ca-cert`), and then the - `my-cluster-name-psmdb-issuer` issuer is used to create SSL certificates - (`my-cluster-name-ssl` and `my-cluster-name-ssl-internal`) signed by - the `my-cluster-name-ca-cert` CA certificate. + If you configured [`tls.issuerConf.kind: ClusterIssuer`](tls-cert-manager.md#use-an-existing-clusterissuer), + check cluster-scoped issuers: + + ```bash + kubectl get clusterissuer + ``` + + When the Operator manages the CA chain with `ClusterIssuer`, you see issuers + such as `my-cluster-name-psmdb-ca-issuer` and `my-cluster-name-psmdb-issuer`. + When you use an existing organizational issuer, only your issuer appears; + the Operator creates `Certificate` resources in the database namespace that + reference it. + + If the Operator manages the CA chain with `ClusterIssuer`, the CA + `Certificate` and its Secret (`my-cluster-name-ca-cert`) are in the + cert-manager namespace, + not in the database namespace. + + These commands are provided by cert-manager; if you don't have it installed, you can still use `kubectl get secrets`. 3. Now use the following command to find out the certificates validity dates, substituting Secrets names if necessary: @@ -159,12 +181,35 @@ Operator version prior to 1.9.0), you should move through the 2. If cert-manager is used, delete issuer and TLS certificates: - ```bash - { - kubectl delete issuer/my-cluster-name-psmdb-ca-issuer issuer/my-cluster-name-psmdb-issuer - kubectl delete certificate/my-cluster-name-ssl certificate/my-cluster-name-ssl-internal - } - ``` + === "Namespace-scoped Issuer (default)" + + ```bash + { + kubectl delete issuer/my-cluster-name-psmdb-ca-issuer issuer/my-cluster-name-psmdb-issuer + kubectl delete certificate/my-cluster-name-ssl certificate/my-cluster-name-ssl-internal + } + ``` + + === "ClusterIssuer" + + If the Operator manages issuers as `ClusterIssuer` resources: + + ```bash + { + kubectl delete clusterissuer/my-cluster-name-psmdb-ca-issuer clusterissuer/my-cluster-name-psmdb-issuer + kubectl delete certificate/my-cluster-name-ssl certificate/my-cluster-name-ssl-internal + kubectl delete -n cert-manager certificate/my-cluster-name-ca-cert + kubectl delete -n cert-manager secret/my-cluster-name-ca-cert + } + ``` + + Replace `cert-manager` with your cert-manager namespace if you set + [`CERTMANAGER_NAMESPACE`](env-vars-operator.md#certmanager_namespace) + to a different value. + + If you use an existing organizational `ClusterIssuer`, delete only the + Operator-managed `Certificate` resources and Secrets. Do not delete your + organization's issuer. 3. Delete Secrets to force the SSL reconciliation: @@ -203,37 +248,91 @@ a cluster named `cluster1`: 2. Deletion takes time. Check that all Pods disappear with `kubectl -n get pods` command, and delete certificate related resources: - - ```bash - kubectl -n delete issuer.cert-manager.io/cluster1-psmdb-ca-issuer issuer.cert-manager.io/cluster1-psmdb-issuer certificate.cert-manager.io/cluster1-ssl-internal certificate.cert-manager.io/cluster1-ssl certificate.cert-manager.io/cluster1-ca-cert secret/cluster1-ca-cert secret/cluster1-ssl secret/cluster1-ssl-internal - ``` + + === "Namespace-scoped Issuer (default)" + + ```bash + kubectl -n delete issuer.cert-manager.io/cluster1-psmdb-ca-issuer issuer.cert-manager.io/cluster1-psmdb-issuer certificate.cert-manager.io/cluster1-ssl-internal certificate.cert-manager.io/cluster1-ssl certificate.cert-manager.io/cluster1-ca-cert secret/cluster1-ca-cert secret/cluster1-ssl secret/cluster1-ssl-internal + ``` + + === "ClusterIssuer" + + ```bash + kubectl -n delete certificate.cert-manager.io/cluster1-ssl-internal certificate.cert-manager.io/cluster1-ssl secret/cluster1-ssl secret/cluster1-ssl-internal + kubectl delete clusterissuer.cert-manager.io/cluster1-psmdb-ca-issuer clusterissuer.cert-manager.io/cluster1-psmdb-issuer + kubectl -n cert-manager delete certificate.cert-manager.io/cluster1-ca-cert secret/cluster1-ca-cert + ``` + + Replace `cert-manager` with your cert-manager namespace if needed. 3. Create your own custom CA: - ```yaml title="my_new_ca.yml" - apiVersion: cert-manager.io/v1 - kind: Issuer - metadata: - name: cluster1-psmdb-ca-issuer - spec: - selfSigned: {} - --- - apiVersion: cert-manager.io/v1 - kind: Certificate - metadata: - name: cluster1-ca-cert - spec: - commonName: cluster1-ca - duration: 10000h0m0s - isCA: true - issuerRef: - kind: Issuer - name: cluster1-psmdb-ca-issuer - renewBefore: 730h0m0s - secretName: cluster1-ca-cert - ``` + === "Namespace-scoped Issuer (default)" - Apply it as usual, with the `kubectl -n apply -f my_new_ca.yml` command. + ```yaml title="my_new_ca.yml" + apiVersion: cert-manager.io/v1 + kind: Issuer + metadata: + name: cluster1-psmdb-ca-issuer + spec: + selfSigned: {} + --- + apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: cluster1-ca-cert + spec: + commonName: cluster1-ca + duration: 10000h0m0s + isCA: true + issuerRef: + kind: Issuer + name: cluster1-psmdb-ca-issuer + renewBefore: 730h0m0s + secretName: cluster1-ca-cert + ``` + + Apply it as usual, with the `kubectl -n apply -f my_new_ca.yml` command. + + === "ClusterIssuer" + + Configure the Custom Resource to use `ClusterIssuer` and apply the CA + resources before recreating the cluster: + + ```yaml title="deploy/cr.yaml (fragment)" + spec: + tls: + issuerConf: + kind: ClusterIssuer + ``` + + ```yaml title="my_new_ca.yml" + apiVersion: cert-manager.io/v1 + kind: ClusterIssuer + metadata: + name: cluster1-psmdb-ca-issuer + spec: + selfSigned: {} + --- + apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: cluster1-ca-cert + namespace: cert-manager + spec: + commonName: cluster1-ca + duration: 10000h0m0s + isCA: true + issuerRef: + kind: ClusterIssuer + name: cluster1-psmdb-ca-issuer + renewBefore: 730h0m0s + secretName: cluster1-ca-cert + ``` + + Apply the CA manifest with `kubectl apply -f my_new_ca.yml`. The CA + `Certificate` must be in the cert-manager namespace (or the namespace + set by [`CERTMANAGER_NAMESPACE`](env-vars-operator.md#certmanager_namespace)). 4. Recreate the cluster from the original `deploy/cr.yaml` configuration file: @@ -241,4 +340,4 @@ a cluster named `cluster1`: kubectl -n apply -f deploy/cr.yaml ``` -5. Verify certificate duration [in usual way](#check-your-certificates-for-expiration). \ No newline at end of file +5. Verify certificate duration [in usual way](#check-your-certificates-for-expiration). From da002837141bf20837c10b358026469573f81c16 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 11:49:29 +0300 Subject: [PATCH 15/22] K8SPSMDB-1596 Documented how to install on Rancher (#360) modified: docs/System-Requirements.md modified: docs/kubectl.md modified: mkdocs-base.yml modified: variables.yml new file: docs/rke2.md --- docs/System-Requirements.md | 1 + docs/kubectl.md | 1 + docs/rke2.md | 184 ++++++++++++++++++++++++++++++++++++ mkdocs-base.yml | 1 + 4 files changed, 187 insertions(+) create mode 100644 docs/rke2.md diff --git a/docs/System-Requirements.md b/docs/System-Requirements.md index 78b580f6..f4c29a03 100644 --- a/docs/System-Requirements.md +++ b/docs/System-Requirements.md @@ -47,5 +47,6 @@ Choose how you wish to install the Operator: * [on Google Kubernetes Engine (GKE)](gke.md) * [on Amazon Elastic Kubernetes Service (AWS EKS)](eks.md) * [on Microsoft Azure Kubernetes Service (AKS)](aks.md) +* [on Rancher Kubernetes Engine (RKE2)](rke2.md) * [on Openshift](openshift.md) * [in a Kubernetes-based environment](kubernetes.md) diff --git a/docs/kubectl.md b/docs/kubectl.md index 46e75328..4c0a4f79 100644 --- a/docs/kubectl.md +++ b/docs/kubectl.md @@ -22,6 +22,7 @@ To install Percona Distribution for MongoDB, you need the following: * [Create and configure the GKE cluster](gke.md#create-and-configure-the-gke-cluster) * [Set up Amazon Elastic Kubernetes Service](eks.md#prerequisites) * [Create and configure the AKS cluster](aks.md#create-and-configure-the-aks-cluster) + * [Create the RKE2 cluster](rke2.md#create-the-rke2-cluster) --8<-- "what-you-install.md" diff --git a/docs/rke2.md b/docs/rke2.md new file mode 100644 index 00000000..8d71e465 --- /dev/null +++ b/docs/rke2.md @@ -0,0 +1,184 @@ +# Install Percona Server for MongoDB on Rancher Kubernetes Engine (RKE2) + +This guide shows you how to deploy Percona Operator for MongoDB on +[Rancher Kubernetes Engine (RKE2) :octicons-link-external-16:](https://docs.rke2.io/). +RKE2 is a CNCF-certified Kubernetes distribution that you can run standalone or +manage with the [Rancher :octicons-link-external-16:](https://ranchermanager.docs.rancher.com/) +Kubernetes management platform. + +The document assumes some experience with the platform. For more information, +see the [RKE2 official documentation :octicons-link-external-16:](https://docs.rke2.io/). + +## Prerequisites + +The following tools and access are required: + +1. **Linux hosts** that meet the [RKE2 requirements :octicons-link-external-16:](https://docs.rke2.io/install/requirements). For a production-like setup, use at least 3 nodes so the Operator can schedule a replica set according to the [system requirements](System-Requirements.md#resource-limits). + +2. **Root or sudo** access on each host to install and start RKE2 services. + +3. **kubectl** to manage and deploy applications on Kubernetes. Install it + [following the official installation instructions :octicons-link-external-16:](https://kubernetes.io/docs/tasks/tools/install-kubectl/). + RKE2 also ships a `kubectl` binary under `/var/lib/rancher/rke2/bin/` on + server nodes. + +4. Optionally, a **Rancher** management server if you prefer to provision and + manage the RKE2 cluster from the Rancher UI instead of installing RKE2 + manually. See the [Rancher documentation :octicons-link-external-16:](https://ranchermanager.docs.rancher.com/). + +## Create the RKE2 cluster + +You can create the cluster [with the RKE2 installation script :octicons-link-external-16:](https://docs.rke2.io/install/quickstart) or [provision it +through Rancher :octicons-link-external-16:](https://ranchermanager.docs.rancher.com/how-to-guides/new-user-guides/launch-kubernetes-with-rancher). Both approaches give you a standard Kubernetes API endpoint +that the Operator uses. + + +## Configure kubectl access + +On a server node, RKE2 writes the kubeconfig to `/etc/rancher/rke2/rke2.yaml`. +Copy it to your workstation and point `kubectl` at it: + +```bash +mkdir -p ~/.kube +sudo cat /etc/rancher/rke2/rke2.yaml > ~/.kube/rke2.yaml +export KUBECONFIG=~/.kube/rke2.yaml +``` + +If you connect from a remote machine, replace `127.0.0.1` in the kubeconfig +`server:` URL with the reachable address of your RKE2 server node. + +Verify that the nodes are ready: + +```bash +kubectl get nodes +``` + +## Configure storage + +Percona Server for MongoDB needs PersistentVolumes for database data. Confirm +that your cluster has a default StorageClass (or note the StorageClass name to +set in the Custom Resource): + +```bash +kubectl get storageclass +``` + +RKE2 does not always ship a default StorageClass. For testing, you can install +the [Local Path Provisioner :octicons-link-external-16:](https://github.com/rancher/local-path-provisioner). +For production, use a CSI driver appropriate for your infrastructure, such as +[Longhorn :octicons-link-external-16:](https://longhorn.io/) when you manage the cluster with Rancher. + +## Install the Operator and deploy your MongoDB cluster + +1. Deploy the Operator. By default deployment will be done in the `default` + namespace. If that's not the desired one, you can create a new namespace + and/or set the context for the namespace as follows (replace the `` placeholder with some descriptive name): + + ```bash + kubectl create namespace + kubectl config set-context $(kubectl config current-context) --namespace= + ``` + + At success, you will see the message that `namespace/` was created, and the context was modified. + + Deploy the Operator, using the following command: + + ```bash + kubectl apply --server-side -f https://raw.githubusercontent.com/percona/percona-server-mongodb-operator/v{{ release }}/deploy/bundle.yaml + ``` + + ??? example "Expected output" + + ``` {.text .no-copy} + customresourcedefinition.apiextensions.k8s.io/perconaservermongodbs.psmdb.percona.com serverside-applied + customresourcedefinition.apiextensions.k8s.io/perconaservermongodbbackups.psmdb.percona.com serverside-applied + customresourcedefinition.apiextensions.k8s.io/perconaservermongodbrestores.psmdb.percona.com serverside-applied + role.rbac.authorization.k8s.io/percona-server-mongodb-operator serverside-applied + serviceaccount/percona-server-mongodb-operator serverside-applied + rolebinding.rbac.authorization.k8s.io/service-account-percona-server-mongodb-operator serverside-applied + deployment.apps/percona-server-mongodb-operator serverside-applied + ``` + +2. The Operator has been started, and you can deploy your MongoDB cluster: + + ```bash + kubectl apply -f https://raw.githubusercontent.com/percona/percona-server-mongodb-operator/v{{ release }}/deploy/cr.yaml + ``` + + ??? example "Expected output" + + ``` {.text .no-copy} + perconaservermongodb.psmdb.percona.com/my-cluster-name created + ``` + +3. The creation process may take some time. When the process is over your + cluster will obtain the `ready` status. You can check it with the following + command: + + ```bash + kubectl get psmdb + ``` + + ??? example "Expected output" + + ``` {.text .no-copy} + NAME ENDPOINT STATUS AGE + my-cluster-name my-cluster-name-mongos.default.svc.cluster.local ready 5m26s + ``` + +Congratulations! You have deployed Percona Server for MongoDB with the default configuration, which includes three mongod, three mongos, and three config server instances. + +For how to install Percona Server for MongoDB with customize parameters, see [Install Percona Operator for MongoDB with customized parameters](custom-install.md). + +## Verifying the cluster operation + +It may take ten minutes to get the cluster started. When `kubectl get psmdb` +command finally shows you the cluster status as `ready`, you can try to connect +to the cluster. + +{% include 'assets/fragments/connectivity.txt' %} + +## Troubleshooting + +If `kubectl get psmdb` command doesn't show `ready` status too long, you can +check the creation process with the `kubectl get pods` command: + +```bash +kubectl get pods +``` + +??? example "Expected output" + + --8<-- "cli/kubectl-get-pods-response.md" + +If the command output had shown some errors, you can examine the problematic +Pod with the `kubectl describe ` command as follows: + +```bash +kubectl describe pod my-cluster-name-rs0-2 +``` + +Review the detailed information for `Warning` statements and then correct the +configuration. An example of a warning is as follows: + +`Warning FailedScheduling 68s (x4 over 2m22s) default-scheduler 0/1 nodes are available: 1 node(s) didn’t match pod affinity/anti-affinity, 1 node(s) didn’t satisfy existing pods anti-affinity rules.` + +If Pods stay in the `Pending` state because volumes cannot be provisioned, +confirm that a StorageClass exists and that your Custom Resource references the +correct one. + +## Removing the RKE2 cluster + +To tear down a manually installed RKE2 cluster, run the uninstall script on each +node (agent nodes first, then server nodes): + +```bash +/usr/local/bin/rke2-uninstall.sh +``` + +If you provisioned the cluster with Rancher, delete the cluster from the Rancher +UI instead. + +!!! warning + + After deleting the cluster, all data stored in it will be lost! diff --git a/mkdocs-base.yml b/mkdocs-base.yml index 8c3c1764..5222c56a 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -202,6 +202,7 @@ nav: - "Install on Google Kubernetes Engine (GKE)": gke.md - "Install on Amazon Elastic Kubernetes Service (AWS EKS)": eks.md - "Install on Microsoft Azure Kubernetes Service (AKS)": aks.md + - "Install on Rancher Kubernetes Engine (RKE2)": rke2.md - "Generic Kubernetes installation": kubernetes.md - "Install on OpenShift": openshift.md From b2915641aa0ce9ad0d3de29e1ece389a9832c90e Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 12:27:38 +0300 Subject: [PATCH 16/22] K8SPSMDB-1537-Documented the new Secret type - connection secret (#350) * Documented the new Secret type - connection secret Updated connect to db docs Added cross-references to the new doc modified: docs/app-users.md modified: docs/assets/fragments/connectivity.txt modified: docs/cluster-wide.md modified: docs/connect.md new file: docs/connection-secrets.md modified: docs/expose.md modified: docs/kubernetes.md modified: docs/openshift.md modified: docs/system-users-vault-setup.md modified: docs/system-users-vault.md modified: docs/system-users.md modified: docs/users.md modified: mkdocs-base.yml --- docs/app-users.md | 13 +- docs/assets/fragments/connectivity.txt | 100 ++++++++----- docs/cluster-wide.md | 51 +++---- docs/connect.md | 68 ++++----- docs/connection-secrets.md | 185 +++++++++++++++++++++++++ docs/expose.md | 53 ++++--- docs/kubernetes.md | 2 +- docs/openshift.md | 4 +- docs/system-users-vault-setup.md | 47 ++++--- docs/system-users-vault.md | 1 - docs/system-users.md | 10 ++ docs/users.md | 2 + mkdocs-base.yml | 1 + 13 files changed, 389 insertions(+), 148 deletions(-) create mode 100644 docs/connection-secrets.md diff --git a/docs/app-users.md b/docs/app-users.md index 5681605b..9dd0e0e3 100644 --- a/docs/app-users.md +++ b/docs/app-users.md @@ -39,12 +39,6 @@ users: After you apply the configuration, the Operator creates a Secret named `-custom-user-secret`, generates a password for the user, and sets it by the key named after the user name. -!!! note "External database users" - - The Operator doesn't generate passwords for users created in the **`$external`** database. You can't set the `passwordSecretRef` for these users either. - - Such users are used for authentication via an external authentication source, such as an LDAP server. The user credentials are stored in an external authentication source, and their usernames are mapped to those in the `$external` database during authentication. - ### Generate user passwords manually If you don't want the Operator to generate a user password automatically, you can create a Secret resource that contains the user password. Then specify a reference to this Secret resource in the `passwordSecretRef` key. You can find a detailed description of the corresponding options in the [Custom Resource reference](operator.md#operator-users-section). @@ -93,6 +87,13 @@ Here's how to do it: kubectl apply -f deploy/cr.yaml ``` +!!! note "External database users" + + The Operator doesn't generate passwords for users created in the **`$external`** database. You can't set the `passwordSecretRef` for these users either. + + Such users are used for authentication via an external authentication source, such as an LDAP server. The user credentials are stored in an external authentication source, and their usernames are mapped to those in the `$external` database during authentication. + + The Operator tracks password changes in the Secret object and updates the user password in the database. This applies to [manually created users](#create-users-manually) as well: if a user was created manually in the database before creating the user via Custom Resource, the existing user is updated. However, manual password updates in the database are not tracked: the Operator doesn't overwrite changed passwords with the old ones from the users Secret. diff --git a/docs/assets/fragments/connectivity.txt b/docs/assets/fragments/connectivity.txt index b4bdb409..0e362eee 100644 --- a/docs/assets/fragments/connectivity.txt +++ b/docs/assets/fragments/connectivity.txt @@ -1,61 +1,85 @@ -To connect to Percona Server for MongoDB you need to construct the MongoDB connection URI string. It includes the credentials of the admin user, which are stored in the [Secrets :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/secret/) object. +To connect to Percona Server for MongoDB, use the connection string Secret that the Operator creates for the `databaseAdmin` user. This Secret is available starting with Operator version 1.23.0 and newer. For previous versions, refer to the [Connect manually](#connect-manually) section. -1. List the Secrets objects +1. List the Secrets objects: ```bash {{ commandName }} get secrets -n ``` - The Secrets object you are interested in has the - `{{ clusterName }}-secrets` name by default. + The connection string Secret is named `{{ clusterName }}-databaseadmin-conn-str` by default. -2. View the Secret contents to retrieve the admin user credentials. +2. Retrieve the connection string - ```bash - {{ commandName }} get secret {{ clusterName }}-secrets -o yaml - ``` - The command returns the YAML file with generated Secrets, including the `MONGODB_DATABASE_ADMIN_USER` - and `MONGODB_DATABASE_ADMIN_PASSWORD` strings, which should look as follows: - - ??? example "Sample output" - - ```{.yaml .no-copy} - ... - data: - ... - MONGODB_DATABASE_ADMIN_PASSWORD: aDAzQ0pCY3NSWEZ2ZUIzS1I= - MONGODB_DATABASE_ADMIN_USER: ZGF0YWJhc2VBZG1pbg== + === "if sharding is on" + + ```bash + {{ commandName }} get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_mongos_connectionString}' | base64 --decode && echo ``` - The actual login name and password on the output are base64-encoded. To bring it - back to a human-readable form, run: + === "if sharding is off" + + ```bash + {{ commandName }} get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_rs0_connectionStringSrv}' | base64 --decode && echo + ``` - ```bash - echo 'MONGODB_DATABASE_ADMIN_USER' | base64 --decode - echo 'MONGODB_DATABASE_ADMIN_PASSWORD' | base64 --decode - ``` + See [Connection secrets](connection-secrets.md) for other available keys. 3. Run a container with a MongoDB client and connect its console output to your terminal. The following command does this, naming the new Pod `percona-client`: ```bash - {{ commandName }} run -i --rm --tty percona-client --image=percona/percona-server-mongodb:{{ mongodb70recommended }} --restart=Never -- bash -il + {{ commandName }} run -i --rm --tty percona-client --image=percona/percona-server-mongodb:{{ mongodb80recommended }} --restart=Never -- bash -il ``` Executing it may require some time to deploy the corresponding Pod. -3. Now run `mongosh` tool inside the `percona-client` command shell using the admin user credentialds you obtained from the - Secret, and a proper namespace name instead of the `` - placeholder. The command will look different depending on whether sharding - is on (the default behavior) or off: +4. Connect using the connection string from step 2: - === "if sharding is on" - ```bash - mongosh "mongodb://databaseAdmin:databaseAdminPassword@{{ clusterName }}-mongos..svc.cluster.local/admin?ssl=false" - ``` + ```bash + mongosh "" + ``` + +## Connect manually (alternative) + +If you need to build a connection URI yourself, retrieve credentials from the user Secret and construct the URI. + +1. List the Secrets objects: + + ```bash + {{ commandName }} get secrets -n + ``` + + The Secrets object you are interested in has the `-secrets` name. (For the cluster `my-cluster-name`, the Secret name is `my-cluster-name-secrets`). + +2. Retrieve the admin username and password: + + ```bash + {{ commandName }} get secret -n -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_USER}' | base64 --decode && echo + {{ commandName }} get secret -n -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_PASSWORD}' | base64 --decode && echo + ``` + +3. Run a container with a MongoDB client and connect its console output to your terminal. The following command does this, naming the new Pod `percona-client`: + + ```bash + kubectl -n run -i --rm --tty percona-client --image=percona/percona-server-mongodb:{{ mongodb80recommended }} --restart=Never -- bash -il + ``` + + It may take some time to deploy the corresponding Pod. + +4. Now run `mongosh` tool inside the `percona-client` command shell using the admin user credentials you obtained from the Secret, and a proper namespace name instead of the `` placeholder. The command will look different depending on whether sharding is on (the default behavior) or off: + + === "sharding is on" + + ```bash + mongosh "mongodb://databaseAdmin:databaseAdminPassword@my-cluster-name-mongos..svc.cluster.local/admin?ssl=false" + ``` + + === "sharding is off" + + ```bash + mongosh "mongodb+srv://databaseAdmin:databaseAdminPassword@my-cluster-name-rs0..svc.cluster.local/admin?replicaSet=rs0&ssl=false" + ``` - === "if sharding is off" - ```bash - mongosh "mongodb+srv://databaseAdmin:databaseAdminPassword@{{ clusterName }}-rs0..svc.cluster.local/admin?replicaSet=rs0&ssl=false" - ``` \ No newline at end of file diff --git a/docs/cluster-wide.md b/docs/cluster-wide.md index d562d4b7..f7b4d7f0 100644 --- a/docs/cluster-wide.md +++ b/docs/cluster-wide.md @@ -119,25 +119,25 @@ It may take ten minutes to get the cluster started. When `kubectl get psmdb` command finally shows you the cluster status as `ready`, you can try to connect to the cluster. -1. You will need the login and password for the admin user to access the - cluster. Use `kubectl get secrets` command to see the list of Secrets - objects (by default the Secrets object you are interested in has - `my-cluster-name-secrets` name). Then - `kubectl get secret my-cluster-name-secrets -o yaml` command will return - the YAML file with generated Secrets, including the `MONGODB_DATABASE_ADMIN` - and `MONGODB_DATABASE_ADMIN_PASSWORD` strings, which should look as follows: +1. You will need a connection string to access the cluster. Starting with Operator version 1.23.0, retrieve it from the `-databaseadmin-conn-str` Secret: - ```yaml - ... - data: - ... - MONGODB_DATABASE_ADMIN_PASSWORD: aDAzQ0pCY3NSWEZ2ZUIzS1I= - MONGODB_DATABASE_ADMIN_USER: ZGF0YWJhc2VBZG1pbg== - ``` + === "if sharding is on" + + ```bash + kubectl get secret my-cluster-name-databaseadmin-conn-str -n psmdb \ + -o jsonpath='{.data.databaseAdmin_mongos_connectionString}' | base64 --decode && echo + ``` + + === "if sharding is off" + + ```bash + kubectl get secret my-cluster-name-databaseadmin-conn-str -n psmdb \ + -o jsonpath='{.data.databaseAdmin_rs0_connectionStringSrv}' | base64 --decode && echo + ``` + + See [Connection secrets](connection-secrets.md) for other key names. - Here the actual login name and password are base64-encoded. Use - `echo 'aDAzQ0pCY3NSWEZ2ZUIzS1I=' | base64 --decode` command to bring it - back to a human-readable form. + Alternatively, retrieve the login and password for the admin user from the `my-cluster-name-secrets` Secret using `kubectl get secrets` and `kubectl get secret my-cluster-name-secrets -o yaml`. Decode base64-encoded values as described in [System users](system-users.md). 2. Run a container with a MongoDB client and connect its console output to your terminal. The following command will do this, naming the new Pod @@ -149,17 +149,8 @@ to the cluster. Executing it may require some time to deploy the correspondent Pod. -3. Now run `mongo` tool in the percona-client command shell using the login - (which is normally `databaseAdmin`) and a proper password obtained from the - Secret. The command will look different depending on whether sharding - is on (the default behavior) or off: - - === "if sharding is on" - ```bash - mongosh "mongodb://databaseAdmin:databaseAdminPassword@my-cluster-name-mongos.psmdb.svc.cluster.local/admin?ssl=false" - ``` +3. Connect using the connection string from step 1: - === "if sharding is off" - ```bash - mongosh "mongodb+srv://databaseAdmin:databaseAdminPassword@my-cluster-name-rs0.psmdb.svc.cluster.local/admin?replicaSet=rs0&ssl=false" - ``` + ```bash + mongosh "" + ``` diff --git a/docs/connect.md b/docs/connect.md index 4d4624be..492dd7ae 100644 --- a/docs/connect.md +++ b/docs/connect.md @@ -2,7 +2,7 @@ In this tutorial, you will connect to the Percona Server for MongoDB cluster you deployed previously. -To connect to Percona Server for MongoDB you need to construct the MongoDB connection URI string. It includes the credentials of the admin user, which are stored in the Secrets object. +Starting with Operator version 1.23.0, the Operator creates a Secret with a ready-to-use connection string for the `databaseAdmin` user. Use it to connect to the database. Here's how to do it: {.power-number} @@ -13,33 +13,44 @@ Here's how to do it: kubectl get secrets -n ``` - The Secrets object we target is named as - `-secrets`. The `` value is - the [name of your Percona Distribution for MongoDB](operator.md#metadata). The default variant is: + The connection string Secret is named `-databaseadmin-conn-str`. The `` value is the [name of your Percona Distribution for MongoDB](operator.md#metadata). The default variant is: === "via kubectl" - `my-cluster-name-secrets` + `my-cluster-name-databaseadmin-conn-str` === "via Helm" - `cluster1-psmdb-db-secrets` + `cluster1-databaseadmin-conn-str` -2. Retrieve the admin user credentials. Replace the `secret-name` and `namespace` with your values in the following commands: +2. Retrieve the connection string. Replace `` and `` with your values: - * Retrieve the login + === "sharding is on" + + ```bash + kubectl get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_mongos_connectionString}' | base64 --decode && echo + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + mongodb://databaseAdmin:password123456@34.118.227.158:27017/?authSource=admin + ``` - ```bash - kubectl get secret -n -o yaml -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_USER}' | base64 --decode | tr '\n' ' ' && echo " " - ``` + === "sharding is off" - The default value is `databaseAdmin` + ```bash + kubectl get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_rs0_connectionStringSrv}' | base64 --decode && echo + ``` - * Retrieve the password + ??? example "Sample output" - ```bash - kubectl get secret -n -o yaml -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_PASSWORD}' | base64 --decode | tr '\n' ' ' && echo " " - ``` + ```{.text .no-copy} + mongodb+srv://databaseAdmin:password123456@my-cluster-name-rs0.mongodb-operator.svc.cluster.local/?authSource=admin&replicaSet=rs0 + ``` + See [Connection secrets](connection-secrets.md) for other key names (standard URI, exposed endpoints, custom users). 3. Run a container with a MongoDB client and connect its console output to your terminal. The following command does this, naming the new Pod `percona-client`: @@ -47,29 +58,22 @@ Here's how to do it: kubectl -n run -i --rm --tty percona-client --image=percona/percona-server-mongodb:{{ mongodb80recommended }} --restart=Never -- bash -il ``` -4. Connect to Percona Server for MongoDB. The format of the MongoDB connection URI string is the following: +4. Connect to Percona Server for MongoDB using the connection string from step 2: - === "sharding is on" + ```bash + mongosh "" + ``` - ``` - mongosh "mongodb://:@-mongos..svc.cluster.local/admin?ssl=false" - ``` + ??? example - === "sharding is off" + The following example connects to the `admin` database of a Percona Server for MongoDB 8.0 sharded cluster named `my-cluster-name` in the `mongodb-operator` namespace: - ``` - mongosh "mongodb://:@-rs0..svc.cluster.local/admin?replicaSet=rs0&ssl=false" + ```bash + mongosh "mongodb://databaseAdmin:databaseAdminPassword@my-cluster-name-mongos.mongodb-operator.svc.cluster.local/admin?authSource=admin" ``` - If you run MongoDB 5.0 and earlier, use the old `mongo` client instead of `mongosh`. + The exact URI depends on your cluster configuration. Use the value retrieved from the connection string Secret. - ??? example - - The following example connects to the `admin` database of Percona Server for MongoDB 6.0 sharded cluster with the name `my-cluster-name`. The cluster runs in the namespace `mongodb-operator`: - - ``` - mongosh "mongodb://databaseAdmin:databaseAdminPassword@my-cluster-name-mongos.mongodb-operator.svc.cluster.local/admin?ssl=false" - ``` Congratulations! You have connected to Percona Server for MongoDB. diff --git a/docs/connection-secrets.md b/docs/connection-secrets.md new file mode 100644 index 00000000..8e7fc654 --- /dev/null +++ b/docs/connection-secrets.md @@ -0,0 +1,185 @@ +# Connection Secrets + +!!! note "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +The Operator creates and maintains Kubernetes Secrets that contain ready-to-use MongoDB connection strings your applications need. This gives your developers and administrators a single, reliable source of connection information without manual configuration. + +The Operator updates connection Secrets when cluster topology, external access settings, or user passwords change. If you try to manually update a connection Secret, the Operator overwrites your changes with the next reconciliation. + +## Secret names + +The Operator creates connection Secrets for the following users: + +* The **`databaseAdmin`** system user. +* **Operator-managed application-level users** declared in the Custom Resource. + +| User type | Password Secret | Connection string Secret | +|:----------|:----------------|:-------------------------| +| `databaseAdmin` | `-secrets` (by default) | `-databaseadmin-conn-str` | +| Custom user (auto-generated password) | `-custom-user-secret` | `-custom-user-secret-conn-str` | +| Custom user (manual password) | Name from `passwordSecretRef.name` | `-conn-str` | + +The `` value is the `metadata.name` of your `PerconaServerMongoDB` Custom Resource. + +### `databaseAdmin` connection Secret + +The Operator creates a dedicated connection Secret for the `databaseAdmin` system user, named `-databaseadmin-conn-str`. Credentials for `databaseAdmin` and all other system users such as `userAdmin`, `clusterAdmin`, `backup`, and so on, are included in the password Secret `-secrets`. + +### Connection Secret for application users + +For application users that you define in the cluster Custom Resource, the Operator creates one connection Secret per password Secret. If several application users share the same password Secret, the Operator stores connection strings for all of them in a single connection Secret. Each user has its own set of keys inside that Secret. + +The Operator does **not** create connection Secrets for users in the **`$external`** database — the ones you create for LDAP and other external authentication methods. + +## Secret structure + +A connection Secret is a standard Kubernetes `Secret`. Its `data` map holds one base64-encoded MongoDB URI per key. Each key name tells you which user, target, and connection type the URI is for. + +Keys follow the pattern `__`: + +* The `` part matches the Percona Server for MongoDB username. For example, `databaseAdmin`. Characters that are not allowed in Kubernetes Secret keys are replaced with underscores. +* The `` part is the name of each replica set. For sharded clusters, `` matches the name of each shard, config server replica set and `mongos`. +* The `` part defines the connection type. Available types are: + + * `_connectionString` - for internal connection using internal replica-set addresses. + * `_connectionStringSrv` - for connection using the replica set Service hostname + * `_connectionStringExposed` - for external access when a replica set or `mongos` Service is [exposed](expose.md) and its exposed endpoint differs from its internal URI. + +The following is the example of the `data` map for the sharded cluster: + +=== "`-databaseadmin-conn-str` Secret" + + ```yaml + data: + databaseAdmin_cfg_connectionString: # config server — internal Pod addresses + databaseAdmin_cfg_connectionStringSrv: # config server — via Service DNS (mongodb+srv) + databaseAdmin_cfg_connectionStringExposed: # config server — external endpoints (when exposed) + databaseAdmin_rs0_connectionString: # shard rs0 — internal Pod addresses + databaseAdmin_rs0_connectionStringSrv: # shard rs0 — via Service DNS (mongodb+srv) + databaseAdmin_rs0_connectionStringExposed: # shard rs0 — external endpoints (when exposed) + databaseAdmin_mongos_connectionString: # mongos router — internal access + databaseAdmin_mongos_connectionStringExposed: # mongos router — external endpoints (when service per Pod is enabled) + ``` + +=== "`-conn-str` Secret" + + For custom users on sharded clusters, only `mongos` keys are present. + + ```yaml + data: + _mongos_connectionString: # mongos router — internal access + _mongos_connectionStringExposed: # mongos router — external endpoints (when service per Pod is enabled) + ``` + +## URI format + +Generated URIs include: + +* URL-encoded username and password +* `authSource` — `admin` for the `databaseAdmin` user, or the user's database for custom users +* `replicaSet` — for replica set connection strings +* `tls=true` — when [TLS is enabled](TLS.md) for the cluster + +When TLS is disabled, the URI does not include TLS parameters. + +## Retrieve a connection string + +Replace ``, ``, and the key name with your values. + +=== "Sharded cluster (via mongos)" + + ```bash + kubectl get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_mongos_connectionString}' | base64 --decode && echo + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + mongodb://databaseAdmin:databaseAdmin123456@my-cluster-name-mongos..svc.cluster.local:27017/?authSource=admin&tls=true + ``` + +=== "Replica set (standard URI)" + + ```bash + kubectl get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_rs0_connectionString}' | base64 --decode && echo + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + mongodb://databaseAdmin:databaseAdmin123456@my-cluster-name-rs0-0.my-cluster-name-rs0..svc.cluster.local:27017,my-cluster-name-rs0-1.my-cluster-name-rs0..svc.cluster.local:27017,my-cluster-name-rs0-2.my-cluster-name-rs0..svc.cluster.local:27017/?authSource=admin&replicaSet=rs0&tls=true + ``` + +=== "Replica set (SRV URI)" + + ```bash + kubectl get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_rs0_connectionStringSrv}' | base64 --decode && echo + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + mongodb+srv://databaseAdmin:databaseAdmin123456@my-cluster-name-rs0.mongodb-operator.svc.cluster.local/?authSource=admin&replicaSet=rs0 + ``` + +=== "Exposed replica set" + + ```bash + kubectl get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_rs0_connectionStringExposed}' | base64 --decode && echo + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + mongodb://databaseAdmin:databaseAdmin123456@35.254.99.120:27017,34.132.106.13:27017,136.64.169.49:27017/?authSource=admin&replicaSet=rs0&tls=true + ``` + +To inspect all available keys: + +```bash +kubectl get secret -databaseadmin-conn-str -n -o jsonpath='{.data}' | jq 'keys' +``` + +??? example "Expected output" + + ```{.text .no-copy} + [ + "databaseAdmin_cfg_connectionString", + "databaseAdmin_cfg_connectionStringExposed", + "databaseAdmin_cfg_connectionStringSrv", + "databaseAdmin_mongos_connectionString", + "databaseAdmin_rs0_connectionString", + "databaseAdmin_rs0_connectionStringExposed", + "databaseAdmin_rs0_connectionStringSrv" + ] + ``` + +## Use in an application Deployment + +Reference the connection string Secret in your application manifest: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-app +spec: + template: + spec: + containers: + - name: app + image: my-app:latest + env: + - name: MONGODB_URI + valueFrom: + secretKeyRef: + name: my-cluster-name-custom-user-secret-conn-str + key: my-user_mongos_connectionString +``` + +For the `databaseAdmin` user, use `-databaseadmin-conn-str` as the Secret name. Prefer [application-level users](app-users.md) for application workloads instead of system users. + diff --git a/docs/expose.md b/docs/expose.md index b3fec92a..b6d47ed2 100644 --- a/docs/expose.md +++ b/docs/expose.md @@ -26,17 +26,36 @@ kubectl get psmdb my-cluster-name my-cluster-name-mongos..svc.cluster.local ready 85m ``` -To connect to MongoDB, you need to construct the MongoDB connection string URI. For the sharded cluster, specify the `mongos` endpoint for the connection string URI. This is the example format: +To connect to MongoDB, you need the MongoDB connection string URI. The Operator automatically constructs it for the `databaseAdmin` user and stores it in the connection Secret `-databaseadmin-conn-str`. To learn more about connection secrets, see [Connection secrets](connection-secrets.md). + +For a sharded cluster, use the value from the `databaseAdmin_mongos_connectionString` key of the connection Secret. + +Run the following command to retrieve the value: + +```bash +kubectl get secret -databaseadmin-conn-str -n \ + -o jsonpath='{.data.databaseAdmin_mongos_connectionString}' | base64 --decode && echo +``` + +??? example "Sample output" + + ```{.text .no-copy} + mongodb://databaseAdmin:databaseAdminPassword@34.118.227.158:27017/admin?authSource=admin + ``` + +Alternatively, you can construct the MongoDB connection string URI manually. For the sharded cluster, specify the `mongos` endpoint. This is the example format: ```bash -mongosh "mongodb://userAdmin:userAdminPassword@my-cluster-name-mongos..svc.cluster.local/admin?ssl=false" +mongosh "mongodb://databaseAdmin:databaseAdminPassword@my-cluster-name-mongos..svc.cluster.local/admin?authSource=admin" ``` Make sure every part of the connection string reflects your environment: -- **userAdmin** and **userAdminPassword**: replace with your admin username and the actual admin password. Get the username and password from the Kubernetes Secret created for your cluster. +- **databaseAdmin** and **databaseAdminPassword**: replace with your admin username and the actual admin password. Get them from the Kubernetes Secret created for your cluster, or use a ready-made URI from the connection string Secret. - **my-cluster-name**: use the name of your database cluster. Get the name by running `kubectl get psmdb` command -- ****: the Kubernetes namespace where your cluster is deployed +- ****: the Kubernetes namespace where your cluster is deployed + +If [TLS is enabled](TLS.md), include the appropriate TLS parameters in the URI or use the connection string Secret, which adds them automatically. !!! warning @@ -67,15 +86,17 @@ kubectl get psmdb my-cluster-name my-cluster-name-rs0..svc.cluster.local ready 2m19s ``` -To connect to a MongoDB replica set, you need to specify each replica set member for the MongoDB connection string URI. This is the example format: +To connect to a MongoDB replica set, use the `databaseAdmin__connectionString` or `databaseAdmin__connectionStringSrv` key from the `-databaseadmin-conn-str` Secret. See [Connection secrets](connection-secrets.md). + +Alternatively, construct the URI manually. This is the example format: ```bash -mongosh "mongodb://databaseAdmin:databaseAdminPassword@my-cluster-name-rs0..svc.cluster.local/admin?replicaSet=rs0&ssl=false" +mongosh "mongodb+srv://databaseAdmin:databaseAdminPassword@my-cluster-name-rs0..svc.cluster.local/admin?authSource=admin&replicaSet=rs0" ``` Make sure every part of the connection string reflects your environment: -- **userAdmin** and **userAdminPassword**: replace with your admin username and the actual admin password. Get the username and password from the Kubernetes Secret created for your cluster. +- **databaseAdmin** and **databaseAdminPassword**: replace with your admin username and the actual admin password. Get them from the Kubernetes Secret created for your cluster, or use a ready-made URI from the connection string Secret. - **my-cluster-name**: use the name of your database cluster. Get the name by running `kubectl get psmdb` command - ****: the Kubernetes namespace where your cluster is deployed @@ -96,6 +117,14 @@ To expose Pods externally, configure the following option in the Custom Resource * **`ClusterIP`**: Exposes the Pod with an internal static IP address. This makes the Service reachable only from within the Kubernetes cluster. * **`NodePort`**: Exposes the Pod on each Kubernetes Node’s IP address at a static port. A ClusterIP Service is automatically created, and the Node port routes traffic to it. The Service is reachable from outside the cluster using the Node address and port number, but the address is bound to a specific Kubernetes Node. + If the NodePort type is used, the URI looks like this: + + ``` + mongodb://databaseAdmin:databaseAdminPassword@:,:,:/admin?replicaSet=rs0&ssl=false + ``` + + All Node addresses should be *directly* reachable by the application. + The `expose.externalTrafficPolicy` Custom Resource option in [`replsets`](operator.md#replsetsexposeexternaltrafficpolicy), [`sharding.configsvrReplSet`](operator.md#shardingconfigsvrreplsetexposeexternaltrafficpolicy), and [`sharding.mongos`](operator.md#shardingmongosexternaltrafficpolicy) subsections controls how external traffic is routed: * `Local`: Traffic is routed to node-local endpoints. External requests will be dropped if there is no available Pod on the Node. @@ -103,15 +132,7 @@ To expose Pods externally, configure the following option in the Custom Resource * **`LoadBalancer`**: Exposes the Pod externally using a cloud provider’s load balancer. Both [ClusterIP and NodePort Services are automatically created :octicons-link-external-16:](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) in this variant. - Cloud load balancers often assign long, auto-generated hostnames (for example, `a1b2c3d4e5.elb.amazonaws.com`). To publish stable, human-readable hostnames, configure [External DNS](expose.md#automatic-dns-records-with-external-dns), available in the Operator 1.23.0 and later. To learn more, see [Automatic DNS records with External DNS](#automatic-dns-records-with-external-dns). - -If the NodePort type is used, the URI looks like this: - -``` -mongodb://databaseAdmin:databaseAdminPassword@:,:,:/admin?replicaSet=rs0&ssl=false -``` - -All Node addresses should be *directly* reachable by the application. +When replica sets or `mongos` Pods are exposed, the Operator adds `_connectionStringExposed` keys to the connection Secret. Use them instead of building external URIs manually. See [Connection secrets](connection-secrets.md). ## Automatic DNS records with External DNS diff --git a/docs/kubernetes.md b/docs/kubernetes.md index 07b68a45..3df949c0 100644 --- a/docs/kubernetes.md +++ b/docs/kubernetes.md @@ -81,7 +81,7 @@ kubectl create -f deploy/secrets.yaml ``` - More details about secrets can be found in [Users](users.md). + More details about secrets can be found in [Users](users.md). After the cluster reaches the `ready` status, the Operator also creates [connection secrets](connection-secrets.md) with ready-to-use MongoDB URIs. 7. Now certificates should be generated. By default, the Operator generates certificates automatically, and no actions are required at this step. Still, diff --git a/docs/openshift.md b/docs/openshift.md index d9df6c86..6c8c4eca 100644 --- a/docs/openshift.md +++ b/docs/openshift.md @@ -124,7 +124,7 @@ Following steps will allow you to deploy the Operator and Percona Server for Mon oc create -f deploy/secrets.yaml ``` - More details about secrets can be found in [Users](users.md). + Learn more about secrets in [Users](users.md). After the cluster reaches the `ready` status, the Operator also creates [connection secrets](connection-secrets.md) with ready-to-use MongoDB URIs. 2. Now certificates should be generated. By default, the Operator generates certificates automatically, and no actions are required at this step. Still, @@ -146,7 +146,7 @@ Following steps will allow you to deploy the Operator and Percona Server for Mon ... ``` - 2. (optional) In you’re using minishift, please adjust antiaffinity policy to `none` + 2. (optional) If you're using minishift, please adjust anti-affinity policy to `none` ```yaml affinity: diff --git a/docs/system-users-vault-setup.md b/docs/system-users-vault-setup.md index 1a69c9c7..7b7f2767 100644 --- a/docs/system-users-vault-setup.md +++ b/docs/system-users-vault-setup.md @@ -382,39 +382,42 @@ To verify that the Operator retrieves passwords from Vault, we'll do the followi Here's how to do it: -1. Get the user credentials from the Secret `-secrets`. Run the following commands to retrieve the username and password for the database admin user: +1. Get the connection string from the `-databaseadmin-conn-str` Secret: + + === "sharding is on" + + ```bash + kubectl get secret my-cluster-name-databaseadmin-conn-str -n $CLUSTER_NAMESPACE \ + -o jsonpath='{.data.databaseAdmin_mongos_connectionString}' | base64 --decode && echo + ``` + + === "sharding is off" + + ```bash + kubectl get secret my-cluster-name-databaseadmin-conn-str -n $CLUSTER_NAMESPACE \ + -o jsonpath='{.data.databaseAdmin_rs0_connectionString}' | base64 --decode && echo + ``` + + See [Connection secrets](connection-secrets.md) for other key names. - ```bash - kubectl get secret my-cluster-name-secrets -n $CLUSTER_NAMESPACE -o yaml -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_USER}' | base64 --decode | tr '\n' ' ' && echo " " - kubectl get secret my-cluster-name-secrets -n $CLUSTER_NAMESPACE -o yaml -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_PASSWORD}' | base64 --decode | tr '\n' ' ' && echo " " - ``` - 2. Spin up a `mongo` client Pod: ```bash kubectl -n $CLUSTER_NAMESPACE run -i --rm --tty percona-client --image=percona/percona-server-mongodb:{{ mongodb80recommended }} --restart=Never -- bash -il ``` -3. Inside the Pod, run the following command: +3. Inside the Pod, connect using the connection string from step 1: - === "sharding is on" - - ``` - mongosh "mongodb://:@my-cluster-name-mongos..svc.cluster.local/admin?ssl=false" - ``` + ```bash + mongosh "" + ``` - === "sharding is off" + ??? example "Expected output" + ```{.text .no-copy} + ..... + [direct: mongos] admin> ``` - mongosh "mongodb://:@my-cluster-name-rs0..svc.cluster.local/admin?replicaSet=rs0&ssl=false" - ``` - - ??? example "Expected output" - - ```{.text .no-copy} - ..... - [direct: mongos] admin> - ``` 4. Update the password for the `MONGODB_DATABASE_ADMIN_PASSWORD` user: diff --git a/docs/system-users-vault.md b/docs/system-users-vault.md index 68959c7f..cd3f0aa2 100644 --- a/docs/system-users-vault.md +++ b/docs/system-users-vault.md @@ -6,7 +6,6 @@ This allows you to centralize password management, enforce rotation policies, an ## How it works - When [Vault is enabled](system-users-vault-setup.md#configure-vault), the Operator: * Retrieves system user passwords from Vault during cluster creation diff --git a/docs/system-users.md b/docs/system-users.md index 6d086817..7db7ec2e 100644 --- a/docs/system-users.md +++ b/docs/system-users.md @@ -180,3 +180,13 @@ These development-mode credentials from `deploy/secrets.yaml` are: The Operator creates and updates an additional Secrets object which is named based on the cluster name, like `internal-my-cluster-name-users`. This Secrets object is used only by the Operator. Users must not change it. This object contains secrets with the same passwords as the one specified in `spec.secrets.users` (e.g., `my-cluster-name-secrets`). When the user updates the `my-cluster-name-secrets` Secret, the Operator propagates these changes to the internal `internal-my-cluster-name-users` Secrets object. + +## Connection string Secret + +Starting with Operator version 1.23.0, the Operator creates a `-databaseadmin-conn-str` Secret with ready-to-use MongoDB connection strings for the **`databaseAdmin`** user. The Secret includes URIs for internal cluster access, SRV-style endpoints, and exposed endpoints when applicable. + +The Operator updates this Secret when cluster topology, exposure settings, or the `databaseAdmin` password change. Do not edit it manually. + +Use this Secret to connect to the cluster or wire applications to MongoDB. See [Connection secrets](connection-secrets.md) for key names and usage examples. + +Connection string Secrets are created for `databaseAdmin` only. Other system users do not have dedicated connection string Secrets. diff --git a/docs/users.md b/docs/users.md index 2470840d..b7fd210f 100644 --- a/docs/users.md +++ b/docs/users.md @@ -18,6 +18,8 @@ When the Operator creates application-level (unprivileged) users, it uses the us For system users, the Operator creates the required Secret automatically when it creates the cluster. If a Secret with the expected name already exists (as specified in the CR), the Operator will reuse it. Starting with version 1.22.0, you can also [store and manage system user credentials in HashiCorp Vault](system-users-vault.md). In this case, the Operator retrieves the passwords from Vault and creates or updates the relevant Secrets based on the Vault-stored credentials. +Starting with version 1.23.0, the Operator also creates [connection Secrets](connection-secrets.md) with ready-to-use MongoDB URIs for the `databaseAdmin` user and for operator-managed application-level users. + ## Authentication Authentication is enabled in Percona Server for MongoDB clusters by default. If you need to disable authentication for development, testing, or migration purposes, see [Disable authentication](auth-disable.md). diff --git a/mkdocs-base.yml b/mkdocs-base.yml index 5222c56a..c7927622 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -226,6 +226,7 @@ nav: - "About application and system users": users.md - "Application-level (unprivileged) users": app-users.md - "System users": system-users.md + - "Connection secrets": connection-secrets.md - Manage system users with Vault: - "Overview": system-users-vault.md - "Configuration": system-users-vault-setup.md From a684e5a60efdd810e66ec1c021994167e1b6b5d2 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 12:28:02 +0300 Subject: [PATCH 17/22] K8sPSMDB-1701, K8sPSMDB-1728 custom readiness liveness probes for pmm, pbm, logcollector and logrotate (#357) * K8SPSMDB-1701, K8SPSMDB-1728 Documented custo, liveness and reasiness probes for PBM, PMM, Logcollector and logrotate --- docs/operator.md | 252 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/docs/operator.md b/docs/operator.md index f70eb4cb..1946d7e1 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -2046,6 +2046,77 @@ The [Kubernetes Memory requests :octicons-link-external-16:](https://kubernetes | ----------- | ---------- | | :material-code-string: string | `256M` | +### `pmm.livenessProbe.httpGet` + +A custom [Kubernetes liveness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for the `pmm-client` sidecar container. When not set, the Operator uses its built-in HTTP GET call on its status page on port 7777 (`:7777/local/Status`). Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc |
 path: /local/Status 
port: 7777
| + +### `pmm.livenessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the liveness probe + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `60` | + +### `pmm.livenessProbe.timeoutSeconds` + +Number of seconds after which the liveness probe times out + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `5` | + +### `pmm.livenessProbe.periodSeconds` + +How often to perform the liveness probe (in seconds) + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `10` | + +### `pmm.livenessProbe.failureThreshold` + +Number of consecutive unsuccessful tries of the liveness probe to be undertaken before giving up. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `5` | + +### `pmm.readinessProbe` + +A custom [Kubernetes readiness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for the `pmm-client` sidecar container. When not set, the container has no readiness probe. Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `tcpSocket: { port: 7777 }` | + +### `pmm.readinessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the readiness probe + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `60` | + +### `pmm.readinessProbe.periodSeconds` + +How often to perform the readiness probe (in seconds) + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `10` | + +### `pmm.readinessProbe.failureThreshold` + +Number of consecutive unsuccessful tries of the readiness probe to be undertaken before giving up. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `5` | ## Sharding Section @@ -3313,6 +3384,71 @@ A custom [Kubernetes Security Context for a Container :octicons-link-external-16 | ----------- | ---------- | | :material-text-long: subdoc | `privileged: false` | +### `backup.livenessProbe` + +A custom [Kubernetes liveness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for the `backup-agent` sidecar container. When not set, the container has no liveness probe. Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `exec: { command: [/bin/true] }` | + +### `backup.livenessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the liveness probe + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `30` | + + +### `backup.livenessProbe.periodSeconds` + +How often to perform the liveness probe (in seconds) + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `15` | + +### `backup.livenessProbe.failureThreshold` + +Number of consecutive unsuccessful tries of the liveness probe to be undertaken before giving up. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `5` | + +### `backup.readinessProbe` + +A custom [Kubernetes readiness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for the `backup-agent` sidecar container. When not set, the container has no readiness probe. Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `exec: { command: [/bin/true] }` | + +### `backup.readinessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the readiness probe + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `30` | + +### `backup.readinessProbe.periodSeconds` + +How often to perform the readiness probe (in seconds) + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `15` | + +### `backup.readinessProbe.failureThreshold` + +Number of consecutive unsuccessful tries of the readiness probe to be undertaken before giving up. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `5` | + ### `backup.storages.STORAGE-NAME.main` Marks the storage as main. All other storages you define are added as profiles. The Operator saves backups to all storages but it saves oplog chunks for point-in-time recovery only to the main storage. You can define only one storage as main. Read more about [multiple storages for backups](multi-storage.md). @@ -4042,6 +4178,74 @@ The name of a Secret from where environment variables will be loaded for the log | ----------- | ---------- | | :material-code-string: string | `my-secret` | +### `logcollector.livenessProbe` + +A custom [Kubernetes liveness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for the `logs` (Fluent Bit) sidecar container. When not set, the container has no liveness probe. A `tcpSocket` or `httpGet` probe on port `2020` requires the Fluent Bit HTTP server to be enabled via `logcollector.configuration`: + +```yaml +logcollector: + enabled: true + configuration: | + [SERVICE] + HTTP_Server On +``` + +Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `tcpSocket: { port: 2020 }` | + +### `logcollector.livenessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the readiness probe + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `30` | + +### `logcollector.livenessProbe.periodSeconds` + +How often to perform the readiness probe (in seconds) + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `15` | + +### `logcollector.readinessProbe` + +A custom [Kubernetes readiness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for the `logs` (Fluent Bit) sidecar container. When not set, the container has no readiness probe. A `tcpSocket` or `httpGet` probe on port `2020` requires the Fluent Bit HTTP server to be enabled via `logcollector.configuration` (`HTTP_Server On` under `[SERVICE]`): + +```yaml +logcollector: + enabled: true + configuration: | + [SERVICE] + HTTP_Server On +``` + +Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `tcpSocket: { port: 2020 }` | + +### `logcollector.readinessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the readiness probe + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `5` | + +### `logcollector.readinessProbe.periodSeconds` + +How often to perform the readiness probe (in seconds) + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `15` | + ### `logcollector.logrotate.configuration` Overrides the default logrotate configuration used by the log collector sidecar container. @@ -4066,6 +4270,54 @@ Cron expression for the logrotate schedule (default: `0 0 0 * * *`). | ----------- | ---------- | | :material-code-string: string | `"0 0 0 * * *"` | +### `logcollector.logrotate.livenessProbe` + +A custom [Kubernetes liveness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for the `logrotate` sidecar container. When not set, the container has no liveness probe. Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `exec: { command: [/bin/true] }` | + +### `logcollector.logrotate.livenessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the liveness probe + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `30` | + +### `logcollector.logrotate.livenessProbe.periodSeconds` + +How often to perform the liveness probe (in seconds) + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `15` | + +### `logcollector.logrotate.readinessProbe` + +A custom [Kubernetes readiness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) for the `logrotate` sidecar container. When not set, the container has no readiness probe. Available starting with Operator version 1.23.0. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `exec: { command: [/bin/true] }` | + +### `logcollector.logrotate.readinessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the readiness probe + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `5` | + +### `logcollector.logrotate.readinessProbe.periodSeconds` + +How often to perform the readiness probe (in seconds) + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `15` | + ### `logcollector.resources.requests.memory` The [Kubernetes memory requests :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) for a Log Collector sidecar container in a Percona Server for MongoDB Pod. From 1c777d3a14601261906c48294af4d955d2e479d4 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 12:29:14 +0300 Subject: [PATCH 18/22] K8SPSMDB-1602 Documented Workload Identity support for GCS (#353) * K8SPSMDB-1602 Documented Workload Identity support for GCS * Updated after the review * Updated the way to restart pods --- docs/backups-storage-gcp.md | 182 +++++++++++- ...kups-storage-s3-instance-profile-draft.txt | 281 ++++++++++++++++++ docs/backups-storage-s3.md | 34 ++- docs/backups-storage.md | 5 +- docs/operator.md | 6 +- 5 files changed, 485 insertions(+), 23 deletions(-) create mode 100644 docs/backups-storage-s3-instance-profile-draft.txt diff --git a/docs/backups-storage-gcp.md b/docs/backups-storage-gcp.md index d60450e8..98ec6148 100644 --- a/docs/backups-storage-gcp.md +++ b/docs/backups-storage-gcp.md @@ -1,16 +1,186 @@ # Google Cloud storage -To use [Google Cloud Storage (GCS) :octicons-link-external-16:](https://cloud.google.com/storage) as an object store for backups, you need the following information: +To use [Google Cloud Storage (GCS) :octicons-link-external-16:](https://cloud.google.com/storage) as an object store for backups, you need the following: -* a GCS bucket name. Refer to the [GCS bucket naming guidelines :octicons-link-external-16:](https://cloud.google.com/storage/docs/buckets#naming) for bucket name requirements -* authentication keys for your service account in JSON format. +* A GCS bucket name. Refer to the [GCS bucket naming guidelines :octicons-link-external-16:](https://cloud.google.com/storage/docs/buckets#naming) for bucket name requirements +* Authentication to the bucket. See [Choose the authentication method](#choose-the-authentication-method) for available options. + +## Choose the authentication method + +You can use one of the following options to authenticate to GCS: + +* [**Workload Identity (recommended on GKE)**](#automate-access-to-google-cloud-storage-using-workload-identity). Bind a Google service account to the Kubernetes Service Account used by your database Pods. You do not store service account JSON keys in a Kubernetes Secret. Google provides short-lived credentials automatically. This is the recommended approach on Google Kubernetes Engine (GKE) and for environments that forbid exporting service account keys. +* [**Service account JSON keys**](#set-up-google-cloud-storage-access-with-service-account-keys). Store the service account email and private key in a Kubernetes Secret and reference it in your cluster configuration. This method works on any Kubernetes platform and requires that you manage the credentials yourself. !!! note - You can still use the S3-compatible implementation of GCS with HMAC. Refer to the [Amazon S3 storage setup](backups-storage-s3.md) section for steps. + You can still use the S3-compatible implementation of GCS with HMAC keys. Refer to the [Amazon S3 storage setup](backups-storage-s3.md) section for steps. + + However, we don't recommend their usage due to a [known issue in PBM :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/release-notes/2.11.0.html#known-limitations-for-using-hmac-keys-on-gcs) and encourage you to use the native `gcs` storage type instead. + +### How the Operator chooses GCS authentication + +* If a Secret with GCS credentials is defined in the Custom Resource (`gcs.credentialsSecret`), the Operator uses those credentials. +* If `gcs.credentialsSecret` is omitted, the Operator configures Percona Backup for MongoDB to use Application Default Credentials (ADC), such as GKE Workload Identity. + +## Automate access to Google Cloud Storage using Workload Identity + +!!! note "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +[GKE Workload Identity :octicons-link-external-16:](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) lets Pods authenticate to Google Cloud as a Google service account. Percona Backup for MongoDB uses Application Default Credentials and receives short-lived tokens automatically. For how PBM uses Workload Identity and ADC, see the [PBM documentation :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/details/workload-identity-auth.html). + +### Prerequisites + +Before you start, make sure you have the following: + +* A [GKE cluster with Workload Identity enabled :octicons-link-external-16:](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#enable) and the Operator and database deployed. See also [Install on GKE](gke.md). +* A GCS bucket for backups +* The [Google Cloud CLI (gcloud) :octicons-link-external-16:](https://cloud.google.com/sdk/docs/install) and [kubectl :octicons-link-external-16:](https://kubernetes.io/docs/tasks/tools/) installed and configured +* Permission to create service accounts and manage IAM bindings + +Set environment variables for the commands below. Replace the placeholders with your values: + +```bash +export PROJECT_ID= +export GCS_BUCKET= +export GSA_NAME= +export NAMESPACE= +export KSA_NAME=default +``` + +`KSA_NAME` is the Kubernetes Service Account used by your database Pods. By default this is `default`. You can override it with the `serviceAccountName` Custom Resource option in the `replsets`, `sharding.configsvrReplSet`, and `sharding.mongos` subsections of the `deploy/cr.yaml` manifest. + +### Configure Google Cloud access {.power-number} + +1. Create a Google service account (GSA), if you don't have one already: + + ```bash + gcloud iam service-accounts create $GSA_NAME \ + --project=$PROJECT_ID \ + --display-name="Percona MongoDB GCS backups" + ``` + +2. Grant the GSA permissions on the backup bucket. For example, grant object read and write access: + + ```bash + gcloud storage buckets add-iam-policy-binding gs://$GCS_BUCKET \ + --member="serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ + --role="roles/storage.objectUser" + ``` + + !!! tip + + Choose the IAM role that matches your security policy. `roles/storage.objectUser` is a common choice for backup and restore workflows. + +3. Allow the Kubernetes Service Account to impersonate the Google service account: + + ```bash + gcloud iam service-accounts add-iam-policy-binding \ + ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \ + --role roles/iam.workloadIdentityUser \ + --member "serviceAccount:${PROJECT_ID}.svc.id.goog[${NAMESPACE}/${KSA_NAME}]" + ``` + +4. Annotate the Kubernetes Service Account with the Google service account email: + + ```bash + kubectl -n $NAMESPACE annotate serviceaccount $KSA_NAME \ + iam.gke.io/gcp-service-account=${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com \ + --overwrite + ``` + +5. Annotating a Service Account does not restart existing Pods automatically. Restart the database Pods so they pick up the Workload Identity configuration. For a replica set named `rs0`, run the following: + + ```bash + export DBCLUSTER=my-cluster-name + kubectl rollout restart sts/$DBCLUSTER-rs0 -n $NAMESPACE + ``` + +### Configure Percona Server for MongoDB cluster + +Now you are ready to configure Percona Server for MongoDB to use Workload Identity for GCS backups. + +=== "A new cluster deployment" + + 1. Edit the `backup.storages` subsection in the `deploy/cr.yaml` Custom Resource manifest. Give your storage a name and set the following keys: + + * `type` - make sure the type is `gcs` + * `bucket` - where the data will be stored + * `prefix` (optional) - a path (sub-folder) inside the GCS bucket where backups will be stored. If you don't set a prefix, backups are stored in the root directory. + * Omit `gcs.credentialsSecret` so that PBM uses Workload Identity / ADC to access the GCS storage. + + Here's the example configuration: + + ```yaml + ... + backup: + enabled: true + ... + storages: + gcs-wi: + type: gcs + gcs: + bucket: + prefix: mongodb-backup + ... + ``` + + For more storage options, see the [Operator Custom Resource options](operator.md#operator-backup-section). + + 2. Apply the configuration and deploy the cluster: + + ```bash + kubectl apply -f deploy/cr.yaml -n $NAMESPACE + ``` + + 3. Wait for the cluster to report the Ready status: + + ```bash + kubectl get psmdb -n $NAMESPACE + ``` + +=== "Existing cluster" + + If your running Percona Server for MongoDB cluster is currently using a Kubernetes Secret with GCS credentials for backups, you can switch to Workload Identity by following these steps: + + 1. [Configure Google Cloud access](#configure-google-cloud-access) and annotate the Service Account, if you haven't done it before. + 2. Make a rolling restart of the database Pods so they pick up the Workload Identity annotation. + + * Export the cluster name as an environment variable: + + ```bash + export DBCLUSTER=my-cluster-name + ``` + + * Restart the Pods: + + ```bash + kubectl rollout restart sts/$DBCLUSTER-rs0 -n $NAMESPACE + ``` + + 3. Remove the credentials Secret from the Custom Resource. The storage name in the following command is `gcs`. Replace it with your value if you use another name: + + ```bash + kubectl -n $NAMESPACE patch psmdb $DBCLUSTER --type=json \ + -p '[{"op":"remove","path":"/spec/backup/storages/gcs/gcs/credentialsSecret"}]' + ``` + +### Verify access to GCS using Workload Identity + +[Run an on-demand backup](backups-ondemand.md) to confirm that the cluster can write to the GCS bucket. + +### Troubleshooting + +* **Confirm the Service Account annotation.** The Kubernetes Service Account used by the database Pods must have the `iam.gke.io/gcp-service-account` annotation set to the Google service account email. +* **Confirm the IAM binding.** The Google service account must grant `roles/iam.workloadIdentityUser` to `serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]`. +* **Confirm bucket permissions.** The Google service account must have permission to read and write objects in the backup bucket. +* **Remove `credentialsSecret`.** If `gcs.credentialsSecret` is still set in the Custom Resource, the Operator uses the Secret instead of Workload Identity. +* **Restart Pods after annotation changes.** Existing Pods do not pick up a new Workload Identity annotation until you restart them. + +## Set up Google Cloud Storage access with service account keys + +Follow these steps to authenticate using a service account JSON key. This method works on any Kubernetes environment. - However, we don't recommend their usage due to a [known issue in PBM :octicons-link-external-16:](https://docs.percona.com/percona-backup-mongodb/release-notes/2.11.0.html#known-limitations-for-using-hmac-keys-on-gcs) and encourage you to switch to using service accounts keys after the upgrade to the Operator version 1.21.0. - **Configuration steps** {.power-number} diff --git a/docs/backups-storage-s3-instance-profile-draft.txt b/docs/backups-storage-s3-instance-profile-draft.txt new file mode 100644 index 00000000..676a5378 --- /dev/null +++ b/docs/backups-storage-s3-instance-profile-draft.txt @@ -0,0 +1,281 @@ +# Draft: IAM instance profile section for backups-storage-s3.md + +This file contains the proposed **Automate access to Amazon S3 using IAM instance profile** section. Replace lines 465–473 in `backups-storage-s3.md` with the content below (from `## Automate access` through the end of the instance profile section). + +--- + +## Automate access to Amazon S3 using IAM instance profile + +An [IAM instance profile :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) attaches an IAM role to EC2 instances. When your Kubernetes worker nodes run on EC2, Pods obtain AWS credentials through the [EC2 instance metadata service (IMDS) :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html). You do not store AWS access keys in a Kubernetes Secret. Instead, Percona Backup for MongoDB uses the AWS default credential provider chain and receives credentials from the worker node automatically. + +Use this method when your cluster runs on EC2 worker nodes and IRSA is not configured—for example, in self-managed Kubernetes clusters on EC2. All Pods on the same worker node share the node's IAM permissions. + +### Prerequisites + +Before you start, make sure you have the following: + +* A Kubernetes cluster whose worker nodes run on EC2 +* The [Operator and database deployed](kubectl.md), or ready to deploy +* An S3 bucket for backups +* The [AWS CLI :octicons-link-external-16:](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) and [kubectl :octicons-link-external-16:](https://kubernetes.io/docs/tasks/tools/) installed and configured +* Your AWS account ID. You can get it with: + + ```bash + aws sts get-caller-identity --query Account --output text + ``` + +Set environment variables for the commands below. Replace the placeholders with your values: + +```bash +export aws_region= +export s3_bucket= +export policy_name= +export role_name= +export instance_profile_name= +export namespace= +export account_id=$(aws sts get-caller-identity --query Account --output text) +``` + +### Configure the IAM role and instance profile +{.power-number} + +1. Create an IAM policy that grants access to your S3 bucket. Replace `` with your bucket name: + + ```json title="s3-bucket-policy.json" + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:*" + ], + "Resource": [ + "arn:aws:s3:::", + "arn:aws:s3:::/*" + ] + } + ] + } + ``` + + !!! tip + + The example uses broad `s3:*` permissions for simplicity. In production, restrict the policy to the specific S3 actions your backup and restore workflows require. Refer to the [Amazon S3 permissions documentation :octicons-link-external-16:](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-actions.html) and tailor the policy to follow the principle of least privilege. + +2. Create the IAM policy: + + ```bash + aws iam create-policy \ + --policy-name $policy_name \ + --policy-document file://s3-bucket-policy.json + ``` + +3. Create a trust policy that allows EC2 instances to assume the role: + + ```json title="ec2-trust-policy.json" + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + } + ``` + +4. Create the IAM role: + + ```bash + aws iam create-role \ + --role-name $role_name \ + --assume-role-policy-document file://ec2-trust-policy.json \ + --description "Allow EC2 worker nodes to access S3 backups" + ``` + +5. Attach the S3 policy to the role: + + ```bash + aws iam attach-role-policy \ + --role-name $role_name \ + --policy-arn arn:aws:iam::${account_id}:policy/${policy_name} + ``` + +6. Create an instance profile and add the role to it: + + ```bash + aws iam create-instance-profile \ + --instance-profile-name $instance_profile_name + + aws iam add-role-to-instance-profile \ + --instance-profile-name $instance_profile_name \ + --role-name $role_name + ``` + + !!! note "EKS clusters without IRSA" + + Amazon EKS worker nodes already have an instance profile through the node group IAM role. Instead of creating a new instance profile, attach the S3 policy from step 2 to the existing node group role. Skip steps 6–7 in the next section and apply the policy to that role. + +### Attach the instance profile to worker nodes +{.power-number} + +1. Attach the instance profile to each EC2 worker node in your cluster. The exact steps depend on how you manage your nodes: + + * **Self-managed clusters:** Attach the profile when you launch instances, or associate it with running instances: + + ```bash + aws ec2 associate-iam-instance-profile \ + --instance-id \ + --iam-instance-profile Name=$instance_profile_name + ``` + + * **Auto Scaling groups:** Update the launch template or Auto Scaling group to use `$instance_profile_name`. + +2. If you changed the instance profile on running nodes, restart the Operator and database Pods so backup agents pick up the new credentials: + + ```bash + kubectl rollout restart deployment/percona-server-mongodb-operator -n $namespace + kubectl rollout status deployment/percona-server-mongodb-operator -n $namespace + ``` + +3. Verify that worker nodes expose IAM credentials through IMDS. Run this command from a database Pod: + + ```bash + kubectl exec -it -n $namespace -- \ + curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/ + ``` + + ??? example "Sample output" + + ```{.text .no-copy} + my-ec2-role + ``` + + The output should show the IAM role name attached to the worker node. + +### Configure Percona Server for MongoDB cluster + +Now you are ready to configure Percona Server for MongoDB to use the instance profile for backups. + +=== "A new cluster deployment" + + 1. Edit the `backup.storages` subsection in `deploy/cr.yaml` Custom Resource manifest. Give your storage a name (default name is `s3-us-west`) and set the following keys: + + * `type` - make sure the type is `s3` + * `bucket` - where the data will be stored + * `region` - location of the bucket + * `prefix` (optional) - a path (sub-folder) inside the S3 bucket where backups will be stored. If you don't set a prefix, backups are stored in the root directory. + * Omit `s3.credentialsSecret` so that PBM uses the worker node's instance profile to access the S3 storage. + + Here's the example configuration: + + ```yaml + ... + backup: + enabled: true + ... + storages: + aws-s3: + type: s3 + s3: + bucket: + region: + prefix: data/pbm + ... + ``` + + For more storage options, see the [Operator Custom Resource options](operator.md#operator-backup-section). + + 2. Apply the configuration and deploy the cluster: + + ```bash + kubectl apply -f deploy/cr.yaml -n $namespace + ``` + + 3. Wait for the cluster to report the `ready` status: + + ```bash + kubectl get psmdb -n $namespace + ``` + +=== "Existing cluster" + + If your running Percona Server for MongoDB cluster is currently using a Kubernetes Secret with S3 credentials for backups, you can switch to an instance profile by following these steps: + + 1. [Attach the instance profile to worker nodes](#attach-the-instance-profile-to-worker-nodes), if you have not done so already. + + 2. Make a rolling restart of the database Pods. + + * Export the cluster name as an environment variable: + + ```bash + export DBCLUSTER=my-cluster-name + ``` + + * Use the following for loop: + + ```bash + for i in 0 1 2; do + kubectl delete pod $DBCLUSTER-rs0-$i -n $namespace + done + ``` + + 3. Restart the Operator Deployment: + + ```bash + kubectl rollout restart deployment/percona-server-mongodb-operator -n $namespace + ``` + + 4. Remove the credentials Secret by patching the cluster. The storage name in the following command is `aws-s3`. Replace it with your value if you use another name: + + ```bash + kubectl -n $namespace patch psmdb $DBCLUSTER --type=json \ + -p '[{"op":"remove","path":"/spec/backup/storages/aws-s3/s3/credentialsSecret"}]' + sleep 30 + ``` + +### Verify access to S3 using IAM instance profile + +1. Run an on-demand backup to confirm that the cluster can write to the S3 bucket. Here's the example of the backup object configuration: + + ```yaml title="deploy/backup/backup.yaml" + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBBackup + metadata: + name: backup1 + finalizers: + - percona.com/delete-backup + spec: + clusterName: my-cluster-name + storageName: aws-s3 + ``` + +2. Apply the configuration to start the backup: + + ```bash + kubectl apply -f deploy/backup/backup.yaml -n $namespace + ``` + +3. Check the backup progress: + + ```bash + kubectl get psmdb-backup -n $namespace + ``` + + When the backup reaches the `ready` status, the instance profile configuration is working. + +### Troubleshooting + +#### Backup fails with access denied + +* Confirm that the IAM policy is attached to the role associated with the worker node's instance profile. +* Make sure `s3.credentialsSecret` is not set in the Custom Resource. Secret-based credentials override instance profile credentials. +* Verify that Pods can reach IMDS. Some environments block the metadata endpoint or require [IMDSv2 :octicons-link-external-16:](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configured-instance-metadata-service.html). + +#### All Pods on the node share the same permissions + +This is expected behavior for instance profiles. If you need per-Pod S3 permissions, use [IRSA](#automate-access-to-amazon-s3-using-irsa) on EKS instead. diff --git a/docs/backups-storage-s3.md b/docs/backups-storage-s3.md index 59a209b4..0d2e13e4 100644 --- a/docs/backups-storage-s3.md +++ b/docs/backups-storage-s3.md @@ -33,7 +33,13 @@ You can use one of the following options to authenticate to S3: Follow these steps to authenticate using an AWS S3 access key and secret key. This method works on any Kubernetes environment. -1. Encode your `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` keys using base64: +1. Export the namespace as an environment variable: + + ```bash + export NAMESPACE= + ``` + +2. Encode your `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` keys using base64: === ":simple-linux: in Linux" @@ -47,7 +53,7 @@ Follow these steps to authenticate using an AWS S3 access key and secret key. Th echo -n 'plain-text-string' | base64 ``` -2. Create a Secret manifest with your access credentials. Use the [deploy/backup-s3.yaml :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/v{{release}}/deploy/backup-s3.yaml) file as an example. You must specify the following information: +3. Create a Secret manifest with your access credentials. Use the [deploy/backup-s3.yaml :octicons-link-external-16:](https://github.com/percona/percona-server-mongodb-operator/blob/v{{release}}/deploy/backup-s3.yaml) file as an example. You must specify the following information: * `metadata.name` is the name of the Kubernetes secret which you will reference in the Custom Resource * Base64-encoded credentials to access S3 storage. @@ -65,13 +71,13 @@ Follow these steps to authenticate using an AWS S3 access key and secret key. Th AWS_SECRET_ACCESS_KEY: ``` -3. Create the Kubernetes Secret object with this file: +4. Create the Kubernetes Secret object with this file: ```bash kubectl apply -f deploy/backup-s3.yaml -n ``` -4. Configure the storage in the Custom Resource. Modify the `backup.storages` subsection of the `deploy/cr.yaml` file. Give your storage a name (the default name is `s3-us-west`) and define the following information: +5. Configure the storage in the Custom Resource. Modify the `backup.storages` subsection of the `deploy/cr.yaml` file. Give your storage a name (the default name is `s3-us-west`) and define the following information: * `type` - make sure the type is `s3` * `bucket` - where the data will be stored @@ -334,8 +340,8 @@ export namespace= 3. Annotate both service accounts with the needed IAM role ARN: ```bash - kubectl -n $namespace annotate serviceaccount default eks.amazonaws.com/role-arn=$role_arn --overwrite - kubectl -n $namespace annotate serviceaccount percona-server-mongodb-operator eks.amazonaws.com/role-arn=$role-arn --overwrite + kubectl -n $NAMESPACE annotate serviceaccount default eks.amazonaws.com/role-arn=$role_arn --overwrite + kubectl -n $NAMESPACE annotate serviceaccount percona-server-mongodb-operator eks.amazonaws.com/role-arn=$role-arn --overwrite ``` 4. Annotating a Service Account does not restart existing Pods automatically. Restart the Operator and database Pods so they pick up the new `AWS_ROLE_ARN` environment variable: @@ -350,14 +356,14 @@ export namespace= * Check the annotation on both Service Accounts: ```bash - kubectl -n $namespace get sa default -o yaml - kubectl -n $namespace get sa percona-server-mongodb-operator -o yaml + kubectl -n $NAMESPACE get sa default -o yaml + kubectl -n $NAMESPACE get sa percona-server-mongodb-operator -o yaml ``` * Confirm that `AWS_ROLE_ARN` is set inside the Operator Pods: ```bash - kubectl -n $namespace exec -it deploy/percona-server-mongodb-operator -- printenv | grep AWS_ROLE_ARN + kubectl -n $NAMESPACE exec -it deploy/percona-server-mongodb-operator -- printenv | grep AWS_ROLE_ARN ``` ??? example "Sample output" @@ -437,12 +443,10 @@ Now you are ready to configure Percona Server for MongoDB to use IRSA for backup export DBCLUSTER=my-cluster-name ``` - * Use the following for loop: + * Use the following command: ```bash - for i in 0 1 2; do - kubectl delete pod $DBCLUSTER-rs0-$i -n $namespace - done + kubectl rollout restart sts/$DBCLUSTER-rs0 -n $NAMESPACE ``` 3. Restart the Operator Deployment: @@ -454,7 +458,7 @@ Now you are ready to configure Percona Server for MongoDB to use IRSA for backup 4. Confirm that AWS_ROLE_ARN is set inside the Operator and database Pods: ```bash - kubectl -n $namespace exec -it deploy/percona-server-mongodb-operator -- printenv | grep AWS_ROLE_ARN + kubectl -n $NAMESPACE exec -it deploy/percona-server-mongodb-operator -- printenv | grep AWS_ROLE_ARN kubectl exec -it $DBCLUSTER-rs0-0 -- printenv | grep AWS_ROLE_ARN ``` @@ -467,7 +471,7 @@ Now you are ready to configure Percona Server for MongoDB to use IRSA for backup 5. Remove the credentials Secret by patching the cluster. The storage name in the following command is `aws-s3`. Replace it with your value if you use another name: ```bash - kubectl -n $namespace patch psmdb $DBCLUSTER --type=json \ + kubectl -n $NAMESPACE patch psmdb $DBCLUSTER --type=json \ -p '[{"op":"remove","path":"/spec/backup/storages/aws-s3/s3/credentialsSecret"}]' sleep 30 ``` diff --git a/docs/backups-storage.md b/docs/backups-storage.md index fe678432..af724b15 100644 --- a/docs/backups-storage.md +++ b/docs/backups-storage.md @@ -13,7 +13,10 @@ The Operator provides several storage types for different storages. To help you * **oss** - Use this storage type for Alibaba Cloud Object Storage Service (OSS). * **filesystem** - Use this storage type for uploading backups to a remote file server. -For each backup storage, create a [Kubernetes Secret :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/secret/) object with credentials and reference it in the Custom Resource. +For most backup storages, create a [Kubernetes Secret :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/secret/) object with credentials and reference it in the Custom Resource. On cloud platforms, you can instead use identity-based access and omit the Secret: + +* [Amazon S3 with IRSA or an IAM instance profile](backups-storage-s3.md#choose-the-authentication-method) +* [Google Cloud Storage with Workload Identity](backups-storage-gcp.md#automate-access-to-google-cloud-storage-using-workload-identity) ## Storage setup guides diff --git a/docs/operator.md b/docs/operator.md index 1946d7e1..784dc77d 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -3685,7 +3685,11 @@ The path to the data directory in the bucket. If undefined, backups are stored i ### `backup.storages.STORAGE-NAME.gcs.credentialsSecret` -The [Kubernetes secret :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/secret/) for backups. It contains the GCS credentials as either the service account and JSON keys or HMAC keys. +The [Kubernetes Secret :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/secret/) with GCS credentials (service account email and JSON private key, or HMAC keys). + +This option is optional. Omit it when you use [GKE Workload Identity](backups-storage-gcp.md#automate-access-to-google-cloud-storage-using-workload-identity). + +If both a Secret and Workload Identity are available, a defined `credentialsSecret` takes precedence. | Value type | Example | | ----------- | ---------- | From 2977eae11f54eb59ae7ef1e1ebad83f3adfa665d Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 12:31:32 +0300 Subject: [PATCH 19/22] K8 spsmdb 1610 doc pscm support (#352) * K8SPSMDB-1610 Documented the support for PCSM new file: docs/assets/images/clustersync.svg new file: docs/clustersync-options.md new file: docs/clustersync-setup.md new file: docs/clustersync.md modified: docs/cr-statuses.md modified: docs/debug.md modified: docs/operator.md modified: mkdocs-base.yml --- docs/assets/images/clustersync.svg | 4 + docs/clustersync-options.md | 109 +++++++ docs/clustersync-setup.md | 450 +++++++++++++++++++++++++++++ docs/clustersync.md | 112 +++++++ docs/cr-statuses.md | 78 +++++ docs/debug.md | 9 +- docs/operator.md | 1 + mkdocs-base.yml | 22 +- 8 files changed, 775 insertions(+), 10 deletions(-) create mode 100644 docs/assets/images/clustersync.svg create mode 100644 docs/clustersync-options.md create mode 100644 docs/clustersync-setup.md create mode 100644 docs/clustersync.md diff --git a/docs/assets/images/clustersync.svg b/docs/assets/images/clustersync.svg new file mode 100644 index 00000000..5fcae2bb --- /dev/null +++ b/docs/assets/images/clustersync.svg @@ -0,0 +1,4 @@ + + + +
MongoDB Atlas
(source)
mongos
Config Server ReplicaSet
ReplicaSet
Operator
PerconaServerMongoDB
(target)
PSCM
\ No newline at end of file diff --git a/docs/clustersync-options.md b/docs/clustersync-options.md new file mode 100644 index 00000000..8b949d82 --- /dev/null +++ b/docs/clustersync-options.md @@ -0,0 +1,109 @@ +# ClusterSync Resource options + +A ClusterSync resource is a Kubernetes object that tells the Operator how to deploy and manage [Percona ClusterSync for MongoDB (PCSM) :octicons-link-external-16:](https://docs.percona.com/percona-clustersync-for-mongodb/). The `deploy/clustersync.yaml` file is a template for creating the `PerconaServerMongoDBClusterSync` resource. + +This document describes the options you can use to configure ClusterSync. For concepts and limitations, see [Real-time replication with PCSM](clustersync.md). For a hands-on walkthrough, see [Set up and use PCSM](clustersync-setup.md). + +## `apiVersion` + +Specifies the API version of the Custom Resource. +`psmdb.percona.com` indicates the group, and `v1` is the version of the API. + +## `kind` + +Defines the type of resource being created: `PerconaServerMongoDBClusterSync`. + +## `metadata` + +The metadata part of the ClusterSync manifest contains metadata about the resource, such as its name and other attributes. It includes the following keys: + +* `name` - The name of the ClusterSync object. The Operator uses this name for owned resources such as the PCSM Deployment (`-pcsm`) and related Secrets. + +## `spec` + +This section includes the configuration of a ClusterSync resource. + +### `clusterName` + +Specifies the name of the target `PerconaServerMongoDB` cluster in the same namespace. The Operator builds the target connection URI from this cluster. + +| Value type | Example | +| ---------- | ------- | +| :material-code-string: string | `my-target-cluster` | + +### `image` + +Specifies the Percona ClusterSync for MongoDB container image. Required. + +| Value type | Example | +| ---------- | ------- | +| :material-code-string: string | `percona/percona-clustersync-mongodb:{{clustersync}}` | + +### `mode` + +Controls the replication lifecycle. The Operator compares `spec.mode` with `status.mode` and runs the matching PCSM command when they differ. + +Allowed values: + +* `running` - Start or resume replication. This is the default. +* `paused` - Pause an active replication channel. +* `finalized` - Finalize replication, create required indexes on the target, and stop. + +| Value type | Example | +| ---------- | ------- | +| :material-code-string: string | `running` | + +## The `source` subsection + +Defines how PCSM connects to the source MongoDB cluster. You manage the source. + +### `source.uri` + +Specifies the source MongoDB connection string **without credentials**. Include replica set options, TLS parameters, and other driver options in the URI query string as needed. + +For replica sets, use replica set members and `replicaSet`. For sharded clusters, use the `mongos` endpoint. + +| Value type | Example | +| ---------- | ------- | +| :material-code-string: string | `mongodb://host1:27017,host2:27017/admin?replicaSet=rs0` | + +### `source.credentialsSecret` + +Specifies the name of a Kubernetes Secret in the same namespace with `username` and `password` keys for the pcsm user on source. The Operator percent-encodes these values and injects them into the source URI at runtime. + +| Value type | Example | +| ---------- | ------- | +| :material-code-string: string | `my-cluster-sync-source` | + +### `excludeNamespaces` + +Lists MongoDB namespaces to exclude from replication. A namespace is `db` or `db.collection`. These values are passed to PCSM on `pcsm start` only. Changes after start do not re-filter an already running sync. + +| Value type | Example | +| ---------- | ------- | +| :material-text-long: array | `["admin", "local", "app.cache"]` | + +## The `pcsmConfig` subsection + +Controls PCSM process logging. + +### `pcsmConfig.logLevel` + +Sets the PCSM log level. Allowed values: `debug`, `info`, `warn`, `error`. + +| Value type | Example | +| ---------- | ------- | +| :material-code-string: string | `info` | + +## Pod and scheduling options + +These options configure the PCSM Deployment Pod the same way as other Operator-managed workloads. + +### `resources` + +Specifies CPU and memory requests and limits for the PCSM container. + +| Value type | Example | +| ---------- | ------- | +| :material-code-string: object | `requests: {cpu: 500m, memory: 512Mi}` | + diff --git a/docs/clustersync-setup.md b/docs/clustersync-setup.md new file mode 100644 index 00000000..7516b984 --- /dev/null +++ b/docs/clustersync-setup.md @@ -0,0 +1,450 @@ +# Set up and use Percona ClusterSync for MongoDB + +This tutorial shows how to configure [Percona ClusterSync for MongoDB (PCSM) :octicons-link-external-16:](https://docs.percona.com/percona-clustersync-for-mongodb/) with the Operator, start replication from a source MongoDB deployment to an Operator-managed target cluster, and manage the replication lifecycle. + +For concepts, architecture, modes, and limitations, see [Real-time replication and near-zero downtime migration with PCSM](clustersync.md). + +## Prerequisites + +Before you start, make sure that: + +* You run Percona Operator for MongoDB **1.23.0** or later. +* The source and target clusters use the **same major MongoDB version**. Minimum supported versions are listed in [Supported MongoDB deployments](clustersync.md#supported-mongodb-deployments). +* The source and target topologies are compatible for your scenario (replica set to replica set, or sharded cluster to sharded cluster). +* The PCSM Pod can reach the source cluster endpoint over the network. +* You understand the [limitations](clustersync.md#limitations), including that users and roles are not synchronized and initial sync is not resumable after a hard failure. + +This tutorial demonstrates how to set up PCSM with both the source and target clusters deployed as sharded clusters in Kubernetes within the same namespace. This configuration is useful for testing or demonstration purposes. In production environments, source and target clusters are typically deployed in separate environments or networks. In such scenarios, ensure that the PCSM Deployment managed by the Operator has network connectivity to the source cluster. + +Names used in this tutorial are: + +| Resource | Example name | +|----------|--------------| +| Source cluster | `my-source-cluster` | +| Target cluster | `my-target-cluster` | +| ClusterSync CR | `my-cluster-sync` | +| Sync credentials Secret from source | `my-cluster-sync-source` | +| Namespace | `psmdb-operator` | + +Replace them with your values, if needed. + +Percona ClusterSync for MongoDB (PCSM) image and version used in this tutorial are: + +``` +percona/percona-clustersync-for-mongodb:0.9.0 +``` + +## Configuration + +### 1. Prepare the environment + +1. Clone the Percona Operator repository to get access to sample manifests and configuration files: + + ```bash + git clone -b v{{release}} https://github.com/percona/percona-server-mongodb-operator.git + cd percona-server-mongodb-operator + ``` + +2. Set namespace as environment variable: + + ```bash + export NAMESPACE="psmdb-operator" + ``` + +### 2. Deploy the Operator + +Since source and target clusters are in the same namespace, deploy the Operator in the cluster-wide mode: + +```bash +kubectl apply --server-side -f deploy/cw-bundle.yaml + +Refer to the [Install the Operator in the cluster-wide mode](cluster-wide.md#install-percona-operator-for-mongodb-in-multi-namespace-cluster-wide-mode) for how to install the Operator in another namespace. + +### 3. Deploy the source cluster + +1. Deploy the source cluster. Edit the `deploy/cr.yaml` and change the `metadata.name` to `my-source-cluster`. You can keep the default settings. Rename the file to `cr-source.yaml` + +2. Apply the configuration: + + ```bash + kubectl apply -f deploy/cr-source.yaml -n $NAMESPACE + ``` + +3. Wait for the cluster to report the `Ready` state + + ```bash + kubectl get psmdb -n $NAMESPACE + ``` + +### 4. Prepare the source cluster for replication + +You manage the source cluster regardless how it is deployed. Create a MongoDB user for PCSM and store its credentials in a Kubernetes Secret that the Operator can read. + +1. Find the Secret name referenced in your source cluster's CR under `spec.secrets.users` and export it as environment variable. Run this command to check your cluster's configuration: + + ```bash + export SOURCESECRET="$(kubectl get psmdb my-source-cluster -n $NAMESPACE -o jsonpath='{.spec.secrets.users}')" + echo "$SOURCESECRET" + + ??? example "Sample output" + + ``` + my-source-cluster-secrets + ``` + +2. Connect to the `mongos` Primary Pod as the `databaseAdmin` user: + + ```bash + kubectl exec -n $NAMESPACE -it my-source-cluster-mongos-0 -c mongos -- \ + mongosh admin -u databaseAdmin -p "$(kubectl get secret $SOURCESECRET -n $NAMESPACE -o jsonpath='{.data.MONGODB_DATABASE_ADMIN_PASSWORD}' | base64 --decode | tr -d '\n')" + ``` + + !!! tip + + For replica set deployments, connect to the primary `mongod` instance. + +3. Create the source user with these roles: `backup`, `clusterMonitor`, and `readAnyDatabase`. + + ```javascript + db.getSiblingDB("admin").createUser({ + user: "pcsmSource", + pwd: "s3cretPassw0rd", + roles: ["backup", "clusterMonitor", "readAnyDatabase"] + }) + ``` + + For more details, see [Configure authentication in PCSM documentation :octicons-link-external-16:](https://docs.percona.com/percona-clustersync-for-mongodb/install/docker.html). + +4. Create the source credentials Secret in the **same namespace** as the target cluster and the ClusterSync CR. Use the `username` and `password` keys. + + Here's the example file: + + ```yaml title="source-credentials.yaml" + apiVersion: v1 + kind: Secret + metadata: + name: my-cluster-sync-source + type: Opaque + stringData: + username: pcsmSource + password: s3cretPassw0rd + ``` + + Apply it: + + ```bash + kubectl apply -f source-credentials.yaml -n $NAMESPACE + ``` + + !!! note + + Do not put credentials in `spec.source.uri`. The Operator injects them from this Secret at runtime. + +5. Retrieve the endpoint to your source cluster: + + - **For a sharded cluster**, use the `mongos` service as the endpoint. Run the following command to check the endpoint: + + ```bash + kubectl get svc -n $NAMESPACE | grep mongos + ``` + + ??? example "Sample output" + + ``` + my-source-cluster-mongos.psmdb-operator.svc.cluster.local:27017 + ``` + + - **For a replica set**, the endpoint must include each replica set member's Pod name in the format `...svc.cluster.local:port` for each replica set member, separated by commas. For example: + + ``` + my-source-cluster-rs0-0.psmdb-operator.svc.cluster.local:27017, + my-source-cluster-rs0-1.psmdb-operator.svc.cluster.local:27017, + my-source-cluster-rs0-2.psmdb-operator.svc.cluster.local:27017 + ``` + + Replace the service and namespace with your actual values. + +### 5. Deploy the target cluster + +Deploy an Operator-managed Percona Server for MongoDB cluster that will receive the replicated data. Edit the `deploy/cr.yaml` file and change the `metadata.name` to `my-target-cluster`. Rename the file to differentiate the configurations. + +```yaml title="cr-target.yaml" +apiVersion: psmdb.percona.com/v1 +kind: PerconaServerMongoDB +metadata: + name: my-target-cluster +spec: + crVersion: "{{ release }}" + image: percona/percona-server-mongodb:{{ mongodb80recommended }} + replsets: + - name: rs0 + size: 3 + resources: + limits: + cpu: "600m" + memory: "1Gi" + requests: + cpu: "300m" + memory: "1Gi" + volumeSpec: + persistentVolumeClaim: + resources: + requests: + storage: 3Gi + sharding: + enabled: true + configsvrReplSet: + size: 3 + affinity: + antiAffinityTopologyKey: "kubernetes.io/hostname" + podDisruptionBudget: + maxUnavailable: 1 + resources: + limits: + cpu: "600m" + memory: "1Gi" + requests: + cpu: "300m" + memory: "1Gi" + volumeSpec: + persistentVolumeClaim: + resources: + requests: + storage: 3Gi + mongos: + size: 3 + affinity: + antiAffinityTopologyKey: "kubernetes.io/hostname" + resources: + limits: + cpu: "600m" + memory: "1Gi" + requests: + cpu: "300m" + memory: "1Gi" +``` + +Apply the manifest and wait until the cluster is ready: + +```bash +kubectl apply -f deploy/cr-target.yaml -n $NAMESPACE +kubectl get psmdb my-target-cluster -n $NAMESPACE -w +``` + +The cluster status must be `ready` before you create the Percona ClusterSync for MongoDB Custom Resource. + +### 6. Set up Percona ClusterSync for MongoDB + +Create a `PerconaServerMongoDBClusterSync` Custom Resource. Edit the `deploy/clustersync.yaml` configuration file. Specify the following keys: + +* `spec.clusterName` - specify the name of the target cluster +* `spec.source.uri` - specify the endpoint to the source cluster. +* `spec.source.credentialsSecret` - reference the Secret that stores the credentials of the PCSM user from the source cluster. +* `spec.mode` defaults to `running`, so replication starts when the PCSM Pod is ready. + +=== "Replica set" + + Use a replica set connection string for the source. List replica set members, the replica set name and authentication database. If you use TLS, include TLS options too. + + ```yaml title="clustersync-rs.yaml" + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBClusterSync + metadata: + name: my-cluster-sync + spec: + clusterName: my-target-cluster + image: percona/percona-clustersync-mongodb:{{clustersync}} + mode: running + source: + uri: mongodb://my-source-cluster-rs0-0.psmdb-operator.svc.cluster.local:27017,my-source-cluster-rs0-1.psmdb-operator.svc.cluster.local:27017/admin?replicaSet=rs0 + credentialsSecret: my-cluster-sync-source + ``` + +=== "Sharded cluster" + + For sharded clusters, specify the `mongos` Service name for the source URI. Sharded replication is in tech preview. See [Sharding support in PCSM](clustersync.md#sharding-support-in-pcsm-tech-preview). + + ```yaml title="clustersync-sharded.yaml" + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDBClusterSync + metadata: + name: my-cluster-sync + spec: + clusterName: my-target-cluster + image: percona/percona-clustersync-mongodb:{{clustersync}} + mode: running + source: + uri: mongodb://my-source-cluster-mongos.psmdb-operator.svc.cluster.local:27017/admin + credentialsSecret: my-cluster-sync-source + ``` + +Create the `PerconaServerMongoDBClusterSync` Custom Resource: + +```bash +kubectl apply -f clustersync-rs.yaml -n $NAMESPACE +``` + +### 7. Check PCSM status + +To check the status of your Percona ClusterSync (PCSM), use the following command: + +```bash +kubectl get psmdb-clustersync -n $NAMESPACE +``` + +This displays a summary table including the `MODE`, `STATE`, and replication lag time. + +??? example "Sample output" + + ```text + NAME CLUSTER MODE STATE LAG(S) AGE + my-cluster-sync my-target-cluster running running 39m + ``` + +To get detailed information about a ClusterSync resource and see the replication status, use: + +```bash +kubectl describe psmdb-clustersync -n $NAMESPACE +``` + +Key fields to observe for replication status include: +- `status.mode`: The desired state (`running`, `paused`, etc.) +- `status.state`: The current state of the sync process +- `status.lagTimeSeconds`: Current replication lag in seconds +- `status.error`: Any error messages if replication fails + +Monitor these fields to verify active and healthy replication. + +## Usage + +### Verify the replication + +1. Insert some data into the source cluster: + + ```javascript + use test + for (let i = 1; i <= 50; i++) { + db.test.insertOne({ x: i }); + } + ``` + + This inserts 50 documents to the `test` collection in the `test` database. + +2. Verify that data is replicated on the target. Connect to MongoDB on the target cluster and run: + + ```javascript + use test + db.test.countDocuments() + ``` + +### Pause replication + +To pause replication, change the replication mode to `paused` in the Custom Resource. Since it is a running deployment, a recommended way is to patch it. + +```bash +kubectl patch psmdb-clustersync my-cluster-sync -n $NAMESPACE \ + --type=merge -p '{"spec":{"mode":"paused"}}' +``` + +### Resume replication + +To resume replication, change the replication mode to `running`. + +```bash +kubectl patch psmdb-clustersync my-cluster-sync -n $NAMESPACE \ + --type=merge -p '{"spec":{"mode":"running"}}' +``` + +### Finalize the replication + +To finalize replication, change the replication mode to `finalized`. + +1. Check the replication lag: + + ```bash + kubectl get psmdb-clustersync -n $NAMESPACE + ``` + +2. When the `LAG(S)` value is acceptable and you are ready to complete the migration, run: + + ```bash + kubectl patch psmdb-clustersync my-cluster-sync -n $NAMESPACE \ + --type=merge -p '{"spec":{"mode":"finalized"}}' + ``` + +3. PCSM finalizes the replication, creates indexes on the target and stops. Check PCSM status for `state: finalized`. + + !!! warning + + This is a one-time operation. If you update the PerconaServerMongoDBClusterSync resource again and change the mode to `running`, this has no effect. + + To start over, you need to delete the `PerconaServerMongoDBClusterSync` object and recreate it. PCSM starts from the initial data sync. + + +4. Point your applications to the target cluster. See [Connect to Percona Server for MongoDB](connect.md). + +### Clean up + +When you no longer need the ClusterSync record, remove it: + +```bash +kubectl delete psmdb-clustersync my-cluster-sync -n $NAMESPACE +``` + +This removes the PCSM Deployment and Operator-owned Secrets. The source credentials Secret and the MongoDB sync user on the target are not deleted automatically. + +## 5. Troubleshooting + +### PCSM Pod is not ready + +Check the Deployment and Pod: + +```bash +kubectl get deploy,pods -l app.kubernetes.io/component=clustersync -n $NAMESPACE +kubectl describe deploy my-cluster-sync-pcsm -n $NAMESPACE +kubectl logs deploy/my-cluster-sync-pcsm -n $NAMESPACE +``` + +Common causes: + +* Source URI is unreachable from the cluster network +* Source credentials Secret is missing or has wrong keys (`username` / `password`) +* Target cluster is not `ready` +* Source and target major MongoDB versions differ + +### Status shows `failed` + +Inspect the error: + +```bash +kubectl get psmdb-clustersync my-cluster-sync -n $NAMESPACE \ + -o jsonpath='{.status.state}{"\n"}{.status.error}{"\n"}' +``` + +If `spec.mode` is `running`, the Operator retries with `pcsm resume --from-failure` for recoverable failures after initial sync. + +If the failure keeps recurring: + +1. Pause replication to stop retries: + + ```bash + kubectl patch psmdb-clustersync my-cluster-sync -n $NAMESPACE \ + --type=merge -p '{"spec":{"mode":"paused"}}' + ``` + +2. Fix the root cause on the source or network side. +3. Resume with `mode: running`, or delete and recreate the ClusterSync CR to start a fresh initial sync. + +Initial sync cannot be resumed after a hard failure. Recreate the ClusterSync CR to start over. See [Limitations](clustersync.md#limitations). + + +### Inspect PCSM from inside the Pod + +For advanced troubleshooting: + +```bash +kubectl exec -it deploy/my-cluster-sync-pcsm -n $NAMESPACE -- pcsm status +``` + +Use manual `pcsm` commands only when you need details beyond the Custom Resource status. + diff --git a/docs/clustersync.md b/docs/clustersync.md new file mode 100644 index 00000000..e414489c --- /dev/null +++ b/docs/clustersync.md @@ -0,0 +1,112 @@ +# Real-time replication and near-zero downtime migration with Percona ClusterSync for MongoDB (PCSM) + +!!! note "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +[Percona ClusterSync for MongoDB (PCSM) :octicons-link-external-16:](https://docs.percona.com/percona-clustersync-for-mongodb/) is a data migration and replication tool for MongoDB deployments. It clones existing data from source MongoDB deployment to target one and uses MongoDB change stream events to track the changes on the source and replicate them to the target in real time. + +You can use Percona ClusterSync for MongoDB for: + +* One-time migration with near-zero downtime +* A live replica of your data for testing purposes or geographically distributed environments + +You can replicate the full data set or exclude specific namespaces. In either case, PCSM creates the required indexes on the target. + +For more information on PCSM, refer to [PCSM documentation :octicons-link-external-16:](https://docs.percona.com/percona-clustersync-for-mongodb/index.html#features). + +## How it works with the Operator + +The Operator deploys and manages PCSM through a dedicated **`PerconaServerMongoDBClusterSync`** Custom Resource (`psmdb-clustersync`). PCSM runs as a separate Deployment in the same namespace as the target cluster. The Operator uses PCSM API to control the replication flow. + +You configure authentication for PCSM in the source cluster and +provide the user credentials within the Kubernetes Secret and +the cluster endpoint. Then define the source and target clusters +and the replication mode in the `PerconaServerMongoDBClusterSync` custom +resource. After you apply the configuration, the Operator does +the following: + +* Deploys the PCSM Deployment +* Provisions a sync user on the target cluster +* Constructs MongoDB connection URIs to both source and target +clusters. +* Starts the replication: first it does the initial sync and +then replicates the changes from source to target in real time +* Monitors the replication mode changes and pauses, resumes or +finalizes the replication depending on your settings +* Surfaces replication state and lag on the +`PerconaServerMongoDBClusterSync` Custom Resource +* Coordinates backup and restore operations on the target cluster so they do not interfere with active replication + +You can monitor the replication progress. When the replication +lag is acceptable for cutover, finalize the replication. Then +reconfigure client applications to point to the target cluster. + +For step-by-step instructions, see [Set up and use PCSM](clustersync-setup.md). + +## Architecture + +![image](assets/images/clustersync.svg) + +Components of this architecture are: + +* **Source cluster** – The cluster you replicate data from. You can run it on premises (MongoDB Enterprise Advanced), in the cloud (MongoDB Atlas) or as another Kubernetes deployment. You manage the source cluster and must prepare it for replication: configure authentication, create a Kubernetes Secret with the PCSM user credentials and provide the cluster endpoint. + +* **Target cluster** – The cluster you replicate data to. It is managed by the Operator. The Operator creates the sync user and constructs the connection string automatically based on the cluster topology. + +* **PCSM Deployment** — Managed by the Operator. The Operator restarts and re-runs initial sync if it is interrupted during clone. After initial sync, it auto-resumes from a checkpoint on recoverable failures. For a hard failure during initial sync that needs a full reset, see [Troubleshooting](clustersync-setup.md#5-troubleshooting). + +## Supported MongoDB deployments + +Both source and target cluster can be replica sets or sharded clusters and must have the same major version. Minimum supported MongoDB versions are: 6.0.17, 7.0.13, 8.0.0. + +Replication between sharded clusters is in the tech preview stage and is not recommended for production use yet. See [Sharding support](#sharding-support-in-pcsm-tech-preview) to learn more. + +## Replication modes and states + +You control the replication flow through the `PerconaServerMongoDBClusterSync` custom resource. Supported modes are: + +* `running` – Start or resume replication. On start, PCSM runs initial sync, then replicates changes occurred on the source to the target. On resume, PCSM starts from the last saved checkpoint. +* `paused` – The replication is paused. PCSM saves the checkpoint in the change stream so it can resume replication without re-running the initial sync. +* `finalized` – PCSM completes the replication, creates required indexes on the target, and stops. This is a one-time operation. Setting the replication mode to `running` again has no effect. This is done to prevent accidental data resync. To start over, delete the `PerconaServerMongoDBClusterSync` object and recreate it. PCSM starts from the initial data sync. + + +PCSM also reports a runtime **state**, which the Operator stores in `status.state`: `idle`, `running`, `paused`, `finalizing`, `finalized`, `failed`. + +Find more information about modes, states, and conditions in [Custom resource statuses](cr-statuses.md#perconaservermongodbclustersync-status). For all configuration fields, see [ClusterSync Resource options](clustersync-options.md). + +## Sharding support in PCSM (tech preview) + +PCSM can replicate data between sharded clusters. Before the replication, it checks the source cluster for sharded collections and creates matching collections with the same shard keys on the target. The target cluster manages chunk distribution, primary shard names, and zones internally. + +PCSM replicates **data only**, not sharding metadata. It connects through `mongos` on both sides, so source and target can have different numbers of shards. + +## Backup and restore management + +You can run backups and restores on the **source** as usual. + +On the **target**, the Operator holds a lease while PCSM is active, so backups and restores wait. After you finalize replication and PCSM reports `finalized`, the Operator releases the lease and you can back up or restore the target again. + +## Implementation specifics + +* One active `PerconaServerMongoDBClusterSync` Custom Resource per target cluster (enforced by lease). +* Treat `source.uri` and source credentials as **immutable** after start. To change the source, delete and recreate the ClusterSync CR. +* `excludeNamespaces` applies only on `pcsm start`. Later changes do not re-filter an already running sync. +* The target sync user and finalized Deployment/Secrets remain until you delete the `PerconaServerMongoDBClusterSync` CR. + +## Limitations + +PCSM follows upstream [known issues and limitations :octicons-link-external-16:](https://docs.percona.com/percona-clustersync-for-mongodb/limitations.html). + +Notable constraints: + +* Same **major** MongoDB version required on source and target. +* Single source / single target pair only. +* Reverse synchronization is not supported. +* Initial sync is **not resumable**. If PCSM failed during initial sync, it restarts it from scratch. +* PCSM connects to the **primary** only; `directConnection` to secondaries is ignored. +* Users, roles, and `system.*` collections are not synchronized. +* Unsupported types include timeseries, queryable encryption, Percona Memory Engine, and several sharding admin commands during replication. +* External authentication (LDAP, Kerberos, AWS IAM) is not supported for PCSM connections. + +## Next steps + +[Set up and use PCSM](clustersync-setup.md){.md-button} diff --git a/docs/cr-statuses.md b/docs/cr-statuses.md index 0f67249d..99ed5740 100644 --- a/docs/cr-statuses.md +++ b/docs/cr-statuses.md @@ -16,6 +16,7 @@ List your resources and check their high-level STATUS: kubectl get psmdb -n kubectl get psmdb-backup -n kubectl get psmdb-restore -n +kubectl get psmdb-clustersync -n ``` ??? example "Sample output for PerconaServerMongoDB" @@ -220,3 +221,80 @@ kubectl get psmdb-restore -n \ ``` For the full restore workflow, see [PVC snapshot backups — Restore flow](backups-pvc-snapshots.md#restore-flow). + +## PerconaServerMongoDBClusterSync status + +ClusterSync progress and results are on the `PerconaServerMongoDBClusterSync` Custom Resource. Use these fields to track replication intent, runtime state, lag, and failures. + +`spec.mode` is your lifecycle intent. `status.state` is what PCSM is doing. For configuration options, see [ClusterSync Resource options](clustersync-options.md). For concepts, see [Real-time replication with PCSM](clustersync.md). + +Common fields: + +- `status.mode` – last lifecycle intent the Operator successfully applied (`running`, `paused`, `finalized`) +- `status.state` – PCSM-reported runtime state +- `status.lagTimeSeconds` – replication lag in seconds +- `status.error` – error details from PCSM or the Operator (for example, missing Secret or cluster busy) +- `status.startedAt` – timestamp of the first time PCSM reported `running` +- `status.conditions` – condition list with reason and message + +### ClusterSync mode values + +`status.mode` mirrors `spec.mode` after the Operator applies the matching PCSM command: + +| Value | Meaning | +| --- | --- | +| `running` | The Operator started or resumed replication. | +| `paused` | The Operator paused replication. | +| `finalized` | The Operator finalized replication. Further `spec.mode` changes are ignored. | + +### ClusterSync state values + +`status.state` values are: + +| Value | Meaning | +| --- | --- | +| `idle` | PCSM is deployed but has not started replication yet. | +| `running` | PCSM is performing initial sync or real-time replication. PCSM does not distinguish these phases in this field. Use `lagTimeSeconds` to judge catch-up. | +| `paused` | Replication is paused. | +| `finalizing` | PCSM is completing finalization. | +| `finalized` | Replication is complete. Indexes are finalized and the cluster lease is released. | +| `failed` | Replication failed. Check `status.error`. When `spec.mode` is `running`, the Operator retries recoverable failures with `pcsm resume --from-failure`. | + +### Conditions + +Conditions show more detail about ClusterSync state changes in `status.conditions[]`. + +`status.conditions[].type` values: + +| Value | Meaning | +| --- | --- | +| `Running` | `True` while `status.state` is `running`; otherwise `False` with reason such as `PCSMNotRunning`. | +| `Finalized` | `True` once `status.state` is `finalized`. Remains set afterwards. | + +### Example status + +```yaml +status: + mode: running + state: running + lagTimeSeconds: 72 + startedAt: "2026-07-01T12:00:00Z" + conditions: + - type: Running + status: "True" + reason: PCSMReplicating + message: PCSM is applying changes from source +``` + +On failure: + +```yaml +status: + mode: running + state: failed + error: "clone: copy: mydb.mycoll: connection refused" + conditions: + - type: Running + status: "False" + reason: PCSMNotRunning +``` diff --git a/docs/debug.md b/docs/debug.md index 883f0e4b..fdd595f0 100644 --- a/docs/debug.md +++ b/docs/debug.md @@ -6,6 +6,8 @@ Percona Operator for MongoDB uses [Custom Resources :octicons-link-external-16: * `PerconaServerMongoDBBackup` and `PerconaServerMongoDBRestore` Custom Resources contain options for Percona Backup for MongoDB used to backup Percona Server for MongoDB and to restore it from backups (`psmdb-backup` and `psmdb-restore` shortnames are available for them). +* `PerconaServerMongoDBClusterSync` Custom Resource contains options for Percona ClusterSync for MongoDB (`psmdb-clustersync` shortname). + The first thing you can check for the Custom Resource is to query it with `kubectl get` command: @@ -33,9 +35,10 @@ The Custom Resource should have `Ready` status. ??? example "Expected output" ``` {.text .no-copy} - perconaservermongodbbackups psmdb-backup psmdb.percona.com/v1 true PerconaServerMongoDBBackup - perconaservermongodbrestores psmdb-restore psmdb.percona.com/v1 true PerconaServerMongoDBRestore - perconaservermongodbs psmdb psmdb.percona.com/v1 true PerconaServerMongoDB + perconaservermongodbbackups psmdb-backup psmdb.percona.com/v1 true PerconaServerMongoDBBackup + perconaservermongodbclustersyncs psmdb-clustersync psmdb.percona.com/v1 true PerconaServerMongoDBClusterSync + perconaservermongodbrestores psmdb-restore psmdb.percona.com/v1 true PerconaServerMongoDBRestore + perconaservermongodbs psmdb psmdb.percona.com/v1 true PerconaServerMongoDB ``` ## Check the Pods diff --git a/docs/operator.md b/docs/operator.md index 784dc77d..9d7e3439 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -7,6 +7,7 @@ There are the following Custom Resources: * `PerconaServerMongoDB` contains options to configure Percona Server for MongoDB. * `PerconaServerMongoDBBackup` contains options for PBM to make backups. * `PerconaServerMongoDBRestore` contains options to restore Percona Server for MongoDB from backups. +* `PerconaServerMongoDBClusterSync` contains options to deploy and manage Percona ClusterSync for MongoDB (PCSM). See [ClusterSync Resource options](clustersync-options.md). ## PerconaServerMongoDB Custom Resource options diff --git a/mkdocs-base.yml b/mkdocs-base.yml index c7927622..86a881a9 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -307,6 +307,9 @@ nav: - "Fail over workload to the Replica site": replication-failover.md - "Backups with cross-site replication": replication-backups.md - "Splitting replica set across multiple data centers": replication-multi-dc.md + - Real-time replication with Percona ClusterSync for MongoDB: + - "About PCSM integration": clustersync.md + - "Set up and use PCSM": clustersync-setup.md - "Monitor with Percona Monitoring and Management (PMM)": monitoring.md - "Add sidecar containers": sidecar.md @@ -329,20 +332,25 @@ nav: - "Install Percona Server for MongoDB in multi-namespace (cluster-wide) mode": cluster-wide.md - "Configure concurrent reconciliation": reconciliation-concurrency.md - "Monitor Kubernetes": monitor-kubernetes.md - - "Retrieve Percona certified images": image-query.md - "Delete the Operator": delete.md - Reference: - - "Custom Resource options": operator.md - - backup-resource-options.md - - restore-options.md + - Custom Resource reference: + - "PerconaServerMongoDB options": operator.md + - "Backup options": backup-resource-options.md + - "Restore options": restore-options.md + - "ClusterSync options": clustersync-options.md - "Custom resource statuses": cr-statuses.md - - "Percona certified images": images.md + - Certified images: + - "Percona certified images": images.md + - "Retrieve Percona certified images": image-query.md - "Versions compatibility": versions.md - "Operator API": api.md - "Frequently asked questions": faq.md - - "Copyright and licensing information": copyright.md - - "Trademark policy": trademark-policy.md + - Legal: + - "Copyright and licensing information": copyright.md + - "Trademark policy": trademark-policy.md + - Release notes: - "Release notes index": RN/index.md From 3b6d4f5d25789bcf1fd7e436290c0fcbc7481415 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 20:06:51 +0300 Subject: [PATCH 20/22] K8SPSMDB-1634 Removed Red Hat Marketplace from docs (#368) --- docs/update-crd-olm.md | 89 ++++++++++++++++++++++++++++++++++++++-- docs/update_openshift.md | 82 +++++++++++------------------------- 2 files changed, 110 insertions(+), 61 deletions(-) diff --git a/docs/update-crd-olm.md b/docs/update-crd-olm.md index adffd37a..cd4755d5 100644 --- a/docs/update-crd-olm.md +++ b/docs/update-crd-olm.md @@ -1,9 +1,92 @@ -# Upgrade the Operator and CRD via Operator Lifecycle Manager (OLM) +# Upgrade the Operator and CRD on OpenShift via Operator Lifecycle Manager (OLM) If you have [installed the Operator on the OpenShift platform using OLM](openshift.md#install-the-operator-via-the-operator-lifecycle-manager-olm), you can upgrade the Operator within it. -1. List installed Operators for your Namespace to see if there are upgradable items. +If you know the OLM upgrade workflow, jump to the [update Deployment steps](#upgrade-the-operator). + +### Understand how OLM applies Operator upgrades + +OLM manages the Operator using a resource called a `ClusterServiceVersion` (CSV). +Each CSV represents a specific version of the Operator and contains: + +* the Operator Deployment specification +* required RBAC permissions +* CRD definitions +* metadata and examples + +When a new Operator version is available and the upgrade is approved, OLM installs the new CSV and reconciles the Operator Deployment to match it. +The following items are replaced with the values defined in the new CSV: + +* container image +* command and arguments +* labels and annotations +* probes +* most Deployment fields + +If you previously customized the Operator Deployment manually, these changes are overwritten during the upgrade. + +The CRD may be updated too, if the new Operator version introduces schema changes. +However, OLM doesn't modify the `PerconaServerMongoDB` Custom Resource. It remains unchanged and continues running with its current configuration. For how to update it, refer to [Update Percona Server for MongoDB](update_openshift.md). + +#### Persisting custom Operator configuration + +If you need to customize the Operator Deployment (for example, to adjust resource limits or set environment variables), you can do it through the Subscription. + +A Subscription is the OLM resource that defines which operator you want to install and how you want it to be upgraded. A Subscription connects your cluster to an Operator package in a CatalogSource and ensures that OLM continuously manages that Operator according to your chosen update strategy. + +Here's how you can customize the Operator Deployment. This example command sets an environment variable for the Operator: + +```bash +kubectl patch subscription percona-server-mongodb-operator -n \ + --type merge \ + -p '{"spec":{"config":{"env":[{"name":"LOG_LEVEL","value":"DEBUG"}]}}}' +``` + +OLM supports overriding only the following fields through the Subscription: + +* env +* envFrom +* volumes +* volumeMounts +* resources +* nodeSelector +* tolerations +* affinity + +These overrides are applied on top of the CSV and persist across upgrades. All other fields are overridden by the values from the new CSV during the Operator Deployment upgrade. + +## Upgrade the Operator via OLM + +1. Find the initial Operator installation image with `kubectl get deploy` command: + + ```bash + kubectl get deploy percona-server-mongodb-operator -o yaml + ``` + + ??? example "Expected output" + + ``` {.text .no-copy} + ... + "containerImage": "registry.connect.redhat.com/percona/percona-server-mongodb-operator@sha256:201092cf97c9ceaaaf3b60dd1b24c7c5228d35aab2674345893f4cd4d9bb0e2e", + ... + ``` + +2. [Apply a patch :octicons-link-external-16:](https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/) to update the `initImage` option of your cluster Custom Resource with this value taken from `containerImage`. Supposing that your cluster name is `my-cluster-name`, the command should look as follows: + + ```bash + kubectl patch psmdb my-cluster-name --type=merge --patch '{ + "spec": { + "initImage":"registry.connect.redhat.com/percona/percona-server-mongodb-operator@sha256:201092cf97c9ceaaaf3b60dd1b24c7c5228d35aab2674345893f4cd4d9bb0e2e" + }}' + ``` + +3. Login to your OLM installation and list installed Operators for your Namespace to see if there are upgradable items: ![image](assets/images/olm4.svg) -2. Click the "Upgrade available" link to see upgrade details, then click "Preview InstallPlan" button, and finally "Approve" to upgrade the Operator. + +4. Click the "Upgrade available" link to see upgrade details, then click "Preview InstallPlan" button, and finally "Approve" to upgrade the Operator. + +## Next steps + +[Upgrade the database](update_openshift.md){.md-button} \ No newline at end of file diff --git a/docs/update_openshift.md b/docs/update_openshift.md index 3e5bf0f2..bae7deab 100644 --- a/docs/update_openshift.md +++ b/docs/update_openshift.md @@ -1,50 +1,16 @@ -# Upgrade Database and Operator on OpenShift +# Upgrade Percona Server for MongoDB on OpenShift {%set commandName = 'oc' %} -Upgrading database and Operator on [Red Hat Marketplace :octicons-link-external-16:](https://marketplace.redhat.com) or to upgrade Red Hat certified Operators on [OpenShift :octicons-link-external-16:](https://www.redhat.com/en/technologies/cloud-computing/openshift) generally follows the [standard upgrade scenario](update.md), but includes a number of special steps specific for these platforms. - -## Upgrading the Operator and CRD - -1. First of all you need to manually update `initImage` Custom Resource option with the value of an alternative initial Operator installation image. You need doing this for all database clusters managed by the Operator. Without this step the cluster will go into error state after the Operator upgrade. - - 1. Find the initial Operator installation image with `kubectl get deploy` command: - - ```bash - kubectl get deploy percona-server-mongodb-operator -o yaml - ``` - - ??? example "Expected output" - - ``` {.text .no-copy} - ... - "containerImage": "registry.connect.redhat.com/percona/percona-server-mongodb-operator@sha256:201092cf97c9ceaaaf3b60dd1b24c7c5228d35aab2674345893f4cd4d9bb0e2e", - ... - ``` - - 2. [Apply a patch :octicons-link-external-16:](https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/) to update the `initImage` option of your cluster Custom Resource with this value taken from `containerImage`. Supposing that your cluster name is `my-cluster-name`, the command should look as follows: - - ```bash - kubectl patch psmdb my-cluster-name --type=merge --patch '{ - "spec": { - "initImage":"registry.connect.redhat.com/percona/percona-server-mongodb-operator@sha256:201092cf97c9ceaaaf3b60dd1b24c7c5228d35aab2674345893f4cd4d9bb0e2e" - }}' - ``` - -2. Now you can actually update the Operator via the [Operator Lifecycle Manager (OLM) :octicons-link-external-16:](https://docs.redhat.com/en/documentation/openshift_container_platform/4.2/html/operators/understanding-the-operator-lifecycle-manager-olm#olm-overview_olm-understanding-olm) web interface. - - Login to your OLM installation and list installed Operators for your Namespace to see if there are upgradable items: - - ![image](assets/images/olm4.svg) - - Click the "Upgrade available" link to see upgrade details, then click "Preview InstallPlan" button, and finally "Approve" to upgrade the Operator. +--8<-- "update-assumptions.md" ## Upgrading Percona Server for MongoDB -1. Make sure that `spec.updateStrategy` option in the [Custom Resource](operator.md) - is set to `SmartUpdate`, `spec.upgradeOptions.apply` option is set to `Never` - or `Disabled` (this means that the Operator will not carry on upgrades - automatically). +1. Check the version of the Operator you have in your Kubernetes environment. If you need to update it, refer to [the Operator upgrade guide](update-crd-olm.md). +2. Check the [Custom Resource](operator.md) manifest configuration to be the following: + + * `spec.updateStrategy` option is set to `SmartUpdate` + * `spec.upgradeOptions.apply` option is set to `Disabled` or `Never`. ```yaml ... @@ -55,7 +21,7 @@ Upgrading database and Operator on [Red Hat Marketplace :octicons-link-external- ... ``` -2. Find the **new** initial Operator installation image name (it had changed during the Operator upgrade) and other image names for the components of your cluster with the `kubectl get deploy` command: +3. Find the **new** initial Operator installation image name (it had changed during the Operator upgrade) and other image names for the components of your cluster with the `kubectl get deploy` command: ```bash kubectl get deploy percona-server-mongodb-operator -o yaml @@ -79,23 +45,23 @@ Upgrading database and Operator on [Red Hat Marketplace :octicons-link-external- ... ``` -3. [Apply a patch :octicons-link-external-16:](https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/) to set the necessary `crVersion` value (equal to the Operator version) and update images in your cluster Custom Resource. Supposing that your cluster name is `cluster1`, the command should look as follows: - - - ```bash - kubectl patch psmdb my-cluster-name --type=merge --patch '{ - "spec": { - "crVersion":"{{ release }}", - "image": "registry.connect.redhat.com/percona/percona-server-mongodb-operator-containers@sha256:5d29132a60b89e660ab738d463bcc0707a17be73dc955aa8da9e50bed4d9ad3e", - "initImage": "registry.connect.redhat.com/percona/percona-server-mongodb-operator@sha256:8adc57e9445cfcea1ae02798a8f9d6a4958ac89f0620b9c6fa6cf969545dd23f", - "pmm": {"image": "registry.connect.redhat.com/percona/percona-server-mongodb-operator-containers@sha256:165f97cdae2b6def546b0df7f50d88d83c150578bdb9c992953ed866615016f1"}, - "backup": {"image": "registry.connect.redhat.com/percona/percona-server-mongodb-operator-containers@sha256:a73889d61e996bc4fbc6b256a1284b60232565e128a64e4f94b2c424966772eb"} - }}' - ``` +4. We recommend to [update the PMM Server :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/3/pmm-upgrade/index.html) **before** the upgrade of PMM Client. If you haven’t done it yet, exclude PMM Client from the list of images to update. +5. [Apply a patch :octicons-link-external-16:](https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/) to set the necessary `crVersion` value (equal to the Operator version) and update images in your cluster Custom Resource. Supposing that your cluster name is `cluster1`, the command should look as follows: + + === "With PMM Client" - !!! warning + ```bash + kubectl patch psmdb my-cluster-name --type=merge --patch '{ + "spec": { + "crVersion":"{{ release }}", + "image": "registry.connect.redhat.com/percona/percona-server-mongodb-operator-containers@sha256:5d29132a60b89e660ab738d463bcc0707a17be73dc955aa8da9e50bed4d9ad3e", + "initImage": "registry.connect.redhat.com/percona/percona-server-mongodb-operator@sha256:8adc57e9445cfcea1ae02798a8f9d6a4958ac89f0620b9c6fa6cf969545dd23f", + "pmm": {"image": "registry.connect.redhat.com/percona/percona-server-mongodb-operator-containers@sha256:165f97cdae2b6def546b0df7f50d88d83c150578bdb9c992953ed866615016f1"}, + "backup": {"image": "registry.connect.redhat.com/percona/percona-server-mongodb-operator-containers@sha256:a73889d61e996bc4fbc6b256a1284b60232565e128a64e4f94b2c424966772eb"} + }}' + ``` - The above command upgrades various components of the cluster including PMM Client. If you didn't follow the [official recommendation :octicons-link-external-16:](https://docs.percona.com/percona-monitoring-and-management/2/how-to/upgrade.html) to upgrade PMM Server before upgrading PMM Client, you can avoid PMM Client upgrade by removing it from the list of images as follows: + === "Without PMM Client" ```bash kubectl patch psmdb my-cluster-name --type=merge --patch '{ @@ -107,5 +73,5 @@ Upgrading database and Operator on [Red Hat Marketplace :octicons-link-external- }}' ``` -4. The deployment rollout will be automatically triggered by the applied patch. +6. The deployment rollout will be automatically triggered by the applied patch. From c94881d2a02ae23b8b35b1febfc96321b3840096 Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 20:14:20 +0300 Subject: [PATCH 21/22] K8SPSMDB-1654 Documented support for vector search (#361) * K8SPSMDB-1654 Documented support for vector search new file: docs/assets/images/vector-search-arch.svg modified: docs/cr-statuses.md modified: docs/operator.md new file: docs/vector-search-setup.md new file: docs/vector-search.md modified: mkdocs-base.yml --- docs/assets/images/vector-search-arch-2.svg | 4 + docs/assets/images/vector-search-arch.svg | 4 + docs/cr-statuses.md | 31 +- docs/operator.md | 405 ++++++++++++++++++++ docs/search-overview.md | 228 +++++++++++ docs/search-setup.md | 288 ++++++++++++++ mkdocs-base.yml | 5 +- variables.yml | 1 + 8 files changed, 964 insertions(+), 2 deletions(-) create mode 100644 docs/assets/images/vector-search-arch-2.svg create mode 100644 docs/assets/images/vector-search-arch.svg create mode 100644 docs/search-overview.md create mode 100644 docs/search-setup.md diff --git a/docs/assets/images/vector-search-arch-2.svg b/docs/assets/images/vector-search-arch-2.svg new file mode 100644 index 00000000..3431762b --- /dev/null +++ b/docs/assets/images/vector-search-arch-2.svg @@ -0,0 +1,4 @@ + + + +
Operator
Percona Server for MongoDB
Percona Search for MongoDB
PVC
PVC
\ No newline at end of file diff --git a/docs/assets/images/vector-search-arch.svg b/docs/assets/images/vector-search-arch.svg new file mode 100644 index 00000000..31df2179 --- /dev/null +++ b/docs/assets/images/vector-search-arch.svg @@ -0,0 +1,4 @@ + + + +
Operator
Replica set
Replica set - search
PVC
PVC
\ No newline at end of file diff --git a/docs/cr-statuses.md b/docs/cr-statuses.md index 99ed5740..602c00df 100644 --- a/docs/cr-statuses.md +++ b/docs/cr-statuses.md @@ -88,7 +88,7 @@ kubectl get psmdb -n \ ## PerconaServerMongoDB status -The main cluster state is recorded in the `status.state` section. For component-level states, see the `status.replsets` and `status.mongos` sections. +The main cluster state is recorded in the `status.state` section. For component-level states, see the `status.replsets`, `status.mongos`, and `status.search` sections. Common fields: @@ -96,6 +96,7 @@ Common fields: - `status.ready` / `status.size` – number of ready pods and the size of the database cluster - `status.host` – connection endpoint - `status.conditions` – detailed condition list with reason and message +- `status.search` – vector search (`mongot`) readiness per replica set or shard. Available when search is enabled. ### Cluster state values @@ -110,6 +111,34 @@ Common fields: | `ready` | The cluster is up and healthy. | | `error` | The Operator detected an error; check conditions and events. | +When [vector search is enabled](operator.md#searchenabled), the cluster is not marked `ready` until every entry in `status.search` is also `ready`. + +### Vector search status + +!!! note "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +If [`spec.search.enabled`](operator.md#searchenabled) is set to `true`, the Operator shows the search status in the `status.search` field. This field lists the status of each replica set or shard in the sharded cluster, except for the config server replica set. If search is turned off, `status.search` is cleared. + +Common fields under `status.search.`: + +- `size` – desired number of `mongot` pods for that replica set or shard +- `ready` – number of ready `mongot` pods +- `status` – search state. The states are: `initializing`, `ready`, `paused`, `stopping`, `error` +- `message` – optional human-readable details + +**Example. View vector search status:** + +```bash +kubectl get psmdb -n \ + -o jsonpath='{.status.search}' && echo +``` + +??? example "Sample output" + + ```{.json .no-copy} + {"rs0":{"size":1,"ready":1,"status":"ready"}} + ``` + ### Conditions Conditions show more detail about cluster state changes. You can see them in `status.conditions[]`. diff --git a/docs/operator.md b/docs/operator.md index 9d7e3439..68787351 100644 --- a/docs/operator.md +++ b/docs/operator.md @@ -1931,6 +1931,170 @@ Hostnames for [Kubernetes host aliases :octicons-link-external-16:](https://kub | ----------- | ---------- | | :material-text-long: subdoc | | +### `replsets.search.size` + +Per-replica-set override for the number of `mongot` pods for this replica set +or shard. Fully replaces [`search.size`](#searchsize) for this replica set. +The value must be `1`. Has no effect unless +[`search.enabled`](#searchenabled) is `true`. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `1` | + +### `replsets.search.storage.persistentVolumeClaim.resources.requests.storage` + +Per-replica-set override for the `mongot` PVC size. Fully replaces the +cluster-wide [`search.storage`](#searchstoragepersistentvolumeclaimresourcesrequestsstorage) +value for this replica set or shard. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `20Gi` | + +### `replsets.search.resources.requests.cpu` + +Per-replica-set override for `mongot` CPU requests. Fully replaces the +cluster-wide [`search.resources`](#searchresourcesrequestscpu) value for this +replica set or shard. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `"2"` | + +### `replsets.search.resources.requests.memory` + +Per-replica-set override for `mongot` memory requests. Fully replaces the +cluster-wide value for this replica set or shard. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `2Gi` | + +### `replsets.search.resources.limits.cpu` + +Per-replica-set override for `mongot` CPU limits. Fully replaces the +cluster-wide value for this replica set or shard. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `"2"` | + +### `replsets.search.resources.limits.memory` + +Per-replica-set override for `mongot` memory limits. Fully replaces the +cluster-wide value for this replica set or shard. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `2Gi` | + +### `replsets.search.jvmFlags` + +Per-replica-set override for `mongot` JVM flags. Fully replaces the +cluster-wide [`search.jvmFlags`](#searchjvmflags) value for this replica set +or shard. + +| Value type | Example | +| ----------- | ---------- | +| :material-application-array-outline: array | `["-Xmx1g", "-Xms1g"]` | + +### `replsets.search.affinity.antiAffinityTopologyKey` + +Per-replica-set override for the `mongot` +[topologyKey :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity-beta-feature). +Fully replaces the cluster-wide affinity for this replica set or shard. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `kubernetes.io/hostname` | + +### `replsets.search.affinity.advanced` + +Per-replica-set override that allows advanced Kubernetes affinity constraints +for this replica set's `mongot` Pods. Fully replaces the cluster-wide affinity. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | | + +### `replsets.search.nodeSelector` + +Per-replica-set override for the `mongot` node selector. Fully replaces the cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-label-outline: label | `disktype: ssd` | + +### `replsets.search.tolerations.key` + +Per-replica-set override for `mongot` Pod tolerations. Setting tolerations here +replaces the full cluster-wide tolerations list for this replica set or shard. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `node.alpha.kubernetes.io/unreachable` | + +### `replsets.search.tolerations.operator` + +The tolerations operator for this replica set’s `mongot` Pods. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `Exists` | + +### `replsets.search.tolerations.effect` + +The tolerations effect for this replica set’s `mongot` Pods. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `NoExecute` | + +### `replsets.search.tolerations.tolerationSeconds` + +The toleration seconds for this replica set’s `mongot` Pods. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `6000` | + +### `replsets.search.annotations` + +Per-replica-set override for `mongot` Pod annotations. Fully replaces the +cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-label-outline: label | | + +### `replsets.search.labels` + +Per-replica-set override for `mongot` Pod labels. Fully replaces the +cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-label-outline: label | | + +### `replsets.search.containerSecurityContext` + +Per-replica-set override for the `mongot` container security context. Fully +replaces the cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `{}` | + +### `replsets.search.podSecurityContext` + +Per-replica-set override for the `mongot` Pod security context. Fully replaces +the cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `{}` | + ## PMM Section The `pmm` section in the deploy/cr.yaml file contains configuration @@ -2119,6 +2283,247 @@ Number of consecutive unsuccessful tries of the readiness probe to be undertaken | ----------- | ---------- | | :material-numeric-1-box: int | `5` | +## Search section + +The `search` section in the `deploy/cr.yaml` file contains configuration +options for [Search](search-overview.md) process called `mongot`. + +### `search.enabled` + +Enables or disables vector search for the cluster. +Default: `false`. + +| Value type | Example | +| ----------- | ---------- | +| :material-toggle-switch-outline: boolean | `true` | + +### `search.image` + +`mongot` Docker image to use. **Required** when `search.enabled` is `true`. +The same image applies to every `mongot` pod in the cluster. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `percona/percona-server-mongodb-mongot:1.70.1-1` | + +### `search.imagePullPolicy` + +The image pull policy for the `mongot` image. Applies to every `mongot` pod in +the cluster. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `Always` | + +### `search.configuration` + +Raw `mongot` YAML merged on top of the Operator-generated `mongot.conf`. Only +the fields you set are overridden; other generated defaults are preserved. +Applies to every `mongot` pod in the cluster. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc |
 server: 
grpc:
tls:
mode: Disabled
| + +### `search.size` + +Number of `mongot` pods per replica set or shard. Default: `1`. Per-replica-set overrides are accepted for forward +compatibility, but every effective value must equal `1`. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `1` | + +### `search.storage.persistentVolumeClaim.resources.requests.storage` + +The [Kubernetes Persistent Volume :octicons-link-external-16:](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) +size for `mongot` index data. Each `mongot` pod needs its own PVC, separate from the database storage. Refer to [Requirements](search-overview.md#availability-and-requirements) for guidance on estimating storage size search indexes based on your data set size. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `10Gi` | + +### `search.resources.requests.cpu` + +The [Kubernetes CPU requests :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) +for the `mongot` container. Per-replica-set override is allowed. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `"2"` | + +### `search.resources.requests.memory` + +The [Kubernetes Memory requests :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) +for the `mongot` container. Per-replica-set override is allowed. Default is 2Gi. + +If you do not +set `-Xmx` / `-Xms` in [`search.jvmFlags`](#searchjvmflags), the Operator sets the JVM heap to +50% of the effective memory request or limit. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `2Gi` | + +### `search.resources.limits.cpu` + +[Kubernetes CPU limit :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) +for the `mongot` container. Per-replica-set override is allowed. Default is 2 CPU. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `"2"` | + +### `search.resources.limits.memory` + +[Kubernetes Memory limit :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container) +for the `mongot` container. Per-replica-set override is allowed. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `2Gi` | + +### `search.jvmFlags` + +Extra JVM flags for `mongot`. If you do not set `-Xmx` or `-Xms`, the Operator +sets both to half of the effective `resources` memory. Per-replica-set override +is allowed. + +| Value type | Example | +| ----------- | ---------- | +| :material-application-array-outline: array |
"-XX:+UseG1GC"
"-XX:MaxGCPauseMillis=200"
| + +### `search.affinity.antiAffinityTopologyKey` + +The [Kubernetes topologyKey :octicons-link-external-16:](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity-beta-feature) +node affinity constraint for `mongot` Pods. Per-replica-set override replaces +the cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-code-string: string | `kubernetes.io/hostname` | + +### `search.affinity.advanced` + +In cases where the pods require complex tuning, the advanced option turns off the topologyKey effect. This setting allows using the standard Kubernetes affinity constraints of any complexity. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | | + + +### `search.annotations` + +[Kubernetes annotations :octicons-link-external-16:](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) +for `mongot` Pods. Per-replica-set override replaces the cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-label-outline: label | | + +### `search.labels` + +[Kubernetes labels :octicons-link-external-16:](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) +for `mongot` Pods. Per-replica-set override replaces the cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-label-outline: label | | + +### `search.containerSecurityContext` + +A custom [Kubernetes Security Context for a Container :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +for `mongot`. If omitted, the Operator sets a default non-root context +(`runAsUser` / `runAsGroup` `1001` on Kubernetes). Per-replica-set override +replaces the cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `{}` | + +### `search.podSecurityContext` + +A custom [Kubernetes Security Context :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +for `mongot` Pod. If omitted, the Operator sets a default context (`runAsUser` / +`runAsGroup` / `fsGroup` `1001` on Kubernetes). Per-replica-set override +replaces the cluster-wide value. + +| Value type | Example | +| ----------- | ---------- | +| :material-text-long: subdoc | `{}` | + +### `search.livenessProbe.failureThreshold` + +Number of consecutive unsuccessful tries of the +[liveness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) +before giving up. Applies to every `mongot` pod. When no probe handler is set, +the Operator keeps the default HTTP GET against `/health` on port `8080`. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `4` | + +### `search.livenessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the +liveness probe. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `60` | + +### `search.livenessProbe.periodSeconds` + +How often to perform a liveness probe (in seconds). + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `30` | + +### `search.livenessProbe.timeoutSeconds` + +Number of seconds after which the liveness probe times out. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `5` | + +### `search.readinessProbe.failureThreshold` + +Number of consecutive unsuccessful tries of the +[readiness probe :octicons-link-external-16:](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes) +before marking the container not ready. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `3` | + +### `search.readinessProbe.initialDelaySeconds` + +Number of seconds to wait after the container start before initiating the +readiness probe. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `10` | + +### `search.readinessProbe.periodSeconds` + +How often to perform a readiness probe (in seconds). + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `10` | + +### `search.readinessProbe.timeoutSeconds` + +Number of seconds after which the readiness probe times out. + +| Value type | Example | +| ----------- | ---------- | +| :material-numeric-1-box: int | `2` | + + ## Sharding Section The `sharding` section in the deploy/cr.yaml file contains configuration diff --git a/docs/search-overview.md b/docs/search-overview.md new file mode 100644 index 00000000..a7a3b1e0 --- /dev/null +++ b/docs/search-overview.md @@ -0,0 +1,228 @@ +# About search and vector search + +!!! admonition "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +!!! warning "Tech preview" + + Search capabilities feature is in the tech preview stage. We don't recommend using it in + production yet, but we encourage you to try it in a staging or testing + environment and share your feedback. Your feedback helps us shape the + feature in future releases. + +Percona Search for MongoDB is a search engine that enables you to run [vector search :octicons-link-external-16:](https://www.mongodb.com/docs/vector-search/) and [full-text search :octicons-link-external-16:](https://www.mongodb.com/docs/search/) queries in Percona Server for MongoDB managed by the Operator. + +* **Full-text search** finds documents by matching keywords and phrases in the text. +* **Vector search** finds documents by meaning. It compares numerical representations (embeddings) of content, such as text or images so that results can be relevant even when they don’t share the same words. + +You get the same capability that MongoDB Atlas customers and self-managed upstream users already have. The Operator automates the deployment and lifecycle of search, providing the same experience it offers for Percona Server for MongoDB clusters. + +## What you can achieve with Percona Search for MongoDB + +Typical use cases include: + +* **Semantic search** — find documents that are close in meaning to a query, + even when they don't share the same keywords +* **Hybrid search** — combine vector search with full-text search for richer + ranking +* **Generative AI / RAG** — retrieve the most relevant context for large + language models and AI agents from data already stored in MongoDB + +[Configure vector search](search-setup.md){.md-button} + +## Architecture and components + +Full-text and vector search are provided by a separate tool called Percona Search for MongoDB. +You manage Percona Search for MongoDB declaratively through the cluster Custom +Resource. + +When you enable full-text and vector search, the Operator deploys Percona Search for MongoDB as a dedicated +StatefulSet — one per data-bearing replica set or shard. + +The StatefulSet is +named `--search` and has its own PVC and headless Service. + +![image](assets/images/vector-search-arch-2.svg) + + +Existing deployments continue to work as before after you upgrade the +Operator: if you haven't enabled search for the cluster, the Operator does not deploy +search components. + +## How the Percona Server for MongoDB (`mongod`) and Percona Search for MongoDB (`mongot`) communicate + +Percona Search for MongoDB runs as a separate `mongot` process. Your applications and users never connect to it +directly. They still connect to Percona Server for MongoDB (to `mongod` or to `mongos` in a sharded +cluster). The database acts as a proxy: it forwards search commands to +Percona Search for MongoDB (`mongot`), then returns the results to the client. + +When a client runs `$search`, `$vectorSearch`, or `$searchMeta`, this is what +happens: + +1. `mongod` forwards the query to `mongot` over [gRPC](https://grpc.io/). +2. `mongot` searches its indexes and returns matching document IDs and scores. It can use ANN (Approximate Nearest Neighbor) for faster approximate +results, or ENN (Exact Nearest Neighbor) for exact matches. +3. `mongod` loads the matching documents and sends them back to the client. + +Each `mongot` serves one replica set (or one shard) and keeps search indexes +on its own persistent volume, separate from database data. Those indexes are +Lucene-style structures built for search workloads. Index *definitions* (what +to index) live in Percona Server for MongoDB while the index *data* lives on +Percona Search for MongoDB volume. + +To stay in sync with the database, Percona Search for MongoDB opens a long-lived change-stream +connection to a `mongod` in the same replica set — usually a secondary — and +reads data changes as they happen. + +So the connection works both ways: + +* **`mongot` → `mongod`** — reads source data to build and refresh indexes +* **`mongod` → `mongot`** — forwards client search queries and index-management + commands + +### Replica set workflow + +From the client's perspective, a search query looks like any other +aggregation against `mongod`: + +```mermaid +flowchart LR + A[Client] --> B[mongod] + B -- gRPC --> C[mongot] + C --> D[mongod] + D -- loads matching documents --> A +``` + +1. The client sends a `$vectorSearch` (or `$search` / `$searchMeta`) aggregation + to `mongod`. +2. `mongod` forwards the request to its bound `mongot` over gRPC. +3. `mongot` runs the search against its local indexes and returns matching + document identifiers and scores. +4. `mongod` loads the corresponding documents and returns the result set to the + client. + +### Sharded cluster workflow + +In a sharded cluster, the Operator deploys one `mongot` StatefulSet per shard. +`mongos` is the client entry point and coordinates cross-shard search queries. +It scatter-gathers the search across shards and merges results by +`$searchScore`: + +```mermaid +flowchart TD + A[client] --> B[mongos] + B --> C0[shard0.mongod] + C0 -- gRPC --> D0[shard0.mongot] + D0 --> E0[shard0.mongod] + E0 --> B + + B --> C1[shard1.mongod] + C1 -- gRPC --> D1[shard1.mongot] + D1 --> E1[shard1.mongod] + E1 --> B + + B --> CN[shardN.mongod] + CN -- gRPC --> DN[shardN.mongot] + DN --> EN[shardN.mongod] + EN --> B + + B -- merge by $searchScore --> A +``` + +Each shard's `mongod` members point at that shard's `mongot`. For index +management, `mongos` is configured with the `mongot` endpoint of the first +shard (`shard0`). + +## Authentication + +When you enable search, the Operator creates a dedicated MongoDB system user with the built-in +`searchCoordinator` role. Credentials are +stored in the cluster users Secret under `MONGODB_SEARCH_USER` and +`MONGODB_SEARCH_PASSWORD`. + +Percona Search for MongoDB uses this user to authenticate to `mongod` (and to `mongos` in sharded +clusters) over the cluster's existing internal authentication method. The +Operator does not require a separate auth mechanism for search. + +When cluster TLS is enabled (the Operator default), Percona Search for MongoDB reuses the +cluster's internal TLS material. The Operator extends the TLS certificate SANs so they cover the `--search` Service names. + +Don't use the `searchCoordinator` system user from your applications. Create +application users with the privileges your workloads need, the same as for any +other MongoDB feature. + +## Backups and restores + +Percona Backup for MongoDB (PBM) does **not** back up Percona Search for MongoDB PVCs. Search +indexes are derivable from `mongod` data through change streams, so only +database data is included in backups. + +After a PBM restores `mongod` data, the Operator restarts Percona Search for MongoDB pods. Each new Percona Search for MongoDB Pod performs a full initial sync from the restored `mongod` and + rebuilds its indexes. + +Restore completion does **not** wait for Percona Search for MongoDB to become ready. Database +availability returns when the restore finishes; search availability is eventual +and depends on how long index rebuild takes for your dataset. + +## Observability and metrics + +You can scrape metrics from the headless search Service +(`--search`) on port `9946`. Dedicated PMM dashboards for `mongot` +are not included in this tech preview; use the metrics endpoint with your +existing Prometheus-compatible stack, and watch `status.search` on the cluster +Custom Resource for readiness. + +## Availability and requirements + +To use full-text and vector search with the Operator, you must meet the following +requirements: + +1. **Percona Server for MongoDB 8.3 or later.** Percona Search for MongoDB is available only + starting with MongoDB 8.3. The Operator uses [experimental + images of Percona Server for MongoDB 8.3](https://hub.docker.com/r/perconalab/percona-server-mongodb/tags?name=8.3). You must explicitly specify them in + the Custom Resource to use vector search. +2. **Dedicated persistent storage for each Percona Search for MongoDB pod.** Each Percona Search for MongoDB needs + its own PVC; volumes cannot be shared. Index data is typically about 0.25×–2× + the source data size, with 2× headroom recommended for rebuilds. Percona Search for MongoDB + becomes read-only at about 90% disk usage. The default PVC size of `10Gi` is + enough for small datasets; tune storage for larger workloads. +3. **Resource requirements**. The Operator follows upstream [resource requirements :octicons-link-external-16:](https://www.mongodb.com/docs/vector-search/deployment/deployment-options/#resource-usage) +4. **Kubernetes resources.** Default requests are 2 CPU and 2Gi memory per + Percona Search for MongoDB pod. Size resources for your index and query load. + +## Implementation specifics + +* One Percona Search for MongoDB deployment per data-bearing replica set (or per shard in a + sharded cluster). +* The config server replica set has no Percona Search for MongoDB StatefulSet. +* The Operator injects the required `setParameter` values that point to the search endpoint into `mongod` and + `mongos` configuration. Operator-managed keys override conflicting user values + so the search endpoint does not drift. +* You configure cluster-wide defaults under `spec.search` and can fine-tune + resources, storage, and placement per replica set or shard with + `spec.replsets[].search`. Enable/disable, image, and raw Percona Search for MongoDB + configuration stay cluster-wide. +* You can supply a partial Percona Search for MongoDB YAML under `spec.search.configuration`. The + Operator merges it onto the generated defaults and overrides only the fields + you set. +* Cluster status exposes `status.search` keyed by replica set or shard name + (`size`, `ready`, `status`, `message`). Read more about available statuses in [Custom resource statuses](cr-statuses.md) + + +## Limitations + +* **Single Percona Search for MongoDB pod per replica set or shard.** The search StatefulSet is + limited to `size: 1`. Kubernetes `Service` ClusterIP load balancing is L4-only + and cannot correctly distribute long-lived gRPC streams across multiple + backends. Multi-replica Percona Search for MongoDB HA (which needs an L7 gRPC-aware load + balancer) is postponed to a later release. +* **No automated embedding.** Generating and managing embeddings through an + external embedding API (for example automated / Voyage AI embedding) is not supported. You provide and store vector embeddings yourself. +* **No migration from externally managed `mongot`.** Deployments that already + run `mongot` outside the Operator are not imported. Manage them manually, or + switch to Operator-managed Percona Search for MongoDB. +* **Logical restores on sharded clusters with MongoDB 8.3 can leave the + cluster broken.** This is a known PBM 2.15.0 limitation tracked in + [PBM-1764 :octicons-link-external-16:](https://perconadev.atlassian.net/browse/PBM-1764). +* **Search index data are not included in backups.** Plan for reindex time after + restore when you estimate recovery objectives for the search surface. + diff --git a/docs/search-setup.md b/docs/search-setup.md new file mode 100644 index 00000000..2fbb115b --- /dev/null +++ b/docs/search-setup.md @@ -0,0 +1,288 @@ +# Configure vector search with Percona Search for MongoDB + +!!! admonition "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" + +!!! warning "Tech preview" + + Search capabilities feature is in the tech preview stage. We don't recommend using it in + production yet, but we encourage you to try it in a staging or testing + environment and share your feedback. Your feedback helps us shape the + feature in future releases. + +This guide shows how to enable vector search on a cluster managed by +Percona Operator for MongoDB, insert sample vector data, create a vector search +index, and run a `$vectorSearch` query. + +Vector search is implemented via Percona Search for MongoDB search engine that runs the `mongot` search process. To learn how it works with the Operator and what use cases you can implement, see +[About search and vector search](search-overview.md). + +This setup uses the following software versions: + +* Percona Operator for MongoDB 1.23.0 +* Percona Server for MongoDB 8.3 +* Percona Search for MongoDB {{mongot}}. + + +## Before you start + +1. Make sure you understand [requirements](search-overview.md#availability-and-requirements) and [limitations](search-overview.md#limitations) of using Percona Search for MongoDB. +2. Clone the repository with all manifests and source code: + + ```bash + git clone -b v{{release}} https://github.com/percona/percona-server-mongodb-operator + cd percona-server-mongodb-operator + ``` + +3. Create the namespace and export it as environment variable. Replace the `` placeholder with your value: + + ```bash + kubectl create namespace + export NAMESPACE= + ``` + +## Deploy the Operator + +Install the Operator by applying the `deploy/bundle.yaml` manifest. This also installs CRDs, Role-based access control (RBAC) and the Operator deployment: + +```bash +kubectl apply --server-side -f deploy/bundle.yaml +``` + +As the result you will have the Operator Pod up and running. + +## Install Percona Server for MongoDB and enable Percona Search for MongoDB + +1. Edit the `deploy/cr.yaml` Custom Resource. Specify the following keys: + + * Set the database image to Percona Server for MongoDB 8.3 in `spec.image` + * Set `spec.search.enabled` to `true` + * Specify the Percona Search for MongoDB image in `spec.search.image` + * Keep `size: 1` as only one Percona Search for MongoDB pod is allowed per replica set or shard. + * Configure storage for Percona Search for MongoDB based on your data set. Check [Requirements](search-overview.md#availability-and-requirements) for guidance on estimating storage size. + + Here's the example configuration: + + ```yaml + apiVersion: psmdb.percona.com/v1 + kind: PerconaServerMongoDB + metadata: + name: some-name + finalizers: + - percona.com/delete-psmdb-pvc + spec: + image: perconalab/percona-server-mongodb:8.3 + search: + enabled: true + image: perconalab/percona-search-mongodb:{{mongot}} + size: 1 + storage: + persistentVolumeClaim: + resources: + requests: + storage: 10Gi + resources: + requests: + cpu: "2" + memory: 2Gi + replsets: + - name: rs0 + affinity: + antiAffinityTopologyKey: none + resources: + limits: + cpu: "500m" + memory: 1G + requests: + cpu: "100m" + memory: 100Mi + volumeSpec: + persistentVolumeClaim: + resources: + requests: + storage: 3Gi + #The rest of your configuration + ``` + +2. Apply the Custom Resource to install Percona Server for MongoDB: + + ```bash + kubectl apply -f deploy/cr.yaml -n $NAMESPACE + ``` + +### Verify that Percona Search for MongoDB is ready + +Wait until the Percona Search for MongoDB pod is running. For a cluster named `my-cluster-name` +with replica set `rs0`, the pod is `my-cluster-name-rs0-search-0`: + +```bash +kubectl get pods -n $NAMESPACE | grep search +``` + +??? example "Expected output" + + ```{.text .no-copy} + my-cluster-name-rs0-search-0 1/1 Running 0 2m + ``` + +You can also check search status on the cluster Custom Resource: + +```bash +kubectl get psmdb -n $NAMESPACE -o jsonpath='{.status.search}' && echo +``` + +??? example "Expected output" + + ```{.json .no-copy} + {"rs0":{"ready":1,"size":1,"status":"ready"}} + ``` + +When search is ready, `status.search` shows the replica set or shard entry with +`status: ready`. + +## Connect to the cluster + +Open a MongoDB client session the same way as in +[Connect to Percona Server for MongoDB](connect.md). Use an application user +with `readWrite` and `dbAdmin` (or equivalent) on the database where you will +store vectors — not the Operator's `searchCoordinator` system user. + +The examples below use: + +* Database: `myApp` +* Collection: `vectors` +* User: `myApp` / `myPass` (create this user if it does not exist yet) + +Create the user if needed: + +```{.javascript data-prompt="admin>"} +admin> db.getSiblingDB("admin").createUser({ + user: "myApp", + pwd: "myPass", + roles: [ + { db: "myApp", role: "readWrite" }, + { db: "myApp", role: "dbAdmin" } + ] +}) +``` + +Then authenticate as that user, or reconnect with those credentials. + +## Insert vector data + +Switch to your application database and insert documents that include an +embedding field. Each embedding is an array of numbers. In a real workload you +generate embeddings with an embedding model; here we use small sample vectors +so you can try the feature quickly. + +```{.javascript data-prompt="myApp>"} +myApp> use myApp +myApp> db.vectors.insertMany([ + { name: "apple", embedding: [1.0, 0.0, 0.0] }, + { name: "banana", embedding: [0.8, 0.2, 0.0] }, + { name: "carrot", embedding: [0.6, 0.4, 0.0] }, + { name: "dill", embedding: [0.2, 0.8, 0.0] }, + { name: "egg", embedding: [0.0, 1.0, 0.0] } +]) +``` + +Confirm the documents are there: + +```{.javascript data-prompt="myApp>"} +myApp> db.vectors.find().pretty() +``` + +## Create a vector search index + +Create a `vectorSearch` index on the `embedding` field. The +`numDimensions` value must match the length of your embedding arrays (here, +`3`). The `similarity` metric can be `cosine`, `euclidean`, or `dotProduct` — +use the same metric your embedding model expects. + +```{.javascript data-prompt="myApp>"} +myApp> db.vectors.createSearchIndex( + "vector_search_index", + "vectorSearch", + { + fields: [ + { + type: "vector", + path: "embedding", + numDimensions: 3, + similarity: "cosine" + } + ] + } +) +``` + +Wait until the index is ready to serve queries. An index is queryable when +`queryable` is `true` or `status` is `READY`: + +```{.javascript data-prompt="myApp>"} +myApp> db.vectors.getSearchIndexes("vector_search_index") +``` + +??? example "Sample output when the index is ready" + + ```{.json .no-copy} + [ + { + "id": "...", + "name": "vector_search_index", + "status": "READY", + "queryable": true, + "latestDefinitionVersion": { "version": 0, "createdAt": "2026-07-15T06:57:54.000Z" }, + "latestDefinition": { + "fields": [ + { + "type": "vector", + "path": "embedding", + "numDimensions": 3, + "similarity": "cosine" + } + ] + } + } + ... + ] + ``` + +If the index is still building, wait a short time and run +`getSearchIndexes` again. + +## Run a vector search query + +Use the `$vectorSearch` aggregation stage. The `queryVector` must have the same +number of dimensions as the indexed field. This example finds the three nearest +neighbors to `[1.0, 0.0, 0.0]` (closest to `"apple"`): + +```{.javascript data-prompt="myApp>"} +myApp> db.vectors.aggregate([ + { + $vectorSearch: { + index: "vector_search_index", + path: "embedding", + queryVector: [1.0, 0.0, 0.0], + numCandidates: 5, + limit: 3 + } + } +]) +``` + +??? example "Expected nearest neighbors" + + ```{.json .no-copy} + [ + { _id: ObjectId("..."), name: "apple", embedding: [1.0, 0.0, 0.0] }, + { _id: ObjectId("..."), name: "banana", embedding: [0.8, 0.2, 0.0] }, + { _id: ObjectId("..."), name: "carrot", embedding: [0.6, 0.4, 0.0] } + ] + ``` + +You can add further aggregation stages after `$vectorSearch` (for example +`$project`) to shape the output. + +For more index and query options, see the +[MongoDB Vector Search documentation :octicons-link-external-16:](https://www.mongodb.com/docs/vector-search/). + diff --git a/mkdocs-base.yml b/mkdocs-base.yml index 86a881a9..6fdb307f 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -243,6 +243,7 @@ nav: - "Local storage support": storage.md - "Arbiter and non-voting nodes": arbiter.md - "MongoDB sharding": sharding.md + - "Transport encryption (TLS/SSL)": - About TLS security: TLS.md - Configure TLS using cert-manager: tls-cert-manager.md @@ -315,7 +316,9 @@ nav: - "Add sidecar containers": sidecar.md - "Restart or pause the cluster": pause.md - volume-attributes-class.md - + - Search and Vector search: + - About Percona Search for MongoDB: search-overview.md + - Configure search and vector search: search-setup.md - Troubleshooting: - "Troubleshoot the Operator installation issues": troubleshoot-operator.md - "Initial troubleshooting": debug.md diff --git a/variables.yml b/variables.yml index 43a64097..4999dc4c 100644 --- a/variables.yml +++ b/variables.yml @@ -18,6 +18,7 @@ minikuberecommended: '1.38.0' k8srecommended: '1.35.0' certmanagerrecommended: '1.19.3' pbmrecommended: '2.12.0' +mongot: '1.70.1-1' k8s_monitor_tag: 'v0.1.2' year: '2026' From dbe20c14453193079e99bd7290b0bf70bee29c5c Mon Sep 17 00:00:00 2001 From: Anastasia Alexandrova Date: Thu, 23 Jul 2026 20:58:29 +0300 Subject: [PATCH 22/22] K8SPSMDB-1761 Release notes 1.23.0 (#364) * K8SPSMDB-1761 Release notes 1.23.0 new file: docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md modified: docs/RN/index.md modified: docs/assets/fragments/patch.txt modified: docs/assets/templates/pdf_cover_page.tpl modified: docs/versions.md modified: mkdocs-base.yml modified: variables.yml --- ...ernetes-Operator-for-PSMONGODB-RN1.22.0.md | 2 +- ...ernetes-Operator-for-PSMONGODB-RN1.23.0.md | 479 ++++++++++++++++++ docs/RN/index.md | 1 + docs/assets/fragments/patch.txt | 2 +- docs/assets/templates/pdf_cover_page.tpl | 2 +- docs/search-overview.md | 2 +- docs/search-setup.md | 2 +- docs/update-crd-manual.md | 2 +- docs/versions.md | 60 +-- mkdocs-base.yml | 3 +- variables.yml | 30 +- 11 files changed, 534 insertions(+), 51 deletions(-) create mode 100644 docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md diff --git a/docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md b/docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md index ec2bd629..31288576 100644 --- a/docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md +++ b/docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md @@ -269,7 +269,7 @@ Learn more about the workflow and the setup in our [documentation](../system-use The Operator deprecates the support of Percona Server for MongoDB 6.0 as this major version entered end-of-life stage. You can still run Percona Server for MongoDB 6.0 in the Operator and existing functionality remains compatible. However, we will no longer test new features and improvements against this version. -Percona Server for MongoDB 6.0 will be removed from the Operator in version 1.23.0. +Percona Server for MongoDB 6.0 will be removed from the Operator in version 1.24.0. ### Deprecated support for PMM2 diff --git a/docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md b/docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md new file mode 100644 index 00000000..4e9a0ed6 --- /dev/null +++ b/docs/RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md @@ -0,0 +1,479 @@ +# Percona Operator for MongoDB 1.23.0 ({{date.1_23_0}}) + +[Get started with the Operator :material-arrow-right:](../quickstart.md){.md-button} +[Upgrade :material-arrow-right:](../update.md){.md-button} + +## What's new at a glance + +### Data management + +* [Real-time replication or near zero-downtime migration with Percona ClusterSync for MongoDB](#migrate-and-keep-clusters-in-sync-with-the-operator-managed-percona-clustersync-for-mongodb) +* [Vector search support in the Operator (tech preview)](#run-ai-and-semantic-search-workloads-with-vector-search-available-in-percona-operator-for-mongodb-tech-preview) + +### Storage management + +* [Boost backup and restore performance with PVC snapshot support (tech preview)](#boost-backup-and-restore-performance-with-pvc-snapshot-support-tech-preview) +* [Native support of OCI Object Storage](#native-backups-to-oracle-cloud-infrastructure-object-storage) +* [Alibaba Cloud Object Storage Service (OSS) support](#support-of-alibaba-cloud-oss-for-backups) +* [Workload Identity authentication support for GCS backups](#workload-identity-authentication-support-for-gcs-backups) + +### Backup and restore operations + +* [Improved troubleshooting with the ability to restore a collection under a different name](#restore-a-collection-under-a-different-name) + +### Security improvements + +* [Use your existing cert-manager ClusterIssuer for TLS management](#use-your-existing-cert-manager-clusterissuer-for-mongodb-tls) + +### Developer experience + +* [Operator-generated connection strings in Secrets](#connect-applications-using-operator-generated-connection-string-secrets) + +## Release Highlights + +### Migrate and keep clusters in sync with the Operator-managed Percona ClusterSync for MongoDB + +You can now run [Percona ClusterSync for MongoDB (PCSM) :octicons-link-external-16:](https://docs.percona.com/percona-clustersync-for-mongodb/) through the Operator. PCSM clones existing data from source MongoDB deployment to target one and uses MongoDB change stream events to track the changes on the source and replicate them to the target in real time. + +You could use PCSM with the Operator before but you had to deploy it yourself, wire up connection strings and run `pcsm` commands manually. Now you declare the source, target, and replication mode in a dedicated `PerconaServerMongoDBClusterSync` Custom Resource. The Operator deploys PCSM, connects the clusters, manages the replication lifecycle, and reports lag and status in the same way it manages your Percona Server for MongoDB. + +With Percona ClusterSync for MongoDB available in the Operator you can: + +* Move from MongoDB Atlas or MongoDB Enterprise Edition to the Operator-managed Percona Server for MongoDB with less operational risk +* Keep a continuous replica of production data for non-production or disaster recovery workloads +* Run hybrid-cloud sync between external MongoDB and Kubernetes without a separate PCSM stack to maintain + +See the [documentation](../clustersync.md) for setup and day-2 operations. + +### Run AI and semantic search workloads with vector search available in Percona Operator for MongoDB (tech preview) + +You can now use full-text and vector search with Percona Operator for MongoDB. Full-text search finds documents by matching keywords and phrases in the text. Vector search retrieves results based on meaning rather than exact word matches, so you can store and query vector data alongside traditional data in Percona Server for MongoDB. Use it for AI and retrieval-augmented generation (RAG) workloads, semantic search and similarity queries. As a result, you have the same capability that MongoDB Atlas customers and self-managed upstream users already have. + +Full-text and vector search are provided by a separate tool called Percona Search for MongoDB that runs the `mongot` search process. You manage it declaratively in the Custom Resource. The Operator deploys and manages the `mongot` alongside your cluster, wires authentication and TLS, and keeps search in sync with your data for both replica set and sharded deployments. Existing clusters that don’t enable search continue to run unchanged after you upgrade. + +Full-text and vector search require Percona Server for MongoDB 8.3 or later. The Operator uses experimental 8.3 images that you must explicitly specify in the Custom Resource. + +This feature is available as a tech preview and is not recommended for production use yet. Try it in staging or testing environments and share your feedback to help us shape its future. + +Learn more in the [documentation](../search-overview.md) and [setup tutorial](../search-setup.md). + +### Boost backup and restore performance with PVC snapshot support (tech preview) + +You can now use PVC snapshots to speed up backups and restores in your Percona Server for MongoDB clusters. A PVC snapshot is a point-in-time copy of your data volumes taken directly at the storage layer. Instead of streaming data to cloud storage, the Operator creates fast, storage level snapshots. This is especially beneficial for large data set owners, boosting their backup and restore performance. + +This feature is in the tech preview stage and is not recommended for production use yet. We encourage you to try it out in testing or staging environment and leave your feedback. + +Using PVC snapshots, you benefit from: + +* Faster backups — Snapshots typically complete in seconds or minutes, no matter how large your database is. Traditional full backups can take hours. +* Compatibility with encrypted and TLS enabled clusters — PVC snapshots work seamlessly with data at rest encryption and TLS, preserving your existing security posture. +* Faster restores — Creating a new cluster from a snapshot is significantly quicker than restoring from cloud storage. +* Lower resource usage — Snapshots avoid the CPU and network overhead of transferring data to remote storage. + +The Operator uses the PBM workflow for external backups and restores, automating all required steps. You only need to create the `VolumeSnapshotClass`, reference it in the backup object for on demand backups or in the Custom Resource for scheduled backups, and specify the backup type as `external`. + +You can find details about the workflow, requirements, and limitations in the [PVC snapshot support documentation](../backups-pvc-snapshots.md). For setup and usage instructions, refer to our [tutorial](../backups-pvc-setup.md). + +### Connect applications using operator-generated connection string Secrets + +The Operator now creates and maintains Kubernetes Secrets with ready-to-use MongoDB connection strings for the `databaseAdmin` user and for each operator-managed custom user. The Secret names are `-databaseadmin-conn-str` and `-custom-user-secret-conn-str` respectively. You no longer need to assemble URIs yourself from Pod names, Services, credentials, and TLS settings. + +After you deploy a cluster, the Operator generates connection strings that reflect your actual topology — replica set size, sharded layout, internal DNS names, and exposed endpoints when you enable them. Application teams can mount these Secrets directly in Deployments, Jobs, or CI pipelines instead of maintaining separate connection logic. + +The use of connection secrets helps you: + +* Connect applications faster — reference a Secret in your manifest and start using MongoDB without writing custom scripts to build URIs +* Stay correct as the cluster changes — when you scale a replica set or expose services, the Operator updates the connection strings for you. +* Support GitOps and platform workflows — platform teams can standardize on a predictable Secret naming pattern instead of documenting hand-built connection strings for every cluster. + +For details about connection Secrets, see [connection Secrets documentation](../connection-secrets.md). + +### Workload Identity authentication support for GCS backups + +You can now make backup to Google Cloud Storage without storing service account JSON keys in Kubernetes Secrets. This unblocks GKE environments that use [Workload Identity :octicons-link-external-16:](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity) and policies that forbid exporting service account keys. + +To use it: + +1. Enable Workload Identity on your GKE cluster. +2. Create a Google service account with access to your backup bucket (for example, `roles/storage.objectUser`). +3. Bind that Google service account to the Kubernetes Service Account used by your database Pods. + +Then configure GCS storage in the Custom Resource and omit `gcs.credentialsSecret`. The Operator configures Percona Backup for MongoDB to use Application Default Credentials (ADC), so Pods authenticate with short-lived tokens instead of long-lived keys. + +```yaml +backup: + storages: + gcs-wi: + type: gcs + gcs: + bucket: my-backup-bucket + prefix: mongodb-backup + # credentialsSecret omitted — PBM uses Workload Identity / ADC +``` + +This improvement makes keyless GCS backups a first-class option in the Operator. For configuration guidelines, refer to [documentation](../backups-storage-gcp.md#automate-access-to-google-cloud-storage-using-workload-identity). + +### Native backups to Oracle Cloud Infrastructure Object Storage + +You can now store MongoDB backups directly in Oracle Cloud Infrastructure (OCI) Object Storage. If your MongoDB cluster runs on Oracle Cloud or Oracle Kubernetes Engine (OKE), you can store backups in OCI Object Storage natively and no longer need to use an S3-compatible endpoint as a workaround. + +The Operator embeds this capability from Percona Backup for MongoDB, so you get the latest PBM storage enhancements through the familiar Custom Resource workflow. + +Configure storage in the Custom Resource with the `type: oci`, and choose how to authenticate: + +* **User principal** — Use the API signing key and store it in a Kubernetes Secret. This method works inside or outside OCI +* **OKE workload identity** — enjoy keyless access via Service Account IAM policies on enhanced OKE clusters + +You can also encrypt backups at rest with OCI Vault or a customer-provided key. + +With the support of OCI Object Storage, you get the same Operator-managed backup and restore experience on Oracle Cloud as with the other [supported storage services](../backups-storage.md). When you use workload identity, you also benefit from less credential handling. + +Read more about OCI support in our [documentation](../backups-storage-oci.md). + +### Support of Alibaba Cloud OSS for backups + +You can now store backups made through the Operator in [Alibaba Cloud Object Storage Service (OSS) :octicons-link-external-16:](https://www.alibabacloud.com/en/product/object-storage-service). If you operate in Asia-Pacific or China region or already use Alibaba Cloud infrastructure, this ability lets you reduce latency, simplify compliance, and achieve fewer cross-cloud hops. + +With the new `oss` storage type, configure backups the same way as for other cloud storages: create a Secret with Alibaba credentials, point the Custom Resource at your OSS bucket and endpoint, then run on-demand or scheduled backups and restores as usual. + +```yaml +backup: + storages: + alibaba-oss: + type: oss + oss: + bucket: OSS-BACKUP-BUCKET-NAME-HERE + prefix: "some-prefix" + credentialsSecret: my-cluster-name-backup-oss + endpointUrl: https://oss-eu-central-1.aliyuncs.com + region: eu-central-1 +``` + +The Secret must include `ALIBABA_ACCESS_KEY_ID` and `ALIBABA_ACCESS_KEY_SECRET`. Optional settings cover upload retries, multipart upload size, and server-side encryption (SSE-OSS or SSE-KMS) via a per-storage SSE Secret. + +See our [documentation](../backups-storage-oss.md) for configuration and examples. + +With this integration, you no longer need a workaround or a second cloud for backups, since logical, physical, and incremental backups now go straight to OSS. + +### Restore a collection under a different name + +You can now restore a single collection from a full logical backup under a different name up to a certain point in time alongside the current collection in the same database, to a different database or to a different cluster. This is useful when you need to recover from an accidental delete or bad write. Restore the collection side by side, compare or validate the data, then merge what you need back into production. + +The Operator automates the full flow through the Restore Custom Resource, so you don't need to exec into pods or run PBM manually. You get safer partial recovery with less operational risk and a clear, trackable restore status. + +Set the source and target namespaces in the `PerconaServerMongoDBRestore` Custom Resource: + +```yaml +apiVersion: psmdb.percona.com/v1 +kind: PerconaServerMongoDBRestore +metadata: + name: restore-remap +spec: + clusterName: my-cluster-name + backupName: backup1 + selective: + nsFrom: "myApp.test" + nsTo: "myApp.test_remapped" +``` + +The feature is supported for replica sets and unsharded collections. Refer to our [documentation](../backups-restore-new-name.md) for configuration examples and workflows. + +### Configure external nodes as arbiters + +You can now declare an external node as an arbiter in your Custom Resource by setting `arbiterOnly: true` under `replsets.externalNodes`. This lets you add a lightweight tie-breaker vote in a third location without running another data-bearing member in Kubernetes. + +Here's the example configuration: +```yaml +replsets: + - name: rs0 + externalNodes: + - host: arbiter-0.example.com + priority: 0 + votes: 1 + arbiterOnly: true +``` + +For deployments distributed across multiple regions or data centers, this is a practical way to keep an odd number of voters without having to manually restore the majority configuration during a failover. Instead, you can deploy a main cluster with 2 voting members, a replica cluster with 2 voting member and another cluster with only an arbiter in another region . With this setup, you get reliable elections and quorum without the cost and operational overhead of another full replica. + +### More control over TLS certificate management + +If you manage TLS certificates manually, such as through Kubernetes Secrets synced from AWS Secrets Manager or via External Secrets, losing access to those Secrets even briefly can lead to a service outage. + +By default, the Operator treats a missing TLS Secret as a signal to create new certificates, restart the database Pods, and apply the new CA. Applications that still trust your original CA may lose connectivity. + +Starting with version 1.23.0, you can control the Operator's behavior with the `spec.tls.certManagementPolicy` option in the Custom Resource. Available policies are: + +* `auto` (default) — Keeps the existing behavior. If TLS Secrets are missing, the Operator creates new certificates automatically. +* `userProvidedOnly` — Certificate lifecycle stays entirely under your control. The Operator does not create or replace TLS certificates, if a TLS Secret is temporarily unavailable. In this way, your applications can keep using the existing certificates while you restore access to the Secret. + +```yaml +spec: + tls: + mode: preferTLS + certManagementPolicy: userProvidedOnly + allowInvalidCertificates: false + secrets: + ssl: my-cluster-name-ssl + sslInternal: my-cluster-name-ssl-internal +``` + +### Use your existing cert-manager ClusterIssuer for MongoDB TLS + +If you already run `cert-manager` with a cluster-wide issuer, you can now point the Operator at that ClusterIssuer instead of letting it create its own CA chain. This way you include Percona Server for MongoDB managed by the Operator in your organization’s PKI and apply the same renewal and trust policies you already use elsewhere in the cluster. + +Configure your cluster to use your issuer by setting `tls.issuerConf.kind` to `ClusterIssuer` and referencing your existing ClusterIssuer in `tls.issuerConf.name`. The Operator then creates Certificate resources that cert-manager signs through your CA. + +If you pre-create Certificate or ClusterIssuer resources before deploying the cluster, the Operator detects and uses them. This gives you a clean path when your platform team owns cert-manager and you only need the Operator to wire MongoDB into that setup. + +To use the cluster-wide ClusterIssuer resource, the Operator must know the namespace where the `cert-manager` is deployed. By default that namespace is `cert-manager`. If you installed cert-manager elsewhere, set the `CERTMANAGER_NAMESPACE` environment variable on the Operator deployment. + +With this improvement, you keep a single source of truth for TLS in your Kubernetes cluster. The Operator fits seamlessly into the way you already manage TLS across your platform. You keep control, avoid duplication, and Percona Server for MongoDB aligns with the same trusted process your other workloads use. + +### Tune the Operator reconciliation interval to reduce Kubernetes API load + +The Operator re-runs reconciliation on a fixed schedule to keep each cluster aligned with its Custom Resource. Before this release, that interval was hardcoded to 5 seconds. In environments with many clusters, that default can generate a high volume of Kubernetes API requests. + +You can now tune the reconciliation behavior to match your environment. Set the `RECONCILE_INTERVAL` environment variable on the Operator Deployment to reduce API traffic in stable production setups, ease pressure on shared Kubernetes clusters or avoid throttling without rebuilding images. The default value remains `5s` seconds, so existing deployments behave as before. + +Set the value as a Go duration string (for example, `30s` or `1m`): +```yaml +env: + - name: RECONCILE_INTERVAL + value: "30s" +``` + +To learn more, see the documentation for [Operator environment variables](../env-vars-operator.md) and [Configure concurrent reconciliation](../reconciliation-concurrency.md). + +### Control StatefulSet revision history from your Custom Resource + +Every configuration change creates a new revision in the StatefulSet history. Without a limit, old revisions can accumulate and clutter the namespace. + +With this release, you can configure how many past revisions Kubernetes keeps for your database StatefulSets. Set the value for the `spec.revisionHistoryLimit` option in the `PerconaServerMongoDB` Custom Resource: + +```yaml +spec: + updateStrategy: SmartUpdate + revisionHistoryLimit: 10 +``` + +The default number of revisions is 10. + +By adjusting the `revisionHistoryLimit`, you choose the balance that fits your operations: either to keep fewer revisions for a cleaner environment, or to retain more if you rely on additional rollback points during frequent configuration changes. + +### Configure query analytics source for PMM + +You can now choose how PMM collects Query Analytics (QAN) data for your MongoDB clusters: via a `profiler` (default) or via a `mongolog` tool. + +`mongolog` reads slow-query data directly from `mongod` log files so PMM needs almost no ongoing database connections and has minimal impact on the server. You keep full QAN visibility in PMM while reducing the operational cost of query monitoring. This is especially useful in production clusters where using the `profiler` has been a concern. + +The `profiler` remains the default query analytics source, so existing monitoring setups are unchanged. + +To switch to `mongolog`, set the value for the `spec.pmm.querySource` Custom Resource option. Also, ensure your cluster meets these prerequisites: + +* PMM Server and PMM Client version 3.3.0 or newer +* [Log collector enabled](../persistent-logging.md) so `mongod` logs are written to `/data/db/logs/` +* Percona Server for MongoDB configured to log slow operations to the diagnostic log (for example, `operationProfiling.mode: off` with a `slowOpThresholdMs` value) + +Example configuration: + +```yaml +spec: + pmm: + enabled: true + querySource: mongolog + logcollector: + enabled: true + replsets: + - name: rs0 + configuration: | + operationProfiling: + mode: off + slowOpThresholdMs: 200 +``` + +### Custom health probes for sidecar containers + +With this release, you can configure custom liveness and readiness probes for `pmm-client`, `backup`, `logcollector` and `logrotate` sidecar containers. By default, only the PMM Client has a built-in liveness probe; the other sidecars have none. + +Custom probes help when you need to: + +* Match probe timing to slow starts or constrained clusters, so Kubernetes does not restart healthy containers too early +* Add readiness checks so traffic or dependent workflows wait until monitoring, backup, or logging is actually ready +* Meet platform or compliance rules that require health checks on every container in the Pod +* Use environment-specific checks (HTTP, TCP, or exec) instead of a one-size-fits-all default + +Configure probes in the Custom Resource under `pmm`, `backup`, `logcollector`, and `logcollector.logrotate` sections. Defaults stay unchanged until you set a probe. + +### Official support for Rancher Kubernetes Engine (RKE2) + +[Rancher Kubernetes Engine (RKE2) :octicons-link-external-16:](https://docs.rke2.io/) is now an officially supported platform. Every Operator release is now tested on RKE2 to ensure that you can run it on Rancher-managed Kubernetes clusters with confidence. + +### The Operator is now fully supported on ARM64 architectures + +All Operator images are now available for ARM64, giving you native support on ARM based clusters with no extra setup. + +## Documentation improvements + +* Added a new chapter to the documentation covering how to configure OIDC authentication in the Operator. +* Added instructions how to install the Operator with customized parameters using Helm as well as how to override release names. + +## CRD Changes + +* A new CRD `PerconaServerMongoDBClusterSync` is added +* The `backup.storages.gcs.secret` option is now optional if you use Workload Identity Federation. See [Google Cloud storage](../backups-storage-gcp.md) to learn more. +* The `.spec.type` option has a new value `external` + +## Changelog + +### New Features + +* [K8SPSMDB-1031](https://perconadev.atlassian.net/browse/K8SPSMDB-1031) - Added support for configuring an external node as an arbiter in multi-datacenter replica sets. This lets you place a voting arbiter in a third region for high availability without replicating full data copies to that site. (Thank you @tariktunahanakan for contributing to this feature) + +* [K8SPSMDB-1363](https://perconadev.atlassian.net/browse/K8SPSMDB-1363) - Added support for PVC volume snapshots so you can back up large clusters using storage-provider snapshots. This is especially useful for multi-terabyte deployments where object-storage backups are slower or more costly than native volume snapshots. + +* [K8SPSMDB-1413](https://perconadev.atlassian.net/browse/K8SPSMDB-1413) - Improved cert-manager integration so TLS setups that use `issuerConf` work correctly with the Operator. + +* [K8SPSMDB-1458](https://perconadev.atlassian.net/browse/K8SPSMDB-1458) - Added the `certManagementPolicy` field to the `PerconaServerMongoDB` Custom Resource. This gives you explicit control over how the Operator manages TLS Secrets with certificates generated manually. (Thank you Lake Yoo for contributing to this feature) + +* [K8SPSMDB-1519](https://perconadev.atlassian.net/browse/K8SPSMDB-1519) - Added support for Alibaba Cloud Object Storage Service as a backup destination. + +* [K8SPSMDB-1537](https://perconadev.atlassian.net/browse/K8SPSMDB-1537) - Added automatic generation of a Secret that contains ready-to-use MongoDB connection strings. Applications can consume `mongodb://` and `mongodb+srv://` URIs directly without assembling host lists, credentials, and TLS options manually. + +* [K8SPSMDB-1546](https://perconadev.atlassian.net/browse/K8SPSMDB-1546) - Added support for Query Analytics (QAN) via mongolog as a data source for the PMM Client. This lets you use log-based query monitoring, which is better suited for large-scale MongoDB workloads with PMM 3.3.0 and later. + +* [K8SPSMDB-1596](https://perconadev.atlassian.net/browse/K8SPSMDB-1596) - Added Rancher Kubernetes Engine (RKE2) to the certified and tested platforms for the Operator. This confirms that you can run production clusters on Rancher-managed Kubernetes and expect the same reliability as on other supported platforms. + +* [K8SPSMDB-1602](https://perconadev.atlassian.net/browse/K8SPSMDB-1602) - Added support for Workload Identity authentication with Google cloud Storage for backups. This lets PBM authenticate to object storage with cloud identity federation instead of static access keys. (Thank you Christopher Tineo for contributing to this feature) + +* [K8SPSMDB-1603](https://perconadev.atlassian.net/browse/K8SPSMDB-1603) - Added namespace remapping (`nsFrom` / `nsTo`) to the `PerconaServerMongoDBRestore` Custom Resource. You can restore a collection under a different name through a Kubernetes-native restore object, without having to manually run PBM commands. + +* [K8SPSMDB-1608](https://perconadev.atlassian.net/browse/K8SPSMDB-1608) - Added the ability to define the custom external DNS so that each exposed Pod Service gets a unique, human-readable hostname. ExternalDNS can then publish predictable DNS records instead of opaque hostnames generated by the cloud load balancer. (Thank you Lake Yoo for reporting and contributing to this feature) + +* [K8SPSMDB-1610](https://perconadev.atlassian.net/browse/K8SPSMDB-1610) - Added support for Percona ClusterSync for MongoDB (PCSM) so the Operator can deploy and manage real-time replication or near-zero-downtime migration between MongoDB deployments. Replication state and lag are reflected in the `PerconaServerMongoDB` status for easier monitoring and automation. + +* [K8SPSMDB-1644](https://perconadev.atlassian.net/browse/K8SPSMDB-1644) - Added Oracle Cloud Infrastructure (OCI) Object Storage as a supported backup destination in the Custom Resource. You can configure OCI buckets for PBM backups instead of using an S3-compatible endpoint as a workaround. + +* [K8SPSMDB-1654](https://perconadev.atlassian.net/browse/K8SPSMDB-1654) - Added Vector Search support for Percona Server for MongoDB clusters managed by the Operator. This lets you run vector search workloads on Operator-managed clusters. + +* [K8SPSMDB-1701](https://perconadev.atlassian.net/browse/K8SPSMDB-1701) - Added Custom Resource options to override liveness probes and define readiness probes for the `pmm-client` and `backup-agent` sidecars. Defaults remain unchanged, so existing clusters keep current probe behavior unless you customize them. + +* [K8SPSMDB-1705](https://perconadev.atlassian.net/browse/K8SPSMDB-1705) - Upgraded Percona Backup for MongoDB to version 2.15.0. This brings the latest PBM backup and restore improvements into Operator-managed clusters. + +* [K8SPSMDB-1728](https://perconadev.atlassian.net/browse/K8SPSMDB-1728) - Added Custom Resource options to override liveness probes and define readiness probes for the `logcollector` and `logrotate` sidecars. Defaults remain unchanged, so these sidecars stay without probes unless you configure them. + +### Improvements + +* [K8SPSMDB-680](https://perconadev.atlassian.net/browse/K8SPSMDB-680) - Added the ability to set `enableLocalhostAuthBypass=false` for MongoDB instances managed by the Operator. This helps environments that require stricter localhost authentication bypass controls to meet security policy. + +* [K8SPSMDB-1427](https://perconadev.atlassian.net/browse/K8SPSMDB-1427) - Ensured TLS `.pem` files are generated even when containers start in sleep-forever debug mode. This simplifies manual troubleshooting because you no longer need to assemble certificate files by hand before starting `mongod`. + +* [K8SPSMDB-1456](https://perconadev.atlassian.net/browse/K8SPSMDB-1456) - Improved replica set initialization so a failed system user creation no longer leaves the cluster permanently stuck. The Operator retries initialization and can complete cluster setup after a transient failure during user bootstrap.(Thank you Dobes Vandermeer for reporting this issue) + +* [K8SPSMDB-1571](https://perconadev.atlassian.net/browse/K8SPSMDB-1571) - Made the Operator reconciliation interval configurable through an environment variable so that you can adjust Kubernetes API load for your environment instead of relying on the previous fixed five-second interval. (Thank you Alexandre Dutra for contributing to this issue) + +* [K8SPSMDB-1572](https://perconadev.atlassian.net/browse/K8SPSMDB-1572) - Added the `revisionHistoryLimit` option to the `PerconaServerMongoDB` Custom Resource. The Operator applies this value to managed StatefulSets so you can limit retained ControllerRevision objects and keep cluster resource usage under control. (Thank you Lake Yoo for contributing to this issue) + +* [K8SPSMDB-1586](https://perconadev.atlassian.net/browse/K8SPSMDB-1586) - Stopped creating unused encryption key and keyfile Secrets when HashiCorp Vault is configured for secrets management. This avoids confusing unused credentials in clusters that already store keys in Vault. + +* [K8SPSMDB-1711](https://perconadev.atlassian.net/browse/K8SPSMDB-1711) - Switched the Operator Deployment probes to the standard `/healthz` and `/readyz` endpoints. This aligns Operator health checks with common Kubernetes controller patterns and improves readiness detection. (Thank you Ilia Lazebnik for contributing to this issue) + +### Bug Fixes + +* [K8SPSMDB-1139](https://perconadev.atlassian.net/browse/K8SPSMDB-1139) - Fixed unnecessary PVC resize attempts on platforms that provision volumes with `G` units instead of `Gi`. The Operator now handles both unit styles correctly and no longer triggers resize right after cluster creation on environments such as k3d or some on-premises clusters. + +* [K8SPSMDB-1255](https://perconadev.atlassian.net/browse/K8SPSMDB-1255) - Reduced log noise for clusters with arbiter nodes by stopping repeated "Fixing member configurations" messages. The Operator no longer continuously rewrites arbiter member tags on every reconcile cycle. + +* [K8SPSMDB-1389](https://perconadev.atlassian.net/browse/K8SPSMDB-1389) - Fixed a storage scaling error that occurred when a requested size rounded to the same PVC size already in use. The Operator now detects no-op resize cases and avoids invalid StatefulSet updates that previously left the cluster in an Error state. + +* [K8SPSMDB-1444](https://perconadev.atlassian.net/browse/K8SPSMDB-1444) - Stopped creating an unused internal member keyfile Secret when replica set members authenticate with x509 under TLS. The keyfile Secret is now created only for modes that do require shared keyfile authentication. + +* [K8SPSMDB-1455](https://perconadev.atlassian.net/browse/K8SPSMDB-1455) - Fixed a bug where the Operator repeatedly attempted to delete StatefulSets that no longer existed. This removes unnecessary reconcile work and related log noise after resources are already gone. (Thank you Bernard Grymonpon for reporting this issue) + +* [K8SPSMDB-1476](https://perconadev.atlassian.net/browse/K8SPSMDB-1476) - Fixed LoadBalancer Service finalizer handling that caused `UnexpectedlyRemovedFinalizer` warnings on internal load balancers. Service updates no longer strip cloud-provider cleanup finalizers during normal reconciliation. (Thank you user @pave-thien for reporting this issue) + +* [K8SPSMDB-1547](https://perconadev.atlassian.net/browse/K8SPSMDB-1547) - Fixed Helm chart installs that failed when users defined additional replica sets without repeating `volumeSpec` in every override. The chart now supplies the required volume configuration so multi-replica-set installs validate successfully. + +* [K8SPSMDB-1575](https://perconadev.atlassian.net/browse/K8SPSMDB-1575) - Fixed Operator errors after creating custom users with long names caused by user annotation key exceeding the Kubernetes 63-character limit. The Operator now calculates the sha256 sum of `-` and encodes it in base32 this way ensuring the annotation key adheres to the 63-character limit. User creation succeeds without secret annotation validation failures during password or role updates. + +* [K8SPSMDB-1583](https://perconadev.atlassian.net/browse/K8SPSMDB-1583) - Fixed an Operator panic that occurred when PMM was enabled but the required PMM token or API key was missing from the Secret. The Operator now reports a clear configuration error and continues reconciliation safely. + +* [K8SPSMDB-1592](https://perconadev.atlassian.net/browse/K8SPSMDB-1592) - Fixed recovery behavior when a config server replica set StatefulSet is deleted unexpectedly. The Operator now recreates the missing StatefulSet and related configuration so sharded clusters can heal without a manual Operator restart. + +* [K8SPSMDB-1595](https://perconadev.atlassian.net/browse/K8SPSMDB-1595) - Fixed missing SecurityContext on the `pbm-init` container during physical restores. The init container now follows the same security context defaults and configuration options as other Operator-managed init containers. (Thank you Afeedh Shaji for reporting and contributing to this issue) + +* [K8SPSMDB-1607](https://perconadev.atlassian.net/browse/K8SPSMDB-1607) - Fixed endless custom user role updates caused by unordered role comparisons between the Custom Resource and MongoDB. The Operator now treats role sets as equal regardless of order, which stops unnecessary reconcile loops and log spam. (Thank you Romain Acciari for contributing to this issue) + +* [K8SPSMDB-1619](https://perconadev.atlassian.net/browse/K8SPSMDB-1619) - Fixed a backup lock leak where a failed lease acquisition left stale Lease and lock resources behind. Scheduled backups no longer get stuck in Waiting after transient API or network failures during lock creation. + +* [K8SPSMDB-1635](https://perconadev.atlassian.net/browse/K8SPSMDB-1635) - Fixed PMM sidecar authentication so the Operator no longer hardcodes SCRAM-SHA-1 for the monitoring user. You can configure the authentication mechanism, which avoids monitoring failures on clusters that do not advertise SCRAM-SHA-1. (Thank you Roger Reed for reporting this issue) + +* [K8SPSMDB-1640](https://perconadev.atlassian.net/browse/K8SPSMDB-1640) - Fixed a bug where the Operator continuously reset default read and write concerns back to `majority`. Custom default concern settings in MongoDB are now preserved across reconciliation cycles. (Thank you Jesper Carlsson for reporting this issue) + +* [K8SPSMDB-1643](https://perconadev.atlassian.net/browse/K8SPSMDB-1643) - Fixed a deadlock where starting a restore while another backup was still running left both operations hung indefinitely. The Operator now handles concurrent backup and restore requests sequentially. (Thank you user @Vinh1507 for reporting this issue) + +* [K8SPSMDB-1645](https://perconadev.atlassian.net/browse/K8SPSMDB-1645) - Fixed liveness probe behavior that could kill `mongod` during initial sync (`STARTUP2`) when short probe thresholds were configured. The health check now recognizes ongoing initial sync and avoids restarting members before they finish synchronizing. + +* [K8SPSMDB-1679](https://perconadev.atlassian.net/browse/K8SPSMDB-1679) - Fixed logrotate container failures on arm64 caused by a missing cron dependency in the `logcollector` entrypoint. Persistent log rotation now starts correctly on arm64 nodes. + +* [K8SPSMDB-1685](https://perconadev.atlassian.net/browse/K8SPSMDB-1685) - Fixed a bug where LoadBalancer Services for hidden members were repeatedly deleted and recreated. Hidden-member external Services now persist so clients keep a stable load balancer endpoint. + +* [K8SPSMDB-1710](https://perconadev.atlassian.net/browse/K8SPSMDB-1710) - Fixed startup crashes when `readOnlyRootFilesystem` is enabled by providing a writable `/tmp` mount for `mongod` and the backup agent. Containers can again create temporary TLS and WiredTiger files required at runtime. (Thank you Olawale (Walz) Ogundiran for contributing to this issue) + + +## Supported software + +The Operator was developed and tested with the following software: + +* Percona Server for MongoDB 6.0.29-23, 7.0.37-20, and 8.0.26-11 +* Percona Backup for MongoDB 2.15.0 +* PMM Client: 2.44.1-1 +* PMM3 Client: 3.8.1 +* cert-manager: 1.21.0 +* LogCollector based on fluent-bit: 5.0.9-1 + +Other options may also work but have not been tested. + +## Supported platforms + +Percona Operators are designed for compatibility with all [CNCF-certified :octicons-link-external-16:](https://www.cncf.io/training/certification/software-conformance/) Kubernetes distributions. Our release process includes targeted testing and validation on major cloud provider platforms and OpenShift, as detailed below: + +--8<-- [start:platforms] + +* [Google Kubernetes Engine (GKE) :octicons-link-external-16:](https://cloud.google.com/kubernetes-engine) 1.33 - 1.35 +* [Amazon Elastic Kubernetes Service (EKS) :octicons-link-external-16:](https://aws.amazon.com) 1.33 - 1.36 +* [Azure Kubernetes Service (AKS) :octicons-link-external-16:](https://azure.microsoft.com/en-us/services/kubernetes-service/) 1.34 - 1.36 +* [OpenShift Container Platform :octicons-link-external-16:](https://www.redhat.com/en/technologies/cloud-computing/openshift) 4.18 - 4.22 +* [Rancher :octicons-link-external-16:](https://www.rancher.com/) with Rancher Kubernetes Engine (RKE2) 1.33 - 1.35 +* [Minikube :octicons-link-external-16:](https://github.com/kubernetes/minikube) 1.38.1 with Kubernetes v1.35.1 +--8<-- [end:platforms] + +This list only includes the platforms that the Percona Operators are specifically tested on as part of the release process. Other Kubernetes flavors and versions depend on the backward compatibility offered by Kubernetes itself. + +## Percona certified images + +Find Percona's certified Docker images that you can use with the Percona Operator for MongoDB in the following table: + +--8<-- [start:images] + +| Image | Digest | +|:-------------------------------------------------------|:-----------------------------------------------------------------| +| percona/percona-server-mongodb:8.0.26-11 | e258e1faf74fb3d521bb2732d2a05fe3b7318335974ef3ddf33783746f6c084f | +| percona/percona-server-mongodb:8.0.26-11 (ARM64) | 2515c4680c8945febea98de5333a9a9895e39e2bf7f9ec0f240f04b1fe1dc645 | +| percona/percona-server-mongodb:7.0.37-20 | 2762037db63934fa15e20a1fa03258ccfb457633bac7a02cdfbff594d1639c4b | +| percona/percona-server-mongodb:7.0.37-20 (ARM64) | 392b90cc2e8e67c16bff3885c38819439d7db58ad4a7e734ae8a7cfe24a19a14 | +| percona/percona-server-mongodb:6.0.29-23 | cf9254f6d05f7f64b6295a7d96c6b4591d02e521a68488cb99eb54f9720714c1 | +| percona/percona-server-mongodb:6.0.29-23 (ARM64) | 62fbdebb132307ced293ad30eeb597e7f4f7f9bf05ccc222a436c7f2b71d5cbc | +| percona/fluentbit:5.0.9-1 | 1ca02c2c820697ea943b39ab3e033446eca383343bb61acc71981548d31f4c7f | +| percona/fluentbit:5.0.9-1 (ARM64) | 1814577514a49b851c59d1bf6ad5ec360ebd04d53ce9f5ece5209498b5c6a64b | +| percona/pmm-client:3.8.1 | a92cfb7f912bd85d8245575c3ee5c423664ad2baedb674d159a87b113dbd4de2 | +| percona/pmm-client:3.8.1 (ARM64) | 3fe427c0666337df7613824da5f3b5fb7397e849f70402ac557c1324c5d996e6 | +| percona/pmm-client:2.44.1-1 | 52a8fb5e8f912eef1ff8a117ea323c401e278908ce29928dafc23fac1db4f1e3 | +| percona/pmm-client:2.44.1-1 (ARM64) | 390bfd12f981e8b3890550c4927a3ece071377065e001894458047602c744e3b | +| percona/percona-backup-mongodb:2.15.0 | 2c69ec2dbd5be02df31577869df97c72781bf6fe6456471e8087b0e03136f672 | +| percona/percona-backup-mongodb:2.15.0 (ARM64) | 188c38f60e54b9864e74e346209c0a924b6c8b0829062a31d44a5abb42626703 | +| percona/percona-server-mongodb-operator:1.23.0 | 21e9fed2c4309d3e88c6ec64ddf5dce6c0e86ce4be20531ab83c0b838739f89b | +| percona/percona-server-mongodb-operator:1.23.0 (ARM64) | 9747f69b64119ce343cb01ac47fa4b7af8050266852f4faef612908b02d554a2 | + +--8<-- [end:images] + +Find previous version images in the [documentation archive :octicons-link-external-16:](https://docs.percona.com/legacy-documentation/) diff --git a/docs/RN/index.md b/docs/RN/index.md index 3168c45a..687f0020 100644 --- a/docs/RN/index.md +++ b/docs/RN/index.md @@ -1,5 +1,6 @@ # Percona Operator for MongoDB Release Notes +- [Percona Operator for MongoDB 1.23.0 ({{date.1_23_0}})](Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md) - [Percona Operator for MongoDB 1.22.0 ({{date.1_22_0}})](Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md) - [Percona Operator for MongoDB 1.21.2 ({{date.1_21_2}})](Kubernetes-Operator-for-PSMONGODB-RN1.21.2.md) - [Percona Operator for MongoDB 1.21.1 ({{date.1_21_1}})](Kubernetes-Operator-for-PSMONGODB-RN1.21.1.md) diff --git a/docs/assets/fragments/patch.txt b/docs/assets/fragments/patch.txt index a9b8bb12..7a3f1772 100644 --- a/docs/assets/fragments/patch.txt +++ b/docs/assets/fragments/patch.txt @@ -24,7 +24,7 @@ "crVersion":"{{ release }}", "image": "percona/percona-server-mongodb:{{ mongodb80recommended }}", "backup": { "image": "percona/percona-backup-mongodb:{{ pbmrecommended }}" }, - "pmm": { "image": "percona/pmm-client:{{ pmm2recommended }}" }, + "pmm": { "image": "percona/pmm-client:{{ pmm3recommended }}" }, "logcollector": { "image": "percona/fluentbit:{{fluentbitrecommended}}" } }}' ``` diff --git a/docs/assets/templates/pdf_cover_page.tpl b/docs/assets/templates/pdf_cover_page.tpl index 22978080..b6e97a42 100644 --- a/docs/assets/templates/pdf_cover_page.tpl +++ b/docs/assets/templates/pdf_cover_page.tpl @@ -10,4 +10,4 @@ {% if config.site_description %}

{{ config.site_description }}

{% endif %} -

1.22.0 (February 25, 2026)

\ No newline at end of file +

1.23.0 (July 23, 2026)

\ No newline at end of file diff --git a/docs/search-overview.md b/docs/search-overview.md index a7a3b1e0..d24017bb 100644 --- a/docs/search-overview.md +++ b/docs/search-overview.md @@ -1,4 +1,4 @@ -# About search and vector search +# About full-text and vector search !!! admonition "Version added: [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md)" diff --git a/docs/search-setup.md b/docs/search-setup.md index 2fbb115b..12b42a40 100644 --- a/docs/search-setup.md +++ b/docs/search-setup.md @@ -14,7 +14,7 @@ Percona Operator for MongoDB, insert sample vector data, create a vector search index, and run a `$vectorSearch` query. Vector search is implemented via Percona Search for MongoDB search engine that runs the `mongot` search process. To learn how it works with the Operator and what use cases you can implement, see -[About search and vector search](search-overview.md). +[About full-text and vector search](search-overview.md). This setup uses the following software versions: diff --git a/docs/update-crd-manual.md b/docs/update-crd-manual.md index 4c7b780c..f73229ae 100644 --- a/docs/update-crd-manual.md +++ b/docs/update-crd-manual.md @@ -84,7 +84,7 @@ The upgrade includes the following steps. "crVersion":"{{ release }}", "image": "percona/percona-server-mongodb:{{ mongodb80recommended }}", "backup": { "image": "percona/percona-backup-mongodb:{{ pbmrecommended }}" }, - "pmm": { "image": "percona/pmm-client:{{ pmm2recommended }}" }, + "pmm": { "image": "percona/pmm-client:{{ pmm3recommended }}" }, "logcollector": { "image": "percona/fluentbit:{{fluentbitrecommended}}" } }}' ``` diff --git a/docs/versions.md b/docs/versions.md index db7e23b8..b73d7566 100644 --- a/docs/versions.md +++ b/docs/versions.md @@ -6,6 +6,7 @@ Versions of the cluster components and platforms tested with different Operator | Operator | [MongoDB :octicons-link-external-16:](https://www.percona.com/mongodb/software/percona-server-for-mongodb) | [Percona Backup for MongoDB :octicons-link-external-16:](https://www.percona.com/mongodb/software/percona-backup-for-mongodb) | |:--------|:--------|:-----| +| [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md) | 6.0.29-23, 7.0.37-20, 8.0.26-11 | 2.15.0 | | [1.22.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md) | 6.0.27-21, 7.0.30-16, 8.0.19-7 | 2.12.0 | | [1.21.2](RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.2.md) | 6.0 - 8.0 | 2.11.0 | | [1.21.1](RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.1.md) | 6.0 - 8.0 | 2.11.0 | @@ -36,34 +37,35 @@ Versions of the cluster components and platforms tested with different Operator ## Platforms -| Operator | [GKE :octicons-link-external-16:](https://cloud.google.com/kubernetes-engine) | [EKS :octicons-link-external-16:](https://aws.amazon.com) | [Openshift :octicons-link-external-16:](https://www.redhat.com/en/technologies/cloud-computing/openshift) | [AKS :octicons-link-external-16:](https://azure.microsoft.com/en-us/services/kubernetes-service/) | [Minikube :octicons-link-external-16:](https://github.com/kubernetes/minikube) | -|:--------|:------------|:------------|:------------|:------------|:----------------------------------|\ -| [1.22.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md) | 1.32 - 1.33 | 1.32 - 1.35 | 4.17 - 4.21 | 1.32 - 1.34 | 1.38.0 | -| [1.21.2](RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.2.md) | 1.31 - 1.33 | 1.31 - 1.34 | 4.16 - 4.19 | 1.31 - 1.33 | 1.37.0 | -| [1.21.1](RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.1.md) | 1.31 - 1.33 | 1.31 - 1.34 | 4.16 - 4.19 | 1.31 - 1.33 | 1.37.0 | -| [1.21.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.0.md) | 1.31 - 1.33 | 1.31 - 1.34 | 4.16 - 4.19 | 1.31 - 1.33 | 1.37.0 | -| [1.20.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.20.0.md) | 1.30 - 1.32 | 1.30 - 1.32 | 4.14 - 4.18 | 1.30 - 1.32 | 1.35.0 | -| [1.19.1](RN/Kubernetes-Operator-for-PSMONGODB-RN1.19.1.md) | 1.28 - 1.30 | 1.29 - 1.31 | 4.14.44 - 4.17.11 | 1.28 - 1.31 | 1.34.0 | -| [1.19.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.19.0.md) | 1.28 - 1.30 | 1.29 - 1.31 | 4.14.44 - 4.17.11 | 1.28 - 1.31 | 1.34.0 | -| [1.18.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.18.0.md) | 1.28 - 1.30 | 1.28 - 1.31 | 4.13.52 - 4.17.3 | 1.28 - 1.31 | 1.34.0 | -| [1.17.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.17.0.md) | 1.27 - 1.30 | 1.28 - 1.30 | 4.13.48 - 4.16.9 | 1.28 - 1.30 | 1.33.1 | -| [1.16.2](RN/Kubernetes-Operator-for-PSMONGODB-RN1.16.2.md) | 1.26 - 1.29 | 1.26 - 1.29 | 4.12.56 - 4.15.11 | 1.27 - 1.29 | 1.33 | -| [1.16.1](RN/Kubernetes-Operator-for-PSMONGODB-RN1.16.1.md) | 1.26 - 1.29 | 1.26 - 1.29 | 4.12.56 - 4.15.11 | 1.27 - 1.29 | 1.33 | -| [1.16.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.16.0.md) | 1.26 - 1.29 | 1.26 - 1.29 | 4.12.56 - 4.15.11 | 1.27 - 1.29 | 1.33 | -| [1.15.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.15.0.md) | 1.24 - 1.28 | 1.24 - 1.28 | 4.11 - 4.13 | 1.25 - 1.28 | 1.31.2 | -| [1.14.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.14.0.md) | 1.22 - 1.25 | 1.22 - 1.24 | 4.10 - 4.12 | 1.23 - 1.25 | 1.29 | -| [1.13.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.13.0.md) | 1.21 - 1.23 | 1.21 - 1.23 | 4.10 - 4.11 | 1.22 - 1.24 | 1.26 | -| [1.12.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.12.0.md) | 1.19 - 1.22 | 1.19 - 1.22 | 4.7 - 4.10 | - | 1.23 | -| [1.11.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.11.0.md) | 1.19 - 1.22 | 1.18 - 1.22 | 4.7 - 4.9 | - | 1.22 | -| [1.10.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.10.0.md) | 1.17 - 1.21 | 1.16 - 1.21 | 4.6 - 4.8 | - | 1.22 | -| [1.9.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.9.0.md) | 1.17 - 1.21 | 1.16-1.20 | 4.7 | - | 1.20 | -| [1.8.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.8.0.md) | 1.16 - 1.20 | 1.19 | 3.11, 4.7 | - | 1.19 | -| [1.7.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.7.0.md) | 1.15 - 1.17 | 1.15 | 3.11, 4.5 | - | 1.10 | -| [1.6.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.6.0.md) | 1.15 - 1.17 | 1.15 | 3.11, 4.5 | - | 1.10 | -| [1.5.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.5.0.md) | 1.15 - 1.17 | 1.15 | 3.11, 4.5 | - | 1.18 | -| [1.4.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.4.0.md) | 1.13, 1.15 | 1.15 | 3.11, 4.2 | - | 1.16 | -| [1.3.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.3.0.md) | 1.11, 1.14 | - | 3.11, 4.1 | - | 1.12 | -| [1.2.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.2.0.md) | - | - | 3.11, 4.0 | - | - | -| [1.1.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.1.0.md) | - | - | 3.11, 4.0 | - | - | +| Operator | [GKE :octicons-link-external-16:](https://cloud.google.com/kubernetes-engine) | [EKS :octicons-link-external-16:](https://aws.amazon.com) | [Openshift :octicons-link-external-16:](https://www.redhat.com/en/technologies/cloud-computing/openshift) | [AKS :octicons-link-external-16:](https://azure.microsoft.com/en-us/services/kubernetes-service/) | [Minikube :octicons-link-external-16:](https://github.com/kubernetes/minikube)| [Rancher Kubernetes Engine :octicons-link-external-16:](https://docs.rke2.io/)| +|:--------|:------------|:------------|:------------|:------------|:-------------------|:---------------| +| [1.23.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md) | 1.33 - 1.35 | 1.33 - 1.36 | 4.18 - 4.22 | 1.34 - 1.36 | 1.38.1 | 1.33 - 1.35 | +| [1.22.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md) | 1.32 - 1.33 | 1.32 - 1.35 | 4.17 - 4.21 | 1.32 - 1.34 | 1.38.0 | | +| [1.21.2](RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.2.md) | 1.31 - 1.33 | 1.31 - 1.34 | 4.16 - 4.19 | 1.31 - 1.33 | 1.37.0 | | +| [1.21.1](RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.1.md) | 1.31 - 1.33 | 1.31 - 1.34 | 4.16 - 4.19 | 1.31 - 1.33 | 1.37.0 | | +| [1.21.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.0.md) | 1.31 - 1.33 | 1.31 - 1.34 | 4.16 - 4.19 | 1.31 - 1.33 | 1.37.0 | | +| [1.20.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.20.0.md) | 1.30 - 1.32 | 1.30 - 1.32 | 4.14 - 4.18 | 1.30 - 1.32 | 1.35.0 | | +| [1.19.1](RN/Kubernetes-Operator-for-PSMONGODB-RN1.19.1.md) | 1.28 - 1.30 | 1.29 - 1.31 | 4.14.44 - 4.17.11 | 1.28 - 1.31 | 1.34.0 | | +| [1.19.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.19.0.md) | 1.28 - 1.30 | 1.29 - 1.31 | 4.14.44 - 4.17.11 | 1.28 - 1.31 | 1.34.0 | | +| [1.18.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.18.0.md) | 1.28 - 1.30 | 1.28 - 1.31 | 4.13.52 - 4.17.3 | 1.28 - 1.31 | 1.34.0 | | +| [1.17.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.17.0.md) | 1.27 - 1.30 | 1.28 - 1.30 | 4.13.48 - 4.16.9 | 1.28 - 1.30 | 1.33.1 | | +| [1.16.2](RN/Kubernetes-Operator-for-PSMONGODB-RN1.16.2.md) | 1.26 - 1.29 | 1.26 - 1.29 | 4.12.56 - 4.15.11 | 1.27 - 1.29 | 1.33 | | +| [1.16.1](RN/Kubernetes-Operator-for-PSMONGODB-RN1.16.1.md) | 1.26 - 1.29 | 1.26 - 1.29 | 4.12.56 - 4.15.11 | 1.27 - 1.29 | 1.33 | | +| [1.16.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.16.0.md) | 1.26 - 1.29 | 1.26 - 1.29 | 4.12.56 - 4.15.11 | 1.27 - 1.29 | 1.33 | | +| [1.15.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.15.0.md) | 1.24 - 1.28 | 1.24 - 1.28 | 4.11 - 4.13 | 1.25 - 1.28 | 1.31.2 | | +| [1.14.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.14.0.md) | 1.22 - 1.25 | 1.22 - 1.24 | 4.10 - 4.12 | 1.23 - 1.25 | 1.29 | | +| [1.13.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.13.0.md) | 1.21 - 1.23 | 1.21 - 1.23 | 4.10 - 4.11 | 1.22 - 1.24 | 1.26 | | +| [1.12.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.12.0.md) | 1.19 - 1.22 | 1.19 - 1.22 | 4.7 - 4.10 | - | 1.23 | | +| [1.11.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.11.0.md) | 1.19 - 1.22 | 1.18 - 1.22 | 4.7 - 4.9 | - | 1.22 | | +| [1.10.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.10.0.md) | 1.17 - 1.21 | 1.16 - 1.21 | 4.6 - 4.8 | - | 1.22 | | +| [1.9.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.9.0.md) | 1.17 - 1.21 | 1.16-1.20 | 4.7 | - | 1.20 | | +| [1.8.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.8.0.md) | 1.16 - 1.20 | 1.19 | 3.11, 4.7 | - | 1.19 | | +| [1.7.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.7.0.md) | 1.15 - 1.17 | 1.15 | 3.11, 4.5 | - | 1.10 | | +| [1.6.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.6.0.md) | 1.15 - 1.17 | 1.15 | 3.11, 4.5 | - | 1.10 | | +| [1.5.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.5.0.md) | 1.15 - 1.17 | 1.15 | 3.11, 4.5 | - | 1.18 | | +| [1.4.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.4.0.md) | 1.13, 1.15 | 1.15 | 3.11, 4.2 | - | 1.16 | | +| [1.3.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.3.0.md) | 1.11, 1.14 | - | 3.11, 4.1 | - | 1.12 | | +| [1.2.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.2.0.md) | - | - | 3.11, 4.0 | - | - | | +| [1.1.0](RN/Kubernetes-Operator-for-PSMONGODB-RN1.1.0.md) | - | - | 3.11, 4.0 | - | - | | More detailed information about the cluster components for the current version of the Operator can be found [in the system requirements](System-Requirements.md) and [in the list of certified images](images.md). For previous releases of the Operator, you can check the same pages [in the documentation archive :octicons-link-external-16:](https://docs.percona.com/legacy-documentation/). diff --git a/mkdocs-base.yml b/mkdocs-base.yml index d3a07bcc..4349bb48 100644 --- a/mkdocs-base.yml +++ b/mkdocs-base.yml @@ -318,7 +318,7 @@ nav: - "Restart or pause the cluster": pause.md - volume-attributes-class.md - Search and Vector search: - - About Percona Search for MongoDB: search-overview.md + - About full-text and vector search: search-overview.md - Configure search and vector search: search-setup.md - Troubleshooting: - "Troubleshoot the Operator installation issues": troubleshoot-operator.md @@ -359,6 +359,7 @@ nav: - Release notes: - "Release notes index": RN/index.md + - RN/Kubernetes-Operator-for-PSMONGODB-RN1.23.0.md - RN/Kubernetes-Operator-for-PSMONGODB-RN1.22.0.md - RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.2.md - RN/Kubernetes-Operator-for-PSMONGODB-RN1.21.1.md diff --git a/variables.yml b/variables.yml index 4999dc4c..9857e60a 100644 --- a/variables.yml +++ b/variables.yml @@ -2,28 +2,28 @@ commandName: 'kubectl' clusterName: 'my-cluster-name' -release: '1.22.0' +release: '1.23.0' apiversion: '1' -mongodb80recommended: '8.0.19-7' -mongodb70recommended: '7.0.30-16' -mongodb60recommended: '6.0.27-21' +mongodb80recommended: '8.0.26-11' +mongodb70recommended: '7.0.37-20' +mongodb60recommended: '6.0.29-23' pmm2recommended: '2.44.1-1' -pmm3recommended: '3.6.0' -fluentbitrecommended: '4.0.1-2' -gkerecommended: '1.33' -eksrecommended: '1.35' -aksrecommended: '1.34' -openshiftrecommended: '4.21' -minikuberecommended: '1.38.0' -k8srecommended: '1.35.0' -certmanagerrecommended: '1.19.3' -pbmrecommended: '2.12.0' -mongot: '1.70.1-1' +pmm3recommended: '3.8.1' +fluentbitrecommended: '5.0.9-1' +gkerecommended: '1.35' +eksrecommended: '1.36' +aksrecommended: '1.36' +openshiftrecommended: '4.22' +minikuberecommended: '1.38.1' +k8srecommended: '1.35.1' +certmanagerrecommended: '1.21.0' +pbmrecommended: '2.15.0' k8s_monitor_tag: 'v0.1.2' year: '2026' date: + 1_23_0: 2026-07-23 1_22_0: 2026-02-25 1_21_2: 2026-01-12 1_21_1: 2025-10-30