セルフマネージド Oracle データベースをデプロイする

このガイドでは、Google Distributed Cloud(GDC)エアギャップ標準クラスタにセルフマネージド Oracle Database Enterprise インスタンスをデプロイする方法について説明します。このデプロイにより、エアギャップ環境内で Oracle ワークロードを実行し、GDC の既存のストレージ機能とネットワーク機能を活用できます。

データベースのライフサイクル管理を自動化する、Kubernetes 向け公式 Oracle Database オペレーター を使用します。

アーキテクチャ

このアーキテクチャは、GDC 標準クラスタ内の Oracle Database オペレーターによって管理される単一インスタンスの Oracle データベース デプロイについて説明しています。このガイドでは、単一のデータベース インスタンスのデプロイについて説明しますが、クラスタの容量(RAM、CPU、ディスク容量)に応じて、必要な数のインスタンスをデプロイできます。

シングル インスタンスの Oracle データベース デプロイ アーキテクチャの図。

このアーキテクチャは、次の主要なコンポーネントで構成されています。

  • GDC プロジェクト: リソースの プロジェクト コンテナ。
  • 標準 Kubernetes クラスタ: コンピューティング リソースを提供する標準クラスタ
  • Oracle Database オペレーター: Oracle データベースの プロビジョニング、ライフサイクル管理、オブザーバビリティを自動化する Kubernetes オペレーター。 パッチ適用、バックアップ、復元などの複雑なタスクを簡素化し、コンテナ化された環境でステートフル Oracle ワークロードを簡単に実行できるようにします。
  • データベース インスタンス: 永続ストレージを備えたコンテナ化された Oracle Single Instance Database (SIDB)。
  • Harbor: エアギャップ環境内でデータベース、 オペレーター、クライアント イメージをホストするために使用される非公開コンテナ レジストリ。
  • Cert-manager: オペレーターは、ウェブフック証明書の管理に cert-manager を使用します。cert-manager は、GDC 標準クラスタにプリインストールされています。

このガイドでは、オペレーターを独自の Namespace(oracle-database-operator-system)にデプロイし、データベース インスタンスを別の Namespace(oracle-db)にデプロイします。これらの Namespace は、アーキテクチャ図で破線の枠で示されています。

明確さと管理のしやすさから、この分離をおすすめします。ただし、データベースの構成方法はユーザーが決定します。たとえば、ワークロードのニーズ、チームの所有権、セキュリティ仕様に基づいて、特定のデータベースを異なる Namespace にグループ化して、きめ細かいアクセス制御(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 Secret に保存され、クラスタがコンテナのインスタンス化時に Harbor からイメージを pull できるようになります。

  • それぞれに 16 GB 以上のメモリを持つ 2 つのワーカーノードで標準 Kubernetes クラスタを作成します。次に例を示します。

    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 レジストリで認証して、ベースイメージを pull する必要があります。

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 に保存されます。

イメージを pull、タグ付け、push する

公式の Oracle Container Registry からイメージをダウンロードし、内部の Harbor プロジェクトに push します。テスト用に、オペレーター、エンタープライズ データベース、インスタント クライアントをミラーリングします。

  1. Oracle Database オペレーター イメージをミラーリングします。

    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 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. 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"
    

Secret を作成する

Kubernetes Secret を作成して、ローカルの ./docker-harbor/config.json に保存されている認証情報を使用して、クラスタが Harbor からイメージを pull できるようにします。この Secret は、オペレーターの Namespace(オペレーター イメージを pull するため)とデータベースの Namespace(データベース イメージを pull するため)の両方に必要です。

  1. オペレーターの Namespace を作成します。

    kk create ns ${ORACLE_OPERATOR_NAMESPACE}
    
  2. オペレーターの pull Secret を作成します。

    kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ${ORACLE_OPERATOR_NAMESPACE}
    
  3. データベースの Namespace を作成します。

    kk create ns ${DB_NAMESPACE}
    
  4. データベースの pull Secret を作成します。

    kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ${DB_NAMESPACE}
    

Oracle Database オペレーターをインストールする

3 つのマニフェストを適用して、Oracle Database オペレーターをクラスタにインストールします。

  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. オペレーターのデプロイ: オペレーター Pod とカスタム リソース定義(CRD)をデプロイします。このコマンドは、公式マニフェストをダウンロードし、イメージパスを Harbor URL に置き換え、Kubernetes が Harbor で認証できるように imagePullSecrets 構成を挿入して、結果を適用します。

    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 が標準です。

    カスタム初期化パラメータ やリソース上限など、構成オプションの完全なリストについては、公式 ドキュメントをご覧ください。

    データベースの作成はリソースを大量に消費するため、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
    

データベースにアクセスして公開する

デフォルトでは、オペレーターはデータベース用に 2 つのサービスを作成します。

  1. ${DB_NAME}(ClusterIP): クラスタ内の内部トラフィック用。同じクラスタ内で実行されているアプリケーションには、この安定した DNS 名を使用します。
  2. ${DB_NAME}-ext(NodePort): 外部アクセス用。デフォルトでは、これにより、すべてのノードの高ポートでデータベースが公開されます。SingleInstanceDatabase 仕様で loadBalancer: true を設定すると、ロードバランサ サービスにアップグレードできます。

特定の NodePort の定義など、これらのサービスをカスタマイズする方法については、GitHub のドキュメントをご覧ください。

ニーズに応じて、次のいずれかの方法でデータベースにアクセスします。GDC サービスタイプの詳細については、サービスの公開をご覧ください。

クラスタ内でのアクセス(ClusterIP)

同じ Kubernetes クラスタ内で実行されている他の Pod からデータベースにアクセスするには、ClusterIP サービスを使用します。

  1. これを安全に確認するには、一時的なクライアント Pod から直接接続します。
  2. Namespace で利用可能なサービスを確認します。${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
    

VPC 内でのアクセス(内部ロードバランサ)

同じ GDC プロジェクトまたは VPC 内にあり、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}"
    

VPC の外部からのアクセス(外部ロードバランサ)

GDC 環境または VPC の外部にあるクライアント(企業ネットワークや外部クライアントなど)にデータベースを公開するには、外部ロードバランサを使用します。これにより、分離された VPC 境界の外部から到達可能な 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}"
    

次のステップ