Implementa bases de datos de Oracle autoadministradas con alta disponibilidad

En esta guía, se describe la implementación de una configuración de Oracle Data Guard con alta disponibilidad en un clúster estándar aislado de Google Distributed Cloud (GDC). En esta configuración, se usa Oracle Database Enterprise Edition y se aprovechan las capacidades existentes de GDC para el almacenamiento y las redes.

Esta implementación usa el operador de base de datos de Oracle para Kubernetes oficial, que automatiza la administración del ciclo de vida de la base de datos.

Arquitectura

En la arquitectura, se describe una implementación de base de datos de Oracle de alta disponibilidad administrada por el operador de base de datos de Oracle dentro de un clúster estándar de GDC. Una implementación de alta disponibilidad consta de una base de datos principal y una base de datos en espera configurada con Data Guard para la replicación y la conmutación por error.

Diagrama de arquitectura de la implementación de la base de datos de Oracle con alta disponibilidad con Data Guard.

Los componentes clave son los siguientes:

  • Proyecto de GDC: Es el contenedor de proyecto para tus recursos.
  • Clúster de Kubernetes estándar: Es un clúster estándar que proporciona los recursos de procesamiento.
  • Operador de Oracle Database: Es un operador de Kubernetes que automatiza el aprovisionamiento, la administración del ciclo de vida y la observabilidad de las bases de datos de Oracle. Simplifica tareas complejas, como la aplicación de parches, la copia de seguridad y la recuperación, lo que facilita la ejecución de cargas de trabajo de Oracle con estado en un entorno alojado en contenedores.
  • Base de datos principal: Es la instancia de base de datos en contenedores de lectura y escritura activa.
  • Base de datos en espera: Es la instancia de base de datos de réplica de solo lectura (o de lectura y escritura durante la conmutación por error).
  • Data Guard Broker: organiza la configuración y las transiciones de roles (conmutación por error/conmutación por error) entre las bases de datos.
  • Harbor: Es el Container Registry privado que se usa para alojar las imágenes de la base de datos, el operador y el cliente dentro del entorno aislado.
  • Cert-manager: El operador se basa en cert-manager para administrar los certificados de webhooks. cert-manager viene preinstalado en los clústeres estándar de GDC.

En esta guía, implementarás el operador en su propio espacio de nombres (oracle-database-operator-system) y la instancia de la base de datos en un espacio de nombres independiente (oracle-dbs). Estos espacios de nombres se ilustran con cuadros de borde punteado en el diagrama de arquitectura.

Se recomienda esta separación para mayor claridad y facilidad de administración. Sin embargo, depende de ti decidir cómo organizar tus bases de datos. Por ejemplo, puedes agrupar ciertas bases de datos en diferentes espacios de nombres para administrar el control de acceso detallado (RBAC) según las necesidades de la carga de trabajo, la propiedad del equipo o las especificaciones de seguridad.

Antes de comenzar

