الاحتفاظ بنسخة احتياطية من AlloyDB Omni واستعادتها إلى مساحة تخزين متوافقة مع S3 باستخدام أداة تنظيم RPM

1. مقدمة

في هذا الدرس التطبيقي حول الترميز، ستنشئ نسخة احتياطية من مجموعة توفّر إمكانية الوصول العالية (HA) إلى مساحة تخزين كائنات متوافقة مع S3 في AlloyDB Omni باستخدام أداة تنظيم RPM.

يستخدم هذا الدرس التطبيقي حول الترميز المجموعة من الدرس التطبيقي حول الترميز نشر مجموعة AlloyDB Omni عالية التوفّر على أجهزة GCE الافتراضية باستخدام RPM Orchestrator لإنشاء مجموعة عالية التوفّر على أجهزة Compute Engine الافتراضية. في هذا الدرس التطبيقي حول الترميز، ستضيف خادمًا لتخزين العناصر متوافقًا مع S3 على أحد الأجهزة الافتراضية. يمكنك استخدام خادم تخزين الكائنات لمجموعة التوفّر العالي من أجل الاحتفاظ بنسخة احتياطية من البيانات واستعادة المجموعة من الخادم.

تتصل Cloud Shell بالجهاز الظاهري للتحكّم. يشغّل الجهاز الافتراضي للتحكّم Ansible وMinIO، ويتصل psql بالمجموعة من خلال عنوان IP الافتراضي لأجهزة HAProxy الافتراضية. ترسل الأجهزة الافتراضية لقاعدة البيانات نُسخًا احتياطية إلى MinIO على المنفذ 9000.

المتطلبات الأساسية

  • مشروع Google Cloud تم تفعيل الفوترة فيه
  • أدوار "إدارة الهوية وإمكانية الوصول" التي يدرجها الدرس التطبيقي حول الترميز الخاص بالتوفّر العالي
  • معرفة أساسية بأوامر Linux وSQL

ما ستتعلمه

  • كيفية تثبيت خادم تخزين عناصر متوافق مع S3 وتشغيله لعمليات النسخ الاحتياطي
  • كيفية إنشاء خطة احتياطية تكتب النسخ الاحتياطية إلى وحدة تخزين متوافقة مع S3
  • كيفية إنشاء نسخة احتياطية عند الطلب
  • كيفية استعادة مجموعة من نسخة احتياطية وإلى نقطة زمنية

المتطلبات

2. الإعداد والمتطلبات

  1. في هذه الخطوة، يمكنك إنشاء مجموعة توفّر عالٍ باستخدام الدرس التطبيقي حول الترميز نشر مجموعة توفّر عالٍ من AlloyDB Omni على أجهزة GCE الافتراضية باستخدام RPM Orchestrator. أكمِل الخطوات التالية. إذا كان لديك مجموعة من ورشة الترميز، انتقِل إلى الخطوة التالية.
  2. ملاحظة: لا تنفِّذ الخطوة "تنظيف الموارد" في هذه المرحلة. ستنفّذ هذه الخطوة في نهاية هذا الدرس البرمجي.
  3. الرجوع إلى هذا الدرس التطبيقي حول الترميز

3- الربط بالمجموعة وإضافة بيانات نموذجية

