הטמעה לדוגמה של מסד נתונים של MySQL ב-GDC עם air gap

במדריך הזה מוסבר באופן מקיף איך לפרוס MySQL 8.4 InnoDB Cluster בזמינות גבוהה בשלושה אזורי זמינות בסביבה של Google Distributed Cloud (GDC) עם air gap. הארכיטקטורה הזו משתמשת ב-Group Replication לקונצנזוס מבוסס-Paxos, ב-MySQL Router לניתוב חיבורים חכם וב-MySQL Shell לתזמור אשכולות.

ההטמעה הזו מתבססת אך ורק על מכונות וירטואליות (VMs), ולכן היא עוקפת את המגבלות של GDC עם air gap בנוגע לאשכולות Kubernetes stretch בכמה אזורים. כך מובטחת עמידות מלאה בכמה אזורים בלי סיכון לאובדן נתונים.

זו דיאגרמת הארכיטקטורה:

ארכיטקטורה של שלוש מכונות וירטואליות שמריצה סטאק של שירותים באותו מיקום.

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

פריסת מכונות וירטואליות

פועלים לפי ההוראות במאמר יצירה והפעלה של מכונה וירטואלית כדי ליצור שלוש מכונות וירטואליות בשלושת האזורים הזמינים.

מגדירים את הסביבה המקומית כדי ליצור חיבור SSH למכונות הווירטואליות באמצעות זוג מפתחות: התחברות למכונה וירטואלית

כדי להשתמש ב-SCP (פרוטוקול העתקה מאובטחת) להעברת החבילות, צריך: להעביר קבצים

לצורך האימות השתמשנו במערכת ההפעלה Ubuntu 22.04 ובסוג המכונה n3-standard-2-gdc. בסביבת ייצור, כדאי להשתמש בסוג מכונה עם יותר משאבים.

משיגים את כתובות ה-IP של המכונות הווירטואליות באמצעות:

VM_NAME=$1

if [[ -z "$VM_NAME" ]]; then
  echo "Error: VM_NAME must be provided."
  echo "Usage: $0 <VM_NAME>"
  exit 1
fi

# 1. Get External IP from 'instances list'
EXT_IP=$(gdcloud compute instances list | awk -v vm="${VM_NAME}" '$1 == vm {print $5}')

if [[ -z "$EXT_IP" ]]; then
  echo "Error: Could not find VM '${VM_NAME}' in the instance list."
  exit 1
fi

INTERNAL_IP=$(gdcloud compute instances describe "${VM_NAME}" | awk '/^status:/ {in_status=1} in_status && /- [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ {print $2; exit}' | cut -d'/' -f1)

if [[ -z "$INTERNAL_IP" ]]; then
  INTERNAL_IP="<Not assigned or not found>"
fi

echo "${VM_NAME}"
echo "External IP: ${EXT_IP}"
echo "Internal IP: ${INTERNAL_IP}"

הגדרת משתני סביבה

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

export PROJECT_ID="your-project-id"
export VM1_NAME="mysql-node-1"
export VM2_NAME="mysql-node-2"
export VM3_NAME="mysql-node-3"
export VM1_IP="10.0.1.245" # Zone 1
export VM2_IP="10.0.1.241" # Zone 2
export VM3_IP="10.0.1.242" # Zone 3
export CLUSTER_NAME="mysql-ha-cluster"

הגדרת רשת

אם אתם צריכים לגשת למסד הנתונים מחוץ לפרויקט או מחוץ לארגון, זכרו להגדיר את ה-PNP (מדיניות הרשת של הפרויקט) בהתאם.

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

הכנת תוכנה עם air gap

הורדת חבילות באמצעות Docker

כדי לאחזר את רכיבי MySQL 8.4 ו-Shell, מריצים את הפקודה הבאה מתחנת עבודה מחוברת:

mkdir -p ./mysql-packages
docker run --rm -v "$(pwd)/mysql-packages:/packages" ubuntu:22.04 bash -c "
  apt-get update && apt-get install -y curl gnupg apt-rdepends wget lsb-release
  curl -LsS https://dev.mysql.com/get/mysql-apt-config_0.8.39-1_all.deb -o config.deb
  # Configure for MySQL 8.4 LTS
  DEBIAN_FRONTEND=noninteractive dpkg -i config.deb 
  apt-get update
  cd /packages
  PACKAGES='mysql-server mysql-shell mysql-router'
  apt-get download \$(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances --no-pre-depends \${PACKAGES} | grep '^\w')
"

העברה והתקנה

מעלים את הקבצים של .deb אל /tmp/packages/ בכל שלוש המכונות הווירטואליות ומתקינים:

# From workstation: scp ./mysql-packages/*.deb ${VM_IP}:/tmp/packages/
# On each VM:
sudo dpkg -i /tmp/packages/*.deb

מוודאים שה-dpkg לא מחזיר שגיאות. אם כן, בודקים ביומנים אילו חבילות deb חסרות וכוללים אותן בהורדה.

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

הגדרת צומת MySQL

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

עורכים את /etc/mysql/mysql.conf.d/mysqld.cnf בכל הצמתים כדי להפעיל GTIDs ורישום ביומן בינארי:

[mysqld]
bind-address = 0.0.0.0
server-id = 1 # Use 2 and 3 for other VMs
gtid-mode = ON
enforce-gtid-consistency = ON
binlog-format = ROW
log-bin = mysql-bin
report_host = 10.0.1.245 # Use the VM's specific IP

מפעילים מחדש את השירות:

sudo systemctl restart mysql

ואז מתחברים למסד הנתונים:

sudo mysql

ולהגדיר סיסמת בסיס:

CREATE USER 'root'@'%' IDENTIFIED WITH 'caching_sha2_password' BY 'your_new_secure_password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

הפעלה ואימות של אשכול InnoDB

יצירת אשכול באמצעות MySQL Shell

רק ב-VM 1, משתמשים ב-MySQL Shell כדי לאתחל את האשכול:

mysqlsh --uri root@localhost
# Inside MySQL Shell:
\js
dba.configureInstance('root@VM1_IP')
var cluster = dba.createCluster('mysql-ha-cluster')
cluster.addInstance('root@VM2_IP')
cluster.addInstance('root@VM3_IP')
cluster.status()

‫Bootstrap MySQL Router

בכל שלוש המכונות הווירטואליות, מפעילים את הנתב כדי לזהות את האשכול החדש:

sudo mysqlrouter --bootstrap root@VM1_IP --user=mysqlrouter
sudo systemctl restart mysqlrouter
sudo systemctl enable mysqlrouter

אימות האיזון והחיבורים

מריצים את הפקודות האלה מכל צומת כדי לוודא שהנתב מפיץ את התנועה בצורה נכונה.

  1. אימות של ניתוב הכתיבה (ראשי פעיל): שאילתה ליציאה 6446 (RW קלאסי). היא צריכה להחזיר רק את שם המארח של השרת הראשי הנוכחי.

    mysql -u root -pyour_new_secure_password -h 127.0.0.1 -P 6446 -e "SELECT @@hostname;"
    
  2. אימות של איזון הקריאה (Round-Robin): שולחים שאילתה ליציאה 6447 (Classic RO) כמה פעמים. הוא אמור לעבור בין שמות המארחים של כל הצמתים הזמינים באשכול.

    for i in {1..4}; do mysql -u root -pyour_new_secure_password -h 127.0.0.1 -P 6447 -e "SELECT @@hostname;"; done
    
  3. בדיקת טופולוגיית החיבור: משתמשים ב-MySQL Shell כדי לוודא שכל החברים הם ONLINE ומאוזנים בצורה נכונה.

    mysqlsh --uri root@localhost --cluster
    
    # inside the shell
    > cluster.status()
    

הגדרת מאזן עומסים גלובלי

כתובת IP וירטואלית (VIP) אחת ויציבה לאפליקציות באמצעות מאזן העומסים הגלובלי של GDC בשכבה 4. כדי להגדיר את מאזן העומסים הגלובלי הפנימי בשכבה 4 ולהגדיר את המכונות הווירטואליות כיעד שלו, פועלים לפי ההוראות במאמר הגדרת מאזני עומסים גלובליים פנימיים: הגדרת מכונות וירטואליות כיעד של מאזן עומסים.

אימות אוטומטי של יתירות כשל

הבדיקה הזו מאשרת שהאשכול בוחר מנהיג חדש ושהנתב מפנה מחדש את התנועה ללא התערבות ידנית.

סימולציה של כשל ראשי

מזהים את השרת הראשי הנוכחי (למשל, צומת 1) ועוצרים את שירות MySQL:

sudo systemctl stop mysql

אימות של שינוי הבחירה והניתוב

ממתינים 10-20 שניות עד שפרוטוקול הקונצנזוס יבחר מנהיג חדש.

  1. בדיקת הסטטוס של האשכול: מוודאים שנבחרה מכונה ראשית חדשה ממכונה וירטואלית 2 או 3.

    mysqlsh --uri root@localhost --cluster
    
    # inside the shell
    > cluster.status()
    

    מוודאים שאחד מהצמתים שנותרו מסומן כ-PRIMARY ושהצומת שנכשל מסומן כ-UNREACHABLE או כ-MISSING.

  2. אימות של ניתוב הכתיבה: בודקים שוב את יציאת ה-RW‏ (6446). עכשיו אמור לחזור שם המארח של השרת הראשי החדש.

    mysql -u root -p -h 127.0.0.1 -P 6446 -e "SELECT @@hostname;"
    
  3. בדיקת הקישוריות ל-Global VIP: משרת אפליקציות, שולחים שאילתה ל-Global VIP.

    mysql -u root -p -h ${LB_IP} -P 3306 -e "SELECT @@hostname;"
    

שחזור ואימות של הצטרפות מחדש

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

sudo systemctl start mysql
mysqlsh --uri root@localhost --cluster -e "cluster.status()"

מוודאים שכל שלושת הצמתים מחזירים את הסטטוס ONLINE.