Menentukan logika pencadangan dan pemulihan kustom


Saat Anda mengaktifkan agen Pencadangan untuk GKE di cluster Google Kubernetes Engine, Pencadangan untuk GKE akan menyediakan CustomResourceDefinition yang memperkenalkan jenis resource Kubernetes baru: ProtectedApplication.

Menulis ProtectedApplication melibatkan tiga aktivitas:

Resource ProtectedApplication memberi Anda kemampuan ini saat menyesuaikan logika pencadangan dan pemulihan di tingkat aplikasi:

  • Operasi pencadangan dan pemulihan terperinci. Tanpa ProtectedApplications, cakupan pencadangan Anda harus ditentukan di tingkat Namespace (baik dengan memilih allNamespaces atau selectedNamespaces). Logika serupa berlaku untuk pemulihan resource dengan namespace. Dengan membuat resource ProtectedApplication, Anda dapat memberikan nama ke subset resource dalam Namespace. Selanjutnya, Anda dapat mencadangkan dan memulihkan subset tersebut dengan mencantumkan SelectedApplications dalam cakupan pencadangan Anda (dan begitu pula, untuk pemulihan).

  • Orkestrasi detail terperinci tentang proses pencadangan atau pemulihan, termasuk:

    • Melewati volume yang dipilih selama pencadangan.

    • Menggabungkan topologi aplikasi ke dalam pencadangan dan pemulihan (misalnya, hanya mencadangkan satu instance database yang direplikasi dan menggunakannya untuk memulihkan beberapa instance).

    • Mengeksekusi hook yang ditentukan pengguna sebelum dan sesudah volume akan diambil snapshot-nya. Hal ini dapat digunakan, misalnya, untuk mengosongkan dan menjeda beban kerja sebelum mengambil snapshot dan membatalkan jeda setelahnya.

Anda membuat ProtectedApplication melalui kubectl seperti resource Kubernetes lainnya. Opsi ini sepenuhnya bersifat opsional. Jika resource ProtectedApplication tidak ada, Pencadangan untuk GKE akan membuat pencadangan volume untuk semua volume dalam cakupan pencadangan, dan pencadangan volume yang dihasilkan akan konsisten error - semua operasi tulis yang dikosongkan ke disk pada titik waktu tertentu akan diambil (artinya, tidak ada operasi tulis parsial). Namun, beberapa aplikasi dapat menyimpan data dalam memori yang tidak dikosongkan ke disk, sehingga berhasil atau tidaknya aplikasi dipulihkan dari cadangan yang konsisten error atau tidak, bergantung pada logika aplikasi.

Memilih resource

Langkah pertama dalam membangun resource ProtectedApplication adalah mengidentifikasi resource lain dalam Namespace yang sama yang ingin Anda sertakan sebagai bagian dari aplikasi. Ini adalah kumpulan resource yang akan dicadangkan atau dipulihkan jika Anda menyediakan opsi cakupan selectedApplications dalam konfigurasi BackupPlan.

Resource diidentifikasi menggunakan pemilih label. Hal ini mengharuskan Anda memberi label semua resource (menggunakan kolom metadata.label di setiap resource) dengan label yang sama. Perhatikan bahwa ini juga berlaku untuk resource yang dibuat otomatis oleh pengontrol. Resource yang dibuat otomatis ini diberi label menggunakan template yang sesuai. Perhatikan bahwa wajar-wajar saja untuk menggunakan kembali label yang sama yang sudah Anda gunakan untuk mengaitkan Pods dan PersistentVolumeClaims yang dihasilkan dengan resource induknya. Contoh berikut menunjukkan cara menerapkan label app: nginx ke resource lain selain Deployment.

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-vars
  namespace: webserver
  labels:
    app: nginx
  data:
    ...
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-logs
  namespace: webserver
  labels:
    app: nginx
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Mi
  storageClassName: standard-rwo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: webserver
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      volumes:
        - name: nginx-logs
          persistentVolumeClaim:
           claimName: nginx-logs
      containers:
      ...