في هذه الخطوة، عليك تحميل إعدادات المجموعة على الجهاز الظاهري للتحكّم. بعد ذلك، يمكنك الربط بالمجموعة وإضافة جدول يتضمّن بيانات نموذجية.

  1. إذا لم تكن متصلاً بالجهاز الافتراضي للتحكّم، اتّصِل به من Cloud Shell:
    gcloud compute ssh "$CLUSTER-control" --zone="$ZONE" --project="$PROJECT"
    
    تأتي المتغيرات CLUSTER وZONE وPROJECT من خطوة إعداد الأجهزة الافتراضية للنشر في الدرس التطبيقي حول الترميز نشر مجموعة AlloyDB Omni عالية التوفّر على أجهزة Google Compute Engine الافتراضية باستخدام أداة RPM Orchestrator. إذا لم تتضمّن Cloud Shell هذه المتغيّرات، عليك ضبطها مرة أخرى.
  2. على الجهاز الظاهري للتحكّم، انتقِل إلى دليل المنزل وحمِّل متغيرات البيئة. بعد ذلك، أضِف اسم المجموعة ومستخدم SSH إلى ملف البيئة:
    cd ~
    source /tmp/cluster.conf
    cat >> ~/.codelab.env <<EOF
    export CLUSTER="$cluster"
    export SSH_USER="$service_account"
    EOF
    source ~/.codelab.env
    env | grep -E '^(CLUSTER|SSH_USER|VIRTUAL_IP)='
    
    تأكَّد من أنّ الناتج يعرض CLUSTER وSSH_USER وVIRTUAL_IP. ملاحظة: إذا أردت الاتصال بالجهاز الافتراضي للتحكّم مرة أخرى لاحقًا، شغِّل الأمرَين cd ~ وsource ~/.codelab.env قبل المتابعة.
  3. أضِف إعدادات الاتصال إلى ملف البيئة. عندما يطلب الأمر read كلمة المرور، أدخِل كلمة مرور المستخدم postgres. يمكنك ضبط كلمة المرور هذه في خطوة إعداد مجموعة AlloyDB Omni في الدرس التطبيقي حول الترميز نشر مجموعة AlloyDB Omni ذات توفّر عالٍ على أجهزة GCE الافتراضية باستخدام RPM Orchestrator.
    cat >> ~/.codelab.env <<'EOF'
    export PATH="/usr/pgsql-18/bin:$PATH"
    export PGHOST="$VIRTUAL_IP"
    export PGUSER="postgres"
    EOF
    read -rsp "Password of the postgres user: " PGPASSWORD; echo
    printf 'export PGPASSWORD=%q\n' "$PGPASSWORD" >> ~/.codelab.env
    source ~/.codelab.env
    env | grep -E '^(PGHOST|PGUSER|PGPASSWORD)='
    
  4. أنشئ جدولاً وأضِف 1,000 صف:
    psql <<'SQL'
    CREATE TABLE public.orders (
      id integer PRIMARY KEY,
      item text NOT NULL,
      created_at timestamptz NOT NULL DEFAULT pg_catalog.now()
    );
    INSERT INTO public.orders (id, item)
    SELECT g, 'item-' || g FROM pg_catalog.generate_series(1, 1000) AS g;
    SQL
    
  5. احتساب عدد الصفوف:
    psql -c "SELECT pg_catalog.count(*) FROM public.orders;"
    
    تأكَّد من أنّ الناتج يعرض 1000.

4. تثبيت وتشغيل وحدة تخزين متوافقة مع S3

