Для тех кто пользуется облачным сервисом AWS (Amazon Web Services) я предлагаю следующую модель резервного копирования:
1. Создание локальных резервных копий в определенную папку сервера в сервисе EC2 (архивирование ZIP, процедуры SQL Backup и т.п.).
2. Копирование содержимого папки бэкапа в хранилище сервиса S3 (Powershell скрипт с использованием команд AWS CLI).
3. Проверка содержимого облачного хранилища S3 на предмет устаревших архивных копий (Powershell скрипт с использованием команд AWS CLI).
Ниже приведен Powershell скрипт, который использует команды AWS CLI (необходимо установить эти утилиты с сайта AWS). Этот скрипт получает входные данные: регион AWS, имя букета S3, имя служебного профиля (пользователя), пароль и секретную фразу служебного пользователя, папку с локальными резервными копиями, время жизни резервных копий в облаке. Скрипт подключается к указанному букету в облаке S3 и переносит содержимое локальной папки резервных копий в папку с именем сервера в облачном хранилище (используется фильтр по расширению файлов *.bak). После переноса всех файлов скрипт сравнивает даты создания файлов в облаке с текущей датой и удаляет файлы, у которых возраст больше заданного в начальных условиях.
# Input data $ServerName = $env:computername $S3Region = "eu-central-1" $S3BucketName = "my-backup-bucket" $S3Profile = "my_backup" $S3ProfileAccessKey = "ABCD1234ABCD1234ADCB" $S3ProfileSecretKey = "abcd1234abcd1234abcd1234abcd1234abcd1234abc" $LocalFolder = "C:\SQLBackup" $KeepAge = 14 # Calculated data $Destination = "s3://" + $S3BucketName + "/" + $ServerName $CurrentDate = Get-Date $ScriptFolder = $MyInvocation.MyCommand.Path.SubString(0,($MyInvocation.MyCommand.Path.Length - ` $MyInvocation.MyCommand.Name.Length)) $LogFile = $ScriptFolder + (Get-Date -format yyyy_MM_dd) + "_" + ` $MyInvocation.MyCommand.Name.SubString(0,($MyInvocation.MyCommand.Name.Length - 4)) + ".log" # Log-file creation Out-File -FilePath $LogFile Function Write-ScriptLog { Param( [CmdletBinding()] [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [String]$Message, [Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [String]$LogFile ) Process { $LogMessage = Get-Date -uformat "%d.%m.%Y %H:%M:%S" $LogMessage += "`t" $LogMessage += $Message $LogMessage | Out-File -FilePath $LogFile -Append } } Write-ScriptLog -LogFile $LogFile -Message ($MyInvocation.MyCommand.Name + " started") Write-ScriptLog -LogFile $LogFile -Message ("=== Input data ===") Write-ScriptLog -LogFile $LogFile -Message ("Server Name = $ServerName") Write-ScriptLog -LogFile $LogFile -Message ("S3 Region = $S3Region") Write-ScriptLog -LogFile $LogFile -Message ("S3 Bucket Name = $S3BucketName") Write-ScriptLog -LogFile $LogFile -Message ("S3 Profile = $S3Profile") Write-ScriptLog -LogFile $LogFile -Message ("Local Folder = $LocalFolder") Write-ScriptLog -LogFile $LogFile -Message ("Keep Age = $KeepAge") # S3 profile creation # Run it once to create service profile for windows account which executes the script #Set-AWSCredentials -AccessKey $S3ProfileAccessKey -SecretKey $S3ProfileSecretKey -StoreAs $S3Profile # Initializing S3 profile Set-DefaultAWSRegion -Region $S3Region Initialize-AWSDefaults -ProfileName $S3Profile # Get local backup files Write-ScriptLog -LogFile $LogFile -Message ("=== Processing local files ===") $LocalFiles = Get-ChildItem $LocalFolder -Filter *.bak Write-ScriptLog -LogFile $LogFile -Message ($LocalFiles.Count.ToString() + ` " files are found for moving to AWS S3") # Move local backup files to S3 bucket ForEach ($LocalFile in $LocalFiles) { $FileName = $LocalFile.Name Write-ScriptLog -LogFile $LogFile -Message ($LocalFile.Name + " will be moved to AWS S3") Try { Write-S3Object -BucketName $S3BucketName -Key ($ServerName + "/" + $FileName) ` -File ($LocalFile.DirectoryName + "\" + $LocalFile.Name) -StoredCredentials $S3Profile ` -Region $S3Region Remove-Item -Path ($LocalFile.DirectoryName + "\" + $LocalFile.Name) Write-ScriptLog -LogFile $LogFile -Message ($LocalFile.Name + " is moved to $Destination/$FileName") } Catch { $ErrorMessage = $_.Exception.Message Write-ScriptLog -LogFile $LogFile -Message ("Error: " + $ErrorMessage) } } # Get S3 bucket files Write-ScriptLog -LogFile $LogFile -Message ("=== Processing remote files ===") $S3Objects = Get-S3Object -BucketName $S3BucketName -KeyPrefix $ServerName -StoredCredentials $S3Profile ` -Region $S3Region Write-ScriptLog -LogFile $LogFile -Message (($S3Objects.Count - 1).ToString() + ` " files are found in AWS S3") # Deleting old files from S3 bucket ForEach ($S3Object in $S3Objects) { # Get child objects of the server folder If ($S3Object.Key.Length -gt ($ServerName.Length + 1)) { $S3ObjectAge = (Get-Date) - $S3Object.LastModified # Get out-of-date object If ($S3ObjectAge.Days -gt $KeepAge) { Write-ScriptLog -LogFile $LogFile -Message ($S3Object.Key.Substring(($ServerName.Length + 1)) + ` " is out of date (" + $S3ObjectAge.Days.ToString() + " days old) and will be deleted") Remove-S3Object -BucketName $S3BucketName -Key $S3Object.Key -StoredCredentials $S3Profile ` -Region $S3Region -Force Write-ScriptLog -LogFile $LogFile -Message ($S3Object.Key.Substring(($ServerName.Length + 1)) + ` " is deleted from AWS S3") } } } Write-ScriptLog -LogFile $LogFile -Message ($MyInvocation.MyCommand.Name + " stopped")
Этот скрипт нужно поставить в расписание Windows на ежедневный запуск после выполнения локальных операций резервного копирования. Для выполнения скрипта рекомендуется использовать командный файл, приведенный ниже.
powershell.exe "%~DP0Process-S3Backup.ps1"
Скрипт рекомендуется запускать от имени SYSTEM, поэтому в теле скрипта есть закомментированный раздел S3 profile creation, который создает профиль служебного пользователя AWS в текущем профиле пользователя Windows. То есть для создания профиля AWS в профиле SYSTEM нужно раскомментировать строку Set-AWSCredentials -AccessKey $S3ProfileAccessKey -SecretKey $S3ProfileSecretKey -StoreAs $S3Profile и запустить однократно скрипт через расписание Windows от имени SYSTEM, после чего закомментировать строку.
Помимо указанных скриптов необходимо так же настроить безопасность на букете S3. Для этого нужно знать ARN служебного пользователя (можно посмотреть в профиле пользователя в разделе IAM). Политика доступа к букету S3 настраивается в свойствах букета в разделе Permissions - Edit bucket policy.
{ "Version": "2016-12-17", "Id": "Policy1481272123456", "Statement": [ { "Sid": "Stmt1481272123456", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::444222123456:user/my_backup" }, "Action": "s3:*", "Resource": [ "arn:aws:s3:::my-backup-bucket", "arn:aws:s3:::my-backup-bucket/*" ] } ] }