Setelah label yang dipilih diterapkan ke semua resource target (dan template tempat resource tambahan sudah dihasilkan), Anda dapat merujuk resource tersebut dari ProtectedApplication. Contoh:

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1
metadata:
  name: nginx
  namespace: webserver
spec:
  resourceSelection:
    type: Selector
    selector:
      matchLabels:
        app: nginx
  ...

Menentukan aturan orkestrasi

Setelah semua resource dalam ProtectedApplication teridentifikasi, Anda dapat memilih untuk menentukan aturan orkestrasi mendetail untuk subset resource tersebut. Aturan ini hanya dapat berlaku untuk dua jenis resource: Deployment dan StatefulSets serta dirujuk di bagian components pada ProtectedApplication.

Ringkasan komponen

Mengonfigurasi komponen melibatkan langkah berikut:

  • Memilih strategi dasar terkait cara kerja pencadangan dan pemulihan untuk komponen ini. Ada tiga strategi yang tersedia:

    • BackupAllRestoreAll - mencadangkan volume yang terkait dengan semua instance komponen dan memulihkan semuanya dari cadangan.

    • BackupOneRestoreAll - mencadangkan volume hanya dari satu instance komponen dan menggunakan cadangan tersebut untuk memulihkan semua instance.

    • DumpAndLoad - mengekspor data dari aplikasi ke satu volume pada waktu pencadangan dan mengimpor data tersebut ke dalam aplikasi pada waktu pemulihan.

  • Menentukan hook eksekusi yang akan dijalankan selama pencadangan (dan mungkin pemulihan, bergantung pada strateginya). Hook adalah perintah yang dieksekusi dalam container tertentu.

  • Memilih subset volume yang akan dicadangkan.

Hook eksekusi

Hook adalah perintah shell yang dieksekusi Pencadangan untuk GKE dalam container pada fase tertentu dari proses pencadangan atau pemulihan.

Ada empat jenis hook yang berbeda:

  • pre hooks - perintah ini dieksekusi tepat sebelum volume dicadangkan dan umumnya diharapkan untuk mengosongkan data yang saat ini ada dalam memori ke disk, lalu menjeda aplikasi sehingga tidak ada operasi tulis disk baru yang terjadi. Hook ini digunakan dalam strategi BackupAllRestoreAll dan BackupOneRestoreAll.

  • post hooks - perintah ini dieksekusi selama proses pencadangan volume tepat setelah langkah SNAPSHOT dalam proses pencadangan volume (sebelum langkah UPLOAD). Umumnya, langkah SNAPSHOT hanya memerlukan waktu beberapa detik. Proses ini umumnya diharapkan untuk membatalkan jeda aplikasi (misalnya, mengizinkan pemrosesan normal dan penulisan disk untuk dilanjutkan). Hook ini digunakan dalam strategi BackupAllRestoreAll, BackupOneRestoreAll, dan DumpAndLoad.

  • dump hooks - perintah ini dieksekusi sebelum volume dicadangkan dalam strategi DumpAndLoad dan umumnya diharapkan untuk mengekspor data dari aplikasi ke volume cadangan yang ditentukan.

  • load hooks - perintah ini dieksekusi pada waktu pemulihan setelah volume cadangan dipulihkan dalam kasus strategi DumpAndLoad. Perintah ini umumnya diharapkan untuk mengimpor data dari volume cadangan ke aplikasi.

Anda dapat menyediakan lebih dari satu hook untuk setiap jenis, dan Pencadangan untuk GKE akan mengeksekusinya sesuai urutan Anda menentukannya.