في هذه الخطوة، ستكتب ملف Ansible playbook يثبّت خادم MinIO على الجهاز الافتراضي للتحكّم. ينشئ دليل التشغيل أيضًا الحزمة والمستخدم لعمليات النسخ الاحتياطي، ويتأكّد من إمكانية ربط الأجهزة الافتراضية لقاعدة البيانات بـ MinIO. نفِّذ جميع الأوامر في هذه الخطوة على الجهاز الظاهري للتحكّم.

  1. في الجهاز الظاهري للتحكّم، أضِف إعدادات التخزين إلى ملف البيئة. تنشئ الأوامر openssl كلمات مرور عشوائية.
    MD=http://metadata.google.internal/computeMetadata/v1/instance
    S3_IP=$(curl -s -H "Metadata-Flavor: Google" "$MD/network-interfaces/0/ip")
    cat >> ~/.codelab.env <<EOF
    export S3_IP="$S3_IP"
    export S3_HOST="$CLUSTER-control"
    export S3_BUCKET="alloydb-backups"
    export S3_REGION="us-east-1"
    export MINIO_ROOT_USER="s3admin"
    export MINIO_ROOT_PASSWORD="$(openssl rand -hex 16)"
    export S3_ACCESS_KEY_ID="alloydb-backup"
    export S3_SECRET_ACCESS_KEY="$(openssl rand -hex 16)"
    export MINIO_URL="https://github.com/minio/minio/releases/download/RELEASE.2024-05-10T01-41-38Z/minio.linux-amd64.RELEASE.2024-05-10T01-41-38Z"
    export MC_URL="https://github.com/minio/mc/releases/download/RELEASE.2024-05-09T17-04-24Z/mc.linux-amd64.RELEASE.2024-05-09T17-04-24Z"
    EOF
    source ~/.codelab.env
    echo "$S3_HOST $S3_IP"
    
    تأكَّد من أنّ الناتج يعرض اسم وعنوان IP الداخلي للجهاز الافتراضي للتحكّم، مثل my-cluster-control 10.1.0.2. تستخدم الأجهزة الافتراضية لقاعدة البيانات اسم المضيف وعنوان IP هذا للاتصال بـ MinIO. يوفّر خادم البيانات الوصفية للجهاز الافتراضي عنوان IP. لمزيد من المعلومات، يُرجى الاطّلاع على مستندات البيانات الوصفية الخاصة بالجهاز الافتراضي.قيمتا MINIO_URL وMC_URL هما عنوانا URL للتنزيل الخاصين بخادم MinIO وبرنامج MinIO (mc).
  2. ثبِّت مجموعة community.crypto Ansible المطلوبة على الجهاز الافتراضي للتحكّم:
    ansible-galaxy collection install community.crypto
    
  3. إنشاء دليل إرشادي s3_server.yaml:
    cat > s3_server.yaml <<EOF
    - name: Install and run MinIO on the control VM
      hosts: localhost
      connection: local
      become: true
      gather_facts: false
      tasks:
        - name: Create MinIO directories
          ansible.builtin.file:
            path: "{{ item }}"
            state: directory
            mode: "0755"
          loop:
            - /var/lib/minio/data
            - /var/lib/minio/certs
    
        - name: Download MinIO server and client
          ansible.builtin.get_url:
            url: "{{ item.url }}"
            dest: "{{ item.dest }}"
            mode: "0755"
          loop:
            - url: "$MINIO_URL"
              dest: /usr/local/bin/minio
            - url: "$MC_URL"
              dest: /usr/local/bin/mc
    
        - name: Generate MinIO TLS private key
          community.crypto.openssl_privatekey:
            path: /var/lib/minio/certs/private.key
            size: 2048
            mode: "0600"
    
        - name: Generate MinIO certificate signing request
          community.crypto.openssl_csr_pipe:
            privatekey_path: /var/lib/minio/certs/private.key
            common_name: "$S3_HOST"
            subject_alt_name:
              - "DNS:$S3_HOST"
              - "DNS:$S3_BUCKET.$S3_HOST"
              - "DNS:localhost"
              - "IP:127.0.0.1"
              - "IP:$S3_IP"
          register: minio_csr
    
        - name: Generate self-signed MinIO TLS certificate
          community.crypto.x509_certificate:
            path: /var/lib/minio/certs/public.crt
            csr_content: "{{ minio_csr.csr }}"
            privatekey_path: /var/lib/minio/certs/private.key
            provider: selfsigned
            selfsigned_not_after: "+365d"
            mode: "0644"
    
        - name: Create MinIO systemd service unit
          ansible.builtin.copy:
            dest: /etc/systemd/system/minio.service
            mode: "0600"
            content: |
              [Unit]
              Description=MinIO Object Storage
              After=network.target
    
              [Service]
              Environment="MINIO_ROOT_USER=$MINIO_ROOT_USER"
              Environment="MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD"
              Environment="MINIO_DOMAIN=$S3_HOST"
              ExecStart=/usr/local/bin/minio server /var/lib/minio/data --certs-dir /var/lib/minio/certs
              Restart=on-failure
    
              [Install]
              WantedBy=multi-user.target
    
        - name: Start and enable MinIO service
          ansible.builtin.systemd_service:
            name: minio
            daemon_reload: true
            state: started
            enabled: true
    
        - name: Add storage host names to /etc/hosts on the control VM
          ansible.builtin.lineinfile:
            path: /etc/hosts
            line: "$S3_IP $S3_HOST $S3_BUCKET.$S3_HOST"
            state: present
    
        - name: Wait for MinIO health endpoint
          ansible.builtin.uri:
            url: "https://$S3_HOST:9000/minio/health/live"
            ca_path: /var/lib/minio/certs/public.crt
            status_code: 200
          register: minio_health
          until: minio_health.status == 200
          retries: 6
          delay: 5
    
        - name: Create backup bucket and user in MinIO
          ansible.builtin.command:
            argv: "{{ item }}"
          loop:
            - - /usr/local/bin/mc
              - --insecure
              - alias
              - set
              - s3repo
              - "https://$S3_HOST:9000"
              - "$MINIO_ROOT_USER"
              - "$MINIO_ROOT_PASSWORD"
            - - /usr/local/bin/mc
              - --insecure
              - mb
              - --ignore-existing
              - "s3repo/$S3_BUCKET"
            - - /usr/local/bin/mc
              - --insecure
              - admin
              - user
              - add
              - s3repo
              - "$S3_ACCESS_KEY_ID"
              - "$S3_SECRET_ACCESS_KEY"
            - - /usr/local/bin/mc
              - --insecure
              - admin
              - policy
              - attach
              - s3repo
              - readwrite
              - --user
              - "$S3_ACCESS_KEY_ID"
          become: false
          no_log: true
    
    - name: Configure database VMs for MinIO
      hosts: primary_instance_nodes
      become: true
      gather_facts: false
      vars:
        ansible_user: $SSH_USER
        ansible_ssh_private_key_file: $HOME/ssh-key-cluster-sa
      tasks:
        - name: Set SELinux to permissive mode
          ansible.builtin.command:
            cmd: setenforce 0
    
        - name: Add storage host names to /etc/hosts
          ansible.builtin.lineinfile:
            path: /etc/hosts
            line: "$S3_IP $S3_HOST $S3_BUCKET.$S3_HOST"
            state: present
    
        - name: Verify storage host resolution
          ansible.builtin.getent:
            database: hosts
            key: "$S3_BUCKET.$S3_HOST"
    
        - name: Verify connection to MinIO
          ansible.builtin.uri:
            url: "https://$S3_HOST:9000/minio/health/live"
            validate_certs: false
            status_code: 200
    EOF
    
    يتيح المتغيّر MINIO_DOMAIN لخدمة MinIO قبول الطلبات بأسلوب المضيف الظاهري. يستخدم منسّق RPM المستخدم alloydb-backup لكتابة النُسخ الاحتياطية. سياسة readwrite هي سياسة مضمَّنة في MinIO.
  4. تشغيل الدليل الإرشادي:
    ansible-playbook s3_server.yaml -i deployment_spec.yaml
    
    تأكَّد من أنّ الناتج PLAY RECAP يعرض failed=0 لكل من localhost ولكل جهاز ظاهري لقاعدة البيانات.
  5. تأكَّد من توفّر الحزمة:
    mc --insecure ls s3repo
    
    تأكَّد من أنّ الناتج يعرض الحزمة alloydb-backups/.

