部署自行管理的 Oracle 資料庫

本指南說明如何在 Google Distributed Cloud (GDC) 實體隔離標準叢集,部署自行管理的 Oracle Database Enterprise 執行個體。這項部署作業可讓您在實體隔離環境中執行 Oracle 工作負載,並運用 GDC 現有的儲存和網路功能。

這個解決方案使用官方的 Kubernetes 專用 Oracle Database Operator,可自動管理資料庫生命週期。

架構

這個架構說明由 GDC 標準叢集內的 Oracle Database Operator 管理的單一執行個體 Oracle 資料庫部署作業。雖然本指南示範的是部署單一資料庫執行個體,但您可以在叢集容量 (RAM、CPU、磁碟空間) 允許的範圍內,部署任意數量的執行個體。

單一執行個體 Oracle 資料庫部署作業架構圖。

此架構包含下列主要元件:

  • GDC 專案:資源的專案容器。
  • 標準 Kubernetes 叢集:提供運算資源的標準叢集。
  • Oracle Database Operator:Kubernetes 運算子,可自動佈建、管理生命週期及觀測 Oracle 資料庫。這項服務可簡化修補、備份和復原等複雜工作,讓您在容器化環境中輕鬆執行有狀態的 Oracle 工作負載。
  • 資料庫執行個體:容器化的 Oracle 單一執行個體資料庫 (SIDB),具有永久儲存空間。
  • Harbor:用於在實體隔離環境中代管資料庫、operator 和用戶端映像檔的私人 Container Registry。
  • Cert-manager:運算子會依賴 cert-manager 管理 Webhook 憑證。cert-manager 已預先安裝在 GDC 標準叢集。

在本指南中,您會將運算子部署至專屬命名空間 (oracle-database-operator-system),並將資料庫執行個體部署至另一個命名空間 (oracle-db)。在架構圖中,這些命名空間會以虛線框表示。