Anda menentukan hook sebagai bagian dari bagian komponen spesifikasi ProtectedApplication. Semua definisi hook memiliki kolom yang teredia yang sama:

  • name - nama yang Anda tetapkan ke hook.

  • container - (opsional) nama penampung untuk menjalankan perintah di dalamnya. Jika Anda tidak menyediakan penampung, Pencadangan untuk GKE akan menjalankan hook di penampung pertama yang ditentukan untuk Pod target.

  • command - ini adalah perintah aktual yang dikirimkan ke container, yang disusun sebagai array kata. Kata pertama dalam array adalah jalur ke perintah dan kata-kata berikutnya adalah argumen yang akan diteruskan ke perintah.

  • timeoutSeconds - (opsional) waktu sebelum eksekusi hook dibatalkan. Jika tidak ditentukan, durasi defaultnya adalah 30 detik.

  • onError - (opsional) perilaku yang dilakukan saat hook gagal. Dapat ditetapkan ke Ignore atau Fail (default). Jika Anda menyetelnya ke Fail, saat hook gagal, pencadangan volume akan gagal. Jika menyetelnya ke Ignore, kegagalan hook ini akan diabaikan.

Sebelum menerapkan hook ProtectedApplication ke aplikasi, Anda harus menguji perintah tersebut dengan menggunakan kubectl exec untuk memastikan bahwa hook tersebut berperilaku seperti yang diharapkan:

kubectl exec POD_NAME -- COMMAND

Ganti yang berikut ini:

  • POD_NAME: nama Pod yang berisi resource ProtectedApplication.
  • COMMAND: array yang berisi perintah yang ingin Anda jalankan dalam container, misalnya /sbin/fsfreeze, -f, /var/log/nginx.

Memilih subset volume yang akan dicadangkan

Terkadang, aplikasi menulis ke volume yang tidak menarik untuk dipulihkan (misalnya, volume scratch atau log tertentu). Anda dapat menyembunyikan pencadangan volume ini dengan menggunakan pemilih volume.

Untuk menggunakan fitur ini, Anda harus terlebih dahulu menerapkan label umum ke volume yang ingin dicadangkan, lalu membiarkan label ini menonaktifkan volume yang tidak ingin dicadangkan. Kemudian, Anda menyertakan klausa volumeSelector dalam definisi komponen sebagai berikut:

spec:
  ...
  components:
  ...
    strategy:
      ...
      volumeSelector:
        matchLabels:
          label_name: label_value

Jika Anda menyediakan volumeSelector untuk komponen, hanya volume yang memiliki label tertentu yang akan dicadangkan dan dipulihkan. Pada waktu pemulihan, volume lain akan disediakan sebagai kosong alih-alih dipulihkan dari cadangan volume.

Strategi: BackupAllRestoreAll

Ini adalah strategi paling sederhana dan mencadangkan semua volume komponen pada waktu pencadangan dan memulihkan semuanya dari cadangan volumenya pada waktu pemulihan. Ini adalah pilihan terbaik jika aplikasi Anda tidak memiliki replikasi di antara Pods.

Strategi ini mendukung parameter berikut:

  • backupPreHooks - (opsional) daftar yang diurutkan untuk hook yang dieksekusi tepat sebelum volume dicadangkan. Perintah ini dieksekusi di semua Pods dalam komponen.

  • backupPostHooks - (opsional) daftar yang diurutkan untuk hook yang dieksekusi setelah pencadangan volume mencapai fase UPLOAD. Perintah ini dieksekusi di semua Pods dalam komponen.

  • volumeSelector - (opsional) logika untuk mencocokkan subset volume ke cadangan.

Contoh ini membuat resource ProtectedApplication yang menjeda sistem file sebelum mencadangkan volume log dan membatalkan jeda setelah pencadangan:

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1
metadata:
  name: nginx
  namespace: sales
spec:
  resourceSelection:
    type: Selector
    selector:
      matchLabels:
        app: nginx
  components:
  - name: nginx-app
    resourceKind: Deployment
    resourceNames: ["nginx"]
    strategy:
      type: BackupAllRestoreAll
      backupAllRestoreAll:
        backupPreHooks:
        - name: fsfreeze
          container: nginx
          command: [ /sbin/fsfreeze, -f, /var/log/nginx ]
        backupPostHooks:
        - name: fsunfreeze
          container: nginx
          command: [ /sbin/fsfreeze, -u, /var/log/nginx ]