5- وضع خطة احتياطية

تحتوي خطة النسخ الاحتياطي على موقع التخزين والجدول الزمني ومدة الاحتفاظ بنُسخ احتياطية من مجموعة. في هذه الخطوة، عليك إنشاء خطة احتياطية لحزمة MinIO.

  1. على الجهاز الافتراضي للتحكّم، أنشئ دليل التشغيل الخاص بالنسخة الاحتياطية ودليل التشغيل الخاص بالحالة. يمكنك استخدام دليل النسخ الاحتياطي لموارد Secret وBackupPlan وBackup. يمكنك استخدام دليل التشغيل الخاص بالحالة لعرض حالة أحد المراجع.
    cat > backup.yaml <<EOF
    - name: Manage AlloyDB Omni backups
      hosts: localhost
      roles:
        - role: google.alloydbomni_orchestrator.backup
    EOF
    cat > status.yaml <<EOF
    - name: Get resource status
      hosts: localhost
      roles:
        - role: google.alloydbomni_orchestrator.status
    EOF
    
  2. أنشئ مورد Secret لبيانات اعتماد S3. بعد ذلك، طبِّق المرجع:
    S3_KEY_ID_B64=$(printf '%s' "$S3_ACCESS_KEY_ID" | base64 -w 0)
    S3_KEY_B64=$(printf '%s' "$S3_SECRET_ACCESS_KEY" | base64 -w 0)
    cat > s3_secret.yaml <<EOF
    Secret:
      metadata:
        name: s3-backup-secret
      spec:
        type: Opaque
        data:
          access-key-id: "$S3_KEY_ID_B64"
          access-key: "$S3_KEY_B64"
    EOF
    ansible-playbook backup.yaml -i deployment_spec.yaml \
        -e resource_spec=s3_secret.yaml
    
    يجب أن تكون أسماء المفاتيح في القسم data هي access-key-id وaccess-key. يجب تطبيق مورد Secret قبل تطبيق مورد BackupPlan.
  3. أنشئ المرجع BackupPlan ثم طبِّقه:
    cat > backup_plan.yaml <<EOF
    BackupPlan:
      metadata:
        name: s3-backup-plan
      spec:
        dbclusterRef: $CLUSTER
        backupLocation:
          type: S3
          s3Options:
            bucket: $S3_BUCKET
            key: /backups
            endpoint: https://$S3_HOST:9000
            region: $S3_REGION
            secretRef:
              name: s3-backup-secret
            caBundle:
              - |
    $(sed 's/^/            /' /var/lib/minio/certs/public.crt)
    EOF
    ansible-playbook backup.yaml -i deployment_spec.yaml \
        -e resource_spec=backup_plan.yaml
    
    قيمة key هي مسار النسخ الاحتياطية في الحزمة. يجب أن يبدأ هذا المسار بشرطة مائلة (/). يحتوي الحقل caBundle على شهادة CA بترميز PEM التي تتحقّق من صحة شهادة خادم التخزين S3.
  4. تأكَّد من أنّ خطة الاحتفاظ بنسخة احتياطية جاهزة:
    ansible-playbook status.yaml -i deployment_spec.yaml \
        -e resource_type=BackupPlan -e resource_name=s3-backup-plan
    
    تأكَّد من أنّ الحقل phase يعرض Ready. إذا لم تكن المرحلة Ready، انتظِر دقيقة واحدة وأعِد تنفيذ الأمر.
  5. عند إنشاء خطة احتياطية، يبدأ منسّق RPM في إجراء عملية الاحتفاظ الكامل بنسخة احتياطية أولية تلقائيًا. تأكَّد من اكتمال عملية الاحتفاظ بنسخة احتياطية أولية قبل إنشاء نسخة احتياطية عند الطلب:
    ansible-playbook status.yaml -i deployment_spec.yaml \
        -e resource_type=Backup
    
    تأكَّد من نجاح مرحلة الاحتفاظ بنسخة احتياطية الأولية.

