diff --git a/docs/examples/oracle/dataguard/dataguard.yaml b/docs/examples/oracle/dataguard/dataguard.yaml new file mode 100644 index 000000000..7f3d469f5 --- /dev/null +++ b/docs/examples/oracle/dataguard/dataguard.yaml @@ -0,0 +1,85 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Oracle +metadata: + name: oracle-sample + namespace: demo +spec: + dataGuard: + applyLagThreshold: 0 + fastStartFailover: + fastStartFailoverThreshold: 15 + observer: + podTemplate: + spec: + containers: + - name: observer + resources: + limits: + cpu: "1" + memory: 2Gi + requests: + cpu: 500m + memory: 2Gi + initContainers: + - name: observer-init + resources: + limits: + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + podPlacementPolicy: + name: default + storage: + resources: + requests: + storage: 1Gi + protectionMode: MaximumProtection + standbyType: PHYSICAL + syncMode: SYNC + transportLagThreshold: 0 + deletionPolicy: Delete + edition: enterprise + mode: DataGuard + podTemplate: + spec: + containers: + - name: oracle + resources: + limits: + cpu: "4" + memory: 10Gi + requests: + cpu: "1500m" + memory: 4Gi + - name: oracle-coordinator + resources: + limits: + memory: 256Mi + requests: + cpu: 200m + memory: 256Mi + initContainers: + - name: oracle-init + resources: + limits: + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + podPlacementPolicy: + name: default + securityContext: + fsGroup: 54321 + runAsGroup: 54321 + runAsUser: 54321 + serviceAccountName: oracle-sample + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 30Gi + storageType: Durable + version: 21.3.0 \ No newline at end of file diff --git a/docs/examples/oracle/quickstart/standalone.yaml b/docs/examples/oracle/quickstart/standalone.yaml new file mode 100644 index 000000000..0f9637de8 --- /dev/null +++ b/docs/examples/oracle/quickstart/standalone.yaml @@ -0,0 +1,41 @@ +apiVersion: kubedb.com/v1alpha2 +kind: Oracle +metadata: + name: oracle + namespace: demo +spec: + deletionPolicy: Delete + edition: enterprise + mode: Standalone + podTemplate: + spec: + containers: + - name: oracle + resources: + limits: + cpu: "4" + memory: 10Gi + requests: + cpu: "2" + memory: 3Gi + initContainers: + - name: oracle-init + resources: + limits: + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + securityContext: + fsGroup: 54321 + runAsGroup: 54321 + runAsUser: 54321 + replicas: 1 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 30Gi + storageType: Durable + version: 21.3.0 \ No newline at end of file diff --git a/docs/guides/mysql/failure-and-disaster-recovery/overview.md b/docs/guides/mysql/failure-and-disaster-recovery/overview.md index 2e44ce981..a0380240a 100644 --- a/docs/guides/mysql/failure-and-disaster-recovery/overview.md +++ b/docs/guides/mysql/failure-and-disaster-recovery/overview.md @@ -133,7 +133,7 @@ ha-mysql-2 2/2 Running 0 34m app.kubernetes.io/component=data The pod having `kubedb.com/role=primary` is the primary and `kubedb.com/role=standby` are the standby's. -Lets create a table in the primary. +Let's create a table in the primary. ```shell # find the primary pod @@ -239,7 +239,7 @@ ha-mysql-2 standby #### Case 1: Delete the current primary -Lets delete the current primary and see how the role change happens almost immediately. +Let's delete the current primary and see how the role change happens almost immediately. ```shell $ kubectl delete pods -n demo ha-mysql-0 diff --git a/docs/guides/oracle/README.md b/docs/guides/oracle/README.md new file mode 100644 index 000000000..a2cba691f --- /dev/null +++ b/docs/guides/oracle/README.md @@ -0,0 +1,41 @@ +--- +title: Oracle +menu: + docs_{{ .version }}: + identifier: oracle-readme + name: Oracle + parent: guides-oracle + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +url: /docs/{{ .version }}/guides/oracle/ +aliases: + - /docs/{{ .version }}/guides/oracle/README/ +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +## Supported PostgreSQL Features + +| Features | Availability | +|------------------------------------|:------------:| +| Clustering | ✓ | +| Data Guard | ✓ | +| Synchronous Replication | ✓ | +| Streaming Replication | ✓ | +| Automatic Failover | ✓ | +| Persistent Volume | ✓ | +| Initialization using Script | ✓ | +| Using Custom docker image | ✓ | + +## Life Cycle of a PostgreSQL Object + +

+ lifecycle +

