המסמך הזה מיועד לאדמינים של מסדי נתונים, לאדריכלי ענן ולמומחי תפעול שרוצים לפרוס טופולוגיה של MySQL עם זמינות גבוהה ב-Google Kubernetes Engine.
במדריך הזה נסביר איך לפרוס MySQL InnoDB Cluster ו-MySQL InnoDB ClusterSet, בנוסף לתוכנת הביניים MySQL Router באשכול GKE, ואיך לבצע שדרוגים.
מטרות
במדריך הזה תלמדו איך:- יצירה ופריסה של שירות Kubernetes עם שמירת מצב.
- פריסת אשכול MySQL InnoDB לזמינות גבוהה.
- פריסת תוכנת ביניים של נתב לניתוב פעולות במסד הנתונים.
- פריסת MySQL InnoDB ClusterSet לעמידות בפני אסון.
- סימולציה של מעבר לגיבוי בענן באשכול MySQL.
- מבצעים שדרוג של גרסת MySQL.
בקטעים הבאים מתואר הארכיטקטורה של הפתרון שתבנו במדריך הזה.
MySQL InnoDB Cluster
באשכול GKE האזורי, באמצעות StatefulSet, פורסים מכונה של מסד נתונים MySQL עם השמות וההגדרות הנדרשים ליצירת אשכול MySQL InnoDB. כדי לספק סבילות לתקלות וזמינות גבוהה, אתם פורסים שלושה פודים של מופעי מסד נתונים. כך מובטח שרוב ה-Pods באזורים שונים יהיו זמינים בכל רגע נתון לבחירה מוצלחת של ה-Primary באמצעות פרוטוקול קונצנזוס, ושה-MySQL InnoDB Cluster יהיה עמיד בפני כשלים באזור יחיד.
אחרי הפריסה, צריך להגדיר Pod אחד כאירוע הראשי שישרת גם פעולות קריאה וגם פעולות כתיבה. שני ה-Pods האחרים הם רפליקות משניות לקריאה בלבד. אם יש כשל בתשתית של המופע הראשי, אפשר להפוך את אחד משני תאי ה-Pod המשוכפלים האלה לראשי.
במרחב שמות נפרד, פורסים שלושה פודי MySQL Router כדי לספק ניתוב חיבורים לשיפור העמידות. במקום להתחבר ישירות לשירות מסד הנתונים, האפליקציות שלכם מתחברות ל-Pods של MySQL Router. כל Router Pod מודע לסטטוס ולמטרה של כל MySQL InnoDB Cluster Pod, ומנתב פעולות של אפליקציות אל ה-Pod התקין המתאים. מצב הניתוב נשמר במטמון ב-Router Pods ומעודכן ממטא-הנתונים של האשכול שמאוחסנים בכל צומת של MySQL InnoDB Cluster. במקרה של כשל במכונה, הנתב מתאים את ניתוב החיבור למכונה פעילה.
MySQL InnoDB ClusterSet
אפשר ליצור ClusterSet של MySQL InnoDB מ-MySQL InnoDB Cluster ראשוני. כך אפשר לשפר את עמידות המערכת בפני אסונות אם האשכול הראשי לא זמין יותר.
אם המכונה הראשית של MySQL InnoDB Cluster לא זמינה יותר, אפשר להגדיר עותק משוכפל של אשכול ב-ClusterSet כראשי. כשמשתמשים בתוכנת ביניים (middleware) של MySQL Router, האפליקציה לא צריכה לעקוב אחרי תקינות מופע מסד הנתונים הראשי. הניתוב מותאם כך שהחיבורים יישלחו לשרת הראשי החדש אחרי הבחירה. עם זאת, באחריותכם לוודא שאפליקציות שמתחברות לתווכה של MySQL Router פועלות בהתאם לשיטות המומלצות לחוסן (resilience), כך שהמערכת תנסה להתחבר מחדש אם מתרחשת שגיאה במהלך יתירות כשל של האשכול.
עלויות
במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:
כדי להעריך את ההוצאות בהתאם לתחזית השימוש שלכם, אתם יכולים להיעזר במחשבון העלויות.
כשמסיימים את המשימות שמתוארות במסמך הזה אפשר למחוק את המשאבים שיצרתם כדי להימנע מחיובים נוספים. מידע נוסף זמין בקטע הסרת המשאבים.
לפני שמתחילים
הגדרת הפרויקט
- נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
-
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
Roles required to create a project
To create a project, you need the Project Creator role (
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles. -
Verify that billing is enabled for your Google Cloud project.
Enable the GKE API.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.-
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
Roles required to create a project
To create a project, you need the Project Creator role (
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles. -
Verify that billing is enabled for your Google Cloud project.
Enable the GKE API.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.
הגדרת תפקידים
-
מעניקים תפקידים לחשבון המשתמש. מריצים את הפקודה הבאה לכל אחד מהתפקידים הבאים ב-IAM:
role/storage.objectViewer, role/logging.logWriter, role/artifactregistry.Admin, roles/container.clusterAdmin, role/container.serviceAgent, roles/serviceusage.serviceUsageAdmin, roles/iam.serviceAccountAdmingcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE
מחליפים את מה שכתוב בשדות הבאים:
-
PROJECT_ID: מזהה הפרויקט. -
USER_IDENTIFIER: המזהה של חשבון המשתמש . לדוגמה,myemail@example.com. -
ROLE: תפקיד ה-IAM שאתם מקצים לחשבון המשתמש.
-
מגדירים את הסביבה
במדריך הזה משתמשים ב-Cloud Shell כדי לנהל משאבים שמתארחים ב-Google Cloud. ב-Cloud Shell מותקנים מראש Docker, kubectl וה-CLI של gcloud.
כדי להשתמש ב-Cloud Shell להגדרת הסביבה:
מגדירים משתני סביבה.
export PROJECT_ID=PROJECT_ID export CLUSTER_NAME=gkemulti-west export CONTROL_PLANE_LOCATION=CONTROL_PLANE_LOCATIONמחליפים את הערכים הבאים:
- PROJECT_ID: Google Cloud מזהה הפרויקט.
- CONTROL_PLANE_LOCATION: האזור של Compute Engine במישור הבקרה של האשכול. במדריך הזה, האזור הוא
us-west1. בדרך כלל, כדאי לבחור אזור שקרוב אליכם.
מגדירים את משתני הסביבה שמוגדרים כברירת מחדל.
gcloud config set project PROJECT_ID gcloud config set compute/region CONTROL_PLANE_LOCATIONמשכפלים את מאגר המקורות של הקוד.
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samplesעוברים לספריית העבודה.
cd kubernetes-engine-samples/databases/gke-stateful-mysql/kubernetes
יצירת אשכול GKE
בקטע הזה יוצרים אשכול GKE אזורי. בשונה מאשכול אזורי, רמת הבקרה של אשכול אזורי משוכפלת לכמה אזורים, כך שהפסקת חשמל באזור אחד לא גורמת לרמת הבקרה להיות לא זמינה.
כדי ליצור אשכול GKE:
טייס אוטומטי
ב-Cloud Shell, יוצרים אשכול GKE Autopilot באזור
us-west1.gcloud container clusters create-auto $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATIONמקבלים את פרטי הכניסה לאשכול GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATIONפריסת שירות בשלושה אזורים. במדריך הזה נעשה שימוש בפריסת Kubernetes. פריסה היא אובייקט Kubernetes API שמאפשר להפעיל כמה רפליקות של Pods שמפוזרות בין הצמתים באשכול.
kubectl apply -f prepare-for-ha.yamlכברירת מחדל, Autopilot מקצה משאבים בשני אזורים. הפריסה שמוגדרת ב-
prepare-for-ha.yamlמבטיחה ש-Autopilot יקצה צמתים בשלושה אזורים באשכול, על ידי הגדרתreplicas:3,podAntiAffinityעםrequiredDuringSchedulingIgnoredDuringExecutionו-topologyKey: "topology.kubernetes.io/zone".בודקים את הסטטוס של הפריסה.
kubectl get deployment prepare-three-zone-ha --watchכשרואים שלושה פודים במצב מוכן, מבטלים את הפקודה הזו באמצעות
CTRL+C. הפלט אמור להיראות כך:NAME READY UP-TO-DATE AVAILABLE AGE prepare-three-zone-ha 0/3 3 0 9s prepare-three-zone-ha 1/3 3 1 116s prepare-three-zone-ha 2/3 3 2 119s prepare-three-zone-ha 3/3 3 3 2m16sמריצים את הסקריפט הזה כדי לוודא שה-Pods נפרסו בשלושה אזורים.
bash ../scripts/inspect_pod_node.sh defaultכל שורה בפלט מתאימה ל-Pod, והעמודה השנייה מציינת את האזור. הפלט אמור להיראות כך:
gk3-gkemulti-west1-default-pool-eb354e2d-z6mv us-west1-b prepare-three-zone-ha-7885d77d9c-8f7qb gk3-gkemulti-west1-nap-25b73chq-739a9d40-4csr us-west1-c prepare-three-zone-ha-7885d77d9c-98fpn gk3-gkemulti-west1-default-pool-160c3578-bmm2 us-west1-a prepare-three-zone-ha-7885d77d9c-phmhj
רגילה
ב-Cloud Shell, יוצרים אשכול GKE Standard באזור
us-west1.gcloud container clusters create $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION \ --machine-type="e2-standard-2" \ --disk-type="pd-standard" \ --num-nodes="5"מקבלים את פרטי הכניסה לאשכול GKE.
gcloud container clusters get-credentials $CLUSTER_NAME \ --location=$CONTROL_PLANE_LOCATION
פריסת StatefulSets של MySQL
בקטע הזה, פורסים MySQL StatefulSet אחד. StatefulSet הוא בקר Kubernetes ששומר על זהות ייחודית ומתמשכת לכל אחד מה-Pods שלו.
כל StatefulSet מורכב משלושה עותקים משוכפלים של MySQL.
כדי לפרוס את MySQL StatefulSet, מבצעים את השלבים הבאים:
יוצרים מרחב שמות ל-StatefulSet.
kubectl create namespace mysql1יוצרים את הסוד של MySQL.
kubectl apply -n mysql1 -f secret.yamlהסיסמה נפרסת עם כל Pod, ומשמשת סקריפטים ופקודות לניהול של פריסת MySQL InnoDB Cluster ו-ClusterSet במדריך הזה.
יוצרים את StorageClass.
kubectl apply -n mysql1 -f storageclass.yamlסוג האחסון הזה משתמש בסוג
pd-balancedPersistent Disk שמאזן בין ביצועים לעלות. השדהvolumeBindingModeמוגדר לערךWaitForFirstConsumer, כלומר GKE מעכב את הקצאת המקום של PersistentVolume עד ליצירת ה-Pod. ההגדרה הזו מבטיחה שהדיסק יוקצה באותו אזור שבו מתוזמן ה-Pod.פורסים את ה-StatefulSet של ה-Pods של מכונות MySQL.
kubectl apply -n mysql1 -f c1-mysql.yamlהפקודה הזו פורסת את StatefulSet שמורכב משלוש רפליקות. במדריך הזה, אשכול MySQL הראשי נפרס על פני שלושה אזורים ב-
us-west1. הפלט אמור להיראות כך:service/mysql created statefulset.apps/dbc1 createdבמדריך הזה, המגבלות והבקשות של המשאבים מוגדרות לערכים מינימליים כדי לחסוך בעלויות. כשמתכננים עומס עבודה של ייצור, חשוב להגדיר את הערכים האלה בהתאם לצרכים של הארגון.
מוודאים שה-StatefulSet נוצר בהצלחה.
kubectl get statefulset -n mysql1 --watchיכולות לעבור כ-10 דקות עד שה-StatefulSet יהיה מוכן.
כשכל שלושת הפודים במצב מוכן, יוצאים מהפקודה באמצעות
Ctrl+C. אם מופיעות שגיאותPodUnscheduleableבגלל מחסור במעבד או בזיכרון, צריך להמתין כמה דקות עד שמישור הבקרה ישנה את הגודל שלו כדי להתאים לעומס העבודה הגדול.הפלט אמור להיראות כך:
NAME READY AGE dbc1 1/3 39s dbc1 2/3 50s dbc1 3/3 73sכדי לבדוק את המיקום של ה-Pods בצמתים של אשכול GKE, מריצים את הסקריפט הזה:
bash ../scripts/inspect_pod_node.sh mysql1 mysqlהפלט מציג את שם ה-Pod, את שם הצומת ב-GKE ואת האזור שבו הצומת הוקצה, והוא נראה בערך כך:
gke-gkemulti-west-5-default-pool-4bcaca65-jch0 us-west1-b dbc1-0 gke-gkemulti-west-5-default-pool-1ac6e8b5-ddjx us-west1-c dbc1-1 gke-gkemulti-west-5-default-pool-1f5baa66-bf8t us-west1-a dbc1-2העמודות בפלט מייצגות את שם המארח, אזור הענן ושם ה-Pod, בהתאמה.
המדיניות
topologySpreadConstraintsבמפרט StatefulSet (c1-mysql.yaml) מנחה את מתזמן העבודה למקם את ה-Pods באופן שווה בדומיין הכשל (topology.kubernetes.io/zone).המדיניות
podAntiAffinityאוכפת את ההגבלה שלפיה אסור למקם את ה-Pods באותו צומת של אשכול GKE (kubernetes.io/hostname). עבור ה-Pods של מופע MySQL, המדיניות הזו גורמת לפריסה שווה של ה-Pods בשלושת האזורים ב Google Cloud region. המיקום הזה מאפשר זמינות גבוהה של MySQL InnoDB Cluster, כי כל מופע של מסד נתונים ממוקם בדומיין כשל נפרד.
הכנת קלאסטר MySQL InnoDB ראשי
כדי להגדיר אשכול MySQL InnoDB, מבצעים את השלבים הבאים:
במסוף Cloud Shell, מגדירים את ההגדרות של שכפול הקבוצה עבור מופעי MySQL שרוצים להוסיף לאשכול.
bash ../scripts/c1-clustersetup.shהסקריפט יתחבר מרחוק לכל אחת משלוש מכונות MySQL כדי להגדיר ולשמור את משתני הסביבה הבאים:
-
group_replication_ip_allowlist: מאפשר למכונה באשכול להתחבר לכל מכונה בקבוצה. -
binlog_transaction_dependency_tracking='WRITESET': מאפשר עסקאות מקבילות שלא יתנגשו.
בגרסאות MySQL מוקדמות יותר מ-8.0.22, משתמשים ב-
group_replication_ip_whitelistבמקום ב-group_replication_ip_allowlist.-
פותחים טרמינל שני, כדי שלא תצטרכו ליצור מעטפת לכל Pod.
מתחברים אל MySQL Shell ב-Pod
dbc1-0.kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql.mysql1.svc.cluster.local"'בודקים את הרשימה הלבנה של שכפול קבוצות MySQL כדי להתחבר למופעים אחרים.
\sql SELECT @@group_replication_ip_allowlist;הפלט אמור להיראות כך:
+----------------------------------+ | @@group_replication_ip_allowlist | +----------------------------------+ | mysql.mysql1.svc.cluster.local | +----------------------------------+מוודאים שכל מופע של
server-idהוא ייחודי.\sql SELECT @@server_id;הפלט אמור להיראות כך:
+-------------+ | @@server_id | +-------------+ | 21 | +-------------+מגדירים כל מופע לשימוש ב-MySQL InnoDB Cluster ויוצרים חשבון אדמין בכל מופע.
\js dba.configureInstance('root@dbc1-0.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")}); dba.configureInstance('root@dbc1-1.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")}); dba.configureInstance('root@dbc1-2.mysql.mysql1.svc.cluster.local', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});כדי ש-MySQL InnoDB Cluster יפעל בצורה תקינה, לכל המקרים צריכים להיות שם משתמש וסיסמה זהים. הפלט של כל פקודה אמור להיראות כך:
... The instance 'dbc1-2.mysql:3306' is valid to be used in an InnoDB cluster. Cluster admin user 'icadmin'@'%' created. The instance 'dbc1-2.mysql.mysql1.svc.cluster.local:3306' is already ready to be used in an InnoDB cluster. Successfully enabled parallel appliers.מוודאים שהמופע מוכן לשימוש ב-MySQL InnoDB Cluster.
dba.checkInstanceConfiguration()הפלט אמור להיראות כך:
... The instance 'dbc1-0.mysql.mysql1.svc.cluster.local:3306' is valid to be used in an InnoDB cluster. { "status": "ok" }אפשר גם להתחבר לכל מופע של MySQL ולחזור על הפקודה הזו. לדוגמה, מריצים את הפקודה הזו כדי לבדוק את הסטטוס במכונה
dbc1-1:kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-1.mysql.mysql1.svc.cluster.local" \ --js --execute "dba.checkInstanceConfiguration()"'
יצירת אשכול ראשי של MySQL InnoDB
לאחר מכן, יוצרים את MySQL InnoDB Cluster באמצעות הפקודה createCluster של MySQL Admin. מתחילים עם מופע dbc1-0, שיהיה המופע הראשי של האשכול, ואז מוסיפים לאשכול שני עותקים משוכפלים נוספים.
כדי לאתחל את MySQL InnoDB Cluster, פועלים לפי השלבים הבאים:
יוצרים את אשכול MySQL InnoDB.
var cluster=dba.createCluster('mycluster');הפעלת הפקודה
createClusterמפעילה את הפעולות הבאות:- פורסים את סכימת המטא-נתונים.
- מוודאים שההגדרה נכונה עבור שכפול קבוצתי.
- רושמים אותו כמופע הזרע של האשכול החדש.
- יוצרים את החשבונות הפנימיים הנדרשים, כמו חשבון המשתמש לשכפול.
- מפעילים את Group Replication.
הפקודה הזו מפעילה את MySQL InnoDB Cluster עם המארח
dbc1-0כראשי. ההפניה לאשכול מאוחסנת במשתנה האשכול.הפלט אמור להיראות כך:
A new InnoDB cluster will be created on instance 'dbc1-0.mysql:3306'. Validating instance configuration at dbc1-0.mysql:3306... This instance reports its own address as dbc1-0.mysql.mysql1.svc.cluster.local:3306 Instance configuration is suitable. NOTE: Group Replication will communicate with other instances using 'dbc1-0.mysql:33061'. Use the localAddress option to override. Creating InnoDB cluster 'mycluster' on 'dbc1-0.mysql.mysql1.svc.cluster.local:3306'... Adding Seed Instance... Cluster successfully created. Use Cluster.addInstance() to add MySQL instances. At least 3 instances are needed for the cluster to be able to withstand up to one server failure.מוסיפים את המופע השני לאשכול.
cluster.addInstance('icadmin@dbc1-1.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});מוסיפים את המופע הנותר לאשכול.
cluster.addInstance('icadmin@dbc1-2.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});הפלט אמור להיראות כך:
... The instance 'dbc1-2.mysql:3306' was successfully added to the cluster.בודקים את הסטטוס של האשכול.
cluster.status()הפקודה הזו מציגה את הסטטוס של האשכול. הטופולוגיה מורכבת משלושה מארחים, אחד ראשי ושני מקרים משניים. אפשר גם להתקשר אל
cluster.status({extended:1}).הפלט אמור להיראות כך:
{ "clusterName": "mysql1", "defaultReplicaSet": { "name": "default", "primary": "dbc1-0.mysql:3306", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "dbc1-0.mysql:3306": { "address": "dbc1-0.mysql:3306", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.28" }, "dbc1-1.mysql:3306": { "address": "dbc1-1.mysql:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.28" }, "dbc1-2.mysql:3306": { "address": "dbc1-2.mysql:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": null, "role": "HA", "status": "ONLINE", "version": "8.0.28" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "dbc1-0.mysql:3306" }אפשר גם להתקשר אל
cluster.status({extended:1})כדי לקבל פרטים נוספים על הסטטוס.
יצירת מסד נתונים לדוגמה
כדי ליצור מסד נתונים לדוגמה:
יוצרים מסד נתונים וטוענים לתוכו נתונים.
\sql create database loanapplication; use loanapplication CREATE TABLE loan (loan_id INT unsigned AUTO_INCREMENT PRIMARY KEY, firstname VARCHAR(30) NOT NULL, lastname VARCHAR(30) NOT NULL , status VARCHAR(30) );מכניסים נתונים לדוגמה למסד הנתונים. כדי להוסיף נתונים, צריך להתחבר למופע הראשי של האשכול.
INSERT INTO loan (firstname, lastname, status) VALUES ( 'Fred','Flintstone','pending'); INSERT INTO loan (firstname, lastname, status) VALUES ( 'Betty','Rubble','approved');מוודאים שהטבלה מכילה את שלוש השורות שהוספתם בשלב הקודם.
SELECT * FROM loan;הפלט אמור להיראות כך:
+---------+-----------+------------+----------+ | loan_id | firstname | lastname | status | +---------+-----------+------------+----------+ | 1 | Fred | Flintstone | pending | | 2 | Betty | Rubble | approved | +---------+-----------+------------+----------+ 2 rows in set (0.0010 sec)
יצירת ClusterSet של MySQL InnoDB
אתם יכולים ליצור ClusterSet של MySQL InnoDB כדי לנהל שכפול מהאשכול הראשי לאשכולות של העתקים, באמצעות ערוץ שכפול ייעודי של ClusterSet.
MySQL InnoDB ClusterSet מספק סבילות לכשלים בפריסות של MySQL InnoDB Cluster על ידי קישור של MySQL InnoDB Cluster ראשי עם עותק משוכפל אחד או יותר של עצמו במיקומים חלופיים, כמו אזורים מרובים ואזורים שונים.
אם סגרתם את MySQL Shell, יוצרים מעטפת חדשה על ידי הפעלת הפקודה הבאה בטרמינל חדש של Cloud Shell:
kubectl -n mysql1 exec -it dbc1-0 -- \
/bin/bash -c 'mysqlsh \
--uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql.mysql1.svc.cluster.local"'
כדי ליצור MySQL InnoDB ClusterSet, פועלים לפי השלבים הבאים:
בטרמינל של MySQL Shell, מקבלים אובייקט של אשכול.
\js cluster=dba.getCluster()הפלט אמור להיראות כך:
<Cluster:mycluster>מאתחלים ClusterSet של MySQL InnoDB עם אשכול MySQL InnoDB קיים שמאוחסן באובייקט האשכול כאשכול הראשי.
clusterset=cluster.createClusterSet('clusterset')הפלט אמור להיראות כך:
A new ClusterSet will be created based on the Cluster 'mycluster'. * Validating Cluster 'mycluster' for ClusterSet compliance. * Creating InnoDB ClusterSet 'clusterset' on 'mycluster'... * Updating metadata... ClusterSet successfully created. Use ClusterSet.createReplicaCluster() to add Replica Clusters to it. <ClusterSet:clusterset>בודקים את הסטטוס של MySQL InnoDB ClusterSet.
clusterset.status()הפלט אמור להיראות כך:
{ "clusters": { "mycluster": { "clusterRole": "PRIMARY", "globalStatus": "OK", "primary": "dbc1-0.mysql:3306" } }, "domainName": "clusterset", "globalPrimaryInstance": "dbc1-0.mysql:3306", "primaryCluster": "mycluster", "status": "HEALTHY", "statusText": "All Clusters available." }אפשר גם להתקשר אל
clusterset.status({extended:1})כדי לקבל פרטים נוספים על הסטטוס, כולל מידע על האשכול.יוצאים מ-MySQL Shell.
\q
פריסת MySQL Router
אפשר לפרוס נתב MySQL כדי להפנות את התנועה של אפליקציות לקוח לאשכולות המתאימים. הניתוב מבוסס על יציאת החיבור של האפליקציה שמבצעת פעולה במסד הנתונים:
- פעולות כתיבה מנותבות למופע הראשי של Cluster ב-ClusterSet הראשי.
- אפשר להפנות פעולות קריאה לכל מכונה באשכול הראשי.
כשמפעילים את MySQL Router, הוא מופעל מתוך פריסת MySQL InnoDB ClusterSet. המכונות של MySQL Router שמחוברות ל-MySQL InnoDB ClusterSet מודעות לכל מעבר מבוקר או מעבר לגיבוי במקרה חירום, ומפנות את התנועה לאשכול הראשי החדש.
כדי לפרוס נתב MySQL, מבצעים את השלבים הבאים:
בטרמינל של Cloud Shell, פורסים את MySQL Router.
kubectl apply -n mysql1 -f c1-router.yamlהפלט אמור להיראות כך:
configmap/mysql-router-config created service/mysql-router created deployment.apps/mysql-router createdבודקים את המוכנות של פריסת MySQL Router.
kubectl -n mysql1 get deployment mysql-router --watchכאשר כל שלושת ה-Pods מוכנים, הפלט דומה לזה:
NAME READY UP-TO-DATE AVAILABLE AGE mysql-router 3/3 3 0 3m36sאם מופיעה שגיאת
PodUnschedulableבמסוף, צריך להמתין דקה או שתיים בזמן ש-GKE מקצה עוד צמתים. מרעננים את הדף, ואז אמור להופיע3/3 OK.מפעילים את MySQL Shell בכל אחד מהחברים באשכול הקיים.
kubectl -n mysql1 exec -it dbc1-0 -- \ /bin/bash -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'הפקודה הזו מתחברת ל-Pod
dbc1-0, ואז מפעילה מעטפת שמחוברת למופע MySQLdbc1-0.מאמתים את הגדרות הנתב.
clusterset=dba.getClusterSet() clusterset.listRouters()הפלט אמור להיראות כך:
{ "domainName": "clusterset", "routers": { "mysql-router-7cd8585fbc-74pkm::": { "hostname": "mysql-router-7cd8585fbc-74pkm", "lastCheckIn": "2022-09-22 23:26:26", "roPort": 6447, "roXPort": 6449, "rwPort": 6446, "rwXPort": 6448, "targetCluster": null, "version": "8.0.27" }, "mysql-router-7cd8585fbc-824d4::": { ... }, "mysql-router-7cd8585fbc-v2qxz::": { ... } } }יוצאים מ-MySQL Shell.
\qמריצים את הסקריפט הזה כדי לבדוק את המיקום של פודים של MySQL Router.
bash ../scripts/inspect_pod_node.sh mysql1 | sortהסקריפט מציג את הצומת ואת המיקום של אזור הענן של כל ה-Pods במרחב השמות
mysql1, והפלט דומה לזה:gke-gkemulti-west-5-default-pool-1ac6e8b5-0h9v us-west1-c mysql-router-6654f985f5-df97q gke-gkemulti-west-5-default-pool-1ac6e8b5-ddjx us-west1-c dbc1-1 gke-gkemulti-west-5-default-pool-1f5baa66-bf8t us-west1-a dbc1-2 gke-gkemulti-west-5-default-pool-1f5baa66-kt03 us-west1-a mysql-router-6654f985f5-qlfj9 gke-gkemulti-west-5-default-pool-4bcaca65-2l6s us-west1-b mysql-router-6654f985f5-5967d gke-gkemulti-west-5-default-pool-4bcaca65-jch0 us-west1-b dbc1-0אפשר לראות שרכיבי ה-Pod של MySQL Router מפוזרים באופן שווה בין האזורים, כלומר, הם לא ממוקמים באותו צומת כמו רכיב Pod של MySQL, או באותו צומת כמו רכיב Pod אחר של MySQL Router.
ניהול שדרוגים של GKE ושל MySQL InnoDB Cluster
עדכונים ל-MySQL ול-Kubernetes מתפרסמים בלוח זמנים קבוע. מומלץ לפעול לפי שיטות מומלצות לתפעול כדי לעדכן את סביבת התוכנה באופן קבוע. כברירת מחדל, GKE מנהל את השדרוגים של האשכולות ומאגרי הצמתים בשבילכם. בנוסף, Kubernetes ו-GKE מספקים תכונות נוספות כדי להקל על שדרוגים של תוכנת MySQL.
תכנון שדרוגים של GKE
אם אתם מפעילים שירותים עם שמירת מצב, אתם יכולים לנקוט צעדים יזומים ולהגדיר הגדרות כדי לצמצם את הסיכון ולשדרג את האשכול בצורה חלקה יותר. בין היתר, אתם יכולים:
אשכולות Standard: כדאי לפעול לפי השיטות המומלצות לשדרוג אשכולות ב-GKE. כדי לוודא שהשדרוגים יתבצעו במהלך חלון הזמנים לתחזוקה, צריך לבחור אסטרטגיית שדרוג מתאימה:
- כדאי לבחור באפשרות שדרוגים בעומס שימוש אם אופטימיזציה של העלויות חשובה לכם, ואם עומסי העבודה יכולים לעמוד בהשבתה מסודרת תוך פחות מ-60 דקות.
- כדאי לבחור באפשרות שדרוגים מסוג blue-green אם עומסי העבודה שלכם פחות סובלניים לשיבושים, ואם אתם מוכנים לספוג עלייה זמנית בעלויות בגלל שימוש גבוה יותר במשאבים.
מידע נוסף זמין במאמר בנושא שדרוג אשכול שמריץ עומס עבודה עם שמירת מצב. השדרוג של אשכולות Autopilot מתבצע באופן אוטומטי, על סמך ערוץ ההפצה שבחרתם.
כדאי להשתמש בחלונות תחזוקה כדי לוודא שהשדרוגים יתבצעו בזמן שאתם רוצים. לפני חלון זמן לתחזוקה, חשוב לוודא שגיבויי מסד הנתונים בוצעו בהצלחה.
לפני שמאפשרים תנועה לצמתי MySQL המשודרגים, משתמשים בבדיקות מוכנות ובבדיקות פעילות כדי לוודא שהם מוכנים לתנועה.
יוצרים בדיקות שמעריכות אם השכפול מסונכרן לפני אישור התנועה. אפשר לעשות את זה באמצעות סקריפטים בהתאמה אישית, בהתאם למורכבות ולגודל של מסד הנתונים.
הגדרה של מדיניות תקציב לשיבוש Pod (PDB)
כשקלאסטר MySQL InnoDB פועל ב-GKE, צריך להפעיל בכל רגע נתון מספר מספיק של מופעים כדי לעמוד בדרישת הקוורום.
במדריך הזה, בהינתן אשכול MySQL של שלוש מכונות, שתי מכונות צריכות להיות זמינות כדי ליצור קוורום. מדיניות PodDisruptionBudget מאפשרת להגביל את מספר ה-Pods שאפשר להפסיק בכל זמן נתון. התכונה הזו שימושית גם לפעולות במצב יציב של שירותים עם שמירת מצב וגם לשדרוגים של אשכולות.
כדי להבטיח שמספר מוגבל של Pods יופרעו בו-זמנית, מגדירים את ה-PDB של עומס העבודה ל-maxUnavailable: 1. כך מובטח שבכל נקודה במהלך פעולת השירות, לא יותר מ-Pod אחד לא יפעל.
מניפסט המדיניות הבא PodDisruptionBudget מגדיר את מספר ה-Pods המקסימלי שלא זמינים לאפליקציית MySQL לאחד.
כדי להחיל את מדיניות ה-PDB על האשכול, פועלים לפי השלבים הבאים:
מחילים את מדיניות ה-PDB באמצעות
kubectl.kubectl apply -n mysql1 -f mysql-pdb-maxunavailable.yamlהצגת הסטטוס של ה-PDB.
kubectl get poddisruptionbudgets -n mysql1 mysql-pdb -o yamlבקטע
statusשל הפלט, אפשר לראות את ספירת ה-Pods שלcurrentHealthyושלdesiredHealthy. הפלט אמור להיראות כך:status: ... currentHealthy: 3 desiredHealthy: 2 disruptionsAllowed: 1 expectedPods: 3 ...
תכנון שדרוגים בינאריים של MySQL
Kubernetes ו-GKE מספקים תכונות שמקלות על שדרוגים של קובץ ה-MySQL הבינארי. עם זאת, צריך לבצע כמה פעולות כדי להתכונן לשדרוגים.
לפני שמתחילים בתהליך השדרוג, חשוב לזכור את הנקודות הבאות:
- קודם צריך לבצע את השדרוגים בסביבת בדיקה. במערכות ייצור, צריך לבצע בדיקות נוספות בסביבת טרום-ייצור.
- בגרסאות בינאריות מסוימות, אי אפשר לשנמך את הגרסה אחרי שמשדרגים אותה. חשוב להקדיש זמן כדי להבין את ההשלכות של השדרוג.
- מקורות השכפול יכולים לשכפל לגרסה חדשה יותר. עם זאת, בדרך כלל אי אפשר להעתיק מגרסה חדשה לגרסה ישנה.
- לפני שפורסים את הגרסה המשודרגת, חשוב לוודא שיש גיבוי מלא של מסד הנתונים.
- חשוב לזכור את האופי האפמרי של קבוצות Pod ב-Kubernetes. כל מצב הגדרה שאוחסן על ידי ה-Pod ולא נמצא בכרך המתמשך יאבד כשה-Pod יופעל מחדש.
- לשדרוגים בינאריים של MySQL, משתמשים באותה אסטרטגיה של PDB, עדכון מאגר צמתים ובדיקות כמו שמתואר למעלה.
בסביבת ייצור, כדאי לפעול לפי השיטות המומלצות הבאות:
- יוצרים קובץ אימג' של קונטיינר עם הגרסה החדשה של MySQL.
- שומרים את הוראות ה-build של התמונה במאגר של בקרת מקור.
- משתמשים בצינור אוטומטי ליצירת קובצי אימג' ובדיקה, כמו Cloud Build, ומאחסנים את הקובץ הבינארי של האימג' במאגר אימג'ים כמו Artifact Registry.
כדי שהמדריך הזה יהיה פשוט, לא תיצרו קובץ אימג' של קונטיינר ולא תשמרו אותו. במקום זאת, תשתמשו בקובצי אימג' ציבוריים של MySQL.
פריסת הקובץ הבינארי המשודרג של MySQL
כדי לבצע את השדרוג הבינארי של MySQL, מריצים פקודה הצהרתית שמשנה את גרסת התמונה של משאב StatefulSet. GKE מבצע את השלבים הנדרשים כדי לעצור את ה-Pod הנוכחי, לפרוס Pod חדש עם הקובץ הבינארי המשודרג ולצרף את דיסק האחסון המתמיד ל-Pod החדש.
בודקים שקובץ ה-PDB נוצר.
kubectl get poddisruptionbudgets -n mysql1מקבלים את רשימת ה-stateful sets.
kubectl get statefulsets -n mysql1מקבלים את רשימת ה-Pods הפועלים באמצעות התווית
app.kubectl get pods --selector=app=mysql -n mysql1מעדכנים את תמונת ה-MySQL ב-StatefulSet.
kubectl -n mysql1 \ set image statefulset/dbc1 \ mysql=mysql/mysql-server:8.0.30הפלט אמור להיראות כך:
statefulset.apps/mysql image updatedבודקים את הסטטוס של ה-Pods שמסתיימים ושל ה-Pods החדשים.
kubectl get pods --selector=app=mysql -n mysql1
אימות השדרוג הבינארי של MySQL
במהלך השדרוג, תוכלו לבדוק את סטטוס ההשקה, את ה-Pods החדשים ואת השירות הקיים.
מריצים את הפקודה
rollout statusכדי לאשר את השדרוג.kubectl rollout status statefulset/dbc1 -n mysql1הפלט אמור להיראות כך:
partitioned roll out complete: 3 new pods have been updated...כדי לאשר את גרסת התמונה, בודקים את קבוצת ה-StatefulSet.
kubectl get statefulsets -o wide -n mysql1הפלט אמור להיראות כך:
NAME READY AGE CONTAINERS IMAGES dbc1 3/3 37m mysql mysql/mysql-server:8.0.30בודקים את הסטטוס של האשכול.
kubectl -n mysql1 \ exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh \ --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-1.mysql.mysql1.svc.cluster.local" \ --js \ --execute "print(dba.getClusterSet().status({extended:1})); print(\"\\n\")"'בפלט, מחפשים את ערכי הסטטוס והגרסה של כל מופע של אשכול. הפלט אמור להיראות כך:
... "status": "ONLINE", "version": "8.0.30" ...
חזרה לפריסה הקודמת של האפליקציה
כשמבטלים את הפריסה של גרסה בינארית משודרגת, תהליך ההשקה מתהפך וקבוצה חדשה של Pods נפרסת עם גרסת התמונה הקודמת.
כדי לחזור לגרסה הקודמת של הפריסה, משתמשים בפקודה rollout undo:
kubectl rollout undo statefulset/dbc1 -n mysql1
הפלט אמור להיראות כך:
statefulset.apps/dbc1 rolled back
הגדלת קלאסטר מסדי הנתונים באופן אופקי
כדי להרחיב את MySQL InnoDB Cluster באופן אופקי, מוסיפים עוד צמתים למאגר הצמתים של GKE (נדרש רק אם משתמשים ב-Standard), פורסים עוד מופעים של MySQL ואז מוסיפים כל מופע ל-MySQL InnoDB Cluster הקיים.
הוספת צמתים לאשכול Standard
אם אתם משתמשים באשכול Autopilot, אין צורך לבצע את הפעולה הזו.
כדי להוסיף צמתים לאשכול רגיל, פועלים לפי ההוראות שבהמשך ל-Cloud Shell או למסוף Google Cloud . הוראות מפורטות זמינות במאמר בנושא שינוי הגודל של מאגר צמתים
gcloud
ב-Cloud Shell, משנים את הגודל של מאגר הצמתים שמוגדר כברירת מחדל לשמונה מופעים בכל קבוצת מופעים מנוהלת.
gcloud container clusters resize ${CLUSTER_NAME} \
--node-pool default-pool \
--num-nodes=8
המסוף
כדי להוסיף צמתים לאשכול Standard:
- פותחים את הדף
gkemulti-west1Cluster במסוף Google Cloud . - בוחרים באפשרות Nodes (צמתים) ולוחצים על default pool (מאגר ברירת המחדל).
- גוללים למטה אל Instance groups [קבוצות של מופעים].
- בכל קבוצת מופעים, משנים את הערך
Number of nodesמ-5 ל-8 צמתים.
הוספת Pods של MySQL לאשכול הראשי
כדי לפרוס עוד פודים של MySQL כדי להרחיב את האשכול באופן אופקי, פועלים לפי השלבים הבאים:
ב-Cloud Shell, מעדכנים את מספר הרפליקות בפריסת MySQL משלוש רפליקות לחמש רפליקות.
kubectl scale -n mysql1 --replicas=5 -f c1-mysql.yamlבודקים את התקדמות הפריסה.
kubectl -n mysql1 get pods --selector=app=mysql -o wideכדי לקבוע אם ה-Pods מוכנים, משתמשים בדגל
--watchכדי לצפות בפריסה. אם אתם משתמשים באשכולות Autopilot ומופיעות שגיאותPod Unschedulable, יכול להיות ש-GKE מקצה צמתים כדי להכיל את ה-Pods הנוספים.הגדרת ההגדרות של שכפול הקבוצה עבור מופעי MySQL החדשים שרוצים להוסיף לאשכול
bash ../scripts/c1-clustersetup.sh 3 4הסקריפט שולח את הפקודות למופעים שפועלים ב-Pods עם מספרי סידורי 3 עד 4.
פותחים את MySQL Shell.
kubectl -n mysql1 \ exec -it dbc1-0 -- \ /bin/bash \ -c 'mysqlsh \ --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'מגדירים את שני מופעי MySQL החדשים.
dba.configureInstance('root:$MYSQL_ROOT_PASSWORD@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")}); dba.configureInstance('root:$MYSQL_ROOT_PASSWORD@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"),clusterAdmin: 'icadmin', clusterAdminPassword: os.getenv("MYSQL_ADMIN_PASSWORD")});הפקודות בודקות אם המכונה מוגדרת בצורה נכונה לשימוש ב-MySQL InnoDB Cluster ומבצעות את שינויי ההגדרה הנדרשים.
מוסיפים אחד מהמופעים החדשים לאשכול הראשי.
cluster = dba.getCluster() cluster.addInstance('icadmin@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});מוסיפים מופע חדש שני לאשכול הראשי.
cluster.addInstance('icadmin@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});מקבלים את הסטטוס של ClusterSet, שכולל גם את הסטטוס של Cluster.
clusterset = dba.getClusterSet() clusterset.status({extended: 1})הפלט אמור להיראות כך:
"domainName": "clusterset", "globalPrimaryInstance": "dbc1-0.mysql:3306", "metadataServer": "dbc1-0.mysql:3306", "primaryCluster": "mycluster", "status": "HEALTHY", "statusText": "All Clusters available."יוצאים מ-MySQL Shell.
\q
הסרת המשאבים
כדי להימנע מחיובים בחשבון Google Cloud בגלל השימוש במשאבים שנעשה במסגרת המדריך הזה, אפשר למחוק את הפרויקט שמכיל את המשאבים, או להשאיר את הפרויקט ולמחוק את המשאבים בנפרד.
מחיקת הפרויקט
הדרך הקלה ביותר להימנע מחיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך.
כדי למחוק Google Cloud פרויקט:
gcloud projects delete PROJECT_ID
המאמרים הבאים
- כאן אפשר לקרוא מידע נוסף על האופן שבו השילוב של Google Cloud Observability עם MySQL אוסף מדדי ביצועים שקשורים ל-InnoDB.
- מידע נוסף על גיבוי ל-GKE, שירות לגיבוי ושחזור של עומסי עבודה ב-GKE
- אפשר לעיין בפרטים נוספים על Persistent Volumes.