6. إنشاء نسخة احتياطية عند الطلب

في هذه الخطوة، يمكنك إنشاء نسخة احتياطية عند الطلب من المجموعة.

  1. على الجهاز الظاهري للتحكّم، أنشئ مورد Backup. بعد ذلك، طبِّق المرجع:
    cat > create_backup.yaml <<EOF
    Backup:
      metadata:
        name: s3-backup-1
      spec:
        backupPlanRef: s3-backup-plan
        dbclusterRef: $CLUSTER
    EOF
    ansible-playbook backup.yaml -i deployment_spec.yaml \
        -e resource_spec=create_backup.yaml
    
    يمثّل الحقل backupPlanRef اسم خطة النسخ الاحتياطي. الحقل dbclusterRef هو اسم المجموعة.
  2. تأكَّد من اكتمال عملية الاحتفاظ بنسخة احتياطية:
    ansible-playbook status.yaml -i deployment_spec.yaml \
        -e resource_type=Backup -e resource_name=s3-backup-1
    
    تأكَّد من أنّ الحقل phase يعرض Succeeded. إذا لم تكن المرحلة Succeeded، انتظِر دقيقة واحدة وأعِد تنفيذ الأمر.
  3. تأكَّد من أنّ ملفات النسخ الاحتياطية موجودة في الحزمة:
    mc --insecure tree "s3repo/$S3_BUCKET"
    
    تأكَّد من أنّ الناتج يعرض مجلد backup يحتوي على مجلد db.

