Déployer des bases de données Oracle autogérées

Ce guide décrit le déploiement d'une instance Oracle Database Enterprise autogérée sur un cluster standard Google Distributed Cloud (GDC) sous air gap. Ce déploiement vous permet d'exécuter des charges de travail Oracle dans l'environnement isolé, en tirant parti des capacités de stockage et de mise en réseau existantes de GDC.

Il utilise l'Oracle Database Operator for Kubernetes officiel, qui automatise la gestion du cycle de vie de la base de données.

Architecture

L'architecture décrit un déploiement de base de données Oracle à instance unique géré par l'opérateur de base de données Oracle dans un cluster standard GDC. Bien que ce guide montre comment déployer une seule instance de base de données, vous pouvez en déployer autant que la capacité de votre cluster (RAM, processeur, espace disque) le permet.

Schéma de l'architecture de déploiement d'une base de données Oracle à instance unique.

L'architecture comprend les principaux composants suivants :

  • Projet GDC : conteneur project pour vos ressources.
  • Cluster Kubernetes standard : cluster standard fournissant les ressources de calcul.
  • Oracle Database Operator : opérateur Kubernetes qui automatise le provisionnement, la gestion du cycle de vie et l'observabilité des bases de données Oracle. Il simplifie les tâches complexes telles que l'application de correctifs, la sauvegarde et la récupération, ce qui facilite l'exécution des charges de travail Oracle avec état dans un environnement conteneurisé.
  • Instance de base de données : base de données Oracle Single Instance Database (SIDB) conteneurisée avec stockage persistant.
  • Harbor : registre de conteneurs privé utilisé pour héberger les images de base de données, d'opérateur et de client dans l'environnement isolé.
  • Cert-manager : l'opérateur s'appuie sur cert-manager pour gérer les certificats de webhook. cert-manager est préinstallé sur les clusters GDC standards.

Dans ce guide, vous déployez l'opérateur dans son propre espace de noms (oracle-database-operator-system) et l'instance de base de données dans un espace de noms distinct (oracle-db). Ces espaces de noms sont illustrés par des cadres en pointillés dans le schéma d'architecture.

Cette séparation est recommandée pour plus de clarté et de facilité de gestion. Toutefois, c'est à vous de décider comment organiser vos bases de données. Par exemple, vous pouvez regrouper certaines bases de données dans différents espaces de noms pour gérer un contrôle d'accès précis (RBAC) en fonction des besoins de la charge de travail, de la propriété de l'équipe ou des spécifications de sécurité.

Avant de commencer