Strategi: BackupOneAndRestoreAll

Strategi ini mencadangkan satu salinan Pod yang dipilih. Satu salinan ini adalah sumber untuk memulihkan semua Pod selama pemulihan. Metode ini dapat membantu mengurangi biaya penyimpanan dan waktu pencadangan. Strategi ini berfungsi di konfigurasi ketersediaan tinggi saat komponen di-deploy dengan satu PersistentVolumeClaim utama dan beberapa PersistentVolumeClaims sekunder.

Strategi ini mendukung parameter berikut:

  • backupTargetName - (wajib) menentukan Deployment atau StatefulSet yang ingin Anda gunakan untuk mencadangkan data. Pod terbaik untuk dicadangkan akan otomatis dipilih. Dalam konfigurasi ketersediaan tinggi, sebaiknya tetapkan ini ke salah satu replika aplikasi Anda.

  • backupPreHooks - (opsional) daftar yang diurutkan untuk hook yang dieksekusi tepat sebelum volume dicadangkan. Perintah ini hanya dieksekusi di Pod cadangan yang dipilih.

  • backupPostHooks - (opsional) daftar yang diurutkan untuk hook yang dieksekusi setelah pencadangan volume mencapai fase UPLOAD. Perintah ini hanya dieksekusi di Pod cadangan yang dipilih.

  • volumeSelector - (opsional) logika untuk mencocokkan subset volume ke cadangan.

Jika komponen dikonfigurasi dengan beberapa Deployment atau StatefulSets, semua resource harus memiliki struktur PersistentVolume yang sama, yang berarti komponen tersebut harus mengikuti aturan berikut:

  • Jumlah PersistentVolumeClaims yang digunakan oleh semua Deployment atau StatefulSet harus sama.
  • Tujuan PersistentVolumeClaims dalam indeks yang sama harus sama. Untuk StatefulSets, indeks ditentukan dalam volumeClaimTemplate. Untuk Deployment, indeks ditentukan dalam Volumes dan volume yang tidak persisten akan dilewati.
  • Jika komponen aplikasi terdiri dari Deployment, setiap Deployment harus memiliki tepat satu replika.

Dengan pertimbangan ini, beberapa kumpulan volume dapat dipilih untuk pencadangan, tetapi hanya satu volume dari setiap kumpulan volume yang akan dipilih.

Contoh ini, dengan asumsi arsitektur satu StatefulSet utama dan StatefulSet sekunder, akan menampilkan cadangan volume satu Pod di StatefulSet sekunder, lalu pemulihan ke semua volume lainnya:

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1
metadata:
  name: mariadb
  namespace: mariadb
spec:
  resourceSelection:
    type: Selector
    selector:
      matchLabels:
        app: mariadb
  components:
  - name: mariadb
    resourceKind: StatefulSet
    resourceNames: ["mariadb-primary", "mariadb-secondary"]
    strategy:
      type: BackupOneRestoreAll
      backupOneRestoreAll:
        backupTargetName: mariadb-secondary
        backupPreHooks:
        - name: quiesce
          container: mariadb
          command: [...]
        backupPostHooks:
        - name: unquiesce
          container: mariadb
          command: [...]

Strategi: DumpAndLoad

Strategi ini menggunakan volume khusus untuk proses pencadangan dan pemulihan serta mewajibkan PersistentVolumeClaim khusus yang terpasang ke komponen yang menyimpan data dump.