7. استعادة المجموعة من نسخة احتياطية

يعيد منسّق RPM مجموعة إلى مكانها. في هذه الخطوة، عليك حذف جدول واستعادته من النسخة الاحتياطية. بعد ذلك، يمكنك اختياريًا استعادة المجموعة إلى نقطة زمنية معيّنة.

تنبيه: تؤدي عملية الاستعادة إلى الكتابة فوق جميع البيانات في مجموعة قواعد البيانات.

استعادة البيانات من نسخة احتياطية

  1. على الجهاز الظاهري للتحكّم، احذف الجدول orders. بعد ذلك، احسب عدد الصفوف:
    psql -c "DROP TABLE public.orders;"
    psql -c "SELECT pg_catalog.count(*) FROM public.orders;"
    
    تأكَّد من أنّ الأمر الثاني يتعذّر تنفيذه بسبب ظهور خطأ. تعرض رسالة الخطأ أنّ العلاقة غير متوفّرة. على سبيل المثال، "ERROR: table "orders" does not exist"
  2. أنشئ دليلًا إرشاديًا للاستعادة:
    cat > restore.yaml <<EOF
    - name: Restore AlloyDB Omni cluster
      hosts: localhost
      roles:
        - role: google.alloydbomni_orchestrator.restore
    EOF
    
  3. أنشئ مورد Restore لعملية النسخ الاحتياطي s3-backup-1. بعد ذلك، طبِّق المرجع:
    cat > restore_backup.yaml <<EOF
    Restore:
      metadata:
        name: s3-restore-1
      spec:
        sourceDBCluster: $CLUSTER
        backup: s3-backup-1
    EOF
    ansible-playbook restore.yaml -i deployment_spec.yaml \
        -e resource_spec=restore_backup.yaml
    
  4. تأكَّد من اكتمال عملية الاستعادة:
    ansible-playbook status.yaml -i deployment_spec.yaml \
        -e resource_type=Restore -e resource_name=s3-restore-1
    
    تأكَّد من أنّ الحقل phase يعرض ProvisionSucceeded. إذا لم تكن المرحلة ProvisionSucceeded، انتظِر دقيقة واحدة وأعِد تنفيذ الأمر.
  5. احسب عدد الصفوف في الجدول الذي تم استعادته:
    psql -c "SELECT pg_catalog.count(*) FROM public.orders;"
    
    تأكَّد من أنّ الناتج يعرض 1000.

(اختياري) استعادة البيانات إلى نقطة زمنية معيّنة

تستخدم عملية الاستعادة في نقطة زمنية معيّنة نسخة احتياطية وسجلّ الكتابة المسبقة (WAL) المؤرشف. يمكنك استعادة المجموعة إلى أي وقت خلال فترة الاسترداد المحدّدة في خطة الاحتفاظ بنسخة احتياطية.