建議您分開設定,為求明確並方便管理。不過,您可以自行決定如何整理資料庫。舉例來說,您可以將特定資料庫分組到不同命名空間,根據工作負載需求、團隊擁有權或安全性規格,管理精細的存取控管 (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 專案,託管本指南所需的容器映像檔。

  • 將 Harbor 執行個體管理員角色授予使用者,以便將映像檔上傳至 Harbor 執行個體:

    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=harbor-instance-admin
    
  • 在 Harbor 專案中建立 Harbor 機器人帳戶。在本指南稍後的步驟中,機器人帳戶的憑證會儲存在 Kubernetes 密鑰中,讓叢集在例項化容器時,能從 Harbor 提取映像檔。

  • 建立標準 Kubernetes 叢集,其中包含兩個 worker 節點,每個節點至少有 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 Operator 的資訊清單和容器映像檔。如果是在沒有網路連線能力的機器上執行這項操作,您必須另外取得這些資產 (例如使用 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 專案。您將鏡像運算子、企業資料庫和 Instant Client,以便進行測試。

  1. 鏡像 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}
    
  2. 建立 Oracle 資料庫 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. 鏡像 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
    

設定叢集存取權

部署資源前,請先擷取標準叢集的憑證,並建立方便使用的別名:

  1. 擷取標準叢集的 kubeconfig:

    KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \
      get-credentials ${CLUSTER_NAME} \
      --standard \
      --project ${PROJECT_ID} \
      --zone ${ZONE}
    
  2. 建立 kk 別名,簡化後續指令:

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

建立密鑰

建立 Kubernetes 密鑰,讓叢集使用儲存在本機 ./docker-harbor/config.json 中的憑證,從 Harbor 提取映像檔。您必須在運算子的命名空間 (用於提取運算子映像檔) 和資料庫的命名空間 (用於提取資料庫映像檔) 中,提供這個密鑰。

  1. 為運算子建立命名空間:

    kk create ns ${ORACLE_OPERATOR_NAMESPACE}
    
  2. 為運算子建立提取密鑰:

    kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ${ORACLE_OPERATOR_NAMESPACE}
    
  3. 建立資料庫的命名空間:

    kk create ns ${DB_NAMESPACE}
    
  4. 建立資料庫的提取密鑰:

    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 安裝到叢集:

  1. 叢集角色繫結:設定運算子在整個叢集運作所需的權限。

    kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/cluster-role-binding.yaml
    
  2. 節點 RBAC:授予讀取節點拓撲的權限,這對正確排定 Pod 相當重要。

    kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/node-rbac.yaml
    
  3. Operator 部署作業:部署 Operator 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 執行個體,適合用於開發或測試。

  1. 建立 Kubernetes Secret,儲存資料庫管理密碼:

    kk create secret generic oracle-db-password \
      --from-literal=password=${ADMIN_PASSWORD} \
      -n ${DB_NAMESPACE}
    
  2. 套用 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: password
    

    重要設定參數:

    • sid/pdbName:定義系統 ID (SID) 和可插式資料庫 (PDB) 名稱。
    • edition:指定資料庫版本 (在本例中為 enterprise)。
    • image:指向私人 Harbor 登錄檔映像檔。
    • persistence:使用 standard-rwo StorageClass 要求 50 Gi 永久磁碟區,這會在 GDC 中建立可用區永久磁碟。
    • replicas:將 Pod 數量設為 1。雖然單一執行個體通常為 1,但您可以針對特定用途增加這個值,例如滾動式更新 (在舊 Pod 終止前建立新 Pod),或使用支援並行存取的共用儲存空間後端。如果是基本的單一執行個體部署作業,1 是標準做法。

    如需完整的設定選項清單 (包括自訂 init 參數和資源限制),請參閱官方說明文件。

    建立資料庫會耗用大量資源,可能需要 10 到 20 分鐘。

  3. 等待資料庫 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
    
  4. 接著觀察記錄,等待 DATABASE IS READY TO USE! 訊息出現:

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

    輸出會包含下列內容:

    #########################
    DATABASE IS READY TO USE!
    #########################
    
  5. 確認狀態為 Healthy:

    kk get singleinstancedatabase -n ${DB_NAMESPACE}
    

    輸出內容應如下所示:

    NAME    EDITION      STATUS    ROLE
    my-db   Enterprise   Healthy   PRIMARY
    

存取及公開資料庫

根據預設,運算子會為資料庫建立兩項服務:

  1. ${DB_NAME} (ClusterIP):用於叢集內的內部流量。在同一個叢集內執行的應用程式,請使用這個穩定的 DNS 名稱。
  2. ${DB_NAME}-ext (NodePort):用於外部存取。根據預設,這會在每個節點的高通訊埠上公開資料庫。只要在 SingleInstanceDatabase 規格中設定 loadBalancer: true,即可將其升級為負載平衡器服務。

如要進一步瞭解如何自訂這些服務 (例如定義特定 NodePort),請參閱 GitHub 說明文件。

請根據需求,選擇下列其中一種方法存取資料庫。如要進一步瞭解 GDC 服務類型,請參閱「公開服務」。

叢集內存取 (ClusterIP)

如要從在同一個 Kubernetes 叢集內執行的其他 Pod 存取資料庫,請使用 ClusterIP 服務。

  1. 如要安全地驗證,請直接從臨時用戶端 Pod 連線。
  2. 查看命名空間中的可用服務。請記下名為 ${DB_NAME} 的 ClusterIP 服務 (例如 my-db)。這個名稱會做為內部連線的主機名稱。
  3. 部署含有 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 提示,表示連線成功。

  4. 建立範例資料表,驗證寫入權限:

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

    輸出內容應如下所示:

            ID NAME
    ---------- --------------------------------------------------
            1 John Doe
    
  5. 結束工作階段:

    exit
    

在虛擬私有雲內存取 (內部負載平衡器)

如要將資料庫公開給位於相同 GDC 專案或虛擬私有雲,但位於 Kubernetes 叢集外部的其他資源 (例如 VM),請使用內部負載平衡器。這樣一來,流量就會保留在隔離的網路環境中,詳情請參閱 GDC 內部負載平衡器說明文件。

由於運算子不會自動支援在產生的服務中新增註解,因此您必須建立獨立的服務資源。請注意,必須有 networking.gke.io/load-balancer-type: internal 註解,才能佈建內部負載平衡器。

  1. 建立內部負載平衡器服務:

    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
    
  2. 擷取內部 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}"
    

從虛擬私有雲外部存取 (外部負載平衡器)

如要將資料庫公開給完全位於 GDC 環境或虛擬私有雲以外的用戶端 (例如公司網路或外部用戶端),可以使用外部負載平衡器。這會指派可從獨立虛擬私有雲邊界外部連線的 IP 位址。詳情請參閱 GDC 外部負載平衡器說明文件。

如要建立外部負載平衡器,請更新 SingleInstanceDatabase 規格 ,將 設為 loadBalancer: true。這會將現有的 ${DB_NAME}-ext 服務類型從 NodePort 變更為 LoadBalancer。

  1. 更新規格:

    kk patch sidb ${DB_NAME} -n ${DB_NAMESPACE} --type='merge' \
      -p '{"spec":{"loadBalancer":true}}'
    
  2. 擷取外部 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}"
    

後續步驟