Antes de comenzar la implementación, debes asegurarte de que tu entorno cumpla con los siguientes requisitos:

  • Crea un proyecto que servirá como contenedor para todos los recursos que se generen en esta guía.
  • Otorga a tu usuario los roles de administrador de clústeres y administrador de clústeres estándar para tu proyecto. Esto te permite crear un clúster de Kubernetes estándar y administrar sus recursos:

    export PROJECT_ID=PROJECT_ID
    export USER_NAME=USER_NAME
    
    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=cluster-admin
    
    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=standard-cluster-admin
    
  • Crea una instancia de Harbor y un proyecto de Harbor para alojar las imágenes de contenedor que se necesitan en esta guía.

  • Otorga a tu usuario el rol de administrador de instancias de Harbor para que puedas subir imágenes a tu instancia de Harbor:

    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=harbor-instance-admin
    
  • Crea una cuenta de robot de Harbor en tu proyecto de Harbor. Más adelante en esta guía, las credenciales de la cuenta de robot se almacenarán en Secrets de Kubernetes, lo que permitirá que el clúster extraiga imágenes de Harbor cuando se creen instancias de contenedores.

  • Crea un clúster de Kubernetes estándar con al menos dos nodos trabajadores, cada uno con un mínimo de 16 GB de memoria. Por ejemplo:

    kubectl --kubeconfig MGMT_API_KUBECONFIG create -f - <<EOF
    apiVersion: cluster.gdc.goog/v1
    kind: Cluster
    metadata:
      name: ${CLUSTER_NAME}
      namespace: ${PROJECT_ID}
    spec:
      nodePools:
      - machineTypeName: n3-standard-8-gdc
        nodeCount: 2
        name: ${CLUSTER_NAME}-node-pool
    EOF
    
  • Configura las variables de entorno. Se usarán en toda la guía para crear recursos y hacer referencia a ellos:

    Notas:

    • En esta guía, las dos instancias de base de datos se llaman blue y green de forma arbitraria. Inicialmente, la instancia blue es la principal y green es la de espera.
    # General info
    export PROJECT_ID="PROJECT_ID"
    export ZONE="ZONE"
    export ORG_NAME="ORG_NAME"
    export CLUSTER_NAME="CLUSTER_NAME"
    
    # Software versions
    export ORACLE_OPERATOR_VERSION="2.1.0"
    export ORACLE_DB_VERSION="21.3.0.0"
    
    # Namespaces
    export ORACLE_OPERATOR_NAMESPACE="ORACLE_OPERATOR_NAMESPACE"
    export DB_NAMESPACE="DATABASE_NAMESPACE"
    
    # Harbor config
    export HARBOR_INSTANCE_PROJECT_ID="HARBOR_PROJECT_ID"
    export HARBOR_INSTANCE_NAME="HARBOR_INSTANCE_NAME"
    export HARBOR_INSTANCE_URL="HARBOR_INSTANCE_URL"
    export HARBOR_PROJECT="HARBOR_PROJECT"
    export HARBOR_PULL_SECRET_NAME="HARBOR_PULL_SECRET_NAME"
    export HARBOR_ROBOT_ACCOUNT="robot\$HARBOR_PROJECT+ROBOT_NAME"
    export HARBOR_ROBOT_SECRET="HARBOR_ROBOT_SECRET"
    
    # Oracle database config
    export ADMIN_PASSWORD="ADMIN_PASSWORD"
    export ADMIN_PASSWORD_SECRET_NAME="ADMIN_PASSWORD_SECRET_NAME"
    
    # Database names
    export DB_NAME_BLUE="database-blue"
    export DB_NAME_GREEN="database-green"
    
  • Nota de red: En esta guía, se supone que se ejecuta desde un nodo de bastión que tiene acceso a las APIs de GDC y también a Internet para descargar los manifiestos y las imágenes de contenedor del operador de Oracle. Si ejecutas esto desde una máquina sin acceso a Internet, debes obtener estos recursos por separado (por ejemplo, con docker save para exportar imágenes desde una máquina conectada y docker load para importarlas) y subirlos de forma segura a tu entorno antes de continuar.

  • Antes de continuar, debes crear una cuenta y obtener un token de API en container-registry.oracle.com y, luego, aceptar el contrato de licencia para las imágenes de Oracle Database Enterprise Edition y Oracle Instant Client.

Carga imágenes en Harbor

Dado que los clústeres dentro de Google Distributed Cloud aislado no pueden acceder a registros externos, debes duplicar las imágenes requeridas en tu instancia privada de Harbor.

Accede a Oracle Container Registry

Primero, debes autenticarte con el registro oficial de Oracle para extraer las imágenes base:

docker --config=./docker-oracle login container-registry.oracle.com

Después de un acceso exitoso, las credenciales se guardarán en ./docker-oracle/config.json.

Accede a Harbor

Autentícate con tu instancia privada de Harbor:

docker --config=./docker-harbor login ${HARBOR_INSTANCE_URL} \
  -u ${HARBOR_ROBOT_ACCOUNT} \
  -p ${HARBOR_ROBOT_SECRET}

Después de acceder correctamente, las credenciales de la cuenta de robot se guardarán en ./docker-harbor/config.json.

Extrae, etiqueta y envía imágenes