قواعد الوقت المستهدَف

يجب اتّباع جميع القواعد لاختيار القيمة والتنسيق للوقت المستهدف:

  • استخدِم تنسيق RFC 3339 بالتوقيت العالمي المتفق عليه: YYYY-MM-DDThh:mm:ssZ. على سبيل المثال، 2026-06-19T14:30:00Z هو 14:30:00 بالتوقيت العالمي المتفق عليه في 19 يونيو 2026. يفصل الحرف T بين التاريخ والوقت. يشير الحرف Z إلى التوقيت العالمي المتفق عليه.
  • استخدِم وقتًا في الماضي.
  • استخدِم وقتًا بعد قيمة begin في حقل recoveryWindow من تعريف الموارد المخصّصة BackupPlan.

لعرض الوقت الحالي بتنسيق RFC 3339، نفِّذ الأمر التالي:

date -u +%Y-%m-%dT%H:%M:%SZ

لتغيير الوقت المحلي إلى هذا التنسيق، أضِف إزاحة التوقيت العالمي المتفق عليه للوقت المحلي إلى الأمر date. على سبيل المثال، يغيّر الأمر التالي 16:30:00 في 19 June 2026 في ‎UTC+02:00:

date -u -d "2026-06-19 16:30:00 +0200" +%Y-%m-%dT%H:%M:%SZ

يعرض الأمر 2026-06-19T14:30:00Z.

استرداد الملف إلى نسخته في وقت معيّن

في هذا الإجراء، ستضيف صفوفًا إلى الجدول وتسجّل وقتًا. عند تسجيل وقت، يمكنك وضع إشارة مرجعية على اللحظة المحدّدة التي تكون فيها قاعدة البيانات سليمة تمامًا (أي تحتوي على 1,500 صف بالضبط)، ثم حذف الصفوف واستعادة المجموعة إلى الوقت المسجّل.

  1. أضِف 500 صف إلى الجدول:
    psql <<'SQL'
    INSERT INTO public.orders (id, item)
    SELECT g, 'item-' || g FROM pg_catalog.generate_series(1001, 1500) AS g;
    SQL
    
  2. تسجيل الوقت يحتوي الجدول على 1,500 صف في الوقت الحالي.
    sleep 5
    PITR_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
    echo "export PITR_TIME=$PITR_TIME" >> ~/.codelab.env
    echo "$PITR_TIME"
    sleep 5
    
    تأكَّد من أنّ الناتج يعرض وقتًا بالتنسيق YYYY-MM-DDThh:mm:ssZ، مثلاً 2026-10-05T11:16:02Z.
  3. احذف صفوفًا من الجدول لمحاكاة عملية حذف البيانات بدون قصد. بعد ذلك، ابدأ ملف WAL جديدًا:
    psql -c "DELETE FROM public.orders WHERE id > 1000;"
    psql -c "SELECT pg_catalog.count(*) FROM public.orders;"
    psql -c "SELECT pg_catalog.pg_switch_wal();"
    
    تأكَّد من أنّ طلب البحث count يعرض 1000. تؤدي الدالة pg_switch_wal إلى بدء الخادم ملف WAL جديد. بعد ذلك، يمكن للخادم أرشفة ملف WAL الذي يحتوي على التغييرات.
  4. تأكَّد من أنّ فترة الاسترداد في خطة النسخ الاحتياطي تتضمّن الوقت المسجّل:
    test -n "$PITR_TIME" || { echo "PITR_TIME is not set. Run step 2 again."; exit 1; }
    echo "$PITR_TIME"
    ansible-playbook status.yaml -i deployment_spec.yaml \
        -e resource_type=BackupPlan -e resource_name=s3-backup-plan
    
    تأكَّد من أنّ قيمة PITR_TIME تأتي بعد قيمة begin في الحقل recoveryWindow.
  5. أنشئ مورد Restore للوقت المسجَّل. بعد ذلك، طبِّق المرجع:
    cat > restore_pitr.yaml <<EOF
    Restore:
      metadata:
        name: s3-restore-pitr
      spec:
        sourceDBCluster: $CLUSTER
        pointInTime: "$PITR_TIME"
    EOF
    ansible-playbook restore.yaml -i deployment_spec.yaml \
        -e resource_spec=restore_pitr.yaml
    
  6. تأكَّد من اكتمال عملية الاستعادة:
    ansible-playbook status.yaml -i deployment_spec.yaml \
        -e resource_type=Restore -e resource_name=s3-restore-pitr
    
    تأكَّد من أنّ الحقل phase يعرض ProvisionSucceeded. إذا لم تكن المرحلة ProvisionSucceeded، انتظِر دقيقة واحدة وأعِد تنفيذ الأمر.
  7. احتساب عدد الصفوف:
    psql -c "SELECT pg_catalog.count(*) FROM public.orders;"
    
    تأكَّد من أنّ الناتج يعرض 1500.

