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

הארכיטקטורה כוללת את הרכיבים העיקריים הבאים:
- פרויקט GDC: מאגר הפרויקט של המשאבים שלכם.
- אשכול Kubernetes רגיל: אשכול רגיל שמספק את משאבי המחשוב.
- Oracle Database Operator: אופרטור של Kubernetes שמבצע אוטומציה של הקצאת משאבים, ניהול מחזור חיים וניטור של מסדי נתונים של Oracle. הוא מפשט משימות מורכבות כמו תיקון, גיבוי ושחזור, ומקל על הפעלת עומסי עבודה של Oracle עם שמירת מצב בסביבה בקונטיינרים.
- מכונה של מסד נתונים: מסד נתונים של מכונה יחידה (SIDB) של Oracle בקונטיינר עם אחסון מתמיד.
- Harbor: ה-Container Registry הפרטי שמשמש לאירוח קובצי האימג' של מסד הנתונים, ה-operator והלקוח בסביבה עם air gap.
- 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 Instance Admin:
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"הערה לגבי הרשת: ההנחה במדריך הזה היא שההפעלה מתבצעת מצומת באסטיון שיש לו גישה לממשקי ה-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 הפנימי. תשכפלו את האופרטור, את מסד הנתונים של הארגון ואת ה-instant client לצורך בדיקה.
משכפלים את קובץ האימג' של 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: נותן הרשאות לקרוא את הטופולוגיה של הצומת, שחיונית לתזמון נכון של pod.
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 Edition שמתאימה לפיתוח או לבדיקה.
יוצרים סוד ב-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: passwordsid/pdbName: מגדיר את מזהה המערכת (SID) ואת שם מסד הנתונים הניתן לחיבור (PDB).-
edition: מציין את מהדורת מסד הנתונים (enterpriseבמקרה הזה). -
image: מפנה לתמונת המאגר הפרטי של Harbor. -
persistence: בקשה לנפח אחסון מתמיד של 50Gi באמצעות StorageClassstandard-rwo, שיוצר דיסק לאחסון מתמיד של תחום ב-GDC. -
replicas: מגדיר את מספר הפודים ל-1. הערך1אופייני למכונה אחת, אבל אפשר להגדיל אותו במקרים ספציפיים כמו עדכונים בהדרגה (rolling) (שבהם נוצר Pod חדש לפני שה-Pod הישן מסתיים) או אם משתמשים בקצה עורפי של נפח אחסון משותף שתומך בגישה בו-זמנית. בפריסות בסיסיות של מכונה אחת,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.
למידע נוסף על התאמה אישית של השירותים האלה, כמו הגדרת NodePorts ספציפיים, עיינו במסמכי התיעוד של GitHub.
בוחרים באחת מהשיטות הבאות כדי לגשת למסד הנתונים, בהתאם לצרכים שלכם. לפרטים נוספים על סוגי השירותים של GDC, קראו את המאמר חשיפת שירותים.
גישה בתוך האשכול (ClusterIP)
כדי לגשת למסד הנתונים מקבוצות Pod אחרות שפועלות באותו אשכול Kubernetes, משתמשים בשירות ClusterIP.
- כדי לאמת את זה בצורה מאובטחת, צריך להתחבר ישירות מ-Pod זמני של לקוח.
- בודקים את השירותים הזמינים במרחב השמות. שימו לב לשירות
ClusterIPשנקרא${DB_NAME}(לדוגמה,my-db). השם הזה משמש כשם המארח לחיבורים פנימיים. פורסים pod זמני שמכיל את הלקוח 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 (מאזן עומסים פנימי)
כדי לחשוף את מסד הנתונים למשאבים אחרים (כמו מכונות וירטואליות) שנמצאים באותו פרויקט או VPC ב-GDC, אבל מחוץ לאשכול 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 בניהול עצמי עם זמינות גבוהה