0

[Cloud Thực Chiến] Build Pipeline tự động Backup MySQL lên AWS S3 Glacier bằng Laravel

Bất kỳ hệ thống e-commerce hay ứng dụng quản lý nào cũng coi Database là sinh mệnh. Nhưng backup Database để ở đâu?

  • Lưu trên cùng server chạy app? Server sập là mất trắng.
  • Lưu ở S3 Standard? Database càng phình to, tiền lưu trữ hàng tháng càng "đau ví".

Giải pháp tối ưu: Viết một Command trong Laravel gọi lệnh mysqldump nén file lại, sau đó đẩy thẳng lên S3 với cờ (flag) định dạng là Glacier. Cuối cùng, dùng Task Scheduling để nó tự chạy vào lúc 2h sáng mỗi ngày.

Bước 1: Chuẩn bị "đồ nghề"

  1. AWS IAM User: Tạo một user có quyền AmazonS3FullAccess (hoặc cấu hình Policy chỉ cho phép ghi vào đúng một bucket) và lấy AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
  2. S3 Bucket: Tạo một bucket trên AWS (VD: my-system-backup-db).
  3. Package S3 cho Laravel: Cài đặt driver AWS S3 bằng Composer:
Package S3 cho Laravel: Cài đặt driver AWS S3 bằng Composer:

Cấu hình file .env:

AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_DEFAULT_REGION=ap-southeast-1
AWS_BUCKET=my-system-backup-db

Bước 2: Khởi tạo Command Backup

Trong Laravel, tạo một command mới chuyên xử lý logic này:

php artisan make:command BackupDatabaseToGlacier

Mở file app/Console/Commands/BackupDatabaseToGlacier.php và tùy chỉnh lại logic:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;

class BackupDatabaseToGlacier extends Command
{
    // Tên lệnh để gọi trên terminal
    protected $signature = 'backup:database';
    protected $description = 'Dump MySQL Database and upload directly to AWS S3 Glacier';

    public function handle()
    {
        $this->info('Bắt đầu quá trình backup...');

        // 1. Khởi tạo tên file với Timestamp
        $filename = 'backup_' . Carbon::now()->format('Y_m_d_His') . '.sql.gz';
        $storagePath = storage_path('app/backups/' . $filename);

        // Đảm bảo thư mục tồn tại
        if (!file_exists(storage_path('app/backups'))) {
            mkdir(storage_path('app/backups'), 0755, true);
        }

        // 2. Lấy thông tin DB từ config
        $host = env('DB_HOST');
        $username = env('DB_USERNAME');
        $password = env('DB_PASSWORD');
        $database = env('DB_DATABASE');

        // 3. Thực thi lệnh mysqldump và nén gzip trực tiếp
        $command = "mysqldump -h {$host} -u {$username} -p{$password} {$database} | gzip > {$storagePath}";
        
        $output = null;
        $resultCode = null;
        exec($command, $output, $resultCode);

        if ($resultCode === 0) {
            $this->info("Dump thành công! Đang upload lên Glacier...");

            // 4. Upload file lên S3 với Storage Class là GLACIER
            $fileStream = fopen($storagePath, 'r');
            
            Storage::disk('s3')->put('db_backups/' . $filename, $fileStream, [
                'StorageClass' => 'GLACIER' // Điểm ăn tiền là ở đây!
            ]);

            fclose($fileStream);

            // 5. Dọn dẹp rác trên server local
            unlink($storagePath);

            $this->info("Upload thành công và đã dọn dẹp file local!");
        } else {
            $this->error("Quá trình dump DB thất bại.");
        }
    }
}

Lưu ý cực quan trọng: Phép màu nằm ở ['StorageClass' => 'GLACIER']. Chỉ với một dòng cấu hình này, file của bạn khi bắn lên S3 sẽ tự động chui thẳng vào tủ đông Glacier, hưởng mức giá siêu rẻ thay vì nằm ở S3 Standard.

Bước 3: Lên lịch tự động (Cron Job)

Đã viết Command xong thì phải cho nó chạy tự động. Mở app/Console/Kernel.php (hoặc routes/console.phpnếu dùng phiên bản mới) và đăng ký lịch trình:

protected function schedule(Schedule $schedule)
{
    // Chạy lúc 2:00 sáng mỗi ngày - thời điểm hệ thống ít người truy cập nhất
    $schedule->command('backup:database')->dailyAt('02:00');
}

Cuối cùng, trỏ Cron của hệ điều hành server (Linux) vào Laravel Task Scheduler. Mở terminal server gõ crontab -evà thêm dòng sau:

* * * * * cd /path-to-your-laravel-project && php artisan schedule:run >> /dev/null 2>&1

4. Cảnh báo "nhẹ" dành cho anh em

  • Khôi phục dữ liệu (Restore): Nhớ rằng dữ liệu lưu ở Glacier không thể bấm tải về cái "xoẹt" được đâu nhé. Bạn sẽ phải làm lệnh "Initiate Restore" trên AWS Console và đợi vài tiếng để file rã đông thì mới có thể kéo về restore lại DB được.
  • Bảo mật Pass DB: Không bao giờ hardcode pass database trong code, luôn gọi qua env(). Lệnh exec() ở trên nếu in ra lỗi có thể lộ password, hãy cẩn thận trong việc ghi log file.

Lời kết

Chỉ với vài chục dòng code gọn gàng chuẩn MVC, anh em đã thiết lập xong một hệ thống Backup chuẩn Enterprise, vừa an toàn vĩnh viễn vừa tiết kiệm tối đa chi phí hạ tầng. Không cần cài cắm tool bên thứ 3 phức tạp.

Anh em có đang dùng package nào xịn sò hơn (như Spatie Laravel Backup) để làm việc này không? Cùng trao đổi cách anh em custom nó để đẩy lên Glacier ở dưới comment nhé!


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.