+ +## User Guide + +- [Quickstart PostgreSQL](/docs/guides/postgres/quickstart/quickstart.md) with KubeDB Operator. + + diff --git a/docs/guides/oracle/_index.md b/docs/guides/oracle/_index.md new file mode 100644 index 000000000..6f765658b --- /dev/null +++ b/docs/guides/oracle/_index.md @@ -0,0 +1,10 @@ +--- +title: Oracle +menu: + docs_{{ .version }}: + identifier: guides-oracle + name: Oracle + parent: guides + weight: 1 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/oracle/concepts/oracle.md b/docs/guides/oracle/concepts/oracle.md new file mode 100644 index 000000000..e8338cda3 --- /dev/null +++ b/docs/guides/oracle/concepts/oracle.md @@ -0,0 +1,233 @@ +--- +title: Oracle CRD +menu: + docs_{{ .version }}: + identifier: orc-concepts + name: Oracle + parent: orc-concepts-oracle + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Oracle CRD + +## What is Oracle CRD? + +`Oracle` is a Kubernetes Custom Resource Definition (CRD) maintained by KubeDB. It provides a declarative configuration for Oracle database instances in your Kubernetes cluster, enabling you to manage Oracle databases using native Kubernetes tools and practices. + +## Key Features + +- **Native Kubernetes Integration**: Manage Oracle databases using kubectl and Kubernetes APIs +- **Flexible Deployment Modes**: Support for both Standalone and DataGuard configurations +- **High Availability**: Built-in support for Oracle DataGuard for disaster recovery +- **Resource Management**: Fine-grained control over CPU, memory, and storage resources +- **Security Controls**: Built-in security context configuration for enhanced security +- **Automated Operations**: Simplified deployment and management of complex Oracle setups + +## Deployment Modes + +KubeDB Oracle supports two primary deployment modes: + +### 1. Standalone Mode +- Single instance Oracle database deployment +- Suitable for development and testing environments +- Simplified configuration and management + +### 2. DataGuard Mode +- High availability configuration with primary and standby databases +- Built-in disaster recovery capabilities +- Support for synchronous and asynchronous replication +- Observer process for automated failover + +## Oracle CRD Specification + +Like any official Kubernetes resource, an `Oracle` object has standard fields: +- `apiVersion`: Specifies the API version (kubedb.com/v1alpha2) +- `kind`: Defines the resource type (Oracle) +- `metadata`: Contains name, namespace, and other metadata +- `spec`: Defines the desired state of your Oracle instance + +### Sample Oracle Configuration + +#### 1. Standalone Mode Configuration + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Oracle +metadata: + name: oracle + namespace: demo +spec: + version: 21.3.0 + mode: Standalone + edition: enterprise + replicas: 1 + storageType: Durable + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 30Gi + podTemplate: + spec: + securityContext: + fsGroup: 54321 + runAsGroup: 54321 + runAsUser: 54321 + containers: + - name: oracle + resources: + limits: + cpu: "4" + memory: 10Gi + requests: + cpu: "2" + memory: 3Gi + deletionPolicy: Delete +``` +```shell +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/oracle/quickstart/standalone.yaml +oracle.kubedb.com/oracle created + +``` +#### 2. DataGuard Mode Configuration + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Oracle +metadata: + name: oracle-sample + namespace: demo +spec: + version: 21.3.0 + mode: DataGuard + edition: enterprise + replicas: 3 + + # DataGuard Specific Configuration + dataGuard: + protectionMode: MaximumProtection + standbyType: PHYSICAL + syncMode: SYNC + applyLagThreshold: 0 + transportLagThreshold: 0 + fastStartFailover: + fastStartFailoverThreshold: 15 + observer: + podTemplate: + spec: + containers: + - name: observer + resources: + limits: + cpu: "1" + memory: 2Gi + requests: + cpu: 500m + memory: 2Gi + storage: + resources: + requests: + storage: 1Gi + + # Storage Configuration + storageType: Durable + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 30Gi + + # Pod Configuration + podTemplate: + spec: + securityContext: + fsGroup: 54321 + runAsGroup: 54321 + runAsUser: 54321 + serviceAccountName: oracle-sample + containers: + - name: oracle + resources: + limits: + cpu: "4" + memory: 10Gi + requests: + cpu: "1500m" + memory: 4Gi + - name: oracle-coordinator + resources: + limits: + memory: 256Mi + requests: + cpu: 200m + memory: 256Mi + + deletionPolicy: Delete +``` + +### Configuration Parameters Explained + +#### Core Parameters +- `version`: Oracle database version (e.g., 21.3.0) +- `mode`: Deployment mode (Standalone or DataGuard) +- `edition`: Oracle edition (enterprise, standard) +- `replicas`: Number of database instances + +#### DataGuard Specific Parameters +- `protectionMode`: Defines the data protection mode (MaximumProtection, MaximumAvailability, MaximumPerformance) +- `standbyType`: Type of standby database (PHYSICAL) +- `syncMode`: Synchronization mode between primary and standby (SYNC, ASYNC) +- `applyLagThreshold`: Maximum acceptable lag in applying changes +- `transportLagThreshold`: Maximum acceptable transport lag +- `fastStartFailover`: Configuration for automated failover +- `observer`: Configuration for the DataGuard observer process + +#### Storage Configuration +- `storageType`: Type of storage (Durable for persistent storage) +- `storage`: Kubernetes PVC configuration + - `accessModes`: Volume mount access modes + - `resources`: Storage resource requests and limits + +#### Pod Configuration +- `podTemplate`: Pod customization options + - `securityContext`: Security settings + - `containers`: Resource configurations for various containers + - `serviceAccountName`: Kubernetes service account to use + +#### Lifecycle Management +- `deletionPolicy`: Resource cleanup policy on deletion + +## Best Practices + +1. **Deployment Mode Selection**: + - Use Standalone mode for development/testing + - Choose DataGuard mode for production environments requiring high availability + +2. **Resource Planning**: + - Allocate sufficient resources based on workload + - Consider overhead for DataGuard synchronization + - Plan observer resources carefully + +3. **Storage Configuration**: + - Use enterprise-grade storage for production + - Configure appropriate storage class + - Plan for backup storage + +4. **Security**: + - Implement proper security contexts + - Use service accounts with minimum required permissions + - Regular security patches and updates + +5. **Monitoring and Maintenance**: + - Monitor replication lag in DataGuard setups + - Regular backup testing + - Keep track of resource usage patterns + +6. **High Availability**: + - Configure appropriate FastStart Failover thresholds + - Regular failover testing + - Monitor observer health diff --git a/docs/guides/oracle/failover/_index.md b/docs/guides/oracle/failover/_index.md new file mode 100644 index 000000000..ea09eb3f4 --- /dev/null +++ b/docs/guides/oracle/failover/_index.md @@ -0,0 +1,11 @@ +--- +title: Oracle Fdr +menu: + docs_{{ .version }}: + identifier: guides-oracle-fdr + name: Failover and Disaster Recovery + parent: guides-oracle + weight: 5 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- \ No newline at end of file diff --git a/docs/guides/oracle/failover/overview.md b/docs/guides/oracle/failover/overview.md new file mode 100644 index 000000000..6a1616f91 --- /dev/null +++ b/docs/guides/oracle/failover/overview.md @@ -0,0 +1,523 @@ +--- + +title: Oracle Failover and DR Scenarios +menu: +docs_{{ .version }}: +identifier: guides-oracle-failure-and-disaster-recovery-overview +name: Guide +parent: guides-oracle-failure-and-disaster-recovery +weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +----------------------- + +> New to KubeDB? Please start [here](/docs/setup/README.md). + +# Maximizing Oracle Uptime and Reliability + +## A Guide to KubeDB's Data Guard Based High Availability and Auto-Failover + +For mission-critical workloads, Oracle databases are often deployed with `Data Guard`, Oracle’s proven +technology for disaster recovery and failover. KubeDB extends this capability by natively supporting Data +Guard based replication and automatic failover within Kubernetes clusters. + +When the `primary database` becomes unavailable, `KubeDB` together with `Oracle Data Guard` and its `observer process` +ensures a healthy standby is automatically promoted to primary. This guarantees minimal downtime, strict data +consistency, and seamless recovery from failures without manual intervention. + +This guide demonstrates how to set up an `Oracle HA cluster` with `Data Guard` enabled in `KubeDB`, and how failover works in different scenarios. + +--- + +### Before You Start + +* A running Kubernetes cluster with `kubectl` configured. +* KubeDB operator and CLI installed ([instructions](/docs/setup/README.md)). +* A valid `StorageClass` available for persistent volumes. + +Check StorageClasses: + +```bash +$ kubectl get storageclasses +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 13d + +``` + +* We’ll use the `demo` namespace for isolation: + +```bash +$ kubectl create ns demo +``` + +--- + +### Step 1: Deploy Oracle with Data Guard Enabled + +Save the following YAML as `oracle-dataguard.yaml`: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Oracle +metadata: + name: oracle-sample + namespace: demo +spec: + version: 21.3.0 + edition: enterprise + mode: DataGuard + replicas: 3 + storageType: Durable + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 30Gi + deletionPolicy: Delete + + dataGuard: + protectionMode: MaximumProtection + standbyType: PHYSICAL + syncMode: SYNC + applyLagThreshold: 0 + transportLagThreshold: 0 + fastStartFailover: + fastStartFailoverThreshold: 15 + observer: + podTemplate: + spec: + containers: + - name: observer + resources: + requests: + cpu: 500m + memory: 2Gi + limits: + cpu: "1" + memory: 2Gi + initContainers: + - name: observer-init + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + memory: 512Mi + + podTemplate: + spec: + serviceAccountName: oracle-sample + securityContext: + runAsUser: 54321 + runAsGroup: 54321 + fsGroup: 54321 + containers: + - name: oracle + resources: + requests: + cpu: "1500m" + memory: 4Gi + limits: + cpu: "4" + memory: 10Gi + - name: oracle-coordinator + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + memory: 256Mi + initContainers: + - name: oracle-init + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + memory: 512Mi +``` +Here, +- `dataGuard.protectionMode` sets the Data Guard protection level. MaximumProtection ensures zero data loss by requiring standby acknowledgment before commit. + +- `dataGuard.standbyType` defines the standby as `PHYSICAL`, a block-for-block replica of the primary. + +- `dataGuard.syncMode` determines redo log transport. SYNC mode waits for standby confirmation before committing. + +- `dataGuard.applyLagThreshold` and `dataGuard.transportLagThreshold` define maximum allowable lag for redo application and transport; 0 enforces immediate synchronization. + +- `dataGuard.fastStartFailover.fastStartFailoverThreshold` sets the FSFO trigger time in seconds; here, 15 means automatic failover if the primary is unresponsive for 15s. + +- `dataGuard.observer.podTemplate` configures the observer pod, which monitors the primary and triggers FSFO, with CPU and memory resources specified. + + +Apply the manifest: + +```bash +$ kubectl apply -f oracle-dataguard.yaml +``` + +```shell +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/oracle/dataguard/dataguard.yaml +oracle.kubedb.com/oracle created + +``` +Monitor status until all pods are ready: + +```bash +$ watch kubectl get oracle -n demo +NAME VERSION MODE STATUS AGE +oracle-sample 21.3.0 DataGuard Ready 25m + +``` + +--- + +### Step 2: Understanding Oracle Data Guard Failover + +Oracle Data Guard in KubeDB works by maintaining **synchronous replication** between a `primary` and `standby` +databases. Key concepts: + +* **Primary**: Accepts all writes (read/write). +* **Physical Standby**: Exact replica kept in sync by continuously applying **redo logs**. +* **Redo Logs**: Every change in Oracle (INSERT/UPDATE/DELETE) generates redo entries. These are written + to the primary’s redo logs, then shipped and applied to the standby. This ensures durability and that + the standby is always consistent with the primary. +* **Observer**: External monitoring process that detects failures and coordinates **Fast-Start Failover (FSFO)**. +* **Maximum Protection mode**: Ensures **zero data loss** by requiring at least one synchronous standby to + acknowledge receipt of redo logs before a transaction is committed. +* **FastStartFailover (FSFO)**: Automates failover by monitoring the primary. If the primary is unavailable + beyond the configured `fastStartFailoverThreshold` (e.g., 15s), the observer promotes a healthy standby + to primary without human intervention. + +--- + +### How Redo Logs Work (Oracle’s Write-Ahead Mechanism) + +1. When a transaction is issued on the primary (e.g., an `INSERT`), Oracle writes the changes into `redo logs`. +2. The `redo logs` are then transported to `standby` databases. + * **SYNC mode** → Primary waits for standby confirmation before commit (`zero data loss`). + * **ASYNC mode** → Primary does not wait; minimal latency but potential small data loss. +3. The standby continuously applies redo logs so its data stays in sync with the primary. +4. During failover, the new primary already has all the applied redo logs and can immediately continue serving traffic. + +--- + +### How FSFO(FastStartFailover) Works + +* `Observer process` continuously monitors the primary and standbys. +* If the primary is unavailable for longer than `fastStartFailoverThreshold`, FSFO triggers an `automatic failover`. +* A `standby` with the most recent redo logs is promoted to `primary`. +* The failed primary, once recovered, rejoins as a `standby` and `resynchronizes`. + +Together, **Redo Logs** and **FSFO** guarantee that Oracle databases deployed with KubeDB remain highly available, +consistent, and resilient against node or pod failures. + + +### Step 3: Simulating Failover Scenarios + +You can check current roles: + +```bash +$ kubectl get pods -n demo --show-labels | grep role +oracle-sample-0 2/2 Running 0 49m app.kubernetes.io/component=database,app.kubernetes.io/instance=oracle-sample,app.kubernetes.io/managed-by=kubedb.com,app.kubernetes.io/name=oracles.kubedb.com,apps.kubernetes.io/pod-index=0,controller-revision-hash=oracle-sample-6d6fdb69ff,kubedb.com/role=primary,oracle.db/role=instance,statefulset.kubernetes.io/pod-name=oracle-sample-0 +oracle-sample-1 2/2 Running 0 49m app.kubernetes.io/component=database,app.kubernetes.io/instance=oracle-sample,app.kubernetes.io/managed-by=kubedb.com,app.kubernetes.io/name=oracles.kubedb.com,apps.kubernetes.io/pod-index=1,controller-revision-hash=oracle-sample-6d6fdb69ff,kubedb.com/role=standby,oracle.db/role=instance,statefulset.kubernetes.io/pod-name=oracle-sample-1 +oracle-sample-2 2/2 Running 0 48m app.kubernetes.io/component=database,app.kubernetes.io/instance=oracle-sample,app.kubernetes.io/managed-by=kubedb.com,app.kubernetes.io/name=oracles.kubedb.com,apps.kubernetes.io/pod-index=2,controller-revision-hash=oracle-sample-6d6fdb69ff,kubedb.com/role=standby,oracle.db/role=instance,statefulset.kubernetes.io/pod-name=oracle-sample-2 +oracle-sample-observer-0 1/1 Running 0 49m app.kubernetes.io/component=database,app.kubernetes.io/instance=oracle-sample,app.kubernetes.io/managed-by=kubedb.com,app.kubernetes.io/name=oracles.kubedb.com,apps.kubernetes.io/pod-index=0,controller-revision-hash=oracle-sample-observer-68648c7957,oracle.db/role=observer,statefulset.kubernetes.io/pod-name=oracle-sample-observer-0 + +``` +The pod having `kubedb.com/role=primary` is the primary, `kubedb.com/role=standby` are the standby's and +`oracle-sample-observer-0` is the observer. + + +Let's create a table in the primary. +```shell +kubectl exec -it -n demo oracle-sample-0 -- bash +Defaulted container "oracle" out of: oracle, oracle-coordinator, oracle-init (init) +bash-4.2$ sqlplus / as sysdba + +SQL*Plus: Release 21.0.0.0.0 - Production on Tue Sep 30 06:02:05 2025 +Version 21.3.0.0.0 + +Copyright (c) 1982, 2021, Oracle. All rights reserved. + + +Connected to: +Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 + +SQL> CREATE TABLE kathak ( + id NUMBER PRIMARY KEY, + name VARCHAR2(100), + age NUMBER +); + 2 3 4 5 +Table created. + +SQL> INSERT INTO kathak (id, name, age) VALUES (1, 'Radha', 25); +1 row created. + +SQL> INSERT INTO kathak (id, name, age) VALUES (2, 'Gopal', 28); + +1 row created. + +SQL> commit; + +Commit complete. + +# The following commands help format the table for better readability. +SQL> COLUMN id FORMAT 9999 +COLUMN name FORMAT A20 +COLUMN age FORMAT 999 + +SQL> SELECT * FROM kathak; + + ID NAME AGE +----- -------------------- ---- + 1 Radha 25 + 2 Gopal 28 + + +SQL> exit +Disconnected from Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 +bash-4.2$ exit +exit + +``` +Verify that the table has been created on the standby nodes. Note that standby pods have read-only access, +so you won't be able to perform any write operations. +```shell +kubectl exec -it -n demo oracle-sample-0 -- bash +Defaulted container "oracle" out of: oracle, oracle-coordinator, oracle-init (init) +bash-4.2$ sqlplus / as sysdba + +SQL*Plus: Release 21.0.0.0.0 - Production on Tue Sep 30 06:50:32 2025 +Version 21.3.0.0.0 + +Copyright (c) 1982, 2021, Oracle. All rights reserved. + + +Connected to: +Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 + +SQL> COLUMN id FORMAT 9999 +COLUMN name FORMAT A20 +COLUMN age FORMAT 999 + +SQL> SELECT database_role, open_mode FROM v$database; + +DATABASE_ROLE OPEN_MODE +---------------- -------------------- +PHYSICAL STANDBY MOUNTED + +SQL> ALTER DATABASE OPEN READ ONLY; + +Database altered. + +SQL> SELECT * FROM kathak; + + ID NAME AGE +----- -------------------- ---- + 1 Radha 25 + 2 Gopal 28 + + +``` +Typical output: + +```shell +$ watch -n 2 "kubectl get pods -n demo -o jsonpath='{range .items[*]}{.metadata.name} {.metadata.labels.kubedb\\.com/role}{\"\\n\"}{end}'" +``` + +```bash +oracle-sample-0 primary +oracle-sample-1 standby +oracle-sample-2 standby +oracle-sample-observer-0 +``` + +--- + +#### Case 1: Delete the Primary + +```bash +$ kubectl delete pod -n demo oracle-sample-0 +``` + +Within few minutes (defined by `fastStartFailoverThreshold`), a standby is promoted: + +``` +oracle-sample-0 standby +oracle-sample-1 primary +oracle-sample-2 standby +oracle-sample-observer-0 + +``` + +The deleted pod comes back as a **standby** and automatically resynchronizes. +Now we know how failover is done, let's check if the new primary is working. +```shell +kubectl exec -it -n demo oracle-sample-1 -- bash +Defaulted container "oracle" out of: oracle, oracle-coordinator, oracle-init (init) +bash-4.2$ sqlplus / as sysdba + +SQL*Plus: Release 21.0.0.0.0 - Production on Tue Sep 30 06:46:31 2025 +Version 21.3.0.0.0 + +Copyright (c) 1982, 2021, Oracle. All rights reserved. + + +Connected to: +Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 + + +SQL> COLUMN id FORMAT 9999 +COLUMN name FORMAT A20 +COLUMN age FORMAT 999 +SQL> SQL> SQL> +SQL> SELECT * FROM kathak; + + ID NAME AGE +----- -------------------- ---- + 1 Radha 25 + 2 Gopal 28 + +SQL> INSERT INTO kathak (id, name, age) VALUES (3, 'Mohan', 30); + +1 row created. + +SQL> commit; + +Commit complete. + +SQL> SELECT * FROM kathak; + + ID NAME AGE +----- -------------------- ---- + 1 Radha 25 + 2 Gopal 28 + 3 Mohan 30 + +SQL> exit +Disconnected from Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 +bash-4.2$ exit + +``` + +Let's verify the new `standby` is working perfectly +```shell +kubectl exec -it -n demo oracle-sample-0 -- bash +Defaulted container "oracle" out of: oracle, oracle-coordinator, oracle-init (init) +bash-4.2$ sqlplus / as sysdba + +SQL*Plus: Release 21.0.0.0.0 - Production on Tue Sep 30 06:50:32 2025 +Version 21.3.0.0.0 + +Copyright (c) 1982, 2021, Oracle. All rights reserved. + + +Connected to: +Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 + +SQL> COLUMN id FORMAT 9999 +COLUMN name FORMAT A20 +COLUMN age FORMAT 999 + +SQL> SELECT database_role, open_mode FROM v$database; + +DATABASE_ROLE OPEN_MODE +---------------- -------------------- +PHYSICAL STANDBY MOUNTED + +SQL> ALTER DATABASE OPEN READ ONLY; + +Database altered. + +SQL> SELECT * FROM kathak; + + ID NAME AGE +----- -------------------- ---- + 1 Radha 25 + 3 Gopal 28 + 2 Mohan 30 + +SQL> exit +Disconnected from Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 +bash-4.2$ command terminated with exit code 137 + +``` +#### Case 2: Delete Primary and One Standby + +```bash +$ kubectl delete pod -n demo oracle-sample-0 oracle-sample-1 +pod "oracle-sample-0" deleted +pod "oracle-sample-1" deleted + +``` + +The remaining standby (`oracle-sample-2`) is promoted to primary. The deleted pods return and rejoin as standbys. + +```shell +oracle-sample-0 primary +oracle-sample-1 standby +oracle-sample-2 standby +oracle-sample-observer-0 + +``` + +#### Case 3: Delete All Standbys + +```bash +$ kubectl delete pod -n demo oracle-sample-1 oracle-sample-2 +``` + +The primary (`oracle-sample-0`) continues serving traffic. Once the standbys are recreated, they rejoin the Data Guard configuration and catch up from archived redo logs. + +```bash +oracle-sample-0 primary +oracle-sample-1 standby +oracle-sample-2 standby +oracle-sample-observer-0 + +``` + +#### Case 4: Delete All Pods + +```bash +$ kubectl delete pod -n demo oracle-sample-0 oracle-sample-1 oracle-sample-2 +pod "oracle-sample-0" deleted +pod "oracle-sample-1" deleted +pod "oracle-sample-2" deleted +``` +```shell +oracle-sample-0 +oracle-sample-1 +oracle-sample-observer-0 +``` +After restart, the cluster automatically re-establishes Data Guard roles: + +```bash +oracle-sample-0 primary +oracle-sample-1 standby +oracle-sample-2 standby +oracle-sample-observer-0 + +``` + + +### CleanUp + +To delete resources run: + +```bash +kubectl delete oracle -n demo oracle-sample +kubectl delete ns demo +``` + + diff --git a/docs/guides/oracle/quickstart/Monitoring.png b/docs/guides/oracle/quickstart/Monitoring.png new file mode 100644 index 000000000..1b01a2ec3 Binary files /dev/null and b/docs/guides/oracle/quickstart/Monitoring.png differ diff --git a/docs/guides/oracle/quickstart/_index.md b/docs/guides/oracle/quickstart/_index.md new file mode 100644 index 000000000..2935e568a --- /dev/null +++ b/docs/guides/oracle/quickstart/_index.md @@ -0,0 +1,11 @@ +--- +title: Oracle Quickstart +menu: + docs_{{ .version }}: + identifier: guides-oracle-quickstart + name: Quickstart + parent: guides-oracle + weight: 15 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- \ No newline at end of file diff --git a/docs/guides/oracle/quickstart/guide.md b/docs/guides/oracle/quickstart/guide.md new file mode 100644 index 000000000..180ca94cc --- /dev/null +++ b/docs/guides/oracle/quickstart/guide.md @@ -0,0 +1,304 @@ +--- +title: Oracle Quickstart +menu: + docs_{{ .version }}: + identifier: guides-oracle-quickstart + name: Quickstart + parent: guides-oracle + weight: 15 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + + +# Oracle QuickStart + +This tutorial will show you how to use KubeDB to run an Oracle database. + +

  lifecycle