Descarga las imágenes del registro de contenedores oficial de Oracle y envíalas a tu proyecto interno de Harbor. Duplicarás el operador, la base de datos empresarial y el cliente instantáneo para realizar pruebas.

  1. Duplica la imagen del operador de la base de datos de Oracle:

    docker --config=./docker-oracle pull \
      container-registry.oracle.com/database/operator:${ORACLE_OPERATOR_VERSION} \
      --platform linux/amd64
    
    docker tag container-registry.oracle.com/database/operator:${ORACLE_OPERATOR_VERSION} \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-operator:${ORACLE_OPERATOR_VERSION}
    
    docker --config=./docker-harbor push \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-operator:${ORACLE_OPERATOR_VERSION}
    
  2. Duplica la imagen de Oracle Database Enterprise:

    docker --config=./docker-oracle pull \
      container-registry.oracle.com/database/enterprise:${ORACLE_DB_VERSION} \
      --platform linux/amd64
    
    docker tag container-registry.oracle.com/database/enterprise:${ORACLE_DB_VERSION} \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-enterprise:${ORACLE_DB_VERSION}
    
    docker --config=./docker-harbor push \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-enterprise:${ORACLE_DB_VERSION}
    
  3. Duplica la imagen del cliente instantáneo de Oracle:

    docker --config=./docker-oracle pull \
      container-registry.oracle.com/database/instantclient:latest \
      --platform linux/amd64
    
    docker tag container-registry.oracle.com/database/instantclient:latest \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-instantclient:latest
    
    docker --config=./docker-harbor push \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-instantclient:latest
    

Configura el acceso al clúster

Antes de implementar recursos, recupera las credenciales de tu clúster estándar y crea un alias conveniente:

  1. Recupera el archivo kubeconfig para tu clúster estándar:

    KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \
      get-credentials ${CLUSTER_NAME} \
      --standard \
      --project ${PROJECT_ID} \
      --zone ${ZONE}
    
  2. Crea el alias kk para simplificar los comandos posteriores:

    alias kk="kubectl --kubeconfig kubeconfig-${CLUSTER_NAME}.yaml"
    

Crea Secrets

Crea un Secret de Kubernetes para permitir que el clúster extraiga imágenes de Harbor con las credenciales guardadas en tu ./docker-harbor/config.json local. Necesitas este Secret tanto en el espacio de nombres del operador (para extraer la imagen del operador) como en el de la base de datos (para extraer la imagen de la base de datos).

  1. Crea el espacio de nombres para el operador:

    kk create ns ${ORACLE_OPERATOR_NAMESPACE}
    
  2. Crea el secreto de extracción para el operador:

    kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ${ORACLE_OPERATOR_NAMESPACE}
    
  3. Crea el espacio de nombres para las bases de datos:

    kk create ns ${DB_NAMESPACE}
    
  4. Crea el Secret de extracción de imágenes para los contenedores de la base de datos:

    kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ${DB_NAMESPACE}
    
  5. Crea el Secret para la contraseña administrativa de las bases de datos:

    kk create secret generic ${ADMIN_PASSWORD_SECRET_NAME} \
      --from-literal=password=${ADMIN_PASSWORD} \
      -n ${DB_NAMESPACE}
    

Instala el operador de Oracle Database

Ahora, instala el operador de Oracle Database en tu clúster aplicando tres manifiestos:

  1. Vinculación de rol de clúster: Configura los permisos necesarios para que el operador funcione en todo el clúster.

    kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/cluster-role-binding.yaml
    
  2. RBAC de nodo: Otorga permisos para leer la topología del nodo, lo que es fundamental para la programación correcta de los Pods.

    kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/node-rbac.yaml
    
  3. Implementación del operador: Implementa los Pods del operador y las definiciones de recursos personalizados. Este comando descarga el manifiesto oficial, reemplaza la ruta de la imagen por tu URL de Harbor, inserta la configuración de imagePullSecrets para que Kubernetes pueda autenticarse con Harbor y aplica el resultado:

    curl -L https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/oracle-database-operator.yaml \
      | sed "s|container-registry.oracle.com/database/operator:latest|${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-operator:${ORACLE_OPERATOR_VERSION}|g" \
      | awk "/terminationGracePeriodSeconds: 10/{print; print \"      imagePullSecrets:\n      - name: ${HARBOR_PULL_SECRET_NAME}\"; next}1" \
      | kk apply -f -
    

    Espera a que los Pods del operador se estén ejecutando:

    kk get pods -n ${ORACLE_OPERATOR_NAMESPACE} --watch
    

    El resultado debe verse de la siguiente manera:

    NAME                                                           READY   STATUS    RESTARTS   AGE
    oracle-database-operator-controller-manager-5f7b56874d-k9v4z   1/1     Running   0          45s
    oracle-database-operator-controller-manager-5f7b56874d-n2x8m   1/1     Running   0          45s
    oracle-database-operator-controller-manager-5f7b56874d-r6z7q   1/1     Running   0          45s
    

Implementa bases de datos principal y en espera

Ahora, implementarás dos instancias de base de datos en el mismo espacio de nombres de forma secuencial.

