{"id":508788,"date":"2022-11-11T04:48:03","date_gmt":"2022-11-11T01:48:03","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-backup-kubernetes-mysql-operator-clusters\/"},"modified":"2022-11-11T04:48:03","modified_gmt":"2022-11-11T01:48:03","slug":"how-to-backup-kubernetes-mysql-operator-clusters","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/","title":{"rendered":"#How to Backup Kubernetes MySQL Operator Clusters"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a3d8316dc910\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a3d8316dc910\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#%E2%80%9CHow_to_Backup_Kubernetes_MySQL_Operator_Clusters%E2%80%9D\" >&#8220;How to Backup Kubernetes MySQL Operator Clusters&#8221;<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#Preparing_a_Database_Cluster\" >Preparing a Database Cluster<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#Defining_a_Backup_Schedule\" >Defining a Backup Schedule<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#Creating_Backup_Profiles\" >Creating Backup Profiles<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#S3_Storage\" >S3 Storage<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#OCI_Storage\" >OCI Storage<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#Kubernetes_Volume_Storage\" >Kubernetes Volume Storage<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#Setting_Backup_Options\" >Setting Backup Options<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#Restoring_a_Backup\" >Restoring a Backup<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-backup-kubernetes-mysql-operator-clusters\/#Summary\" >Summary<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h1><span class=\"ez-toc-section\" id=\"%E2%80%9CHow_to_Backup_Kubernetes_MySQL_Operator_Clusters%E2%80%9D\"><\/span>&#8220;How to Backup Kubernetes MySQL Operator Clusters&#8221;<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<div>\n<!-- UNCACHED CONTENT --><br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage alignnone size-full wp-image-817757\" data-pagespeed-no-defer=\"\" src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/07\/MySQL.jpg?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Graphic showing the MySQL logo\" width=\"1202\" height=\"677\"\/><\/p>\n<p>Oracle\u2019s <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/mysql\/mysql-operator\">MySQL Operator<\/a> for Kubernetes is a convenient way to automate MySQL database provisioning within your cluster. One of the operator\u2019s headline features is integrated hands-off backup support that increases your resiliency. Backups copy your database to external storage on a recurring schedule.<\/p>\n<p>This article will walk you through setting up backups to an Amazon S3-compatible object storage service. You\u2019ll also see how to store backups in Oracle Cloud Infrastructure (OCI) storage or local persistent volumes inside your cluster.<\/p>\n<h2 id=\"preparing-a-database-cluster\"><span class=\"ez-toc-section\" id=\"Preparing_a_Database_Cluster\"><\/span>Preparing a Database Cluster<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Install the MySQL operator in your Kubernetes cluster and create a simple database instance for testing purposes. Copy the YAML below and save it to <code>mysql.yaml<\/code>:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>v1<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>Secret<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-root-user<strong class=\"co4\">\nstringData<\/strong>:<strong class=\"co3\">\n  rootHost<\/strong><strong class=\"sy2\">: <\/strong><strong class=\"st0\">\"%\"<\/strong><strong class=\"co3\">\n  rootUser<\/strong><strong class=\"sy2\">: <\/strong><strong class=\"st0\">\"root\"<\/strong><strong class=\"co3\">\n  rootPassword<\/strong><strong class=\"sy2\">: <\/strong><strong class=\"st0\">\"P@$$w0rd\"<\/strong>\n\u00a0\n<strong class=\"sy1\">---<\/strong>\n<strong class=\"co3\">\napiVersion<\/strong><strong class=\"sy2\">: <\/strong>mysql.oracle.com\/v2<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>InnoDBCluster<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-cluster<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  secretName<\/strong><strong class=\"sy2\">: <\/strong>mysql-root-user<strong class=\"co3\">\n  instances<\/strong><strong class=\"sy2\">: <\/strong>3<strong class=\"co3\">\n  tlsUseSelfSigned<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co4\">\n  router<\/strong>:<strong class=\"co3\">\n    instances<\/strong><strong class=\"sy2\">: <\/strong>1<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Use Kubectl to <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a>ly the manifest:<\/p>\n<pre>$ kubectl apply -f mysql.yaml<\/pre>\n<p>Wait a few minutes while the MySQL operator provisions your Pods. Use Kubectl\u2019s <code>get pods<\/code> command to check on the progress. You should see four running Pods: one MySQL router instance and three MySQL server replicas.<\/p>\n<pre>$ kubectl get pods&#13;\nNAME                                    READY   STATUS    RESTARTS   AGE&#13;\nmysql-cluster-0                         2\/2     Running   0          2m&#13;\nmysql-cluster-1                         2\/2     Running   0          2m&#13;\nmysql-cluster-2                         2\/2     Running   0          2m&#13;\nmysql-cluster-router-6b68f9b5cb-wbqm5   1\/1     Running   0          2m<\/pre>\n<h2 id=\"defining-a-backup-schedule\"><span class=\"ez-toc-section\" id=\"Defining_a_Backup_Schedule\"><\/span>Defining a Backup Schedule<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The MySQL operator requires two components to successfully create a backup:<\/p>\n<ul>\n<li>A <strong>backup schedule<\/strong> which defines when the backup will run.<\/li>\n<li>A <strong>backup profile<\/strong> which configures the storage location and MySQL export options.<\/li>\n<\/ul>\n<p>Schedules and profiles <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/dev.mysql.com\/doc\/mysql-operator\/en\/mysql-operator-backups.html\">are created independently<\/a> of each other. This lets you run multiple backups on different schedules using the same profile.<\/p>\n<p>Each schedule and profile is associated with a specific database cluster. They\u2019re created as nested resources within your <code>InnoDBCluster<\/code> objects. Each database you create with the MySQL operator needs its own backup configuration.<\/p>\n<p>Backup schedules are defined by your database\u2019s <code>spec.backupSchedules<\/code> field. Each item requires a <code>schedule<\/code> field that specifies when to run the backup using a cron expression. Here\u2019s an example that starts a backup every hour:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>mysql.oracle.com\/v2<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>InnoDBCluster<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-cluster<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  secretName<\/strong><strong class=\"sy2\">: <\/strong>mysql-root-user<strong class=\"co3\">\n  instances<\/strong><strong class=\"sy2\">: <\/strong>3<strong class=\"co3\">\n  tlsUseSelfSigned<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co4\">\n  router<\/strong>:<strong class=\"co3\">\n    instances<\/strong><strong class=\"sy2\">: <\/strong>1<strong class=\"co4\">\n   backupSchedules<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly<strong class=\"co3\">\n      enabled<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co3\">\n      schedule<\/strong><strong class=\"sy2\">: <\/strong><strong class=\"st0\">\"0 * * * *\"<\/strong><strong class=\"co3\">\n      backupProfileName<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>The <code>backupProfileName<\/code> field references the backup profile to use. You\u2019ll create this in the next step.<\/p>\n<h2 id=\"creating-backup-profiles\"><span class=\"ez-toc-section\" id=\"Creating_Backup_Profiles\"><\/span>Creating Backup Profiles<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Profiles are defined in the <code>spec.backupProfiles<\/code> field. Each profile should have a <code>name<\/code> and a <code>dumpInstance<\/code> property that configures the backup operation.<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>mysql.oracle.com\/v2<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>InnoDBCluster<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-cluster<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  secretName<\/strong><strong class=\"sy2\">: <\/strong>mysql-root-user<strong class=\"co3\">\n  instances<\/strong><strong class=\"sy2\">: <\/strong>3<strong class=\"co3\">\n  tlsUseSelfSigned<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co4\">\n  router<\/strong>:<strong class=\"co3\">\n    instances<\/strong><strong class=\"sy2\">: <\/strong>1<strong class=\"co4\">\n  backupSchedules<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly<strong class=\"co3\">\n      enabled<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co3\">\n      schedule<\/strong><strong class=\"sy2\">: <\/strong><strong class=\"st0\">\"0 * * * *\"<\/strong><strong class=\"co3\">\n      backupProfileName<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n  backupProfiles<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n      dumpInstance<\/strong>:<strong class=\"co4\">\n        storage<\/strong><strong class=\"sy2\">:\n<\/strong>          <strong class=\"co1\"># ...<\/strong><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Backup storage is configured on a per-profile basis in the <code>dumpInstance.storage<\/code> field. The properties you need to supply depend on the type of storage you\u2019re using.<\/p>\n<h3 id=\"s3-storage\"><span class=\"ez-toc-section\" id=\"S3_Storage\"><\/span>S3 Storage<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The MySQL operator can upload your backups straight to S3-compatible object storage providers. To use this method, you must create a Kubernetes secret that contains an <code>aws<\/code> CLI config file with your credentials.<\/p>\n<p>Add the following content to <code>s3-secret.yaml<\/code>:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>v1<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>Secret<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>s3-secret<strong class=\"co4\">\nstringData<\/strong>:<strong class=\"co3\">\n  credentials<\/strong><strong class=\"sy2\">: |\n<\/strong><strong class=\"co0\">    [default]\n    aws_access_key_id = YOUR_S3_ACCESS_KEY\n    aws_secret_access_key = YOUR_S3_SECRET_KEY<\/strong><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Substitute in your own S3 access and secret keys, then use Kubectl to create the secret:<\/p>\n<pre>$ kubectl apply -f s3-secret.yaml&#13;\nsecret\/s3-secret created<\/pre>\n<p>Next add the following fields to your backup profile\u2019s <code>storage.s3<\/code> section:<\/p>\n<ul>\n<li><strong><code>bucketName<\/code><\/strong> \u2013 The name of the S3 bucket to upload your backups to.<\/li>\n<li><strong><code>prefix<\/code><\/strong> \u2013 Set this to apply a prefix to your uploaded files, such as <code>\/my-app\/mysql<\/code>. The prefix allows you to create folder trees within your bucket.<\/li>\n<li><strong><code>endpoint<\/code><\/strong> \u2013 Set this to your service provider\u2019s URL when you\u2019re using third-party S3-compatible storage. You can omit this field if you\u2019re using Amazon S3.<\/li>\n<li><strong><code>config<\/code><\/strong> \u2013 The name of the secret containing your credentials file.<\/li>\n<li><strong><code>profile<\/code><\/strong> \u2013 The name of the config profile to use within the credentials file. This was set to <code>default<\/code> in the example above.<\/li>\n<\/ul>\n<p>Here\u2019s a complete example:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>mysql.oracle.com\/v2<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>InnoDBCluster<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-cluster<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  secretName<\/strong><strong class=\"sy2\">: <\/strong>mysql-root-user<strong class=\"co3\">\n  instances<\/strong><strong class=\"sy2\">: <\/strong>3<strong class=\"co3\">\n  tlsUseSelfSigned<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co4\">\n  router<\/strong>:<strong class=\"co3\">\n    instances<\/strong><strong class=\"sy2\">: <\/strong>1<strong class=\"co4\">\n  backupSchedules<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly<strong class=\"co3\">\n      enabled<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co3\">\n      schedule<\/strong><strong class=\"sy2\">: <\/strong><strong class=\"st0\">\"0 * * * *\"<\/strong><strong class=\"co3\">\n      backupProfileName<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n  backupProfiles<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n      dumpInstance<\/strong>:<strong class=\"co4\">\n        storage<\/strong>:<strong class=\"co4\">\n          s3<\/strong>:<strong class=\"co3\">\n            bucketName<\/strong><strong class=\"sy2\">: <\/strong>backups<strong class=\"co3\">\n            prefix<\/strong><strong class=\"sy2\">: <\/strong>\/mysql<strong class=\"co3\">\n            config<\/strong><strong class=\"sy2\">: <\/strong>s3-secret<strong class=\"co3\">\n            profile<\/strong><strong class=\"sy2\">: <\/strong>default<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Applying this manifest will activate hourly database backups to your S3 account.<\/p>\n<h3 id=\"oci-storage\"><span class=\"ez-toc-section\" id=\"OCI_Storage\"><\/span>OCI Storage<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The operator supports Oracle Cloud Infrastructure (OCI) object storage as an alternative to S3. It\u2019s configured in a similar way. First create a secret for your OCI credentials:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>v1<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>Secret<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>oci-secret<strong class=\"co4\">\nstringData<\/strong>:<strong class=\"co3\">\n  fingerprint<\/strong><strong class=\"sy2\">: <\/strong>YOUR_OCI_FINGERPRINT<strong class=\"co3\">\n  passphrase<\/strong><strong class=\"sy2\">: <\/strong>YOUR_OCI_PASSPHRASE<strong class=\"co3\">\n  privatekey<\/strong><strong class=\"sy2\">: <\/strong>YOUR_OCI_RSA_PRIVATE_KEY<strong class=\"co3\">\n  region<\/strong><strong class=\"sy2\">: <\/strong>us-ashburn-1<strong class=\"co3\">\n  tenancy<\/strong><strong class=\"sy2\">: <\/strong>YOUR_OCI_TENANCY<strong class=\"co3\">\n  user<\/strong><strong class=\"sy2\">: <\/strong>YOUR_OCI_USER<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Next configure the backup profile with a <code>storage.ociObjectStorage<\/code> stanza:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>mysql.oracle.com\/v2<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>InnoDBCluster<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-cluster<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  secretName<\/strong><strong class=\"sy2\">: <\/strong>mysql-root-user<strong class=\"co3\">\n  instances<\/strong><strong class=\"sy2\">: <\/strong>3<strong class=\"co3\">\n  tlsUseSelfSigned<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co4\">\n  router<\/strong>:<strong class=\"co3\">\n    instances<\/strong><strong class=\"sy2\">: <\/strong>1<strong class=\"co4\">\n  backupSchedules<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly<strong class=\"co3\">\n      enabled<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co3\">\n      schedule<\/strong><strong class=\"sy2\">: <\/strong><strong class=\"st0\">\"0 * * * *\"<\/strong><strong class=\"co3\">\n      backupProfileName<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n  backupProfiles<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n      dumpInstance<\/strong>:<strong class=\"co4\">\n        storage<\/strong>:<strong class=\"co4\">\n          ociObjectStorage<\/strong>:<strong class=\"co3\">\n            bucketName<\/strong><strong class=\"sy2\">: <\/strong>backups<strong class=\"co3\">\n            prefix<\/strong><strong class=\"sy2\">: <\/strong>\/mysql<strong class=\"co3\">\n            credentials<\/strong><strong class=\"sy2\">: <\/strong>oci-secret<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Modify the <code>bucketName<\/code> and <code>prefix<\/code> fields to set the upload location in your OCI account. The <code>credentials<\/code> field must reference the secret that contains your OCI credentials.<\/p>\n<h3 id=\"kubernetes-volume-storage\"><span class=\"ez-toc-section\" id=\"Kubernetes_Volume_Storage\"><\/span>Kubernetes Volume Storage<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Local persistent volumes are a third storage option. This is less robust as your backup data will still reside inside your Kubernetes cluster. However it can be useful for one-off backups and testing purposes.<\/p>\n<p>First create a persistent volume and accompanying claim:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>v1<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>PersistentVolume<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>backup-pv<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  storageClassName<\/strong><strong class=\"sy2\">: <\/strong>standard<strong class=\"co4\">\n  capacity<\/strong>:<strong class=\"co3\">\n    storage<\/strong><strong class=\"sy2\">: <\/strong>10Gi<strong class=\"co4\">\n  accessModes<\/strong><strong class=\"sy2\">:\n<\/strong>    - ReadWriteOnce<strong class=\"co4\">\n  hostPath<\/strong>:<strong class=\"co3\">\n    path<\/strong><strong class=\"sy2\">: <\/strong>\/tmp\n\u00a0\n<strong class=\"sy1\">---<\/strong>\n<strong class=\"co3\">\napiVersion<\/strong><strong class=\"sy2\">: <\/strong>v1<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>PersistentVolumeClaim<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>backup-pvc<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  storageClassName<\/strong><strong class=\"sy2\">: <\/strong>standard<strong class=\"co4\">\n  accessModes<\/strong><strong class=\"sy2\">:\n<\/strong>    - ReadWriteOnce<strong class=\"co4\">\n  resources<\/strong>:<strong class=\"co4\">\n    requests<\/strong>:<strong class=\"co3\">\n      storage<\/strong><strong class=\"sy2\">: <\/strong>10Gi<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>This example manifest is not suitable for production use. You should select an appropriate <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/storage-classes\">storage class<\/a> and volume mounting mode for your Kubernetes distribution.<\/p>\n<p>Next configure your backup profile to use your persistent volume by adding a <code>storage.persistentVolumeClaim<\/code> field:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>mysql.oracle.com\/v2<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>InnoDBCluster<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-cluster<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  secretName<\/strong><strong class=\"sy2\">: <\/strong>mysql-root-user<strong class=\"co3\">\n  instances<\/strong><strong class=\"sy2\">: <\/strong>3<strong class=\"co3\">\n  tlsUseSelfSigned<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co4\">\n  router<\/strong>:<strong class=\"co3\">\n    instances<\/strong><strong class=\"sy2\">: <\/strong>1<strong class=\"co4\">\n  backupSchedules<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly<strong class=\"co3\">\n      enabled<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co3\">\n      schedule<\/strong><strong class=\"sy2\">: <\/strong><strong class=\"st0\">\"0 * * * *\"<\/strong><strong class=\"co3\">\n      backupProfileName<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n  backupProfiles<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n      dumpInstance<\/strong>:<strong class=\"co4\">\n        storage<\/strong>:<strong class=\"co4\">\n          persistentVolumeClaim<\/strong>:<strong class=\"co3\">\n            claimName<\/strong><strong class=\"sy2\">: <\/strong>backup-pvc<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>The persistent volume claim created earlier is referenced by the <code>claimName<\/code> field. The MySQL operator will now deposit backup data into the volume.<\/p>\n<h2 id=\"setting-backup-options\"><span class=\"ez-toc-section\" id=\"Setting_Backup_Options\"><\/span>Setting Backup Options<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Backups are created using the MySQL Shell\u2019s <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/dev.mysql.com\/doc\/mysql-shell\/8.0\/en\/mysql-shell-utilities-dump-instance-schema.html\"><code>dumpInstance<\/code> utility<\/a>. This defaults to exporting a complete dump of your server. The format writes structure and chunked data files for each table. The output is compressed with zstd.<\/p>\n<p>You can pass options through to <code>dumpInstance<\/code> via the <code>dumpOptions<\/code> field in a MySQL operator backup profile:<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>mysql.oracle.com\/v2<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>InnoDBCluster<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-cluster<strong class=\"co4\">\nspec<\/strong><strong class=\"sy2\">:\n<\/strong>  <strong class=\"co1\"># ...<\/strong><strong class=\"co4\">\n  backupProfiles<\/strong>:<strong class=\"co3\">\n    - name<\/strong><strong class=\"sy2\">: <\/strong>hourly-backup<strong class=\"co4\">\n      dumpInstance<\/strong>:<strong class=\"co4\">\n        dumpOptions<\/strong>:<strong class=\"co3\">\n          chunking<\/strong><strong class=\"sy2\">: <\/strong>false<strong class=\"co3\">\n          compression<\/strong><strong class=\"sy2\">: <\/strong>gzip<strong class=\"co4\">\n        storage<\/strong><strong class=\"sy2\">:\n<\/strong>          <strong class=\"co1\"># ...<\/strong><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>This example disables chunked output, creating one data file per table, and switches to gzip compression instead of zstd. You can find a complete reference for available options in <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/dev.mysql.com\/doc\/mysql-shell\/8.0\/en\/mysql-shell-utilities-dump-instance-schema.html\">the MySQL documentation<\/a>.<\/p>\n<h2 id=\"restoring-a-backup\"><span class=\"ez-toc-section\" id=\"Restoring_a_Backup\"><\/span>Restoring a Backup<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The MySQL operator can initialize new database clusters using previously created files from <code>dumpInstance<\/code>. This allows you to restore your backups straight into your Kubernetes cluster. It\u2019s useful in recovery situations or when you\u2019re migrating an existing database to Kubernetes.<\/p>\n<p>Database initialization is controlled by the <code>spec.initDB<\/code> field on your <code>InnoDBCluster<\/code> objects. Within this stanza, use the <code>dump.storage<\/code> object to reference the backup location you used earlier. The format matches the equivalent <code>dumpInstance.storage<\/code> field in backup profile objects.<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"yaml\">\n<pre class=\"de1\"><strong class=\"co3\">apiVersion<\/strong><strong class=\"sy2\">: <\/strong>v1<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>Secret<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>s3-secret<strong class=\"co4\">\nstringData<\/strong>:<strong class=\"co3\">\n  credentials<\/strong><strong class=\"sy2\">: |\n<\/strong><strong class=\"co0\">    [default]\n    aws_access_key_id = YOUR_S3_ACCESS_KEY\n    aws_secret_access_key = YOUR_S3_SECRET_KEY\n<\/strong>\n<strong class=\"sy1\">---<\/strong>\n<strong class=\"co3\">\napiVersion<\/strong><strong class=\"sy2\">: <\/strong>mysql.oracle.com\/v2<strong class=\"co3\">\nkind<\/strong><strong class=\"sy2\">: <\/strong>InnoDBCluster<strong class=\"co4\">\nmetadata<\/strong>:<strong class=\"co3\">\n  name<\/strong><strong class=\"sy2\">: <\/strong>mysql-cluster-recovered<strong class=\"co4\">\nspec<\/strong>:<strong class=\"co3\">\n  secretName<\/strong><strong class=\"sy2\">: <\/strong>mysql-root-user<strong class=\"co3\">\n  instances<\/strong><strong class=\"sy2\">: <\/strong>3<strong class=\"co3\">\n  tlsUseSelfSigned<\/strong><strong class=\"sy2\">: <\/strong>true<strong class=\"co4\">\n  router<\/strong>:<strong class=\"co3\">\n    instances<\/strong><strong class=\"sy2\">: <\/strong>1<strong class=\"co4\">\n  initDB<\/strong>:<strong class=\"co4\">\n    dump<\/strong>:<strong class=\"co4\">\n      storage<\/strong>:<strong class=\"co4\">\n        s3<\/strong>:<strong class=\"co3\">\n          bucketName<\/strong><strong class=\"sy2\">: <\/strong>backups<strong class=\"co3\">\n          prefix<\/strong><strong class=\"sy2\">: <\/strong>\/mysql\/mysql20221031220000<strong class=\"co3\">\n          config<\/strong><strong class=\"sy2\">: <\/strong>s3-secret<strong class=\"co3\">\n          profile<\/strong><strong class=\"sy2\">: <\/strong>default<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Applying this YAML file will create a new database cluster that\u2019s initialized with the <code>dumpInstance<\/code> output in the specified S3 bucket. The <code>prefix<\/code> field must contain the full path to the dump files within the bucket. Backups created by the operator will automatically be stored in timestamped folders; you\u2019ll need to indicate which one to recover by setting the prefix. If you\u2019re restoring from a persistent volume, use the <code>path<\/code> field instead of <code>prefix<\/code>.<\/p>\n<h2 id=\"summary\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Oracle\u2019s MySQL operator automates MySQL database management within Kubernetes clusters. In this article you\u2019ve learned how to configure the operator\u2019s backup system to store complete database dumps in a persistent volume or object storage bucket.<\/p>\n<p>Using Kubernetes to horizontally scale MySQL adds resiliency, but external backups are still vital in case your cluster\u2019s compromised or data is accidentally deleted. The MySQL operator <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/dev.mysql.com\/doc\/mysql-operator\/en\/mysql-operator-properties.html#mysql-operator-spec-innodbclusterspecinitdb\">can restore a new database instance<\/a> from your backup if you ever need to, simplifying the post-disaster recovery procedure.<\/p>\n<\/div>\n<p><script>\n setTimeout(function(){\n  !function(f,b,e,v,n,t,s)\n  {if(f.fbq)return;n=f.fbq=function(){n.callMethod?\n  n.callMethod.apply(n,arguments):n.queue.push(arguments)};\n  if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';\n  n.queue=[];t=b.createElement(e);t.async=!0;\n  t.src=v;s=b.getElementsByTagName(e)[0];\n  s.parentNode.insertBefore(t,s) } (window, document,'script',\n  'https:\/\/connect.facebook.net\/en_US\/fbevents.js');\n   fbq('init', '335401813750447');\n   fbq('track', 'PageView');\n  },3000);\n<\/script><\/p>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.howtogeek.com\/devops\/how-to-backup-kubernetes-mysql-operator-clusters\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;How to Backup Kubernetes MySQL Operator Clusters&#8221; Oracle\u2019s MySQL Operator for Kubernetes is a convenient way to automate MySQL database provisioning within your cluster. One of the operator\u2019s headline features is integrated hands-off backup support that increases your resiliency. Backups copy your database to external storage on a recurring schedule. This article will walk you&#8230;<\/p>\n","protected":false},"author":1,"featured_media":508789,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/07\/MySQL.jpg?height=200p&trim=2,2,2,2","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-508788","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/508788","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=508788"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/508788\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/508789"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=508788"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=508788"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=508788"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}