במדריך הזה מוסבר איך לפרוס מופע של Oracle Database Enterprise בניהול עצמי באשכול סטנדרטי עם בידוד פיזי (air-gapped) ב-Google Distributed Cloud (GDC). הפריסה הזו מאפשרת להפעיל עומסי עבודה של Oracle בסביבה מבודדת, תוך ניצול יכולות האחסון והרשת הקיימות של GDC.
הוא משתמש בOracle Database Operator for Kubernetes הרשמי, שמבצע אוטומציה של ניהול מחזור החיים של מסד הנתונים.
ארכיטקטורה
הארכיטקטורה מתארת פריסה של מסד נתונים של Oracle עם מופע יחיד שמנוהל על ידי Oracle Database Operator באשכול רגיל של GDC. במדריך הזה מוסבר איך לפרוס מופע יחיד של מסד נתונים, אבל אפשר לפרוס כמה מופעים שהקיבולת של האשכול (RAM, CPU, שטח דיסק) מאפשרת.

הארכיטקטורה כוללת את הרכיבים העיקריים הבאים:
- פרויקט GDC: מאגר הפרויקט של המשאבים שלכם.
- אשכול Kubernetes רגיל: אשכול רגיל שמספק את משאבי המחשוב.
- Oracle Database Operator: אופרטור של Kubernetes שמבצע אוטומציה של הקצאת משאבים, ניהול מחזור חיים ויכולת צפייה במסדי נתונים של Oracle. הוא מפשט משימות מורכבות כמו תיקון, גיבוי ושחזור, ומקל על הפעלת עומסי עבודה (workloads) של Oracle עם שמירת מצב בסביבה מבוססת-קונטיינרים.
- מופע מסד נתונים: מסד נתונים של Oracle Single Instance (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 ופרויקט של Harbor כדי לארח את תמונות הקונטיינר שנדרשות במדריך הזה.
נותנים למשתמש את התפקיד 'אדמין של מופע Harbor' כדי שיוכל להעלות תמונות למופע Harbor:
gdcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="user:${USER_NAME}" \ --role=harbor-instance-adminיוצרים חשבון רובוט של Harborבפרויקט Harbor. בהמשך המדריך הזה, פרטי הכניסה של חשבון הרובוט יאוחסנו בסודות של Kubernetes, כדי לאפשר לאשכול לשלוף תמונות מ-Harbor כשיוצרים מופעים של קונטיינרים.
יוצרים אשכול Kubernetes רגיל עם שני צמתי עובד, שלכל אחד מהם יש זיכרון בנפח 16GB לפחות. לדוגמה:
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"הערה לגבי רשת: המדריך הזה מבוסס על ההנחה שהוא מופעל מצומת bastion שיש לו גישה לממשקי ה-API של GDC וגם גישה לאינטרנט כדי להוריד את המניפסטים ואת תמונות הקונטיינר של Oracle Operator. אם אתם מריצים את הפקודה ממכונה ללא גישה לאינטרנט, אתם צריכים להשיג את הנכסים האלה בנפרד (למשל, באמצעות
docker saveלייצוא תמונות ממכונה מחוברת ו-docker loadלייבוא שלהן) ולהעלות אותם בצורה מאובטחת לסביבה שלכם לפני שתמשיכו.יוצרים חשבון ומקבלים אסימון API בכתובת container-registry.oracle.com, ואז מאשרים את הסכם הרישיון של התמונות Oracle Database Enterprise Edition ו-Oracle Instant Client לפני שממשיכים.
טעינת תמונות ל-Harbor
מכיוון שלקלאסטרים ב-Google Distributed Cloud במודל Air-gapped אין גישה למאגרי מידע חיצוניים, עליכם לשכפל את התמונות הנדרשות למופע הפרטי של 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"
יצירת סודות
יוצרים סוד של Kubernetes כדי לאפשר לאשכול לשלוף תמונות מ-Harbor באמצעות פרטי הכניסה שנשמרו ב-./docker-harbor/config.json המקומי. הסוד הזה נדרש במרחב השמות של האופרטור (כדי לשלוף את תמונת האופרטור) ובמרחב השמות של מסד הנתונים (כדי לשלוף את תמונת מסד הנתונים).
יוצרים את מרחב השמות של האופרטור:
kk create ns ${ORACLE_OPERATOR_NAMESPACE}יוצרים את סוד המשיכה לאופרטור:
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}יוצרים את סוד המשיכה למסד הנתונים:
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 באשכול על ידי החלת שלושה מניפסטים:
Cluster Role Binding: מגדיר את ההרשאות הנדרשות כדי שהאופרטור יפעל בכל האשכול.
kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/cluster-role-binding.yamlNode RBAC: מעניק הרשאות לקריאת טופולוגיית הצומת, שחשובה לתזמון נכון של הפודים.
kk apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/refs/tags/v${ORACLE_OPERATOR_VERSION}/rbac/node-rbac.yamlפריסת אופרטור: פריסת פודים של אופרטורים והגדרות של משאבים בהתאמה אישית (CRD). הפקודה הזו מורידה את המניפסט הרשמי, מחליפה את נתיב התמונה בכתובת ה-URL של 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 -ממתינים עד שהפודים של האופרטור יפעלו:
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 שמתאימה לפיתוח או לבדיקות.
יוצרים סוד ב-Kubernetes כדי לאחסן את סיסמת האדמין של מסד הנתונים:
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: password-
sid/pdbName: מגדיר את מזהה המערכת (SID) ואת שם מסד הנתונים הניתן לחיבור (PDB). -
edition: מציין את מהדורת מסד הנתונים (enterpriseבמקרה הזה). -
image: מצביע על תמונת הרישום הפרטית שלכם ב-Harbor. -
persistence: בקשה לנפח אחסון מתמיד (persistent volume) בנפח 50Gi באמצעותstandard-rwoStorageClass, שיוצר דיסק מתמיד אזורי ב-GDC. -
replicas: מגדיר את מספר ה-Pods ל-1. בדרך כלל, הערך של1מתאים למופע יחיד, אבל אפשר להגדיל אותו לתרחישי שימוש ספציפיים כמו עדכונים מתגלגלים (שבהם נוצר פוד חדש לפני שהפוד הישן מסתיים) או אם אתם משתמשים בקצה עורפי של אחסון משותף שתומך בגישה בו-זמנית. בפריסות בסיסיות של מופע יחיד,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): לגישה חיצונית. כברירת מחדל, מסד הנתונים נחשף ביציאה גבוהה בכל צומת. אפשר לשדרג אותו לשירות איזון עומסים על ידי הגדרתloadBalancer: trueבמפרטSingleInstanceDatabase.
מידע נוסף על התאמה אישית של השירותים האלה, כמו הגדרה של NodePort ספציפיים, זמין במאמרי העזרה של GitHub.
בהתאם לצרכים שלכם, בוחרים אחת מהשיטות הבאות כדי לגשת למסד הנתונים. פרטים נוספים על סוגי השירותים של GDC זמינים במאמר חשיפת שירותים.
גישה בתוך האשכול (ClusterIP)
כדי לגשת למסד הנתונים מקבוצות Pod אחרות שפועלות באותו אשכול Kubernetes, משתמשים בשירות ClusterIP.
- כדי לבצע אימות מאובטח, צריך להתחבר ישירות מ-pod לקוח זמני.
- בודקים את השירותים שזמינים במרחב השמות. שימו לב לשם השירות
ClusterIP${DB_NAME}(לדוגמה,my-db). השם הזה משמש כשם המארח לחיבורים פנימיים. פורסים פוד זמני שמכיל את לקוח SQL*Plus. משתמשים בתמונת
instantclientשמשוכפלת למאגר 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אחרי החיבור, אמורה להופיע שורת הפקודה של 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 (לדוגמה, מרשת ארגונית או מלקוח חיצוני), אפשר להשתמש במאזן עומסים חיצוני. כך מוקצית כתובת IP שאפשר להגיע אליה מחוץ לגבולות ה-VPC המבודד. פרטים נוספים זמינים במסמכי התיעוד של איזון העומסים החיצוני ב-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}"
המאמרים הבאים
- ארכיטקטורת עזר של מסד נתונים של Oracle בניהול עצמי
- פריסת מסדי נתונים של Oracle בניהול עצמי עם זמינות גבוהה