8. تنظيف

لتجنُّب تحصيل رسوم من حسابك على Google Cloud، احذف موارد هذا الدرس التطبيقي حول الترميز والدرس التطبيقي حول الترميز نشر مجموعة توفّر عالي من AlloyDB Omni على أجهزة GCE الافتراضية باستخدام RPM Orchestrator. أولاً، احذف موارد النسخ الاحتياطي، ثم احذف المجموعة وبيئة الحوسبة.

  1. على الجهاز الظاهري لعنصر التحكّم، أنشئ برنامج الحذف النصي:
    cat > delete.yaml <<EOF
    - name: Delete AlloyDB Omni resources
      hosts: localhost
      roles:
        - role: google.alloydbomni_orchestrator.delete
    EOF
    
  2. أدرِج النُسخ الاحتياطية:
    ansible-playbook status.yaml -i deployment_spec.yaml -e resource_type=Backup
    
    تأكَّد من أنّ الناتج يعرض النسخة الاحتياطية s3-backup-1.
  3. احذف النسخة الاحتياطية من بيانات s3-backup-1 باتّباع الخطوات التالية:
    ansible-playbook delete.yaml -i deployment_spec.yaml \
        -e resource_type=Backup -e resource_name=s3-backup-1
    
  4. احذف خطة النسخ الاحتياطي باتّباع الخطوات التالية:
    ansible-playbook delete.yaml -i deployment_spec.yaml \
        -e resource_type=BackupPlan -e resource_name=s3-backup-plan
    
  5. احذف المجموعة وبيئة الحوسبة باستخدام خطوة تنظيف الموارد من الدرس التطبيقي حول الترميز نشر مجموعة AlloyDB Omni عالية التوفّر على أجهزة GCE الافتراضية باستخدام RPM Orchestrator. يقع خادم MinIO والنسخ الاحتياطية فيه على الجهاز الافتراضي للتحكّم. عند حذف بيئة الحوسبة، يتم حذف كل من الخادم والنُسخ الاحتياطية.

9. تهانينا

تهانينا احتفظت بنسخة احتياطية من مجموعة توفّر عالية (HA) في خدمة تخزين عناصر متوافقة مع S3 لـ AlloyDB Omni باستخدام أداة تنظيم RPM. بعد ذلك، استعدت المجموعة من النُسخ الاحتياطية.

المواضيع التي تناولناها

  • كيفية تثبيت MinIO وتشغيله كوحدة تخزين متوافقة مع S3
  • كيفية إنشاء خطة احتياطية ونسخة احتياطية عند الطلب
  • كيفية استعادة مجموعة من نسخة احتياطية وإلى نقطة زمنية

لمزيد من المعلومات، يُرجى الاطّلاع على الصفحات التالية:

10. استطلاع

كيف ستستخدم هذا البرنامج التعليمي؟

قراءة المحتوى فقط قراءة المحتوى وإكمال التمارين