Esegui il deployment di database Oracle autogestiti

Questa guida descrive il deployment di un'istanza di Oracle Database Enterprise autogestita su un cluster standard air-gapped di Google Distributed Cloud (GDC). Questo deployment ti consente di eseguire i carichi di lavoro Oracle nell'ambiente air-gapped, sfruttando le funzionalità di archiviazione e networking esistenti di GDC.

Utilizza l'operatore Oracle Database ufficiale per Kubernetes, che automatizza la gestione del ciclo di vita del database.

Architettura

L'architettura descrive un deployment di database Oracle a singola istanza gestito dall'operatore Oracle Database all'interno di un cluster standard GDC. Sebbene questa guida mostri il deployment di una singola istanza di database, puoi eseguire il deployment di tutte le istanze consentite dalla capacità del cluster (RAM, CPU, spazio su disco).

Diagramma dell'architettura di deployment del database Oracle a singola istanza.

L'architettura comprende i seguenti componenti chiave:

  • Progetto GDC: il container del progetto per le tue risorse.
  • Cluster Kubernetes standard: un cluster standard che fornisce le risorse di calcolo.
  • Operatore Oracle Database: un operatore Kubernetes che automatizza il provisioning, la gestione del ciclo di vita e l'osservabilità dei database Oracle. Semplifica attività complesse come l'applicazione di patch, il backup e il ripristino, semplificando l'esecuzione dei carichi di lavoro Oracle stateful in un ambiente containerizzato.
  • Istanza di database: il database Oracle a singola istanza (SIDB) containerizzato con spazio di archiviazione permanente.
  • Harbor: il registro container privato utilizzato per ospitare le immagini del database, dell'operatore e del client nell'ambiente air-gapped.
  • Cert-manager: l'operatore si basa su cert-manager per la gestione dei certificati webhook. cert-manager è preinstallato sui cluster standard GDC.

In questa guida, esegui il deployment dell'operatore nel suo spazio dei nomi (oracle-database-operator-system) e dell'istanza di database in uno spazio dei nomi separato (oracle-db). Questi spazi dei nomi sono illustrati con riquadri con bordi tratteggiati nel diagramma dell'architettura.

Questa separazione è consigliata per chiarezza e gestibilità. Tuttavia, la decisione su come organizzare i database spetta a te. Ad esempio, potresti raggruppare determinati database in spazi dei nomi diversi per gestire il controllo dell'accesso granulare (RBAC) in base alle esigenze del carico di lavoro, alla proprietà del team o alle specifiche di sicurezza.

Prima di iniziare

Prima di iniziare il deployment, devi assicurarti che il tuo ambiente soddisfi i seguenti requisiti:

  • Crea un progetto che fungerà da contenitore per tutte le risorse generate in questa guida.
  • Assegna all'utente i ruoli Amministratore cluster e Amministratore cluster standard per il progetto. In questo modo potrai creare un cluster Kubernetes standard e gestirne le risorse:

    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 un'istanza Harbor e un progetto Harbor per ospitare le immagini container necessarie per questa guida.

  • Assegna all'utente il ruolo Amministratore istanza Harbor in modo da poter caricare le immagini nell'istanza Harbor:

    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=harbor-instance-admin
    
  • Crea un account robot Harbor nel tuo progetto Harbor. Più avanti in questa guida, le credenziali dell'account robot verranno archiviate nei secret di Kubernetes, consentendo al cluster di eseguire il pull delle immagini da Harbor durante l'istanza dei container.

  • Crea un cluster Kubernetes standard con due nodi worker, ognuno con un minimo di 16 GB di memoria. Ad esempio:

    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
    
  • Imposta le variabili di ambiente. Queste verranno utilizzate in tutta la guida per creare e fare riferimento alle risorse:

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

    Nota sulla rete: questa guida presuppone che venga eseguita da un nodo bastion che ha accesso alle API GDC e anche a internet per scaricare i manifest e le immagini container dell'operatore Oracle. Se esegui questa operazione da una macchina senza accesso a internet, devi ottenere questi asset separatamente (ad esempio, utilizzando docker save per esportare le immagini da una macchina connessa e docker load per importarle) e caricarli in modo sicuro nel tuo ambiente prima di procedere.

  • Crea un account e ottieni un token API all'indirizzo container-registry.oracle.com, quindi accetta il contratto di licenza per le immagini Oracle Database Enterprise Edition e Oracle Instant Client prima di procedere.

Caricare le immagini in Harbor

Poiché i cluster all'interno di Google Distributed Cloud con air gap non possono accedere ai registri esterni, devi eseguire il mirroring delle immagini richieste nella tua istanza Harbor privata.

