Ruby
cron
PostgreSQL
backup
crontab

CronでRubyのBackupを使ってPostgreSQLのデータをS3にアップロードし続ける

More than 3 years have passed since last update.

背景

  • PostgreSQLのデータのバックアップを取りたい
  • S3にアップロードしたい
  • S3容量課金なので、古いバックアップは消してゆきたい
  • Cronで定期的に動かして、普段は気にしないでおきたい
    • Wheneverのような仕組みでcrontabを管理する方法もあるが、crontabだけで管理できる程度のロジックしかなく、また、1層増えるのがいやなのでcrontabをそのまま編集する
  • RubyのBackupというgemが便利そう
  • 処理の途中で失敗したら、Gmailでメールを送るようにする

Backup

公式ドキュメントに詳しい設定が書いてある。

以下が、作った設定ファイル。

storyblog_backup.rb
# encoding: utf-8

##
# Backup Generated: backup_config
# Once configured, you can run the backup with the following command:
#
# $ backup perform -t backup_config [-c <path_to_configuration_file>]
#
# For more information about Backup's components, see the documentation at:
# http://backup.github.io/backup
#
Model.new(:storyblog_backup, 'Backup storyblog data to S3') do

  ##
  # PostgreSQL [Database]
  #
  database PostgreSQL do |db|
    # To dump all databases, set `db.name = :all` (or leave blank)
    db.name               = 'storyblog_production'
    db.username           = ENV['POSTGRESQL_USERNAME']
    db.password           = ENV['POSTGRESQL_PASSWORD']
    db.host               = "localhost"
    db.port               = 5432
    # db.socket             = "/tmp/pg.sock"
    # When dumping all databases, `skip_tables` and `only_tables` are ignored.
    # db.skip_tables        = ["skip", "these", "tables"]
    # db.only_tables        = ["only", "these", "tables"]
    # db.additional_options = ["-xc", "-E=utf8"]
  end

  ##
  # Amazon Simple Storage Service [Storage]
  #
  store_with S3 do |s3|
    # AWS Credentials
    s3.access_key_id     = ENV['S3_ACCESS_KEY']
    s3.secret_access_key = ENV['S3_SECRET']
    # Or, to use a IAM Profile:
    # s3.use_iam_profile = true

    s3.region            = 'ap-northeast-1'
    s3.bucket            = 'storyblog-backup'
    s3.path              = '/backups'
    s3.keep = 5
  end

  ##
  # Amazon S3 [Syncer]
  #
  # sync_with Cloud::S3 do |s3|
  #   # AWS Credentials
  #   s3.access_key_id     = ENV['S3_ACCESS_KEY']
  #   s3.secret_access_key = ENV['S3_SECRET']
  #   # Or, to use a IAM Profile:
  #   # s3.use_iam_profile = true
  #
  #   s3.region            = 'ap-northeast-1'
  #   s3.bucket            = 'storyblog-backup'
  #   s3.path              = '/backups'
  #   s3.mirror            = true
  #   s3.thread_count      = 10
  #
  #   s3.directories do |directory|
  #     directory.add "/path/to/directory/to/sync"
  #     directory.add "/path/to/other/directory/to/sync"
  #
  #     # Exclude files/folders from the sync.
  #     # The pattern may be a shell glob pattern (see `File.fnmatch`) or a Regexp.
  #     # All patterns will be applied when traversing each added directory.
  #     directory.exclude '**/*~'
  #     directory.exclude /\/tmp$/
  #   end
  # end

  ##
  # Gzip [Compressor]
  #
  compress_with Gzip

  ##
  # Mail [Notifier]
  #
  # The default delivery method for Mail Notifiers is 'SMTP'.
  # See the documentation for other delivery options.
  #
  notify_by Mail do |mail|
    mail.on_success           = true
    mail.on_warning           = true
    mail.on_failure           = true

    mail.from                 = ENV['GMAIL_USERNAME']
    mail.to                   = ENV['EMAIL_KATRYO']
    mail.address              = "smtp.gmail.com"
    mail.port                 = 587
    mail.domain               = "gmail.com"
    mail.user_name            = ENV['GMAIL_USERNAME']
    mail.password             = ENV['GMAIL_APPLICATION_SPECIFIC_PASSWORD']
    mail.authentication       = "plain"
    mail.encryption           = :starttls
  end

end

s3.keep = 5と設定しておくと、 Backup/.data/storyblog_backup/S3.yml というファイルが自動的に作られ、それで作成したダンプファイルの個数とタイミングを管理してくれる。

また、Gmailだとアプリケーション固有のパスワード( aplication specific password )を使っているので、 ログインパスワードではなくそれを設定する。

なお、

%  backup generate:model

を実行すると ~/Backup にconfig.rbとmodelsが作られてしまうが、gitで他プロジェクトと同様に管理したいので、~/Backupのディレクトリを、Gemfileのあるディレクトリ内に移動させた。

開発は手元のMacで行い、Githubのリポジトリを通してサーバにソースコードを受けわたすようにした。

cronを動かすサーバに ~/Backup というシンボリックリンクを作り、それが、gitで管理した ~/storyblog_backup/Backup を指し示すように設定した。

これで、

% bundle exec backup perform --trigger storyblog_backup

すれば、PostgreSQLのデータがS3にアップロードされる。

crontab

PATH=/usr/local/bin:/usr/bin:/local/bin:/bin:/home/katryo/.rbenv/shims
MAILTO=mymail@mail.com
(ここに環境変数を書く)

10 4 * * * cd ~/storyblog_backup && bundle exec backup perform --trigger storyblog_backup | logger -s

と、gitで管理したcrontabファイルを作っておいて、

% crontab < ~/my_crontab/crontab

とcrontabに読み込ませる。

% crontab ~/my_crontab/crontab

としたほうがよいかもしれない。どういう差があるかは調査していない。

なお、crontabの設定はsongmuさんのWEB+DBの記事がとても参考になる http://gihyo.jp/dev/serial/01/perl-hackers-hub/002501