Implementa la instancia principal

  1. Ejecuta el siguiente comando para crear la instancia de base de datos principal:

    apiVersion: database.oracle.com/v4
    kind: SingleInstanceDatabase
    metadata:
      name: ${DB_NAME_BLUE}
      namespace: ${DB_NAMESPACE}
    spec:
      replicas: 1
      edition: enterprise
      image:
        pullFrom: "${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-enterprise:${ORACLE_DB_VERSION}"
        pullSecrets: ${HARBOR_PULL_SECRET_NAME}
        prebuiltDB: true
      sid: ORCLBLUE
      pdbName: ORCLPDB1
      archiveLog: true
      flashBack: true
      forceLog: true
      adminPassword:
        secretName: "${ADMIN_PASSWORD_SECRET_NAME}"
        secretKey: "password"
      persistence:
        size: "50Gi"
        storageClass: "standard-rwo"
        accessMode: "ReadWriteOnce"
      resources:
        requests:
          memory: "4Gi"
    

    Parámetros de configuración clave:

    • sid / pdbName: Define el identificador del sistema (SID) y el nombre de la base de datos conectable (PDB).
    • edition: Especifica la edición de la base de datos (enterprise en este caso).
    • image: Apunta a la imagen de tu registro privado de Harbor.
    • persistence: Solicita un volumen persistente de 50 Gi con la StorageClass standard-rwo, que crea un disco persistente zonal en GDC.
    • replicas: Establece la cantidad de Pods en 1 para la instancia.
    • archiveLog: habilita el modo de registro de archivo, que es obligatorio para Data Guard.
    • flashBack: habilita la base de datos Flashback, lo que te permite devolver la base de datos a un momento anterior.
    • forceLog: Habilita el registro forzado, lo que garantiza que se registren todos los cambios, incluso para las operaciones que normalmente omiten el registro.

    Para obtener una lista completa de las opciones de configuración, incluidos los parámetros de inicialización personalizados y los límites de recursos, consulta la documentación oficial.

    La creación de la base de datos consume muchos recursos y puede tardar entre 10 y 20 minutos.

    Espera a que la base de datos esté completamente lista antes de continuar. Esto es fundamental, ya que la base de datos en espera requiere que se pueda acceder a la principal para establecer la replicación.

    Espera hasta que el Pod de la base de datos esté Running:

    kk get po -n ${DB_NAMESPACE} -l app=${DB_NAME_BLUE} -w
    

    El resultado debería verse de la siguiente manera:

    NAME                   READY   STATUS    RESTARTS   AGE
    database-blue-i5xdj   0/1     Pending   0          0s
    database-blue-i5xdj   0/1     Pending   0          0s
    database-blue-i5xdj   0/1     Pending   0          1s
    database-blue-i5xdj   0/1     Init:0/1   0          1s
    database-blue-i5xdj   0/1     PodInitializing   0          98s
    database-blue-i5xdj   0/1     Running           0          99s
    database-blue-i5xdj   1/1     Running           0          99s
    

    Luego, observa los registros y espera el mensaje DATABASE IS READY TO USE!:

    kk logs -n ${DB_NAMESPACE} -l app=${DB_NAME_BLUE} -f
    

    El resultado debería contener lo siguiente:

    #########################
    DATABASE IS READY TO USE!
    #########################
    
  2. Verifica que el estado sea Healthy y que el rol sea PRIMARY:

    kk get sidb -n ${DB_NAMESPACE} ${DB_NAME_BLUE}
    

    El resultado debería verse de la siguiente manera:

    NAME            EDITION      STATUS    ROLE
    database-blue   Enterprise   Healthy   PRIMARY
    

Implementa la instancia en espera