Accedere a Oracle Container Registry

Per prima cosa, devi eseguire l'autenticazione con il registro Oracle ufficiale per eseguire il pull delle immagini di base:

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

Dopo l'accesso, le credenziali verranno salvate in ./docker-oracle/config.json.

Caricare le immagini in Harbor

Esegui l'autenticazione con la tua istanza Harbor privata:

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

Dopo l'accesso, le credenziali dell'account robot verranno salvate in ./docker-harbor/config.json.

Eseguire il pull, il tag e il push delle immagini

Scarica le immagini dal registro container Oracle ufficiale ed esegui il push nel tuo progetto Harbor interno. Eseguirai il mirroring dell'operatore, del database Enterprise e del client istantaneo per i test.

  1. Esegui il mirroring dell'immagine dell'operatore 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. Esegui il mirroring dell'immagine 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. Esegui il mirroring dell'immagine 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
    

Configurare l'accesso al cluster

Prima di eseguire il deployment delle risorse, recupera le credenziali per il cluster standard e crea un alias pratico:

  1. Recupera il file kubeconfig per il cluster standard:

    KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \
      get-credentials ${CLUSTER_NAME} \
      --standard \
      --project ${PROJECT_ID} \
      --zone ${ZONE}
    
  2. Crea l'alias kk per semplificare i comandi successivi:

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

Creare i secret

Crea un secret Kubernetes per consentire al cluster di eseguire il pull delle immagini da Harbor utilizzando le credenziali salvate nel file ./docker-harbor/config.json locale. Hai bisogno di questo secret sia nello spazio dei nomi dell'operatore (per eseguire il pull dell'immagine dell'operatore) sia nello spazio dei nomi del database (per eseguire il pull dell'immagine del database).

  1. Crea lo spazio dei nomi per l'operatore:

    kk create ns ${ORACLE_OPERATOR_NAMESPACE}
    
  2. Crea il secret di pull per l'operatore:

    kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ${ORACLE_OPERATOR_NAMESPACE}
    
  3. Crea lo spazio dei nomi per il database:

    kk create ns ${DB_NAMESPACE}
    
  4. Crea il secret di pull per il database:

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

Installare l'operatore Oracle Database

Ora installa l'operatore Oracle Database nel cluster applicando tre manifest:

  1. Associazione di ruoli cluster: configura le autorizzazioni necessarie per il funzionamento dell'operatore a livello di cluster.

    kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/cluster-role-binding.yaml
    
  2. RBAC nodo: concede le autorizzazioni per leggere la topologia dei nodi, che è fondamentale per la pianificazione corretta dei pod.

    kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/node-rbac.yaml
    
  3. Deployment dell'operatore: esegue il deployment dei pod dell'operatore e delle definizioni di risorse personalizzate (CRD). Questo comando scarica il manifest ufficiale, sostituisce il percorso dell'immagine con l'URL di Harbor, inserisce la configurazione imagePullSecrets in modo che Kubernetes possa eseguire l'autenticazione con Harbor e applica il risultato:

    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 -
    

    Attendi che i pod dell'operatore siano in esecuzione:

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

    L'output dovrebbe essere simile all'esempio seguente:

    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
    

Eseguire il deployment di una nuova istanza di database

Con l'operatore in esecuzione, ora puoi eseguire il deployment di un database Oracle a singola istanza. Questa guida crea un'istanza di Enterprise Edition di base adatta allo sviluppo o ai test.

  1. Crea un secret Kubernetes per archiviare la password amministrativa del database:

    kk create secret generic oracle-db-password \
      --from-literal=password=${ADMIN_PASSWORD} \
      -n ${DB_NAMESPACE}
    
  2. Applica il manifest SingleInstanceDatabase per creare il database:

    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
    

    Parametri di configurazione chiave:

    • sid / pdbName: definisce l'identificatore di sistema (SID) e il nome del database modulare (PDB).
    • edition: specifica la versione del database (enterprise in questo caso).
    • image: punta all'immagine del registro Harbor privato.
    • persistence: richiede un volume permanente di 50 Gi utilizzando la StorageClass standard-rwo, che crea un disco permanente a livello di zona in GDC.
    • replicas: imposta il numero di pod su 1. Sebbene 1 sia tipico per una singola istanza, puoi aumentarlo per casi d'uso specifici come gli aggiornamenti in sequenza (in cui viene creato un nuovo pod prima che quello precedente venga terminato) o se utilizzi un backend di archiviazione condiviso che supporta l'accesso simultaneo. Per i deployment di base a singola istanza, 1 è lo standard.

    Per un elenco completo delle opzioni di configurazione, inclusi i parametri di inizializzazione personalizzati e i limiti delle risorse, consulta la documentazione ufficiale.

    La creazione del database richiede molte risorse e potrebbe richiedere da 10 a 20 minuti.

  3. Attendi che il pod del database sia Running:

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

    L'output dovrebbe essere simile all'esempio seguente:

    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. Poi guarda i log e attendi il messaggio DATABASE IS READY TO USE!:

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

    L'output dovrebbe contenere quanto segue:

    #########################
    DATABASE IS READY TO USE!
    #########################
    
  5. Verifica che lo stato sia Healthy:

    kk get singleinstancedatabase -n ${DB_NAMESPACE}
    

    L'output dovrebbe essere simile all'esempio seguente:

    NAME    EDITION      STATUS    ROLE
    my-db   Enterprise   Healthy   PRIMARY
    

