Jednoduché zálohování malé VPSky

Sepsáno 14.04.2016

Na Wedosu mám pár malých VPS, kde mi běží pár historicky projektů, několik agenturních webů, RSS čtečka a různé sběrače dat. Neznám někoho, kdo by Wedos překonal s cenou, mají SSD virtuály a pokud člověk nehledá 100% dostupnost, je to hodně slušná volba.

Hledal jsem blbuvzdorný setup, co by mi zvládl zazálohovat databáze a obsah, nahrané soubory klientů a obsah co je ve webech běžících na Wordpressu. Volba padla na Ruby gem backup a S3.

Pro každou databázi nebo adresář, co se má zálohovat se vytvoří konfigurační definice podle dokumentace backup gemu. V cronu roota je pak spuštění zálohy pro každou konfiguraci. Zálohy se nahrávají do S3, kde jsou navíc dvě pravidla: po třech dnech se záloha přesune do levnější Glacier a po půl roce se úplně odstraní.

Přestože moje malá VPSka není žádný cloud, mám celou jeji konfiguraci v Puppetu, kdyby mě náhodou Wedos nějak dopálil, Petr Soukup napsal pěkný článek proč puppetit.

Backup bucket v Amazonu

Opět podle pravidla, že infrastruktura má být kód, tohle je CloudFormation šablona která vytvoří bucket pro zálohy, nastaví automatické odsouvání do Glacier, vytvoří Amazoního uživatele, co má právo nahrávat soubory, a vytvoří pro toho uživatele přístupové klíče, které pak uložím do konfigurace gemu.

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "BackupBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [
            {
              "Id": "Move to Glacier",
              "Status": "Enabled",
              "ExpirationInDays": "160",
              "Transition": {
                "TransitionInDays": "3",
                "StorageClass": "Glacier"
              }
            }
          ]
        }
      }
    },
    "BackupBucketPolicy" : {
      "Type" : "AWS::S3::BucketPolicy",
      "Properties" : {
        "Bucket" : { "Ref" : "BackupBucket" },
        "PolicyDocument" : {
          "Version" : "2012-10-17",
          "Statement" : [ {
            "Sid" : "AllowUploadBackups",
            "Effect" : "Allow",
            "Principal" : { "AWS" : [ { "Fn::GetAtt" : [ "BackupUser", "Arn" ] } ] },
            "Action" : [
              "s3:AbortMultipartUpload",
              "s3:GetObjectAcl",
              "s3:GetObject",
              "s3:PutObjectAcl",
              "s3:PutObject"
            ],
            "Resource" : { "Fn::Join" : [ "", [
              "arn:aws:s3:::",
              { "Ref" : "BackupBucket" },
              "/*"
            ] ] }
          } ]
        }
      }
    },

    "BackupUser" : {
      "Type" : "AWS::IAM::User",
      "Properties" : {
        "Path" : "/"
      }
    },

    "BackupUserKey" : {
      "Type" : "AWS::IAM::AccessKey",
       "Properties": {
         "Status": "Active",
         "UserName": { "Ref" : "BackupUser" }
      }
    }
  },
  "Outputs": {
    "BucketName": {
      "Value": {
        "Ref": "BackupBucket"
      },
      "Description": "Name of the sample Amazon S3 bucket with a lifecycle configuration."
    },
    "BackupUserUserAccessKeyID" : {
      "Description" : "Backup user access key ID",
      "Value" : { "Ref" : "BackupUserKey" }
    },

    "BackupUserUserSecretAccessKey" : {
      "Description" : "Backup user secret access key",
      "Value" : {
        "Fn::GetAtt" : ["BackupUserKey", "SecretAccessKey"]
      }
    }
  }
}

Přemýšlel jsem, jestli víc popsat, jak CloudFormation funguje, přijde mi ale, že je naprosto skvěle čitelná i pro nováčka. Jednodušše definuju typy služeb co chci a můžu je mezi sebou provazovat odkazy pomocí { "Ref" : "<ResourceName>" }.

Výstupem stacku jsou tři hodnoty, které si zkopíruju na později.

Něco pro copy-paste

Nastavení gemu na serveru

Po instalaci backup gemu si do /etc/backup/models uložím konfiguraci pro zálohu, na tomhle příkladu třeba databáze.

Backup::Model.new(:vojtechvondra_database, "vojtechvondra_database backup") do
  database MySQL do |db|
    db.name     = "vv"
    db.username = "vv_user"
    db.password = "vv_pass"
    db.host     = "localhost"
  end
  compress_with Bzip2 do |compression|
    compression.level = 9
  end
  split_into_chunks_of 1024
  store_with S3 do |s3|
    s3.access_key_id     = "copied_access_key"
    s3.secret_access_key = "copied_access_secret"
    s3.path              = "database_backups"
    s3.bucket            = "backup-backupbucket-id-of-bucket"
    s3.region            = "eu-central-1"
    s3.storage_class     = :reduced_redundancy
  end
  Logger.configure do
    syslog.enabled  = true
    syslog.ident    = 'backup'
  end
end

No a nakonec do cronu v noci zaregistruju, aby záloha proběhla.

52 1 * * * /path/to/gems/backup perform --trigger vojtechvondra_database --config-file '/etc/backup/config.rb' --tmp-path ~/Backup/.tmp
Vypadá to, že budu mít co žrát.

Jako vždy s Amazonem, kolik to stojí?

Skoro nic, záloh mám pár gigabytů a platím 3 centy za měsíc, to je snad kolem jedný koruny. Dokonce to přesouvání do Glacier je blbost, protože kdybych chtěl vytáhnout starší zálohu, mohlo by mě to stát ranec. Nabídlo se to ale vyzkoušet, tak se to snad někomu bude hodit pro jiné účely.

comments powered by Disqus