פריסת אשכול MySQL עם שמירת מצב ב-GKE

המסמך הזה מיועד לאדמינים של מסדי נתונים, לאדריכלי ענן ולמומחי תפעול שרוצים לפרוס טופולוגיה של 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 יהיה עמיד בפני כשלים באזור יחיד.

דיאגרמת ארכיטקטורה שמציגה את הקשר בין אפליקציות, MySQL Router ו-MySQL Cluster
איור 1: דוגמה לארכיטקטורה של קלאסטר יחיד של MySQL InnoDB

אחרי הפריסה, צריך להגדיר 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 ראשיים ומשוכפלים נשמרים בסנכרון באמצעות שכפול אסינכרוני.
איור 2: דוגמה לארכיטקטורת ClusterSet מרובת אזורים שכוללת אשכול ראשי אחד ואשכול העתקה אחד

אם המכונה הראשית של MySQL InnoDB Cluster לא זמינה יותר, אפשר להגדיר עותק משוכפל של אשכול ב-ClusterSet כראשי. כשמשתמשים בתוכנת ביניים (middleware) של MySQL Router, האפליקציה לא צריכה לעקוב אחרי תקינות מופע מסד הנתונים הראשי. הניתוב מותאם כך שהחיבורים יישלחו לשרת הראשי החדש אחרי הבחירה. עם זאת, באחריותכם לוודא שאפליקציות שמתחברות לתווכה של MySQL Router פועלות בהתאם לשיטות המומלצות לחוסן (resilience), כך שהמערכת תנסה להתחבר מחדש אם מתרחשת שגיאה במהלך יתירות כשל של האשכול.

עלויות

במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

כדי להעריך את ההוצאות בהתאם לתחזית השימוש שלכם, אתם יכולים להיעזר במחשבון העלויות.

משתמשים חדשים של Google Cloud ? יכול להיות שאתם זכאים לתקופת ניסיון בחינם.

כשמסיימים את המשימות שמתוארות במסמך הזה אפשר למחוק את המשאבים שיצרתם כדי להימנע מחיובים נוספים. מידע נוסף זמין בקטע הסרת המשאבים.

לפני שמתחילים

הגדרת הפרויקט

  1. נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. 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 the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. 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 the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  5. 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 the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. 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 the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

הגדרת תפקידים

  1. מעניקים תפקידים לחשבון המשתמש. מריצים את הפקודה הבאה לכל אחד מהתפקידים הבאים ב-IAM: role/storage.objectViewer, role/logging.logWriter, role/artifactregistry.Admin, roles/container.clusterAdmin, role/container.serviceAgent, roles/serviceusage.serviceUsageAdmin, roles/iam.serviceAccountAdmin

    gcloud 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 להגדרת הסביבה:

  1. מגדירים משתני סביבה.

    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. בדרך כלל, כדאי לבחור אזור שקרוב אליכם.
  2. מגדירים את משתני הסביבה שמוגדרים כברירת מחדל.

     gcloud config set project PROJECT_ID
     gcloud config set compute/region CONTROL_PLANE_LOCATION
    
  3. משכפלים את מאגר המקורות של הקוד.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    
  4. עוברים לספריית העבודה.

    cd kubernetes-engine-samples/databases/gke-stateful-mysql/kubernetes
    

יצירת אשכול GKE

בקטע הזה יוצרים אשכול GKE אזורי. בשונה מאשכול אזורי, רמת הבקרה של אשכול אזורי משוכפלת לכמה אזורים, כך שהפסקת חשמל באזור אחד לא גורמת לרמת הבקרה להיות לא זמינה.

כדי ליצור אשכול GKE:

טייס אוטומטי

  1. ב-Cloud Shell, יוצרים אשכול GKE Autopilot באזור us-west1.

    gcloud container clusters create-auto $CLUSTER_NAME \
        --location=$CONTROL_PLANE_LOCATION
    
  2. מקבלים את פרטי הכניסה לאשכול GKE.

    gcloud container clusters get-credentials $CLUSTER_NAME \
      --location=$CONTROL_PLANE_LOCATION
    
  3. פריסת שירות בשלושה אזורים. במדריך הזה נעשה שימוש בפריסת Kubernetes. פריסה היא אובייקט Kubernetes API שמאפשר להפעיל כמה רפליקות של Pods שמפוזרות בין הצמתים באשכול.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: prepare-three-zone-ha
      labels:
        app: prepare-three-zone-ha
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: prepare-three-zone-ha
      template:
        metadata:
          labels:
            app: prepare-three-zone-ha
        spec:
          affinity:
            # Tell Kubernetes to avoid scheduling a replica in a zone where there
            # is already a replica with the label "app: prepare-three-zone-ha"
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - prepare-three-zone-ha
                topologyKey: "topology.kubernetes.io/zone"
          containers:
          - name: prepare-three-zone-ha
            image: busybox:latest
            command:
                - "/bin/sh"
                - "-c"
                - "while true; do sleep 3600; done"
            resources:
              limits:
                cpu: "500m"
                ephemeral-storage: "10Mi"
                memory: "0.5Gi"
              requests:
                cpu: "500m"
                ephemeral-storage: "10Mi"
                memory: "0.5Gi"
    kubectl apply -f prepare-for-ha.yaml
    

    כברירת מחדל, Autopilot מקצה משאבים בשני אזורים. הפריסה שמוגדרת ב-prepare-for-ha.yaml מבטיחה ש-Autopilot יקצה צמתים בשלושה אזורים באשכול, על ידי הגדרת replicas:3, podAntiAffinity עם requiredDuringSchedulingIgnoredDuringExecution ו-topologyKey: "topology.kubernetes.io/zone".

  4. בודקים את הסטטוס של הפריסה.

    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
    
  5. מריצים את הסקריפט הזה כדי לוודא שה-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
    

רגילה

  1. ב-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"
    
  2. מקבלים את פרטי הכניסה לאשכול GKE.

    gcloud container clusters get-credentials $CLUSTER_NAME \
      --location=$CONTROL_PLANE_LOCATION
    

פריסת StatefulSets של MySQL

בקטע הזה, פורסים MySQL StatefulSet אחד. ‫StatefulSet הוא בקר Kubernetes ששומר על זהות ייחודית ומתמשכת לכל אחד מה-Pods שלו.

כל StatefulSet מורכב משלושה עותקים משוכפלים של MySQL.