Accedere al database ed esporlo

Per impostazione predefinita, l'operatore crea due servizi per il database:

  1. ${DB_NAME} (ClusterIP): per il traffico interno al cluster. Utilizza questo nome DNS stabile per le applicazioni in esecuzione all'interno dello stesso cluster.
  2. ${DB_NAME}-ext (NodePort): per l'accesso esterno. Per impostazione predefinita, questo espone il database su una porta alta su ogni nodo. Puoi eseguire l'upgrade a un servizio di bilanciamento del carico impostando loadBalancer: true nella specifica SingleInstanceDatabase.

Per ulteriori informazioni su come personalizzare questi servizi, ad esempio definendo NodePort specifici, consulta la documentazione di GitHub .

Scegli uno dei seguenti metodi per accedere al database in base alle tue esigenze. Per ulteriori dettagli sui tipi di servizi GDC, consulta Esporre i servizi.

Accedere all'interno del cluster (ClusterIP)

Per accedere al database da altri pod in esecuzione all'interno dello stesso cluster Kubernetes, utilizza il servizio ClusterIP.

  1. Per verificarlo in modo sicuro, connettiti direttamente da un pod client temporaneo.
  2. Controlla i servizi disponibili nel tuo spazio dei nomi. Prendi nota del servizio ClusterIP denominato ${DB_NAME} (ad esempio, my-db). Questo nome funge da nome host per le connessioni interne.
  3. Esegui il deployment di un pod temporaneo contenente il client SQL*Plus. Utilizza l'immagine instantclient di cui è stato eseguito il mirroring nel registro Harbor:

    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
    

    Dovresti visualizzare il prompt SQL che indica una connessione riuscita.

  4. Crea una tabella di esempio per verificare l'accesso in scrittura:

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

    L'output dovrebbe essere simile all'esempio seguente:

            ID NAME
    ---------- --------------------------------------------------
            1 John Doe
    
  5. Esci dalla sessione:

    exit
    

Accedere all'interno del VPC (bilanciatore del carico interno)

Per esporre il database ad altre risorse (come le VM) situate all'interno dello stesso progetto GDC o VPC, ma all'esterno del cluster Kubernetes, utilizza un bilanciatore del carico interno. In questo modo il traffico rimane privato all'interno dell'ambiente di rete isolato. Per ulteriori dettagli, consulta la documentazione sul bilanciatore del carico interno GDC.

Poiché l'operatore non supporta automaticamente l'aggiunta di annotazioni al servizio generato, devi creare una risorsa di servizio separata. Prendi nota dell'annotazione networking.gke.io/load-balancer-type: internal, necessaria per eseguire il provisioning di un bilanciatore del carico interno.

  1. Crea il servizio di bilanciamento del carico interno:

    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. Recupera l'indirizzo IP interno:

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

Accedere dall'esterno del VPC (bilanciatore del carico esterno)

Per esporre il database ai client completamente esterni all'ambiente GDC o al VPC (ad esempio, da una rete aziendale o da un client esterno), puoi utilizzare un bilanciatore del carico esterno. In questo modo viene assegnato un indirizzo IP raggiungibile dall'esterno del limite VPC isolato. Per ulteriori dettagli, consulta la documentazione sul bilanciatore del carico esterno GDC.

Per creare un bilanciatore del carico esterno, aggiorna la specifica SingleInstanceDatabase per impostare loadBalancer: true. In questo modo, il tipo di servizio ${DB_NAME}-ext esistente viene modificato da NodePort a LoadBalancer.

  1. Aggiorna la specifica:

    kk patch sidb ${DB_NAME} -n ${DB_NAMESPACE} --type='merge' \
      -p '{"spec":{"loadBalancer":true}}'
    
  2. Recupera l'indirizzo IP esterno:

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

Passaggi successivi