diff --git a/.github/agents/documentation-agent.md b/.github/agents/documentation-agent.md index 2831f303..26226986 100644 --- a/.github/agents/documentation-agent.md +++ b/.github/agents/documentation-agent.md @@ -49,6 +49,7 @@ You are a documentation specialist for the DocumentDB Kubernetes Operator projec - always check for and avoid outdated information in the documentation - always check for and avoid typos and grammatical errors in the documentation - ensure that all documentation is accurate and up-to-date with the latest code changes +- **Never use "cluster" alone** — always qualify as "DocumentDB cluster" or "Kubernetes cluster" to avoid ambiguity ## MkDocs Site diff --git a/.gitignore b/.gitignore index 96f83b7b..874f00cf 100644 --- a/.gitignore +++ b/.gitignore @@ -411,3 +411,6 @@ Chart.lock # Test output *.out .DS_Store + +# MkDocs build output +site/ diff --git a/docs/developer-guides/development-environment.md b/docs/developer-guides/development-environment.md index 2e2eac92..c1f8ce82 100644 --- a/docs/developer-guides/development-environment.md +++ b/docs/developer-guides/development-environment.md @@ -186,7 +186,39 @@ operator through Helm. --- -## 4. Contributing guidelines +## 4. Testing public documentation locally + +To build the documentation and run a development server for live previewing: + +1. Create a Python virtual environment: + + ```bash + python3 -m venv documentdb-k8s-docs-venv + ``` + +2. Activate the virtual environment: + + ```bash + source documentdb-k8s-docs-venv/bin/activate + ``` + +3. Install MkDocs: + + ```bash + pip install mkdocs mkdocs-material + ``` + +4. Run the local MkDocs server for testing: + + ```bash + mkdocs serve + ``` + + This starts a local server (typically at `http://127.0.0.1:8000`) where you can preview documentation changes in real time. + +--- + +## 5. Contributing guidelines Before opening a pull request, review the repository-wide [CONTRIBUTING.md](../../CONTRIBUTING.md) for the CLA process, style guidance, diff --git a/docs/operator-public-documentation/preview/advanced-configuration/README.md b/docs/operator-public-documentation/preview/advanced-configuration/README.md index 845a738e..d13568b7 100644 --- a/docs/operator-public-documentation/preview/advanced-configuration/README.md +++ b/docs/operator-public-documentation/preview/advanced-configuration/README.md @@ -4,198 +4,10 @@ This section covers advanced configuration options for the DocumentDB Kubernetes ## Table of Contents -- [TLS Configuration](#tls-configuration) - [High Availability](#high-availability) -- [Storage Configuration](#storage-configuration) - [Scheduling](#scheduling) -- [Resource Management](#resource-management) - [Security](#security) -## TLS Configuration - -The operator supports three TLS modes for secure gateway connections, each suited to different operational requirements. - -### TLS Modes - -1. **SelfSigned** — Automatic certificate management using cert-manager with self-signed certificates - - Best for: Development, testing, and environments without external PKI - - Zero external dependencies - - Automatic certificate rotation - -2. **Provided** — Use certificates from Azure Key Vault via Secrets Store CSI driver - - Best for: Production environments with centralized certificate management - - Enterprise PKI integration - - Azure Key Vault integration - -3. **CertManager** — Use custom cert-manager issuers (for example, Let's Encrypt or a corporate CA) - - Best for: Production environments with existing cert-manager infrastructure - - Flexible issuer support - - Industry-standard certificates - -### Getting Started with TLS - -For comprehensive TLS setup and testing documentation, see: - -- **[Complete TLS Setup Guide](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/README.md)** — Quick start with automated scripts, detailed configuration for each TLS mode, troubleshooting, and best practices -- **[E2E Testing Guide](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/E2E-TESTING.md)** — Automated and manual testing, validation procedures, and CI/CD integration examples - -### Quick TLS Setup - -For the fastest TLS setup, use the automated script: - -```bash -cd documentdb-playground/tls/scripts - -# Complete E2E setup (AKS + DocumentDB + TLS) -./create-cluster.sh \ - --suffix mytest \ - --subscription-id -``` - -This command will: - -- Create an AKS cluster with all required addons -- Install cert-manager and the CSI driver -- Deploy the DocumentDB operator -- Configure and validate both SelfSigned and Provided TLS modes - -**Duration**: ~25–30 minutes - -### TLS Configuration Examples - -#### SelfSigned Mode - -SelfSigned mode requires no additional configuration beyond setting the mode: - -```yaml -apiVersion: documentdb.io/preview -kind: DocumentDB -metadata: - name: documentdb-selfsigned - namespace: default -spec: - nodeCount: 1 - instancesPerNode: 3 - resource: - storage: - pvcSize: 10Gi - tls: - gateway: - mode: SelfSigned -``` - -#### Provided Mode (Azure Key Vault) - -```yaml -apiVersion: documentdb.io/preview -kind: DocumentDB -metadata: - name: documentdb-provided - namespace: default -spec: - nodeCount: 1 - instancesPerNode: 3 - resource: - storage: - pvcSize: 10Gi - tls: - gateway: - mode: Provided - provided: - secretName: documentdb-tls-akv -``` - -#### CertManager Mode with a custom issuer - -```yaml -apiVersion: documentdb.io/preview -kind: DocumentDB -metadata: - name: documentdb-certmanager - namespace: default -spec: - nodeCount: 1 - instancesPerNode: 3 - resource: - storage: - pvcSize: 10Gi - tls: - gateway: - mode: CertManager - certManager: - issuerRef: - name: letsencrypt-prod - kind: ClusterIssuer - dnsNames: - - documentdb.example.com - - "*.documentdb.example.com" -``` - -### TLS Status and Monitoring - -Check the TLS status of your DocumentDB instance: - -```bash -kubectl get documentdb -n -o jsonpath='{.status.tls}' | jq -``` - -Example output: - -```json -{ - "ready": true, - "secretName": "documentdb-gateway-cert-tls", - "message": "" -} -``` - -### Certificate Rotation - -The operator handles certificate rotation automatically: - -- **SelfSigned and CertManager modes**: cert-manager rotates certificates before expiration -- **Provided mode**: Sync certificates from Azure Key Vault on rotation - -Monitor certificate expiration: - -```bash -# Check certificate expiration -kubectl get certificate -n -o jsonpath='{.status.notAfter}' - -# Inspect the TLS secret directly -kubectl get secret -n -o jsonpath='{.data.tls\.crt}' | \ - base64 -d | openssl x509 -noout -dates -``` - -### Troubleshooting TLS - -For comprehensive troubleshooting, see the [E2E Testing Guide](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/E2E-TESTING.md#troubleshooting). - -Common issues: - -1. **Certificate not ready** — Check cert-manager logs and certificate status -2. **Connection failures** — Verify service endpoints and TLS handshake -3. **Azure Key Vault access denied** — Check managed identity and RBAC permissions - -Quick diagnostics: - -```bash -# Check DocumentDB TLS status -kubectl describe documentdb -n - -# Check certificate status -kubectl describe certificate -n - -# Check cert-manager logs -kubectl logs -n cert-manager deployment/cert-manager - -# Test TLS handshake -EXTERNAL_IP=$(kubectl get svc -n -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -openssl s_client -connect $EXTERNAL_IP:10260 -``` - ---- - ## High Availability Deploy multiple instances for automatic failover and read scalability. @@ -227,138 +39,6 @@ spec: --- -## Storage Configuration - -Configure persistent storage for DocumentDB instances. - -### Storage Classes - -```yaml -spec: - resource: - storage: - pvcSize: 100Gi - storageClass: premium-ssd # Azure Premium SSD -``` - -### Volume Expansion - -```bash -# Ensure storage class allows volume expansion -kubectl get storageclass -o jsonpath='{.allowVolumeExpansion}' - -# Patch DocumentDB for larger storage -kubectl patch documentdb -n --type='json' \ - -p='[{"op": "replace", "path": "/spec/resource/storage/pvcSize", "value":"200Gi"}]' -``` - -### PersistentVolume Security - -The DocumentDB operator automatically applies security-hardening mount options to all PersistentVolumes associated with DocumentDB clusters: - -| Mount Option | Description | -|--------------|-------------| -| `nodev` | Prevents device files from being interpreted on the filesystem | -| `nosuid` | Prevents setuid/setgid bits from taking effect | -| `noexec` | Prevents execution of binaries on the filesystem | - -These options are automatically applied by the PV controller and require no additional configuration. - -### Disk Encryption - -Encryption at rest is essential for protecting sensitive database data. Here's how to configure disk encryption for each cloud provider: - -#### Azure Kubernetes Service (AKS) - -AKS encrypts all managed disks by default using Azure Storage Service Encryption (SSE) with platform-managed keys. No additional configuration is required. - -For customer-managed keys (CMK), use Azure Disk Encryption: - -```yaml -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: managed-csi-encrypted -provisioner: disk.csi.azure.com -parameters: - skuName: Premium_LRS - # For customer-managed keys, specify the disk encryption set - diskEncryptionSetID: /subscriptions//resourceGroups//providers/Microsoft.Compute/diskEncryptionSets/ -reclaimPolicy: Delete -volumeBindingMode: WaitForFirstConsumer -allowVolumeExpansion: true -``` - -#### Google Kubernetes Engine (GKE) - -GKE encrypts all persistent disks by default using Google-managed encryption keys. No additional configuration is required. - -For customer-managed encryption keys (CMEK): - -```yaml -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: pd-ssd-encrypted -provisioner: pd.csi.storage.gke.io -parameters: - type: pd-ssd - # For CMEK, specify the key - disk-encryption-kms-key: projects//locations//keyRings//cryptoKeys/ -reclaimPolicy: Delete -volumeBindingMode: WaitForFirstConsumer -allowVolumeExpansion: true -``` - -#### Amazon Elastic Kubernetes Service (EKS) - -**Important**: Unlike AKS and GKE, EBS volumes on EKS are **not encrypted by default**. You must explicitly enable encryption in the StorageClass: - -```yaml -apiVersion: storage.k8s.io/v1 -kind: StorageClass -metadata: - name: ebs-sc-encrypted -provisioner: ebs.csi.aws.com -parameters: - type: gp3 - encrypted: "true" # Required for encryption - # Optional: specify a KMS key for customer-managed encryption - # kmsKeyId: arn:aws:kms:::key/ -reclaimPolicy: Delete -volumeBindingMode: WaitForFirstConsumer -allowVolumeExpansion: true -``` - -To use the encrypted storage class with DocumentDB: - -```yaml -apiVersion: documentdb.io/preview -kind: DocumentDB -metadata: - name: my-cluster - namespace: default -spec: - environment: eks - resource: - storage: - pvcSize: 100Gi - storageClass: ebs-sc-encrypted # Use the encrypted storage class - # ... other configuration -``` - -### Encryption Summary - -| Provider | Default Encryption | Customer-Managed Keys | -|----------|-------------------|----------------------| -| AKS | ✅ Enabled (SSE) | Optional via DiskEncryptionSet | -| GKE | ✅ Enabled (Google-managed) | Optional via CMEK | -| EKS | ❌ **Not enabled** | Required: set `encrypted: "true"` in StorageClass | - -**Recommendation**: For production deployments on EKS, always create a StorageClass with `encrypted: "true"` to ensure data at rest is protected. - ---- - ## Scheduling Configure pod affinity for a documentdb cluster's database pods. This replicates @@ -370,64 +50,10 @@ spec: ... ``` -## Resource Management - -Configure resource requests and limits for optimal performance. - -### Example Configuration - -```yaml -apiVersion: documentdb.io/preview -kind: DocumentDB -metadata: - name: documentdb-resources - namespace: default -spec: - nodeCount: 1 - instancesPerNode: 3 - resource: - storage: - pvcSize: 100Gi -``` - -### Recommendations - -- **Development**: 1 CPU, 2 GiB memory -- **Production**: 2–4 CPUs, 4–8 GiB memory -- **High-load**: 4–8 CPUs, 8–16 GiB memory - ---- - ## Security Security best practices for DocumentDB deployments. -### Network Policies - -Restrict network access to DocumentDB: - -```yaml -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: documentdb-access - namespace: default -spec: - podSelector: - matchLabels: - app.kubernetes.io/name: documentdb - policyTypes: - - Ingress - ingress: - - from: - - namespaceSelector: - matchLabels: - name: app-namespace - ports: - - protocol: TCP - port: 10260 -``` - ### RBAC The operator requires specific permissions to manage DocumentDB resources. The Helm chart automatically creates the necessary RBAC rules. @@ -456,7 +82,4 @@ For production, consider using: ## Additional Resources -- [Public Documentation](https://documentdb.io/documentdb-kubernetes-operator/preview/) -- [TLS Setup Guide](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/README.md) -- [E2E Testing Guide](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/E2E-TESTING.md) - [GitHub Repository](https://github.com/documentdb/documentdb-kubernetes-operator) diff --git a/docs/operator-public-documentation/preview/backup-and-restore.md b/docs/operator-public-documentation/preview/backup-and-restore.md index a51139e7..64faddb9 100644 --- a/docs/operator-public-documentation/preview/backup-and-restore.md +++ b/docs/operator-public-documentation/preview/backup-and-restore.md @@ -1,5 +1,8 @@ # Backup and Restore +!!! tip + For the complete Backup and ScheduledBackup CRD field definitions, see the [API Reference](api-reference.md#backup). + ## Prerequisites ### For Kind or Minikube diff --git a/docs/operator-public-documentation/preview/configuration/networking.md b/docs/operator-public-documentation/preview/configuration/networking.md new file mode 100644 index 00000000..53355315 --- /dev/null +++ b/docs/operator-public-documentation/preview/configuration/networking.md @@ -0,0 +1,236 @@ +--- +title: Networking Configuration +description: Configure service types, external access, DNS, load balancer annotations, and Network Policies for DocumentDB on AKS, EKS, and GKE. +tags: + - configuration + - networking + - load-balancer +--- + +# Networking Configuration + +## Overview + +Networking controls how clients connect to your DocumentDB cluster. Configure it to choose between internal-only or external access, and to secure traffic with Network Policies. + +The operator creates a Kubernetes [Service](https://kubernetes.io/docs/concepts/services-networking/service/) named `documentdb-service-` to provide a stable endpoint for your applications. Since pod IPs change whenever pods restart, the Service gives you a fixed address that automatically routes traffic to the active primary pod on port **10260**. You can control how this service is exposed by setting the `exposeViaService` field: + +```yaml +apiVersion: documentdb.io/preview +kind: DocumentDB +metadata: + name: my-documentdb +spec: + environment: aks # Optional: aks | eks | gke + exposeViaService: + serviceType: LoadBalancer # ClusterIP (default) | LoadBalancer +``` + +For the full field reference, see [ExposeViaService](../api-reference.md#exposeviaservice) in the API Reference. + +## Service Types + +=== "ClusterIP (Internal)" + + Use [ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#type-clusterip) when your applications run **inside** the same Kubernetes cluster. This is the default and most secure option — the database is not exposed outside the Kubernetes cluster. For local development, use `kubectl port-forward`. + + ```yaml + apiVersion: documentdb.io/preview + kind: DocumentDB + metadata: + name: my-documentdb + namespace: default + spec: + nodeCount: 1 + instancesPerNode: 1 + resource: + storage: + pvcSize: 10Gi + exposeViaService: + serviceType: ClusterIP + ``` + +=== "LoadBalancer (External)" + + Use [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer) when your applications run **outside** the Kubernetes cluster, or you need a public or cloud-accessible endpoint. The cloud provider provisions an external IP (AKS, GKE) or hostname (EKS). + + Setting `environment` is optional but recommended — it adds cloud-specific annotations to the LoadBalancer service: + + - **`aks`**: Explicitly marks the load balancer as external (`azure-load-balancer-external: true`) + - **`eks`**: Uses AWS Network Load Balancer (NLB) with cross-zone balancing and IP-based targeting for lower latency + - **`gke`**: Sets the load balancer type to External + + Without `environment`, a generic LoadBalancer is created that relies on the cloud provider's default behavior. + + === "AKS" + + ```yaml + apiVersion: documentdb.io/preview + kind: DocumentDB + metadata: + name: my-documentdb + namespace: default + spec: + nodeCount: 1 + instancesPerNode: 1 + resource: + storage: + pvcSize: 10Gi + environment: aks + exposeViaService: + serviceType: LoadBalancer + ``` + + === "EKS" + + ```yaml + apiVersion: documentdb.io/preview + kind: DocumentDB + metadata: + name: my-documentdb + namespace: default + spec: + nodeCount: 1 + instancesPerNode: 1 + resource: + storage: + pvcSize: 10Gi + environment: eks + exposeViaService: + serviceType: LoadBalancer + ``` + + === "GKE" + + ```yaml + apiVersion: documentdb.io/preview + kind: DocumentDB + metadata: + name: my-documentdb + namespace: default + spec: + nodeCount: 1 + instancesPerNode: 1 + resource: + storage: + pvcSize: 10Gi + environment: gke + exposeViaService: + serviceType: LoadBalancer + ``` + +## Connect with mongosh + +=== "Connection String" + + Retrieve the connection string from the DocumentDB resource status and connect. This works with both ClusterIP and LoadBalancer service types — the operator automatically populates it with the correct service address. + + The connection string contains embedded `kubectl` commands that resolve your credentials automatically: + + ```bash + CONNECTION_STRING=$(eval echo "$(kubectl get documentdb my-documentdb -n default -o jsonpath='{.status.connectionString}')") + mongosh "$CONNECTION_STRING" + ``` + +=== "Port Forwarding" + + Port forwarding works with any service type and is useful for local development. It connects directly to the pod, bypassing the Kubernetes Service. Run `kubectl port-forward` in one terminal and `mongosh` in a separate terminal, since port forwarding must stay running. + + ```bash + # Terminal 1 — keep this running + kubectl port-forward svc/documentdb-service-my-documentdb -n default 10260:10260 + ``` + + ```bash + # Terminal 2 + mongosh "mongodb://:@localhost:10260/?directConnection=true" + ``` + +## Network Policies + +If your Kubernetes cluster uses restrictive [NetworkPolicies](https://kubernetes.io/docs/concepts/services-networking/network-policies/), ensure the following traffic is allowed: + +| Traffic | From | To | Port | +|---------|------|----|------| +| Application → Gateway | Application namespace | DocumentDB pods | 10260 | +| CNPG instance manager | CNPG operator / DocumentDB pods | DocumentDB pods | 8000 | +| Database replication | DocumentDB pods | DocumentDB pods | 5432 | + +!!! note + The replication rule (port 5432) is only needed when `instancesPerNode > 1`. + +### Example NetworkPolicy Configuration + +If your Kubernetes cluster enforces a default-deny ingress policy, apply the following to allow DocumentDB traffic. + +=== "Gateway Access (port 10260)" + + Allow application traffic to the DocumentDB gateway: + + ```yaml + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-documentdb-gateway + namespace: + spec: + podSelector: + matchLabels: + app: # matches your DocumentDB CR name + policyTypes: + - Ingress + ingress: + - ports: + - protocol: TCP + port: 10260 + ``` + +=== "CNPG Instance Manager (port 8000)" + + Allow CNPG operator health checks. **Required** — without this, CNPG cannot manage pod lifecycle. + + ```yaml + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-cnpg-status + namespace: + spec: + podSelector: + matchLabels: + app: + policyTypes: + - Ingress + ingress: + - ports: + - protocol: TCP + port: 8000 + ``` + +=== "Replication (port 5432)" + + Allow pod-to-pod replication traffic. Only needed when `instancesPerNode > 1`. + + ```yaml + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-documentdb-replication + namespace: + spec: + podSelector: + matchLabels: + app: + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + app: + ports: + - protocol: TCP + port: 5432 + ``` + +See the [Kubernetes NetworkPolicy documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/) for more details. diff --git a/docs/operator-public-documentation/preview/configuration/storage.md b/docs/operator-public-documentation/preview/configuration/storage.md new file mode 100644 index 00000000..7377130c --- /dev/null +++ b/docs/operator-public-documentation/preview/configuration/storage.md @@ -0,0 +1,96 @@ +--- +title: Storage Configuration +description: Configure persistent storage for DocumentDB including storage classes, PVC sizing, volume expansion, reclaim policies, and disk encryption across AKS, EKS, and GKE. +tags: + - configuration + - storage + - encryption +--- + +# Storage Configuration + +## Overview + +Storage controls how DocumentDB persists data — including disk size, storage type, retention behavior, and encryption. + +Each DocumentDB instance stores its data on a Kubernetes [PersistentVolume (PV)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) provisioned through a [PersistentVolumeClaim (PVC)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims). You need to specify at least the disk size; optionally, you can choose a storage class for your cloud provider and control what happens to the data when the DocumentDB cluster is deleted. Configure storage through the `spec.resource.storage` field: + +```yaml +apiVersion: documentdb.io/preview +kind: DocumentDB +metadata: + name: my-documentdb +spec: + resource: + storage: + pvcSize: 100Gi # Required: storage size + storageClass: managed-csi-premium # Optional: defaults to Kubernetes default StorageClass + persistentVolumeReclaimPolicy: Retain # Optional: Retain (default) or Delete +``` + +For the full field reference, see [StorageConfiguration](../api-reference.md#storageconfiguration) in the API Reference. + +## Disk Size (`pvcSize`) + +The `pvcSize` field sets how much disk space each DocumentDB instance gets. This is set at DocumentDB cluster creation time. Online resizing is **coming soon** — see [#298](https://github.com/documentdb/documentdb-kubernetes-operator/issues/298) for tracking. + +## Reclaim Policy (`persistentVolumeReclaimPolicy`) + +The `persistentVolumeReclaimPolicy` field controls what happens to your data when a DocumentDB cluster is deleted: + +| Policy | Behavior | +|--------|----------| +| `Retain` (default) | Data is preserved after DocumentDB deletion. **Recommended for production.** | +| `Delete` | Data is permanently deleted with the DocumentDB cluster. Suitable for development. | + +With `Retain`, you can recover data even after the DocumentDB cluster is gone. See [PersistentVolume Retention and Recovery](../backup-and-restore.md#persistentvolume-retention-and-recovery) for restore steps. + +## Storage Classes (`storageClass`) + +The `storageClass` field selects which type of underlying disk (e.g., SSD vs HDD) to provision. See [Kubernetes StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/) for details. If you don't specify one, Kubernetes uses the default StorageClass in your Kubernetes cluster. + +To see available StorageClasses and which one is the default: + +```bash +kubectl get storageclass +``` + +The default is marked with `(default)` in the output. + +## Disk Encryption + +Disk encryption protects your data at rest — if someone gains physical access to the underlying storage, the data is unreadable without the encryption key. Most cloud providers enable this by default, but EKS requires explicit configuration. + +| Provider | Default Encryption | Customer-Managed Keys | +|----------|-------------------|----------------------| +| **AKS** | ✅ Enabled (platform-managed keys) | [Azure Disk Encryption with CMK](https://learn.microsoft.com/azure/aks/azure-disk-customer-managed-keys) | +| **GKE** | ✅ Enabled (Google-managed keys) | [CMEK for GKE persistent disks](https://cloud.google.com/kubernetes-engine/docs/how-to/using-cmek) | +| **EKS** | ❌ **Not enabled by default** | [EBS CSI driver encryption](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html) — set `encrypted: "true"` in StorageClass | + +!!! warning + For production on EKS, always create a StorageClass with `encrypted: "true"` to ensure data at rest is protected. + + ```yaml + apiVersion: storage.k8s.io/v1 + kind: StorageClass + metadata: + name: ebs-sc-encrypted + provisioner: ebs.csi.aws.com + parameters: + type: gp3 + encrypted: "true" + # kmsKeyId: arn:aws:kms:::key/ # Optional: customer-managed key + reclaimPolicy: Delete + volumeBindingMode: WaitForFirstConsumer + allowVolumeExpansion: true + ``` + +## PersistentVolume Security + +As a defense-in-depth measure, the operator automatically applies security-hardening mount options to all DocumentDB volumes. These prevent common attack vectors even if a container is compromised: + +| Mount Option | What it prevents | +|--------------|------------------| +| `nodev` | Blocks creation of device files that could access host hardware | +| `nosuid` | Blocks privilege escalation via setuid/setgid binaries | +| `noexec` | Blocks execution of malicious binaries written to the data volume | diff --git a/docs/operator-public-documentation/preview/configuration/tls.md b/docs/operator-public-documentation/preview/configuration/tls.md new file mode 100644 index 00000000..0c634094 --- /dev/null +++ b/docs/operator-public-documentation/preview/configuration/tls.md @@ -0,0 +1,296 @@ +--- +title: TLS Configuration +description: Configure TLS encryption for DocumentDB gateway connections with SelfSigned, Provided, and CertManager modes, certificate rotation, and troubleshooting. +tags: + - configuration + - tls + - security +--- + +# TLS Configuration + +## Overview + +TLS encrypts connections between your applications and DocumentDB. Configure it to protect data in transit and meet your security requirements. + +The DocumentDB gateway always encrypts connections — TLS is active regardless of the mode you choose. The `spec.tls.gateway.mode` field controls how the operator manages TLS certificates: + +```yaml +apiVersion: documentdb.io/preview +kind: DocumentDB +metadata: + name: my-documentdb +spec: + tls: + gateway: + mode: SelfSigned # Disabled | SelfSigned | CertManager | Provided +``` + +For the full field reference, see [TLSConfiguration](../api-reference.md#tlsconfiguration) in the API Reference. + +## Configuration + +Select your TLS mode below. Each tab shows prerequisites, the complete YAML configuration, and connection instructions. + +=== "Disabled" + + **Best for:** Development and testing only + + !!! danger "Not recommended for production" + + **Prerequisites:** None + + Disabled mode means the operator does not manage TLS certificates. However, the gateway still encrypts all connections using an internally generated self-signed certificate. Clients must connect with `tls=true&tlsAllowInvalidCertificates=true`. + + ```yaml title="documentdb-tls-disabled.yaml" + apiVersion: documentdb.io/preview + kind: DocumentDB + metadata: + name: my-documentdb + namespace: default + spec: + nodeCount: 1 + instancesPerNode: 1 + resource: + storage: + pvcSize: 10Gi + exposeViaService: + serviceType: ClusterIP + tls: + gateway: + mode: Disabled + ``` + + **Connect with mongosh:** + + ```bash + mongosh "mongodb://:@:10260/?directConnection=true&authMechanism=SCRAM-SHA-256&tls=true&tlsAllowInvalidCertificates=true" + ``` + +=== "SelfSigned" + + **Best for:** Development, testing, and environments without external PKI (Public Key Infrastructure) + + !!! note "Prerequisites" + [cert-manager](https://cert-manager.io/) must be installed in the Kubernetes cluster. See [Install cert-manager](../index.md#install-cert-manager) for setup instructions. + + SelfSigned mode uses cert-manager to automatically generate, manage, and rotate a self-signed server certificate (90-day validity, renewed 15 days before expiry). No additional configuration is needed beyond setting the mode. + + ```yaml title="documentdb-tls-selfsigned.yaml" + apiVersion: documentdb.io/preview + kind: DocumentDB + metadata: + name: my-documentdb + namespace: default + spec: + nodeCount: 1 + instancesPerNode: 3 + resource: + storage: + pvcSize: 10Gi + exposeViaService: + serviceType: ClusterIP + tls: + gateway: + mode: SelfSigned + ``` + + **Connect with mongosh:** + + ```bash + # Extract the CA certificate from the Secret + kubectl get secret my-documentdb-gateway-cert-tls -n default \ + -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt + + # Connect with TLS + mongosh "mongodb://:@:10260/?directConnection=true&authMechanism=SCRAM-SHA-256" \ + --tls --tlsCAFile ca.crt + ``` + +=== "CertManager" + + **Best for:** Production with existing cert-manager infrastructure + + !!! note "Prerequisites" + [cert-manager](https://cert-manager.io/) must be installed (see [Install cert-manager](../index.md#install-cert-manager)), plus a configured [Issuer or ClusterIssuer](https://cert-manager.io/docs/concepts/issuer/). + + ??? example "Setting up a CA Issuer with cert-manager" + + If you don't already have an Issuer, you can bootstrap a simple CA Issuer: + + ```yaml title="cert-manager-ca-issuer.yaml" + # Step 1: A self-signed issuer to bootstrap the CA certificate + apiVersion: cert-manager.io/v1 + kind: Issuer + metadata: + name: selfsigned-bootstrap + spec: + selfSigned: {} + --- + # Step 2: A CA certificate issued by the bootstrap issuer + apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: my-ca + spec: + isCA: true + commonName: my-documentdb-ca + secretName: my-ca-secret + duration: 8760h # 1 year + issuerRef: + name: selfsigned-bootstrap + kind: Issuer + --- + # Step 3: A CA issuer that signs certificates using the CA certificate + apiVersion: cert-manager.io/v1 + kind: Issuer + metadata: + name: my-ca-issuer + spec: + ca: + secretName: my-ca-secret + ``` + + CertManager mode lets you use your own cert-manager [Issuer](https://cert-manager.io/docs/concepts/issuer/#namespaces) (namespace-scoped) or [ClusterIssuer](https://cert-manager.io/docs/concepts/issuer/) (cluster-scoped) to issue TLS certificates for the DocumentDB gateway. This is ideal for production environments that already have PKI infrastructure (for example, a corporate CA). + + Set `issuerRef.name` and `issuerRef.kind` to match your Issuer or ClusterIssuer. The operator will automatically request a certificate and mount it in the gateway. + + ```yaml title="documentdb-tls-certmanager.yaml" + apiVersion: documentdb.io/preview + kind: DocumentDB + metadata: + name: my-documentdb + namespace: default + spec: + nodeCount: 1 + instancesPerNode: 3 + resource: + storage: + pvcSize: 100Gi + exposeViaService: + serviceType: ClusterIP + tls: + gateway: + mode: CertManager + certManager: + issuerRef: + name: my-ca-issuer # (1)! + kind: Issuer # (2)! + dnsNames: # (3)! + - documentdb.example.com + secretName: my-documentdb-tls # (4)! + ``` + + 1. Must match the `metadata.name` of your Issuer or ClusterIssuer (e.g., `my-ca-issuer` from the prerequisite example above). + 2. Use [`ClusterIssuer`](https://cert-manager.io/docs/concepts/issuer/#cluster-resource) for cluster-scoped issuers, or [`Issuer`](https://cert-manager.io/docs/concepts/issuer/#namespaces) for namespace-scoped. + 3. [Subject Alternative Names](https://en.wikipedia.org/wiki/Subject_Alternative_Name) — add all DNS names clients will use to connect. + 4. Optional. The Kubernetes Secret where cert-manager stores the issued certificate — you do not need to create this Secret yourself, cert-manager generates it automatically. Defaults to `-gateway-cert-tls` if not specified. + + For a complete list of CertManager fields, see [CertManagerTLS](../api-reference.md#certmanagertls) in the API Reference. + + **Connect with mongosh:** + + If your CA is private (which most cert-manager setups are), you need `--tlsCAFile` so mongosh can verify the server certificate: + + ```bash + # Extract the CA certificate from the Secret + kubectl get secret my-documentdb-tls -n default \ + -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt + + # Connect with TLS + mongosh "mongodb://:@:10260/?directConnection=true&authMechanism=SCRAM-SHA-256" \ + --tls --tlsCAFile ca.crt + ``` + +=== "Provided" + + **Best for:** Production with centralized certificate management + + !!! note "Prerequisites" + A Kubernetes [TLS Secret](https://kubernetes.io/docs/concepts/configuration/secret/#tls-secrets) containing `tls.crt` and `tls.key`. + + ??? example "Creating a TLS Secret" + + ```bash + kubectl create secret generic my-documentdb-tls -n default \ + --from-file=tls.crt=server.crt \ + --from-file=tls.key=server.key \ + --from-file=ca.crt=ca.crt # (1)! + ``` + + 1. Optional. The gateway only uses `tls.crt` and `tls.key`. Including `ca.crt` stores the CA certificate in the same Secret for easy client-side retrieval. + + Provided mode lets you supply your own TLS certificates. This is ideal when certificates are managed externally (for example, from Azure Key Vault, HashiCorp Vault, or a corporate CA). + + ```yaml title="documentdb-tls-provided.yaml" + apiVersion: documentdb.io/preview + kind: DocumentDB + metadata: + name: my-documentdb + namespace: default + spec: + nodeCount: 1 + instancesPerNode: 3 + resource: + storage: + pvcSize: 100Gi + exposeViaService: + serviceType: ClusterIP + tls: + gateway: + mode: Provided + provided: + secretName: my-documentdb-tls + ``` + + **Connect with mongosh:** + + If your CA is private, you need `--tlsCAFile` so mongosh can verify the server certificate: + + ```bash + # Connect with TLS using your CA certificate + mongosh "mongodb://:@:10260/?directConnection=true&authMechanism=SCRAM-SHA-256" \ + --tls --tlsCAFile ca.crt + ``` + +## Certificate Rotation + +Certificate rotation is automatic and zero-downtime. When a certificate is renewed, the gateway picks up the new certificate without restarting pods. + +| Mode | Rotation | Action required | +|------|----------|-----------------| +| **SelfSigned** | cert-manager auto-renews 15 days before the 90-day expiry | None | +| **CertManager** | cert-manager auto-renews based on the Certificate CR's `renewBefore` | None | +| **Provided** | You update the Secret contents (manually or via CSI driver sync) | Update the Secret | + +### Monitoring Certificate Expiration + +```bash +# Check certificate status via cert-manager +kubectl get certificate -n + +# Check expiration date +kubectl get secret -n \ + -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -dates + +# Check DocumentDB TLS status +kubectl get documentdb -n \ + -o jsonpath='{.status.tls}' | jq +``` + +Example TLS status output: + +```json +{ + "ready": true, + "secretName": "my-documentdb-gateway-cert-tls", + "message": "Gateway TLS certificate ready" +} +``` + +## Additional Resources + +The [`documentdb-playground/tls/`](https://github.com/documentdb/documentdb-kubernetes-operator/tree/main/documentdb-playground/tls) directory provides automated scripts and end-to-end guides for TLS setup on AKS: + +- 📖 **[E2E Testing Guide](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/E2E-TESTING.md)** — Automated and manual E2E testing workflows for all TLS modes +- 📘 **[Manual Provided-Mode Setup](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/MANUAL-PROVIDED-MODE-SETUP.md)** — Step-by-step guide for Provided TLS mode with Azure Key Vault diff --git a/docs/operator-public-documentation/preview/faq.md b/docs/operator-public-documentation/preview/faq.md index 22213fca..f08d54be 100644 --- a/docs/operator-public-documentation/preview/faq.md +++ b/docs/operator-public-documentation/preview/faq.md @@ -23,6 +23,10 @@ The operator works on any conformant Kubernetes distribution (version 1.30 or la The operator is under active development and currently in **preview**. We don't yet recommend it for production workloads. We welcome feedback and contributions as we work toward general availability. +### Where can I find the full CRD field reference? + +See the [API Reference](api-reference.md) for auto-generated documentation of all DocumentDB, Backup, and ScheduledBackup CRD fields with types, defaults, and validation rules. + ## Installation ### Do I need to install CloudNativePG separately? diff --git a/docs/operator-public-documentation/preview/index.md b/docs/operator-public-documentation/preview/index.md index f875fd7a..30b7238c 100644 --- a/docs/operator-public-documentation/preview/index.md +++ b/docs/operator-public-documentation/preview/index.md @@ -184,7 +184,7 @@ documentdb-preview Cluster in healthy state mongodb://... ### Connect to the DocumentDB cluster -Choose a connection method based on your service type. +Choose a connection method based on your service type. For more details on service types, load balancers, and Network Policies, see [Networking](configuration/networking.md). For TLS certificate configuration, see [TLS](configuration/tls.md). #### Option 1: ClusterIP service (default — for local development) @@ -406,14 +406,6 @@ This configuration creates: The operator supports deployment across multiple cloud environments and Kubernetes distributions. For guidance, see the [Multi-Cloud Deployment Guide](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/multi-cloud-deployment/README.md). -### TLS setup - -For advanced TLS configuration and testing: - -- [TLS Setup Guide](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/README.md) — Complete TLS configuration guide -- [E2E Testing](https://github.com/documentdb/documentdb-kubernetes-operator/blob/main/documentdb-playground/tls/E2E-TESTING.md) — Comprehensive testing procedures - - ## Clean up ### Delete the DocumentDB cluster diff --git a/mkdocs.yml b/mkdocs.yml index b9af440f..1bc4e919 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,6 +8,13 @@ theme: name: material features: - content.code.copy + - content.code.annotate + - content.tabs.link + - navigation.tabs + - navigation.sections + - navigation.top + - search.suggest + - search.highlight # mike (https://github.com/jimporter/mike) enables versioned docs on GitHub Pages. # Each release gets a frozen snapshot (e.g., /0.2.0/), and "latest" always points @@ -21,6 +28,10 @@ extra: nav: - Preview: - Get Started: preview/index.md + - Configuration: + - Networking: preview/configuration/networking.md + - TLS: preview/configuration/tls.md + - Storage: preview/configuration/storage.md - Advanced Configuration: preview/advanced-configuration/README.md - Backup and Restore: preview/backup-and-restore.md - API Reference: preview/api-reference.md @@ -33,5 +44,13 @@ plugins: markdown_extensions: - admonition + - attr_list + - md_in_html + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.details - toc: permalink: true