כדי לפרוס את MySQL StatefulSet, מבצעים את השלבים הבאים:

  1. יוצרים מרחב שמות ל-StatefulSet.

    kubectl create namespace mysql1
    
  2. יוצרים את הסוד של MySQL.

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysql-secret
    type: Opaque
    data:
      password: UGFzc3dvcmQkMTIzNDU2 # Password$123456
      admin-password: UGFzc3dvcmQkMTIzNDU2 # Password$123456
    kubectl apply -n mysql1 -f secret.yaml
    

    הסיסמה נפרסת עם כל Pod, ומשמשת סקריפטים ופקודות לניהול של פריסת MySQL InnoDB Cluster ו-ClusterSet במדריך הזה.

  3. יוצרים את StorageClass.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast-storageclass
    provisioner: pd.csi.storage.gke.io
    volumeBindingMode: WaitForFirstConsumer
    reclaimPolicy: Retain
    allowVolumeExpansion: true
    parameters:
      type: pd-balanced
    kubectl apply -n mysql1 -f storageclass.yaml
    

    סוג האחסון הזה משתמש בסוג pd-balanced Persistent Disk שמאזן בין ביצועים לעלות. השדה volumeBindingMode מוגדר לערך WaitForFirstConsumer, כלומר GKE מעכב את הקצאת המקום של PersistentVolume עד ליצירת ה-Pod. ההגדרה הזו מבטיחה שהדיסק יוקצה באותו אזור שבו מתוזמן ה-Pod.

  4. פורסים את ה-StatefulSet של ה-Pods של מכונות MySQL.

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: dbc1
      labels:
        app: mysql
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: mysql
      serviceName: mysql
      template:
        metadata:
          labels:
            app: mysql
        spec:
          topologySpreadConstraints:
          - maxSkew: 1
            topologyKey: "topology.kubernetes.io/zone"
            whenUnsatisfiable: DoNotSchedule
            labelSelector:
              matchLabels:
                app: mysql
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
                  matchExpressions:
                  - key: app
                    operator: In
                    values:
                    - mysql
                topologyKey: "kubernetes.io/hostname"
          containers:
          - name: mysql
            image: mysql/mysql-server:8.0.28
            command:
            - /bin/bash
            args:
            - -c
            - >-
              /entrypoint.sh
              --server-id=$((20 +  $(echo $HOSTNAME | grep -o '[^-]*$') + 1))
              --report-host=${HOSTNAME}.mysql.mysql1.svc.cluster.local
              --binlog-checksum=NONE
              --enforce-gtid-consistency=ON
              --gtid-mode=ON
              --default-authentication-plugin=mysql_native_password
            env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: password
            - name: MYSQL_ADMIN_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: mysql-secret
                  key: admin-password
            - name: MYSQL_ROOT_HOST
              value: '%'
            ports:
            - name: mysql
              containerPort: 3306
            - name: mysqlx
              containerPort: 33060
            - name: xcom
              containerPort: 33061
            resources:
              limits:
                cpu: "500m"
                ephemeral-storage: "1Gi"
                memory: "1Gi"
              requests:
                cpu: "500m"
                ephemeral-storage: "1Gi"
                memory: "1Gi"
            volumeMounts:
            - name: mysql
              mountPath: /var/lib/mysql
              subPath: mysql
            readinessProbe:
              exec:
                command:
                - bash
                - "-c"
                - |
                  mysql -h127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e'SELECT 1'
              initialDelaySeconds: 30
              periodSeconds: 2
              timeoutSeconds: 1
            livenessProbe:
              exec:
                command:
                - bash
                - "-c"
                - |
                  mysqladmin -uroot -p$MYSQL_ROOT_PASSWORD ping
              initialDelaySeconds: 30
              periodSeconds: 10
              timeoutSeconds: 5
      updateStrategy:
        rollingUpdate:
          partition: 0
        type: RollingUpdate
      volumeClaimTemplates:
      - metadata:
          name: mysql
          labels:
            app: mysql
        spec:
          storageClassName: fast-storageclass
          volumeMode: Filesystem
          accessModes:
          - ReadWriteOnce
          resources:
            requests:
              storage: 10Gi
    kubectl apply -n mysql1 -f c1-mysql.yaml
    

    הפקודה הזו פורסת את StatefulSet שמורכב משלוש רפליקות. במדריך הזה, אשכול MySQL הראשי נפרס על פני שלושה אזורים ב-us-west1. הפלט אמור להיראות כך:

    service/mysql created
    statefulset.apps/dbc1 created
    

    במדריך הזה, המגבלות והבקשות של המשאבים מוגדרות לערכים מינימליים כדי לחסוך בעלויות. כשמתכננים עומס עבודה של ייצור, חשוב להגדיר את הערכים האלה בהתאם לצרכים של הארגון.

  5. מוודאים שה-StatefulSet נוצר בהצלחה.

    kubectl get statefulset -n mysql1 --watch
    

    יכולות לעבור כ-10 דקות עד שה-StatefulSet יהיה מוכן.

  6. כשכל שלושת הפודים במצב מוכן, יוצאים מהפקודה באמצעות Ctrl+C. אם מופיעות שגיאות PodUnscheduleable בגלל מחסור במעבד או בזיכרון, צריך להמתין כמה דקות עד שמישור הבקרה ישנה את הגודל שלו כדי להתאים לעומס העבודה הגדול.

    הפלט אמור להיראות כך:

    NAME   READY   AGE
    dbc1   1/3     39s
    dbc1   2/3     50s
    dbc1   3/3     73s
    
  7. כדי לבדוק את המיקום של ה-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, מבצעים את השלבים הבאים:

  1. במסוף Cloud Shell, מגדירים את ההגדרות של שכפול הקבוצה עבור מופעי MySQL שרוצים להוסיף לאשכול.

    bash ../scripts/c1-clustersetup.sh
    
    POD_ORDINAL_START=${1:-0}
    POD_ORDINAL_END=${2:-2}
    for i in $(seq ${POD_ORDINAL_START} ${POD_ORDINAL_END}); do
      echo "Configuring pod mysql1/dbc1-${i}"
      cat <<'  EOF' | kubectl -n mysql1 exec -i dbc1-${i} -- bash -c 'mysql -uroot -proot --password=${MYSQL_ROOT_PASSWORD}'
    INSTALL PLUGIN group_replication SONAME 'group_replication.so';
    RESET PERSIST IF EXISTS group_replication_ip_allowlist;
    RESET PERSIST IF EXISTS binlog_transaction_dependency_tracking;
    SET @@PERSIST.group_replication_ip_allowlist = 'mysql.mysql1.svc.cluster.local';
    SET @@PERSIST.binlog_transaction_dependency_tracking = 'WRITESET';
      EOF
    done

    הסקריפט יתחבר מרחוק לכל אחת משלוש מכונות MySQL כדי להגדיר ולשמור את משתני הסביבה הבאים:

    • group_replication_ip_allowlist: מאפשר למכונה באשכול להתחבר לכל מכונה בקבוצה.
    • binlog_transaction_dependency_tracking='WRITESET': מאפשר עסקאות מקבילות שלא יתנגשו.

    בגרסאות MySQL מוקדמות יותר מ-8.0.22, משתמשים ב-group_replication_ip_whitelist במקום ב-group_replication_ip_allowlist.

  2. פותחים טרמינל שני, כדי שלא תצטרכו ליצור מעטפת לכל Pod.

  3. מתחברים אל 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"'
    
  4. בודקים את הרשימה הלבנה של שכפול קבוצות MySQL כדי להתחבר למופעים אחרים.

    \sql SELECT @@group_replication_ip_allowlist;
    

    הפלט אמור להיראות כך:

    +----------------------------------+
    | @@group_replication_ip_allowlist |
    +----------------------------------+
    | mysql.mysql1.svc.cluster.local   |
    +----------------------------------+
    
  5. מוודאים שכל מופע של server-id הוא ייחודי.

    \sql SELECT @@server_id;
    

    הפלט אמור להיראות כך:

    +-------------+
    | @@server_id |
    +-------------+
    |          21 |
    +-------------+
    
  6. מגדירים כל מופע לשימוש ב-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.
    
  7. מוודאים שהמופע מוכן לשימוש ב-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, פועלים לפי השלבים הבאים:

  1. יוצרים את אשכול 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.
    
  2. מוסיפים את המופע השני לאשכול.

    cluster.addInstance('icadmin@dbc1-1.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
    
  3. מוסיפים את המופע הנותר לאשכול.

    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.
    
  4. בודקים את הסטטוס של האשכול.

    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}) כדי לקבל פרטים נוספים על הסטטוס.