Avant de commencer le déploiement, vous devez vous assurer que votre environnement répond aux exigences suivantes :

  • Créez un projet qui servira de conteneur pour toutes les ressources générées tout au long de ce guide.
  • Attribuez à votre utilisateur les rôles d'administrateur de cluster et d'administrateur de cluster standard pour votre projet. Vous pourrez ainsi créer un cluster Kubernetes standard et gérer ses ressources :

    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
    
  • Créez une instance Harbor et un projet Harbor pour héberger les images de conteneurs nécessaires à ce guide.

  • Attribuez à votre utilisateur le rôle d'administrateur d'instance Harbor pour pouvoir importer des images dans votre instance Harbor :

    gdcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member="user:${USER_NAME}" \
      --role=harbor-instance-admin
    
  • Créez un compte robot Harbor dans votre projet Harbor. Plus loin dans ce guide, les identifiants du compte de robot seront stockés dans des secrets Kubernetes, ce qui permettra au cluster d'extraire des images de Harbor lors de l'instanciation des conteneurs.

  • Créez un cluster Kubernetes standard avec deux nœuds de calcul, chacun disposant d'au moins 16 Go de mémoire. Exemple :

    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
    
  • Configurez vos variables d'environnement. Ces éléments seront utilisés tout au long du guide pour créer des ressources et y faire référence :

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

    Remarque sur le réseau : Ce guide suppose que l'opération est exécutée à partir d'un nœud bastion ayant accès aux API GDC et à Internet pour télécharger les fichiers manifestes et les images de conteneur de l'opérateur Oracle. Si vous exécutez cette opération à partir d'une machine sans accès à Internet, vous devez obtenir ces éléments séparément (par exemple, en utilisant docker save pour exporter des images à partir d'une machine connectée et docker load pour les importer), puis les importer de manière sécurisée dans votre environnement avant de continuer.

  • Créez un compte et obtenez un jeton d'API sur container-registry.oracle.com, puis acceptez le contrat de licence pour les images Oracle Database Enterprise Edition et Oracle Instant Client avant de continuer.

Importer des images dans Harbor

Étant donné que les clusters dans Google Distributed Cloud sous air gap ne peuvent pas accéder aux registres externes, vous devez mettre en miroir les images requises dans votre instance Harbor privée.

Se connecter à Oracle Container Registry

Vous devez d'abord vous authentifier auprès du registre Oracle officiel pour extraire les images de base :

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

Une fois la connexion établie, les identifiants seront enregistrés dans ./docker-oracle/config.json.

Importer des images dans Harbor

Authentifiez-vous auprès de votre instance Harbor privée :

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

Une fois la connexion établie, les identifiants du compte robot sont enregistrés dans ./docker-harbor/config.json.

Extraire, taguer et transférer des images

Téléchargez les images depuis le Container Registry Oracle officiel et transférez-les vers votre projet Harbor interne. Vous allez dupliquer l'opérateur, la base de données d'entreprise et le client instantané pour les tests.

  1. Mettez en miroir l'image 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. Mettez en miroir l'image 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. Mettez en miroir l'image 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
    

Configurer l'accès au cluster

Avant de déployer des ressources, récupérez les identifiants de votre cluster standard et créez un alias pratique :

  1. Récupérez le fichier kubeconfig de votre cluster standard :

    KUBECONFIG=kubeconfig-${CLUSTER_NAME}.yaml gdcloud clusters \
      get-credentials ${CLUSTER_NAME} \
      --standard \
      --project ${PROJECT_ID} \
      --zone ${ZONE}
    
  2. Créez l'alias kk pour simplifier les commandes suivantes :

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

Créer des secrets

Créez un secret Kubernetes pour permettre au cluster d'extraire des images de Harbor à l'aide des identifiants enregistrés dans votre fichier ./docker-harbor/config.json local. Vous avez besoin de ce secret à la fois dans l'espace de noms de l'opérateur (pour extraire l'image de l'opérateur) et dans l'espace de noms de la base de données (pour extraire l'image de la base de données).

  1. Créez l'espace de noms pour l'opérateur :

    kk create ns ${ORACLE_OPERATOR_NAMESPACE}
    
  2. Créez le secret d'extraction pour l'opérateur :

    kk create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ${ORACLE_OPERATOR_NAMESPACE}
    
  3. Créez l'espace de noms pour la base de données :

    kk create ns ${DB_NAMESPACE}
    
  4. Créez le secret d'extraction pour la base de données :

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

Installer l'opérateur de base de données Oracle

Vous allez maintenant installer l'opérateur Oracle Database dans votre cluster en appliquant trois fichiers manifestes :

  1. Liaison de rôle de cluster : configure les autorisations nécessaires pour que l'opérateur fonctionne à l'échelle du 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 des nœuds : accorde des autorisations pour lire la topologie des nœuds, ce qui est essentiel pour la planification correcte des pods.

    kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/node-rbac.yaml
    
  3. Déploiement de l'opérateur : déploie les pods de l'opérateur et les définitions de ressources personnalisées (CRD). Cette commande télécharge le fichier manifeste officiel, remplace le chemin d'accès à l'image par votre URL Harbor, injecte la configuration imagePullSecrets afin que Kubernetes puisse s'authentifier auprès de Harbor et applique le résultat :

    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 -
    

    Attendez que les pods de l'opérateur soient en cours d'exécution :

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

    Le résultat doit se présenter sous la forme suivante :

    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
    

Déployer une nouvelle instance de base de données

Une fois l'opérateur en cours d'exécution, vous pouvez déployer une base de données Oracle à instance unique. Ce guide crée une instance Enterprise Edition de base adaptée au développement ou aux tests.

  1. Créez un secret Kubernetes pour stocker le mot de passe administrateur de la base de données :

    kk create secret generic oracle-db-password \
      --from-literal=password=${ADMIN_PASSWORD} \
      -n ${DB_NAMESPACE}
    
  2. Appliquez le fichier manifeste SingleInstanceDatabase pour créer la base de données :

    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
    

    Paramètres de configuration clés :

    • sid / pdbName : définit l'identifiant système (SID) et le nom de la base de données enfichable (PDB).
    • edition : spécifie l'édition de la base de données (enterprise dans ce cas).
    • image : pointe vers l'image de votre registre Harbor privé.
    • persistence : demande un volume persistant de 50 Gio à l'aide de la StorageClass standard-rwo, qui crée un disque persistant zonal dans GDC.
    • replicas : définit le nombre de pods sur 1. Bien que 1 soit typique pour une instance unique, vous pouvez augmenter cette valeur pour des cas d'utilisation spécifiques, comme les mises à jour progressives (où un nouveau pod est créé avant la fin de l'ancien) ou si vous utilisez un backend de stockage partagé qui prend en charge l'accès simultané. Pour les déploiements de base à une seule instance, 1 est la norme.

    Pour obtenir la liste complète des options de configuration, y compris les paramètres d'initialisation personnalisés et les limites de ressources, consultez la documentation officielle.

    La création de la base de données nécessite beaucoup de ressources et peut prendre entre 10 et 20 minutes.

  3. Attendez que le pod de base de données soit Running :

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

    Le résultat doit se présenter sous la forme suivante :

    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. Ensuite, consultez les journaux et attendez le message DATABASE IS READY TO USE! :

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

    La sortie doit contenir les éléments suivants :

    #########################
    DATABASE IS READY TO USE!
    #########################
    
  5. Vérifiez que l'état est Healthy :

    kk get singleinstancedatabase -n ${DB_NAMESPACE}
    

    Le résultat doit se présenter sous la forme suivante :

    NAME    EDITION      STATUS    ROLE
    my-db   Enterprise   Healthy   PRIMARY
    