+ +>Note: The YAML files used in this tutorial are stored in [docs/examples/oracle/quickstart](https://github.com/kubedb/docs/tree/{{ +< param "info.version" >}}/docs/examples/oracle/quickstart) folder in the GitHub repository kubedb/docs +. + +## Before You Begin + +- You need a Kubernetes cluster and kubectl configured to communicate with it. If you do not have a cluster, + you can create one using kind +- install the KubeDB CLI on your workstation and the KubeDB operator in your cluster following the + instructions here + +- check available StorageClass in your cluster: + +```shell +ubectl get storageclasses +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 28d + +``` +Use a separate namespace for isolation: +```shell +$ kubectl create ns demo +namespace/demo created +``` +## Find Available Oracle Versions + +KubeDB maintains an OracleVersion CRD with all supported Oracle versions: +```shell +$ kubectl get oracleversions +NAME VERSION DISTRIBUTION DB_IMAGE DEPRECATED AGE +21.3.0 21.3.0 ghcr.io/kubedb/oracle-ee:21.3.0 28d + +``` + +## Create an Oracle Database + +KubeDB implements an Oracle CRD to define Oracle database specifications. Below is an example: + +```shell +apiVersion: kubedb.com/v1alpha2 +kind: Oracle +metadata: + name: oracle + namespace: demo +spec: + deletionPolicy: Delete + edition: enterprise + mode: Standalone + podTemplate: + spec: + containers: + - name: oracle + resources: + limits: + cpu: "4" + memory: 10Gi + requests: + cpu: "2" + memory: 3Gi + initContainers: + - name: oracle-init + resources: + limits: + memory: 512Mi + requests: + cpu: 200m + memory: 256Mi + securityContext: + fsGroup: 54321 + runAsGroup: 54321 + runAsUser: 54321 + replicas: 1 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 30Gi + storageType: Durable + version: 21.3.0 +``` +```shell +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/oracle/quickstart/standalone.yaml +oracle.kubedb.com/oracle created + +``` +Here, +- `spec.version`: Refers to the `OracleVersion CRD` specifying the docker image. + +- `spec.edition`: Database edition (`enterprise` in this example). + +- `spec.mode`: Deployment mode (`Standalone` or `DataGuard`). + +- `spec.storageType`: Can be `Durable` (uses PVC) or `Ephemeral` (uses EmptyDir). + +- `spec.storage`: Defines PVC size and access mode. + +- `spec.podTemplate`: Customize resource requests/limits, init containers, and security context. + +- `spec.replicas`: Number of database pods (1 for standalone, ≥2 for DataGuard). + +- `spec.deletionPolicy`: Controls behavior when deleting the Oracle CRD (`Delete`, `Halt`, `WipeOut`). For more details, see [here](https://appscode.com/blog/post/deletion-policy/). + +`KubeDB` operator watches for `Oracle` objects using Kubernetes api. When a `Oracle` object is created, +KubeDB operator will create a new PetSet and a Service with the matching Oracle object name. `KubeDB` +operator will also create a governing service for PetSets with the name `kubedb`, if one is not already +present. +If we describe the `Oracle` CRD we will get an overview of the steps that were followed. +```shell +$ kubectl describe oracle -n demo oracle + +Name: oracle +Namespace: demo +Labels: +Annotations: +API Version: kubedb.com/v1alpha2 +Kind: Oracle +Metadata: + Creation Timestamp: 2025-09-17T09:19:12Z + Finalizers: + kubedb.com/oracle + Generation: 2 + Resource Version: 54974 + UID: 46afbf62-caab-4649-a475-64025c319eba +Spec: + Auth Secret: + Name: oracle-auth + Auto Ops: + Deletion Policy: Delete + Edition: enterprise + Health Checker: + Failure Threshold: 1 + Period Seconds: 10 + Timeout Seconds: 10 + Listener: + Port: 1521 + Protocol: TCP + Service: ORCL + Mode: Standalone + Pod Template: + Controller: + Metadata: + Spec: + Containers: + Name: oracle + Resources: + Limits: + Cpu: 4 + Memory: 10Gi + Requests: + Cpu: 2 + Memory: 3Gi + Security Context: + Name: oracle-coordinator + Resources: + Limits: + Memory: 256Mi + Requests: + Cpu: 200m + Memory: 256Mi + Security Context: + Init Containers: + Name: oracle-init + Resources: + Limits: + Memory: 512Mi + Requests: + Cpu: 200m + Memory: 256Mi + Security Context: + Pod Placement Policy: + Name: default + Security Context: + Fs Group: 54321 + Run As Group: 54321 + Run As User: 54321 + Service Account Name: oracle + Replicas: 1 + Storage: + Access Modes: + ReadWriteOnce + Resources: + Requests: + Storage: 30Gi + Storage Type: Durable + Version: 21.3.0 +Status: + Conditions: + Last Transition Time: 2025-09-17T09:19:12Z + Message: The KubeDB operator has started the provisioning of Oracle: demo/oracle + Observed Generation: 1 + Reason: DatabaseProvisioningStartedSuccessfully + Status: True + Type: ProvisioningStarted + Last Transition Time: 2025-09-17T09:19:26Z + Message: All replicas are ready + Observed Generation: 2 + Reason: AllReplicasReady + Status: True + Type: ReplicaReady + Last Transition Time: 2025-09-17T09:27:58Z + Message: The Oracle: demo/oracle is accepting connection + Observed Generation: 2 + Reason: AcceptingConnection + Status: True + Type: AcceptingConnection + Last Transition Time: 2025-09-17T09:27:58Z + Message: DB is ready because of server getting Online and Running state + Observed Generation: 2 + Reason: AllReplicasReady + Status: True + Type: Ready + Last Transition Time: 2025-09-17T09:21:11Z + Message: The Oracle: demo/oracle is successfully provisioned. + Observed Generation: 2 + Reason: DatabaseSuccessfullyProvisioned + Status: True + Type: Provisioned + Phase: Ready +Events: + +``` + +🔹Status: (What the operator reports now) + + Conditions: + - ProvisioningStarted → operator started creating the DB. + - ReplicaReady → all pods are running. + - AcceptingConnection → DB listener is online at port 1521. + - Ready → fully ready for queries. + - Provisioned → provisioning completed successfully. + Phase: + - Ready → Database is online, healthy, and serving connections. + + + +## Check Resources Created by KubeDB operator: +```shell +$ kubectl get oracle,pods,pvc,services -n demo +NAME VERSION MODE STATUS AGE +oracle.kubedb.com/oracle 21.3.0 Standalone Ready 109m + +NAME READY STATUS RESTARTS AGE +pod/oracle-0 1/1 Running 0 109m + +NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE +persistentvolumeclaim/data-oracle-0 Bound pvc-66385705-e0f3-4658-abcb-78dbacbfc3d7 30Gi RWO local-path 109m + +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +service/oracle ClusterIP 10.43.170.95 1521/TCP 109m +service/oracle-pods ClusterIP None 1521/TCP 109m + +``` + +## Connect to Oracle Database +```shell +$ kubectl exec -it -n demo oracle-0 -- bash +Defaulted container "oracle" out of: oracle, oracle-init (init) +bash-4.2$ sqlplus / as sysdba + +SQL*Plus: Release 21.0.0.0.0 - Production on Wed Sep 24 05:11:41 2025 +Version 21.3.0.0.0 + +Copyright (c) 1982, 2021, Oracle. All rights reserved. + +Connected to: +Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 + +SQL> exit +Disconnected from Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production +Version 21.3.0.0.0 + +``` +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +$ kubectl patch -n demo oracle/oracle -p '{"spec":{"deletionPolicy":"WipeOut"}}' --type="merge" +$ kubectl delete oracle -n demo oracle +$ kubectl delete ns demo +``` diff --git a/tandby b/tandby new file mode 100644 index 000000000..1e3a5466f --- /dev/null +++ b/tandby @@ -0,0 +1,165 @@ +* add-oracle + mariadb-failover + master + mssql-failover + rotateauth + remotes/origin/HEAD -> origin/master + remotes/origin/add-oracle + remotes/origin/add-singlestore + remotes/origin/clickhouse + remotes/origin/concepts-pg-archiver + remotes/origin/deletionpolicy + remotes/origin/dist-mariadb + remotes/origin/draft-appplication-level-es + remotes/origin/druid-failover + remotes/origin/es-ops + remotes/origin/failover + remotes/origin/ferret-failover + remotes/origin/fix-md-version + remotes/origin/fix-menu + remotes/origin/hazelcast + remotes/origin/ignite + remotes/origin/kafka-doc + remotes/origin/kubedb/cli@196a75ca + remotes/origin/kubedb/cli@2b95f75c + remotes/origin/kubedb/cli@3b6a62ec + remotes/origin/kubedb/cli@41139e49 + remotes/origin/kubedb/cli@6980c711 + remotes/origin/kubedb/cli@6adaa37f + remotes/origin/kubedb/cli@73976008 + remotes/origin/kubedb/cli@7aeaa861 + remotes/origin/kubedb/cli@8ff0608c + remotes/origin/kubedb/cli@9953efb7 + remotes/origin/kubedb/cli@bbe4b2ef + remotes/origin/kubedb/cli@be1a1198 + remotes/origin/kubedb/cli@ceb2bda4 + remotes/origin/kubedb/cli@cf49e9aa + remotes/origin/kubedb/cli@da20a307 + remotes/origin/kubedb/cli@f9be578b + remotes/origin/kubedb/provisioner@1998ae5f + remotes/origin/kubedb/provisioner@55454b8e + remotes/origin/kubedb/provisioner@5a184337 + remotes/origin/kubedb/provisioner@77942092 + remotes/origin/kubedb/provisioner@c1442971 + remotes/origin/kubedb/provisioner@c2f93ed2 + remotes/origin/kubedb/provisioner@c3c82f4f + remotes/origin/kubedb/provisioner@ddc05af4 + remotes/origin/kubedb/provisioner@f3804631 + remotes/origin/kubedb/webhook-server@26e96671 + remotes/origin/kubedb/webhook-server@3c0d0c2e + remotes/origin/kubedb/webhook-server@4eab5c8e + remotes/origin/kubedb/webhook-server@7bfab0c6 + remotes/origin/kubedb/webhook-server@cb7d5c65 + remotes/origin/lv808 + remotes/origin/master + remotes/origin/memcached + remotes/origin/mg-archiver + remotes/origin/mg-failover + remotes/origin/mssql-failover + remotes/origin/mysql-failover + remotes/origin/pg-doc + remotes/origin/pgbouncerDocs + remotes/origin/proxysql-doc-2 + remotes/origin/recommendation + remotes/origin/release-0.1 + remotes/origin/release-0.10 + remotes/origin/release-0.11 + remotes/origin/release-0.12 + remotes/origin/release-0.13 + remotes/origin/release-0.2 + remotes/origin/release-0.3 + remotes/origin/release-0.4 + remotes/origin/release-0.5 + remotes/origin/release-0.6 + remotes/origin/release-0.7 + remotes/origin/release-0.8 + remotes/origin/release-0.9 + remotes/origin/release-v2020.07.10-beta.0 + remotes/origin/release-v2020.09.04-beta.0 + remotes/origin/release-v2020.10.24-beta.0 + remotes/origin/release-v2020.10.26-beta.0 + remotes/origin/release-v2020.10.27-rc.0 + remotes/origin/release-v2020.10.27-rc.1 + remotes/origin/release-v2020.10.27-rc.2 + remotes/origin/release-v2020.10.28 + remotes/origin/release-v2020.11.08 + remotes/origin/release-v2020.11.11 + remotes/origin/release-v2020.11.12 + remotes/origin/release-v2020.12.10 + remotes/origin/release-v2021.01.02-rc.0 + remotes/origin/release-v2021.01.14 + remotes/origin/release-v2021.01.15 + remotes/origin/release-v2021.01.26 + remotes/origin/release-v2021.03.11 + remotes/origin/release-v2021.03.17 + remotes/origin/release-v2021.04.16 + remotes/origin/release-v2021.06.21-rc.0 + remotes/origin/release-v2021.06.23 + remotes/origin/release-v2021.08.23 + remotes/origin/release-v2021.09.09 + remotes/origin/release-v2021.09.30 + remotes/origin/release-v2021.11.18 + remotes/origin/release-v2021.11.24 + remotes/origin/release-v2021.12.21 + remotes/origin/release-v2022.02.22 + remotes/origin/release-v2022.03.28 + remotes/origin/release-v2022.05.24 + remotes/origin/release-v2022.08.02-rc.0 + remotes/origin/release-v2022.08.04-rc.1 + remotes/origin/release-v2022.08.08 + remotes/origin/release-v2022.10.12-rc.0 + remotes/origin/release-v2022.10.18 + remotes/origin/release-v2022.12.13-rc.0 + remotes/origin/release-v2022.12.24-rc.1 + remotes/origin/release-v2022.12.28 + remotes/origin/release-v2023.01.17 + remotes/origin/release-v2023.01.31 + remotes/origin/release-v2023.02.28 + remotes/origin/release-v2023.04.10 + remotes/origin/release-v2023.06.13-rc.0 + remotes/origin/release-v2023.06.19 + remotes/origin/release-v2023.08.18 + remotes/origin/release-v2023.10.9 + remotes/origin/release-v2023.11.2 + remotes/origin/release-v2023.11.29-rc.0 + remotes/origin/release-v2023.12.1-rc.1 + remotes/origin/release-v2023.12.11 + remotes/origin/release-v2023.12.21 + remotes/origin/release-v2023.12.28 + remotes/origin/release-v2024.1.19-beta.1 + remotes/origin/release-v2024.1.26-rc.0 + remotes/origin/release-v2024.1.28-rc.1 + remotes/origin/release-v2024.1.31 + remotes/origin/release-v2024.1.7-beta.0 + remotes/origin/release-v2024.11.18 + remotes/origin/release-v2024.11.8-rc.0 + remotes/origin/release-v2024.12.18 + remotes/origin/release-v2024.2.14 + remotes/origin/release-v2024.3.16 + remotes/origin/release-v2024.3.9-rc.0 + remotes/origin/release-v2024.4.27 + remotes/origin/release-v2024.6.4 + remotes/origin/release-v2024.7.11-rc.1 + remotes/origin/release-v2024.7.3-rc.0 + remotes/origin/release-v2024.8.14-rc.3 + remotes/origin/release-v2024.8.2-rc.2 + remotes/origin/release-v2024.8.21 + remotes/origin/release-v2024.9.30 + remotes/origin/release-v2025.1.9 + remotes/origin/release-v2025.2.19 + remotes/origin/release-v2025.2.6-rc.0 + remotes/origin/release-v2025.3.20-rc.1 + remotes/origin/release-v2025.3.24 + remotes/origin/release-v2025.4.30 + remotes/origin/release-v2025.5.30 + remotes/origin/release-v2025.6.30 + remotes/origin/release-v2025.7.30-rc.0 + remotes/origin/release-v2025.7.31 + remotes/origin/release-v2025.8.31 + remotes/origin/remote-replica.bac + remotes/origin/rotateauth + remotes/origin/secret-kind + remotes/origin/sync + remotes/origin/update-dbgate + remotes/origin/update-kafka + remotes/origin/update-mg-docs