יצירת מסד נתונים לדוגמה

כדי ליצור מסד נתונים לדוגמה:

  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) );
    
  2. מכניסים נתונים לדוגמה למסד הנתונים. כדי להוסיף נתונים, צריך להתחבר למופע הראשי של האשכול.

    INSERT INTO loan (firstname, lastname, status) VALUES ( 'Fred','Flintstone','pending');
    INSERT INTO loan (firstname, lastname, status) VALUES ( 'Betty','Rubble','approved');
    
  3. מוודאים שהטבלה מכילה את שלוש השורות שהוספתם בשלב הקודם.

    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, פועלים לפי השלבים הבאים:

  1. בטרמינל של MySQL Shell, מקבלים אובייקט של אשכול.

    \js
    cluster=dba.getCluster()
    

    הפלט אמור להיראות כך:

    <Cluster:mycluster>
    
  2. מאתחלים 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>
    
  3. בודקים את הסטטוס של 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}) כדי לקבל פרטים נוספים על הסטטוס, כולל מידע על האשכול.

  4. יוצאים מ-MySQL Shell.

    \q
    

פריסת MySQL Router

אפשר לפרוס נתב MySQL כדי להפנות את התנועה של אפליקציות לקוח לאשכולות המתאימים. הניתוב מבוסס על יציאת החיבור של האפליקציה שמבצעת פעולה במסד הנתונים:

  • פעולות כתיבה מנותבות למופע הראשי של Cluster ב-ClusterSet הראשי.
  • אפשר להפנות פעולות קריאה לכל מכונה באשכול הראשי.