Accéder à la base de données et l'exposer

Par défaut, l'opérateur crée deux services pour la base de données :

  1. ${DB_NAME} (ClusterIP) : pour le trafic interne au cluster. Utilisez ce nom DNS stable pour les applications exécutées dans le même cluster.
  2. ${DB_NAME}-ext (NodePort) : pour l'accès externe. Par défaut, cela expose la base de données sur un port élevé sur chaque nœud. Vous pouvez le mettre à niveau vers un service d'équilibreur de charge en définissant loadBalancer: true dans la spécification SingleInstanceDatabase.

Pour savoir comment personnaliser ces services, par exemple en définissant des NodePorts spécifiques, consultez la documentation GitHub.

Choisissez l'une des méthodes suivantes pour accéder à votre base de données en fonction de vos besoins. Pour en savoir plus sur les types de services GDC, consultez Exposer des services.

Accès au sein du cluster (ClusterIP)

Pour accéder à la base de données à partir d'autres pods exécutés dans le même cluster Kubernetes, utilisez le service ClusterIP.

  1. Pour le vérifier de manière sécurisée, connectez-vous directement à partir d'un pod client temporaire.
  2. Vérifiez les services disponibles dans votre espace de noms. Notez le service ClusterIP nommé ${DB_NAME} (par exemple, my-db). Ce nom sert de nom d'hôte pour les connexions internes.
  3. Déployez un pod temporaire contenant le client SQL*Plus. Vous utilisez l'image instantclient mise en miroir dans votre registre 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
    

    L'invite SQL devrait s'afficher, indiquant que la connexion a été établie.

  4. Créez un exemple de tableau pour vérifier l'accès en écriture :

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

    Le résultat doit se présenter sous la forme suivante :

            ID NAME
    ---------- --------------------------------------------------
            1 John Doe
    
  5. Quittez la session :

    exit
    

Accès au sein du VPC (équilibreur de charge interne)

Pour exposer la base de données à d'autres ressources (comme des VM) situées dans le même projet ou VPC GDC, mais en dehors du cluster Kubernetes, utilisez un équilibreur de charge interne. Cela permet de maintenir le trafic privé dans votre environnement réseau isolé. Pour en savoir plus, consultez la documentation sur l'équilibreur de charge interne GDC.

Étant donné que l'opérateur ne permet pas d'ajouter automatiquement des annotations au service généré, vous devez créer une ressource de service distincte. Notez l'annotation networking.gke.io/load-balancer-type: internal, qui est requise pour provisionner un équilibreur de charge interne.

  1. Créez le service d'équilibreur de charge interne :

    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. Récupérez l'adresse IP interne :

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

Accès depuis l'extérieur du VPC (équilibreur de charge externe)

Pour exposer la base de données à des clients complètement en dehors de l'environnement ou du VPC GDC (par exemple, à partir d'un réseau d'entreprise ou d'un client externe), vous pouvez utiliser un équilibreur de charge externe. Cela attribue une adresse IP accessible depuis l'extérieur de la limite du VPC isolé. Pour en savoir plus, consultez la documentation sur l'équilibreur de charge externe GDC.

Pour créer un équilibreur de charge externe, mettez à jour la spécification SingleInstanceDatabase pour définir loadBalancer: true. Le type de service ${DB_NAME}-ext existant passe de NodePort à LoadBalancer.

  1. Mettez à jour la spécification :

    kk patch sidb ${DB_NAME} -n ${DB_NAMESPACE} --type='merge' \
      -p '{"spec":{"loadBalancer":true}}'
    
  2. Récupérez l'adresse IP externe :

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

Étapes suivantes