Después de que la instancia principal esté en buen estado, implementa la instancia en espera. Ten en cuenta que los parámetros de Data Guard (archiveLog, flashBack, forceLog) se heredan de la base de datos principal y no se deben especificar en el manifiesto de la base de datos en espera:

  1. Implementa la instancia en espera:

    apiVersion: database.oracle.com/v4
    kind: SingleInstanceDatabase
    metadata:
      name: ${DB_NAME_GREEN}
      namespace: ${DB_NAMESPACE}
    spec:
      replicas: 1
      edition: enterprise
      image:
        pullFrom: "${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-enterprise:${ORACLE_DB_VERSION}"
        pullSecrets: ${HARBOR_PULL_SECRET_NAME}
        prebuiltDB: true
      sid: ORCLGREEN
      pdbName: ORCLPDB1
      adminPassword:
        secretName: "${ADMIN_PASSWORD_SECRET_NAME}"
        secretKey: "password"
      createAs: standby
      primaryDatabaseRef: ${DB_NAME_BLUE}
      persistence:
        size: "50Gi"
        storageClass: "standard-rwo"
        accessMode: "ReadWriteOnce"
      resources:
        requests:
          memory: "4Gi"
    

    Espera hasta que el Pod de la base de datos esté Running:

    kk get po -n ${DB_NAMESPACE} -l app=${DB_NAME_GREEN} -w
    

    El resultado debería verse de la siguiente manera:

    NAME                   READY   STATUS    RESTARTS   AGE
    database-green-q1gur   0/1     Pending   0          0s
    database-green-q1gur   0/1     Pending   0          0s
    database-green-q1gur   0/1     Pending   0          1s
    database-green-q1gur   0/1     Init:0/1   0          1s
    database-green-q1gur   0/1     PodInitializing   0          98s
    database-green-q1gur   0/1     Running           0          99s
    database-green-q1gur   1/1     Running           0          99s
    

    Luego, observa los registros y espera el mensaje DATABASE IS READY TO USE!:

    kk logs -n ${DB_NAMESPACE} -l app=${DB_NAME_GREEN} -f
    

    El resultado debería contener lo siguiente:

    #########################
    DATABASE IS READY TO USE!
    #########################
    
  2. Verifica que el estado sea Healthy y que el rol sea PHYSICAL_STANDBY:

    kk get sidb -n ${DB_NAMESPACE}
    

    El resultado debería verse de la siguiente manera:

    NAME             EDITION      STATUS    ROLE
    database-blue    Enterprise   Healthy   PRIMARY
    database-green                Healthy   PHYSICAL_STANDBY
    

Configura el agente de Data Guard

  1. Implementa el DataguardBroker para administrar la configuración de Data Guard:

    apiVersion: database.oracle.com/v4
    kind: DataguardBroker
    metadata:
      name: broker-blue-green
      namespace: ${DB_NAMESPACE}
    spec:
      primaryDatabaseRef: ${DB_NAME_BLUE}
      standbyDatabaseRefs:
        - ${DB_NAME_GREEN}
      protectionMode: MaxAvailability
      fastStartFailover: false
      loadBalancer: true
    

    Parámetros de configuración clave:

    • protectionMode: Se establece en MaxAvailability para garantizar que no se pierdan datos si hay al menos una instancia en espera disponible, lo que hace la transición al modo asíncrono si se puede acceder a al menos una instancia en espera.
    • fastStartFailover: Se establece en false para inhabilitar la conmutación por error automática. Cuando está habilitado, un proceso de observador puede activar automáticamente una conmutación por error si la base de datos principal deja de estar disponible.
    • loadBalancer: Se establece en true para crear un servicio de Kubernetes LoadBalancer para el agente, lo que proporciona una dirección IP externa estable que siempre se enruta a la base de datos principal actual.
  2. Supervisa el estado del agente hasta que informe Healthy:

    kk get dataguardbroker -n ${DB_NAMESPACE} -w
    

    El resultado debería verse de la siguiente manera:

    NAME                PRIMARY   STANDBYS   PROTECTION MODE   CONNECT STR   STATUS     FSFO
    broker-blue-green                        MaxAvailability                 Creating
    broker-blue-green                        MaxAvailability                 Creating
    broker-blue-green   ORCLBLUE   ORCLGREEN   MaxAvailability   10.0.0.25:32345/DATAGUARD   Creating   false
    broker-blue-green   ORCLBLUE   ORCLGREEN   MaxAvailability   10.0.0.25:32345/DATAGUARD   Healthy    false
    
  3. DataguardBroker crea un Service de Kubernetes (broker-blue-green) que enruta el tráfico de forma automática a la base de datos principal actual. Esto proporciona un punto de conexión estable para las aplicaciones. Obtén este servicio:

    kk get svc -n ${DB_NAMESPACE} broker-blue-green
    

    El resultado debería ser similar al siguiente. Ten en cuenta el aprovisionamiento de un CLUSTER-IP para clientes dentro del clúster y un EXTERNAL-IP para clientes externos con un balanceador de cargas:

    NAME                TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)                         AGE
    broker-blue-green   LoadBalancer   10.0.19.198   100.66.38.138   1521:31116/TCP,5500:31842/TCP   8m
    
  4. Verifica los extremos del servicio de agente. Inicialmente, debe apuntar a la dirección IP del Pod azul:

    kk get endpoints -n ${DB_NAMESPACE} broker-blue-green
    

    El resultado debería ser similar al siguiente, en el que la IP del Pod azul debería aparecer en lugar de BLUE_POD_IP:

    NAME                ENDPOINTS
    broker-blue-green   [BLUE_POD_IP]:5500,[BLUE_POD_IP]:1521
    
  5. Verifica los Pods de la base de datos para correlacionar la IP:

    kk get pod -n ${DB_NAMESPACE} -o wide
    