כשמפעילים את MySQL Router, הוא מופעל מתוך פריסת MySQL InnoDB ClusterSet. המכונות של MySQL Router שמחוברות ל-MySQL InnoDB ClusterSet מודעות לכל מעבר מבוקר או מעבר לגיבוי במקרה חירום, ומפנות את התנועה לאשכול הראשי החדש.

כדי לפרוס נתב MySQL, מבצעים את השלבים הבאים:

  1. בטרמינל של 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
    
  2. בודקים את המוכנות של פריסת 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.

  3. מפעילים את MySQL Shell בכל אחד מהחברים באשכול הקיים.

    kubectl -n mysql1 exec -it dbc1-0 -- \
        /bin/bash -c 'mysqlsh --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
    

    הפקודה הזו מתחברת ל-Pod‏ dbc1-0, ואז מפעילה מעטפת שמחוברת למופע MySQL‏ dbc1-0.

  4. מאמתים את הגדרות הנתב.

    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::": {
          ...
        }
      }
    }
    
  5. יוצאים מ-MySQL Shell.

    \q
    
  6. מריצים את הסקריפט הזה כדי לבדוק את המיקום של פודים של 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 לאחד.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: mysql-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: mysql

כדי להחיל את מדיניות ה-PDB על האשכול, פועלים לפי השלבים הבאים:

  1. מחילים את מדיניות ה-PDB באמצעות kubectl.

    kubectl apply -n mysql1 -f mysql-pdb-maxunavailable.yaml
    
  2. הצגת הסטטוס של ה-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 החדש.

  1. בודקים שקובץ ה-PDB נוצר.

    kubectl get poddisruptionbudgets -n mysql1
    
  2. מקבלים את רשימת ה-stateful sets.

    kubectl get statefulsets -n mysql1
    
  3. מקבלים את רשימת ה-Pods הפועלים באמצעות התווית app.

    kubectl get pods --selector=app=mysql -n mysql1
    
  4. מעדכנים את תמונת ה-MySQL ב-StatefulSet.

    kubectl  -n mysql1 \
        set image statefulset/dbc1 \
        mysql=mysql/mysql-server:8.0.30
    

    הפלט אמור להיראות כך:

    statefulset.apps/mysql image updated
    
  5. בודקים את הסטטוס של ה-Pods שמסתיימים ושל ה-Pods החדשים.

    kubectl get pods --selector=app=mysql -n mysql1
    

אימות השדרוג הבינארי של MySQL