Strategi ini mendukung parameter berikut:

  • dumpTarget - (wajib) menentukan Deployment atau StatefulSet yang ingin Anda gunakan untuk mencadangkan data. Pod terbaik untuk dicadangkan akan otomatis dipilih. Dalam konfigurasi ketersediaan tinggi, sebaiknya tetapkan ini ke salah satu replika aplikasi Anda.

  • loadTarget - (wajib) menentukan Deployment atau StatefulSet yang harus digunakan untuk memuat data. Pod terbaik untuk dicadangkan akan otomatis dipilih. Target pemuatan tidak harus sama dengan target dump.

  • dumpHooks - (wajib) daftar yang diurutkan untuk hook yang dieksekusi untuk mengisi volume cadangan khusus. Perintah ini hanya dieksekusi pada Pod dump yang dipilih.

  • backupPostHooks - (opsional) daftar yang diurutkan untuk hook yang dieksekusi setelah pencadangan volume mencapai fase UPLOAD. Perintah ini hanya dieksekusi pada Pod dump yang dipilih.

  • loadHooks - (wajib) daftar yang diurutkan untuk hook yang dieksekusi untuk memuat data dari volume yang dipulihkan setelah aplikasi dimulai. Perintah ini hanya dieksekusi pada Pod pemuatan yang dipilih.

  • volumeSelector - (wajib) logika untuk mencocokkan volume tunggal ke pencadangan dan pemulihan (volume "dump"). Meskipun hanya boleh cocok dengan satu volume, Anda mengonfigurasi ini dengan cara yang sama seperti saat menangani subset volume ke cadangan yang digunakan oleh strategi lain.

Jika aplikasi terdiri dari Deployment, setiap Deployment harus memiliki tepat satu replika.

Contoh ini, dengan asumsi arsitektur satu StatefulSet utama dan StatefulSet sekunder dengan PersistentVolumeClaims khusus untuk StatefulSets utama dan sekunder, akan menampilkan strategi DumpAndLoad:

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1
metadata:
  name: mariadb
  namespace: mariadb
spec:
  resourceSelection:
    type: Selector
    selector:
      matchLabels:
        app: mariadb
  components:
  - name: mariadb-dump
    resourceKind: StatefulSet
    resourceNames: ["mariadb-primary", "mariadb-secondary"]
    strategy:
      type: DumpAndLoad
      dumpAndLoad:
        loadTarget: mariadb-primary
        dumpTarget: mariadb-secondary
        dumpHooks:
        - name: db_dump
          container: mariadb
          command:
          - bash
          - "-c"
          - |
            mysqldump -u root --all-databases > /backup/mysql_backup.dump
        loadHooks:
        - name: db_load
          container: mariadb
          command:
          - bash
          - "-c"
          - |
            mysql -u root < /backup/mysql_backup.sql
        volumeSelector:
          matchLabels:
            gkebackup.gke.io/backup: dedicated-volume

Memeriksa apakah ProtectedApplication siap untuk pencadangan

Anda dapat memeriksa apakah ProtectedApplication siap untuk pencadangan dengan menjalankan perintah berikut:

kubectl describe protectedapplication APPLICATION_NAME

Ganti APPLICATION_NAME dengan nama database Anda.

Jika siap, deskripsi aplikasi akan menampilkan status Ready to backup sebagai true, seperti dalam contoh ini:

% kubectl describe protectedapplication nginx
Name:         nginx
Namespace:    default
API Version:  gkebackup.gke.io/v1
Kind:         ProtectedApplication
Metadata:
  UID:               90c04a86-9dcd-48f2-abbf-5d84f979b2c2
Spec:
  Components:
    Name:           nginx
    Resource Kind:  Deployment
    Resource Names:
      nginx
    Strategy:
      Backup All Restore All:
        Backup Pre Hooks:
          Command:
             /sbin/fsfreeze
             -f
             /var/log/nginx
          Container:         nginx
          Name:              freeze
        Backup Post Hooks:
          Command:
             /sbin/fsfreeze
             -u
             /var/log/nginx
          Container:         nginx
          Name:              unfreeze
      Type:                  BackupAllRestoreAll
  Resource Selection:
    Selector:
      Match Labels:
        app:        nginx
    Type:           Selector
 Status:
  Ready To Backup:  true 
Events:             <none>

Langkah berikutnya