本指南概述了如何在 Google Distributed Cloud (GDC) 网闸隔离的标准集群上部署高可用性多可用区 Oracle Data Guard 配置。 此设置使用 Oracle Database Enterprise Edition,并利用 GDC 现有的存储和网络功能。
此部署使用官方 Oracle Database Operator for Kubernetes,该 运算符可自动执行数据库的生命周期管理。
架构
该架构描述了由 Oracle Database Operator 在 GDC 标准集群中管理的高可用性 Oracle 数据库部署。高可用性部署由主数据库和备用数据库组成,这些数据库配置了 Data Guard 以进行复制和故障切换。

主要组件如下:
- GDC 项目:用于存放资源的 项目的容器。
- 标准 Kubernetes 集群:提供计算资源的 标准集群 。
- Oracle Database Operator:一个 Kubernetes 运算符,可自动执行 Oracle 数据库的 预配、生命周期管理和可观测性。 它可以简化补丁程序、备份和恢复等复杂任务,从而更轻松地在容器化环境中运行有状态 Oracle 工作负载。
- 主数据库:活跃的读写容器化数据库 实例。
- 备用数据库:副本只读(或在故障切换期间读写) 数据库实例。
- Data Guard 代理:编排数据库之间的配置和角色转换 (切换/故障切换)。
- Harbor:用于在网闸隔离的环境中托管数据库、 运算符和客户端映像的私有容器注册表。
- Cert-manager:运算符依赖于
cert-manager来管理 Webhook 证书。cert-manager预安装在 GDC 标准集群上。
在本指南中,您将在自己的命名空间 (oracle-database-operator-system) 中部署运算符,并在单独的命名空间 (oracle-dbs) 中部署数据库实例。这些命名空间在架构图中用虚线边框框出。
建议进行这种分离,为清晰起见并提高可管理性。不过,您可以自行决定如何组织数据库。例如,您可以根据工作负载需求、团队所有权或安全规范,将某些数据库分组到不同的命名空间中,以管理精细的访问权限控制 (RBAC)。
准备工作
在开始部署之前,您必须确保您的环境满足以下要求:
- 创建一个项目 ,该项目将作为本 指南中生成的所有资源的持有者。
为您的用户授予项目的集群管理员和标准集群管理员角色。这样,您就可以创建标准 Kubernetes 集群并管理其资源:
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为您的用户授予 Harbor 实例管理员角色,以便您可以将映像上传到 Harbor 实例:
gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=harbor-instance-admin在 Harbor 项目中创建一个 Harbor 机器人 账号 。在本指南的后续部分中,机器人账号的凭据将存储在 Kubernetes Secret 中,以便集群在实例化容器时从 Harbor 拉取映像。
创建一个标准 Kubernetes 集群,其中至少包含两个工作器节点,每个节点至少具有 16GB 内存。例如:
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设置环境变量。这些变量将在整个指南中用于创建和引用资源:
注意:
- 在本指南中,这两个数据库实例任意命名为
blue和green。最初,blue实例是主实例,green是备用实例。
# 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"- 在本指南中,这两个数据库实例任意命名为
网络注意事项: 本指南假定它是从有权访问 GDC API 且有权访问互联网以下载 Oracle 运算符的清单和容器映像的堡垒节点运行的。如果您是从无法访问互联网的机器运行此指南,则必须单独获取这些资产(例如,使用
docker save从已连接的机器导出映像,并使用docker load导入映像),并在继续操作之前安全地将其上传到您的环境。在继续操作之前,您必须在 container-registry.oracle.com上创建一个账号并获取 API 令牌, 然后接受 Oracle Database Enterprise Edition 和 Oracle Instant Client 映像的许可协议。
将映像加载到 Harbor
由于 Google Distributed Cloud 网闸隔离配置 中的集群无法访问外部注册表,因此您必须将所需的映像镜像到您的私有 Harbor 实例。
登录 Oracle Container Registry
您必须先使用官方 Oracle 注册表进行身份验证,才能拉取基础映像:
docker --config=./docker-oracle login container-registry.oracle.com
成功登录后,凭据将保存在 ./docker-oracle/config.json 中。
登录 Harbor
使用您的私有 Harbor 实例进行身份验证:
docker --config=./docker-harbor login ${HARBOR_INSTANCE_URL} \
-u ${HARBOR_ROBOT_ACCOUNT} \
-p ${HARBOR_ROBOT_SECRET}
成功登录后,机器人账号的凭据将保存在 ./docker-harbor/config.json 中。
拉取、标记和推送映像
从官方 Oracle 容器注册表中下载映像,并将其推送到您的内部 Harbor 项目。您将镜像运算符、企业数据库和即时客户端以进行测试。
镜像 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}镜像 Oracle 数据库企业版映像:
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}镜像 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
配置集群访问权限
在部署资源之前,请检索标准集群的凭据并创建一个方便的别名:
检索标准集群的 kubeconfig 文件:
KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \ get-credentials ${CLUSTER_NAME} \ --standard \ --project ${PROJECT_ID} \ --zone ${ZONE}创建
kk别名以简化后续命令:alias kk="kubectl --kubeconfig kubeconfig-${CLUSTER_NAME}.yaml"
创建 Secret
创建一个 Kubernetes Secret,以允许集群使用保存在本地 ./docker-harbor/config.json 中的凭据从 Harbor 拉取映像。您需要在运算符的命名空间(用于拉取运算符映像)和数据库的命名空间(用于拉取数据库映像)中都需要此 Secret。
为运算符创建命名空间:
kk create ns ${ORACLE_OPERATOR_NAMESPACE}为运算符创建拉取 Secret:
kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \ --from-file=.dockerconfigjson=./docker-harbor/config.json \ -n ${ORACLE_OPERATOR_NAMESPACE}为数据库创建命名空间:
kk create ns ${DB_NAMESPACE}为数据库容器创建映像拉取 Secret:
kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \ --from-file=.dockerconfigjson=./docker-harbor/config.json \ -n ${DB_NAMESPACE}为数据库的管理密码创建 Secret:
kk create secret generic ${ADMIN_PASSWORD_SECRET_NAME} \ --from-literal=password=${ADMIN_PASSWORD} \ -n ${DB_NAMESPACE}
安装 Oracle Database Operator
现在,通过应用三个清单将 Oracle Database Operator 安装到您的集群中:
集群角色绑定:为运算符设置必要的权限,使其能够在集群范围内运行。
kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/cluster-role-binding.yaml节点 RBAC:授予读取节点拓扑的权限,这对于正确的 Pod 调度至关重要。
kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/node-rbac.yaml运算符部署:部署运算符 Pod 和自定义资源定义。此命令会下载官方清单,将映像路径替换为您的 Harbor 网址,注入
imagePullSecrets配置,以便 Kubernetes 可以使用 Harbor 进行身份验证,并应用结果: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 -等待运算符 Pod 运行:
kk get pods -n ${ORACLE_OPERATOR_NAMESPACE} --watch输出应如下所示:
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
部署主数据库和备用数据库
现在,您将在同一命名空间中按顺序部署两个数据库实例。
部署主实例
运行以下命令以创建主数据库实例:
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"主要配置参数:
sid/pdbName:定义系统标识符 (SID) 和可插入数据库 (PDB) 名称。edition:指定数据库版本(在本例中为enterprise)。image:指向您的私有 Harbor 注册表映像。persistence:使用standard-rwoStorageClass 请求 50Gi 永久性卷,该 StorageClass 会在 GDC 中创建可用区级永久性磁盘。replicas:将实例的 Pod 数量设置为 1。archiveLog:启用归档日志模式,这是 Data Guard 所必需的。flashBack:启用闪回数据库,让您可以将数据库恢复到之前的时间点。forceLog:启用强制日志记录,确保即使对于通常绕过日志记录的操作,也会记录所有更改。
如需查看配置选项的完整列表,包括自定义 init 参数 和资源限制,请参阅官方 文档。
数据库创建过程需要大量资源,可能需要 10 到 20 分钟。
等待数据库完全准备就绪,然后再继续操作。这一点至关重要,因为备用数据库需要能够访问主数据库才能建立复制。
等待数据库 Pod 处于
Running状态:kk get po -n ${DB_NAMESPACE} -l app=${DB_NAME_BLUE} -w输出应如下所示:
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然后查看日志,等待
DATABASE IS READY TO USE!消息:kk logs -n ${DB_NAMESPACE} -l app=${DB_NAME_BLUE} -f输出应包含以下内容:
######################### DATABASE IS READY TO USE! #########################验证状态是否为
Healthy,角色是否为PRIMARY:kk get sidb -n ${DB_NAMESPACE} ${DB_NAME_BLUE}输出应如下所示:
NAME EDITION STATUS ROLE database-blue Enterprise Healthy PRIMARY
部署备用实例
主实例运行正常后,部署备用实例。请注意,Data Guard 参数(archiveLog、flashBack、forceLog)是从主实例继承的,不得在备用清单中指定:
部署备用实例:
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"等待数据库 Pod 处于
Running状态:kk get po -n ${DB_NAMESPACE} -l app=${DB_NAME_GREEN} -w输出应如下所示:
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然后查看日志,等待
DATABASE IS READY TO USE!消息:kk logs -n ${DB_NAMESPACE} -l app=${DB_NAME_GREEN} -f输出应包含以下内容:
######################### DATABASE IS READY TO USE! #########################验证状态是否为
Healthy,角色是否为PHYSICAL_STANDBY:kk get sidb -n ${DB_NAMESPACE}输出应如下所示:
NAME EDITION STATUS ROLE database-blue Enterprise Healthy PRIMARY database-green Healthy PHYSICAL_STANDBY
配置 Data Guard 代理
部署
DataguardBroker以管理 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主要配置参数:
protectionMode:设置为MaxAvailability,以确保在至少有一个备用实例可用时不会丢失数据,并在至少有一个备用实例可访问时转换为异步模式。fastStartFailover:设置为false以停用自动故障切换。 启用后,如果主数据库不可用,观察器进程可以自动触发故障切换。loadBalancer:设置为true以为代理创建 KubernetesLoadBalancer服务,提供始终路由到当前主数据库的稳定外部 IP 地址。
监控代理状态,直到其报告
Healthy:kk get dataguardbroker -n ${DB_NAMESPACE} -w输出应如下所示:
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 falseDataguardBroker会创建一个 Kubernetes 服务 (broker-blue-green),该服务会自动将流量路由到当前主数据库。这为应用提供了一个稳定的连接点。获取此服务:kk get svc -n ${DB_NAMESPACE} broker-blue-green输出应如下所示。请注意,系统会为集群内客户端预配
CLUSTER-IP,并为使用负载均衡器的外部客户端预配EXTERNAL-IP: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检查代理服务的端点。它最初必须指向蓝色 Pod 的 IP 地址:
kk get endpoints -n ${DB_NAMESPACE} broker-blue-green输出应如下所示,其中应显示蓝色 Pod IP,而不是
BLUE_POD_IP:NAME ENDPOINTS broker-blue-green [BLUE_POD_IP]:5500,[BLUE_POD_IP]:1521检查数据库 Pod 以关联 IP:
kk get pod -n ${DB_NAMESPACE} -o wide
测试数据同步和角色
现在,您可以使用集群内客户端 Pod 将数据写入主数据库并从备用数据库读取数据,以验证复制。
使用代理服务写入主数据库
部署临时 Pod 以使用稳定的代理服务连接到主数据库:
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创建一个测试表:
CREATE TABLE employees (id NUMBER, name VARCHAR2(50)); INSERT INTO employees VALUES (1, 'John Doe'); COMMIT; SELECT * FROM employees; exit;输出应如下所示:
ID NAME ---------- -------------------------------------------------- 1 John Doe
从备用数据库读取数据(直接访问)
部署临时 Pod 以直接连接到备用服务:
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验证数据复制:
SELECT * FROM employees; exit;输出应如下所示:
ID NAME ---------- -------------------------------------------------- 1 John Doe
执行手动切换
触发手动切换以反转角色,使绿色数据库成为新的主数据库。运算符需要切换目标的 SID(例如 ORCLGREEN)。
运行以下命令:
kk patch dataguardbroker broker-blue-green -n ${DB_NAMESPACE} --type='merge' \ -p "{\"spec\":{\"setAsPrimaryDatabase\":\"ORCLGREEN\"}}"监控切换进度:
kk get sidb -n ${DB_NAMESPACE} -w切换完成后,输出应如下所示:
NAME EDITION STATUS ROLE database-blue Enterprise Healthy PHYSICAL_STANDBY database-green Healthy PRIMARY确认数据库实例已切换角色,并且绿色数据库现在是主数据库:
kk get dataguardbroker -n ${DB_NAMESPACE}输出应如下所示:
NAME PRIMARY STANDBYS PROTECTION MODE broker-blue-green ORCLGREEN ORCLBLUE MaxAvailability验证
broker-blue-green服务端点是否已更新为指向绿色 Pod 的 IP:kk get endpoints -n ${DB_NAMESPACE} broker-blue-green输出应如下所示,其中应显示绿色 Pod IP,而不是
GREEN_POD_IP:NAME ENDPOINTS broker-blue-green [GREEN_POD_IP]:5500,[GREEN_POD_IP]:1521