במהלך השדרוג, תוכלו לבדוק את סטטוס ההשקה, את ה-Pods החדשים ואת השירות הקיים.

  1. מריצים את הפקודה rollout status כדי לאשר את השדרוג.

    kubectl rollout status statefulset/dbc1 -n mysql1
    

    הפלט אמור להיראות כך:

    partitioned roll out complete: 3 new pods have been updated...
    
  2. כדי לאשר את גרסת התמונה, בודקים את קבוצת ה-StatefulSet.

    kubectl get statefulsets -o wide -n mysql1
    

    הפלט אמור להיראות כך:

    NAME   READY   AGE   CONTAINERS   IMAGES
    dbc1   3/3     37m   mysql        mysql/mysql-server:8.0.30
    
  3. בודקים את הסטטוס של האשכול.

    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:

  1. פותחים את הדף gkemulti-west1 Cluster במסוף Google Cloud .
  2. בוחרים באפשרות Nodes (צמתים) ולוחצים על default pool (מאגר ברירת המחדל).
  3. גוללים למטה אל Instance groups [קבוצות של מופעים].
  4. בכל קבוצת מופעים, משנים את הערך Number of nodes מ-5 ל-8 צמתים.

הוספת Pods של MySQL לאשכול הראשי

כדי לפרוס עוד פודים של MySQL כדי להרחיב את האשכול באופן אופקי, פועלים לפי השלבים הבאים:

  1. ב-Cloud Shell, מעדכנים את מספר הרפליקות בפריסת MySQL משלוש רפליקות לחמש רפליקות.

    kubectl scale  -n mysql1 --replicas=5 -f c1-mysql.yaml
    
  2. בודקים את התקדמות הפריסה.

    kubectl -n mysql1 get pods --selector=app=mysql -o wide
    

    כדי לקבוע אם ה-Pods מוכנים, משתמשים בדגל --watch כדי לצפות בפריסה. אם אתם משתמשים באשכולות Autopilot ומופיעות שגיאות Pod Unschedulable, יכול להיות ש-GKE מקצה צמתים כדי להכיל את ה-Pods הנוספים.

  3. הגדרת ההגדרות של שכפול הקבוצה עבור מופעי MySQL החדשים שרוצים להוסיף לאשכול

    bash ../scripts/c1-clustersetup.sh 3 4
    

    הסקריפט שולח את הפקודות למופעים שפועלים ב-Pods עם מספרי סידורי 3 עד 4.

  4. פותחים את MySQL Shell.

    kubectl -n mysql1 \
      exec -it dbc1-0 -- \
          /bin/bash \
            -c 'mysqlsh \
            --uri="root:$MYSQL_ROOT_PASSWORD@dbc1-0.mysql"'
    
  5. מגדירים את שני מופעי 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 ומבצעות את שינויי ההגדרה הנדרשים.

  6. מוסיפים אחד מהמופעים החדשים לאשכול הראשי.

    cluster = dba.getCluster()
    cluster.addInstance('icadmin@dbc1-3.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
    
  7. מוסיפים מופע חדש שני לאשכול הראשי.

    cluster.addInstance('icadmin@dbc1-4.mysql', {password: os.getenv("MYSQL_ROOT_PASSWORD"), recoveryMethod: 'clone'});
    
  8. מקבלים את הסטטוס של 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."
    
  9. יוצאים מ-MySQL Shell.

    \q
    

הסרת המשאבים

כדי להימנע מחיובים בחשבון Google Cloud בגלל השימוש במשאבים שנעשה במסגרת המדריך הזה, אפשר למחוק את הפרויקט שמכיל את המשאבים, או להשאיר את הפרויקט ולמחוק את המשאבים בנפרד.

מחיקת הפרויקט

הדרך הקלה ביותר להימנע מחיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך.

כדי למחוק Google Cloud פרויקט:

gcloud projects delete PROJECT_ID

המאמרים הבאים

  • כאן אפשר לקרוא מידע נוסף על האופן שבו השילוב של Google Cloud Observability עם MySQL אוסף מדדי ביצועים שקשורים ל-InnoDB.
  • מידע נוסף על גיבוי ל-GKE, שירות לגיבוי ושחזור של עומסי עבודה ב-GKE
  • אפשר לעיין בפרטים נוספים על Persistent Volumes.