本指南简要介绍了如何在 Google Distributed Cloud (GDC) 气隙式标准集群上部署自行管理的 Oracle Database Enterprise 实例。借助此部署,您可以在气隙式环境中运行 Oracle 工作负载,并利用 GDC 的现有存储和网络功能。
它使用官方的 Oracle Database Operator for Kubernetes,该运算符可 自动执行数据库的生命周期管理。
架构
该架构描述了由 Oracle Database Operator 在 GDC 标准集群中管理的单实例 Oracle 数据库部署。虽然本指南演示了如何部署单个数据库实例,但您可以根据集群的容量(RAM、CPU、磁盘空间)部署任意数量的实例。

该架构包含以下关键组件:
- GDC 项目:用于存放资源的 项目的容器。
- 标准 Kubernetes 集群:提供计算资源的 标准集群 。
- Oracle Database Operator:一个 Kubernetes 运算符,可自动执行 Oracle 数据库的 预配、生命周期管理和可观测性。 它可以简化补丁程序、备份和恢复等复杂任务,从而更轻松地在容器化环境中运行有状态 Oracle 工作负载。
- 数据库实例:容器化的 Oracle 单实例数据库 (SIDB),具有永久性存储空间。
- Harbor:用于在气隙式环境中托管数据库、 运算符和客户端映像的私有容器注册表。
- Cert-manager:运算符依赖于
cert-manager来管理 Webhook 证书。cert-manager预安装在 GDC 标准集群上。
在本指南中,您将在自己的命名空间 (oracle-database-operator-system) 中部署运算符,并在单独的命名空间 (oracle-db) 中部署数据库实例。这些命名空间在架构图中使用虚线边框框出。
建议您进行这种分离,以提高清晰度和可管理性。不过,您可以自行决定如何组织数据库。例如,您可以根据工作负载需求、团队所有权或安全规范,将某些数据库分组到不同的命名空间中,以管理精细的访问权限控制 (RBAC)。
准备工作
在开始部署之前,您必须确保您的环境满足以下要求:
- 创建一个项目 ,该项目将作为本 指南中生成的所有资源的持有者。
为您的项目授予 Cluster Admin 和 Standard Cluster Admin 角色。这样,您就可以创建标准 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 Instance Admin 角色,以便您可以将映像上传到 Harbor 实例:
gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=harbor-instance-admin在 Harbor 项目中创建一个 Harbor 机器人 账号 。在本指南的后续部分中,机器人账号的凭据将存储在 Kubernetes Secret 中,以便集群在实例化容器时从 Harbor 中拉取映像。
创建一个包含两个工作器节点的标准 Kubernetes 集群,每个工作器节点至少具有 16 GB 的内存。例如:
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设置环境变量。在本指南中,这些变量将用于创建和引用资源:
# General info export PROJECT_ID="PROJECT_ID" export ZONE="ZONE" export ORG_NAME="ORG_NAME" export CLUSTER_NAME="CLUSTER_NAME" # Oracle operator settings export ORACLE_OPERATOR_VERSION="2.1.0" export ORACLE_DB_VERSION="23.26.1.0" export ORACLE_OPERATOR_NAMESPACE="ORACLE_DBS_OPERATOR-SYSTEM" # 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 DB_NAMESPACE="DB_NAMESPACE" export DB_NAME="DB_NAME"网络说明 :本指南假定它是在可以访问 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 Container Registry 下载映像,并将其推送到您的内部 Harbor 项目。您将镜像运算符、企业数据库和即时客户端以进行测试。
镜像 Oracle Database Operator 映像:
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 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}镜像 Oracle Instant Client 映像:
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}
安装 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 和自定义资源定义 (CRD)。此命令会下载官方清单,将映像路径替换为您的 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
部署新的数据库实例
在运算符运行后,您现在可以部署单实例 Oracle 数据库。本指南将创建一个适用于开发或测试的基本 Enterprise Edition 实例。
创建一个 Kubernetes Secret 来存储数据库管理密码:
kk create secret generic oracle-db-password \ --from-literal=password=${ADMIN_PASSWORD} \ -n ${DB_NAMESPACE}应用
SingleInstanceDatabase清单来创建数据库:apiVersion: database.oracle.com/v4 kind: SingleInstanceDatabase metadata: name: ${DB_NAME} namespace: ${DB_NAMESPACE} spec: sid: ORCLCDB pdbName: ORCLPDB1 edition: enterprise replicas: 1 image: pullFrom: ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/oracle-enterprise:${ORACLE_DB_VERSION} pullSecrets: ${HARBOR_PULL_SECRET_NAME} prebuiltDB: true persistence: size: 50Gi storageClass: standard-rwo accessMode: ReadWriteOnce adminPassword: secretName: oracle-db-password secretKey: passwordsid/pdbName:定义系统标识符 (SID) 和可插拔数据库 (PDB) 名称。edition:指定数据库版本(在本例中为enterprise)。image:指向您的私有 Harbor 注册表映像。persistence:使用standard-rwoStorageClass 请求 50Gi 永久性卷,这会在 GDC 中创建一个可用区级永久性磁盘。replicas:将 pod 的数量设置为1。虽然1对于单实例来说很典型,但您可以针对特定用例(例如滚动更新,即在旧 pod 终止之前创建新 pod)或在使用支持并发访问的共享存储后端时增加此值。对于基本单实例部署,1是标准值。
如需查看配置选项的完整列表(包括自定义 init 参数 和资源限制),请参阅官方 文档。
数据库创建过程需要大量资源,可能需要 10 到 20 分钟。
等待数据库 pod 处于
Running状态:kk get po -n ${DB_NAMESPACE} -l app=${DB_NAME} -w输出应如下所示:
NAME READY STATUS RESTARTS AGE my-db-i5xdj 0/1 Pending 0 0s my-db-i5xdj 0/1 Pending 0 0s my-db-i5xdj 0/1 Pending 0 1s my-db-i5xdj 0/1 Init:0/1 0 1s my-db-i5xdj 0/1 PodInitializing 0 98s my-db-i5xdj 0/1 Running 0 99s my-db-i5xdj 1/1 Running 0 99s然后查看日志,等待
DATABASE IS READY TO USE!消息:kk logs -n ${DB_NAMESPACE} -l app=${DB_NAME} -f输出应包含以下内容:
######################### DATABASE IS READY TO USE! #########################验证状态是否为
Healthy:kk get singleinstancedatabase -n ${DB_NAMESPACE}输出应如下所示:
NAME EDITION STATUS ROLE my-db Enterprise Healthy PRIMARY
访问和公开数据库
默认情况下,运算符会为数据库创建两个服务:
${DB_NAME}(ClusterIP) :用于集群内的内部流量。对于在同一集群内运行的应用,请使用此稳定的 DNS 名称。${DB_NAME}-ext(NodePort) :用于外部访问。默认情况下,这会在每个节点上的高端口公开数据库。您可以通过在SingleInstanceDatabase规范中设置loadBalancer: true将其升级为负载均衡器服务。
如需详细了解如何自定义这些服务(例如定义 特定的 NodePort),请参阅 GitHub 文档。
根据您的需求,选择以下方法之一来访问数据库。如需详细了解 GDC 服务类型,请参阅公开服务。
在集群内访问 (ClusterIP)
如需从在同一 Kubernetes 集群内运行的其他 pod 访问数据库,请使用 ClusterIP 服务。
- 如需安全地验证这一点,请直接从临时客户端 pod 进行连接。
- 检查命名空间中的可用服务。请注意名为
${DB_NAME}(例如my-db)的ClusterIP服务。此名称用作内部连接的主机名。 部署包含 SQL*Plus 客户端的临时 pod。您可以使用镜像到 Harbor 注册表的
instantclient映像:kk run sqlplus-client -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}:1521/ORCLPDB1 as sysdba您应该会看到 SQL 提示符,表明连接成功。
创建一个示例表以验证写入权限:
CREATE TABLE employees (id NUMBER, name VARCHAR2(50)); INSERT INTO employees VALUES (1, 'John Doe'); COMMIT; SELECT * FROM employees;输出应如下所示:
ID NAME ---------- -------------------------------------------------- 1 John Doe退出会话:
exit
在 VPC 内访问(内部负载均衡器)
如需将数据库公开给位于同一 GDC 项目或 VPC 内但在 Kubernetes 集群外的其他资源(例如虚拟机),请使用内部负载均衡器。这样可以确保流量在隔离的网络环境中保持私密。如需了解详情,请参阅 GDC 内部负载均衡器 文档。
由于运算符不会自动支持向生成的服务添加注解,因此您必须创建单独的服务资源。请注意 networking.gke.io/load-balancer-type: internal 注解,这是预配内部负载均衡器所必需的。
创建内部负载均衡器服务:
apiVersion: v1 kind: Service metadata: name: ${DB_NAME}-internal namespace: ${DB_NAMESPACE} annotations: networking.gke.io/load-balancer-type: internal spec: type: LoadBalancer selector: app: ${DB_NAME} ports: - name: sqlnet port: 1521 targetPort: 1521检索内部 IP 地址:
export DB_INT_IP=$(kk get svc ${DB_NAME}-internal -n ${DB_NAMESPACE} \ -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo "Database Internal IP: ${DB_INT_IP}"
从 VPC 外部访问(外部负载均衡器)
如需将数据库公开给完全位于 GDC 环境或 VPC 外部的客户端(例如,来自公司网络或外部客户端),您可以使用外部负载均衡器。这会分配一个可从隔离的 VPC 边界外部访问的 IP 地址。如需了解详情,请参阅 GDC 外部负载均衡器 文档。
如需创建外部负载均衡器,请更新 SingleInstanceDatabase 规范以设置 loadBalancer: true。这会将现有 ${DB_NAME}-ext 服务类型从 NodePort 更改为 LoadBalancer。
更新规范:
kk patch sidb ${DB_NAME} -n ${DB_NAMESPACE} --type='merge' \ -p '{"spec":{"loadBalancer":true}}'检索外部 IP 地址:
export DB_EXT_IP=$(kk get svc ${DB_NAME}-ext -n ${DB_NAMESPACE} \ -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo "Database External IP: ${DB_EXT_IP}"