Prueba la sincronización de datos y los roles

Ahora, verifica la replicación escribiendo datos en la instancia principal y leyéndolos desde la instancia en espera con un Pod de cliente en el clúster.

Escribe en la base de datos principal con el servicio de agente

  1. Implementa un Pod temporal para conectarte a la base de datos principal con el servicio de agente estable:

    kk run sqlplus -n ${DB_NAMESPACE} --rm -it --restart=Never \
      --image=${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-instantclient:latest \
      --image-pull-policy=Always \
      --overrides='{"spec": {"imagePullSecrets": [{"name": "'${HARBOR_PULL_SECRET_NAME}'"}]}}' \
      -- sqlplus sys/${ADMIN_PASSWORD}@broker-blue-green:1521/ORCLPDB1 as sysdba
    
  2. Crea una tabla de prueba:

    CREATE TABLE employees (id NUMBER, name VARCHAR2(50));
    INSERT INTO employees VALUES (1, 'John Doe');
    COMMIT;
    SELECT * FROM employees;
    exit;
    

    El resultado debería verse de la siguiente manera:

            ID NAME
    ---------- --------------------------------------------------
            1 John Doe
    

Lectura desde la instancia en espera (acceso directo)

  1. Implementa un Pod temporal para conectarte directamente al servicio en espera:

    kk run sqlplus -n ${DB_NAMESPACE} --rm -it --restart=Never \
      --image=${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-instantclient:latest \
      --image-pull-policy=Always \
      --overrides='{"spec": {"imagePullSecrets": [{"name": "'${HARBOR_PULL_SECRET_NAME}'"}]}}' \
      -- sqlplus sys/${ADMIN_PASSWORD}@${DB_NAME_GREEN}:1521/ORCLPDB1 as sysdba
    
  2. Verifica la replicación de datos:

    SELECT * FROM employees;
    exit;
    

    El resultado debería verse de la siguiente manera:

            ID NAME
    ---------- --------------------------------------------------
            1 John Doe
    

Realiza un cambio manual

Activa un cambio manual para revertir los roles, lo que convierte a la base de datos verde en la nueva principal. El operador requiere el SID (por ejemplo, ORCLGREEN) para el destino de cambio.

  1. Ejecuta el comando siguiente:

    kk patch dataguardbroker broker-blue-green -n ${DB_NAMESPACE} --type='merge' \
      -p "{\"spec\":{\"setAsPrimaryDatabase\":\"ORCLGREEN\"}}"
    
  2. Supervisa el progreso del cambio:

    kk get sidb -n ${DB_NAMESPACE} -w
    

    Una vez que se complete el cambio, el resultado debería verse de la siguiente manera:

    NAME             EDITION      STATUS    ROLE
    database-blue    Enterprise   Healthy   PHYSICAL_STANDBY
    database-green                Healthy   PRIMARY
    
  3. Confirma que las instancias de la base de datos hayan cambiado de rol y que la base de datos verde ahora sea la principal:

    kk get dataguardbroker -n ${DB_NAMESPACE}
    

    El resultado debe verse de la siguiente manera:

    NAME                PRIMARY     STANDBYS   PROTECTION MODE
    broker-blue-green   ORCLGREEN   ORCLBLUE   MaxAvailability
    
  4. Verifica que los extremos del Service broker-blue-green se hayan actualizado para apuntar a la IP del Pod verde:

    kk get endpoints -n ${DB_NAMESPACE} broker-blue-green
    

    El resultado debería ser similar al siguiente, en el que la IP del Pod verde debería aparecer en lugar de GREEN_POD_IP:

    NAME                ENDPOINTS
    broker-blue-green   [GREEN_POD_IP]:5500,[GREEN_POD_IP]:1521
    

¿Qué sigue?