Имеем windows сервер в AWS и задача настроить резервное копирование. Можно использовать снапшоты, но тогда возникнет проблема с целостностью данных. Ещё хочется хранить недельные и месячные снапшоты, а lifecycle в снапшотах этого не предлагает. Новый сервисе AWS Backup тоже не умеет ещё делать целостные снапшоты или я не нашёл как. Ну и хочется что бы всё это работало максимально без моего участия.
Для достижения поставленой задачи нам потребуется
Для начала нам нужна роль для сервера. Роль должна разрешать AWS SSM и создание EBS снапшотов.
Заходим в IAM → Policies → Create policy.
Переходим в закладку JSON и вставляем
Жмём Review policy в Имя пишем что то типа VssSnapshotPolicy. Сохраняем
Теперь создаём роль.
IAM → Roles → Create Role
Выбираем AWS Service → EC2 и идём в Permissions.
Здесь добавляем AmazonSSMManagedInstanceCore для SMM и нашу полиси которую мы создали ранне VssSnapshotPolicy. При желании присваем таг для нашей роли и даём ей имя допустим VssSnapshotRole.
Затем идём и присваиваем эту роль для желаемых серверов.
Всё теперь ssm может “управлять” этими серверами.
Теперь нам надо на сервера поставить AWSVssComponents. для этого выбираем Run command и жмём Run command ищем AWS-ConfigureAWSPackage.
В Command parameters выбираем Install, Name – AwsVssComponents, Версия последняя.
В Target выбираем системы которые будем бекапить.
Жмём RUN.
После окончания мы можем можем сделать бекап из консоли SSM.
Выбираем Run command, ищем AWSEC2-CreateVssSnapshot. В Target ставим наши сервера. Выбираем параметры как Exclude Boot Volume, Copy Only и No Writers.
Жмём RUN. У нас должны создаться снапшоты.
Для уведомлений о бекапах создадим SNS Topic. И подпишемся на него. Я использую уведомление на почту.
Создаём политику, которая разрешает слать сообщения в нашу очередь
И создаём роль с этой политикой.
Для автоматизации процесса воспользуемся SSM maintenance window.
Жмём Create maintenance window. Заполняем Name, заполняем Schedule какой душе угодно.
Заходим в созданный maintenance window и добавляем Register RUN command task. Заполняем параметры. В Tag я прописываю тип бекапа (TAG Key=SnapshotType,Value=). У меня это три возможных параметра Day, Week, Month и соответственно три maintenance window. Ставим Enable SNS notifications и указываем нашу роль для sns и topic.
Всё теперь снапшоты будут создаваться по расписанию.
И через некоторое время снапшотов у нас станет слишком много – их надо чистить. Для этого воспользуемся другим сервисом AWS – Lambda.
Для начала создадим роль которая умеет читать и удалять снапшоты.
Для этого в IAM создаём policy
И эту policy вешаем на новую роль.
Идём в lambda и создаём новую python функцию.
Роль используем созданную выше. В качестве триггера используем CloudWatch Event.
эта функция проходит по всем volume, ищет для всех volumes снапшоты которые completed, тегом SnapshotType и удаляет все снапшоты которые больше snapshot retentions. У меня храится 5 последних дневных, 3 недельных и 2 месячных снапшота.
Для достижения поставленой задачи нам потребуется
- Windows Server 2008 R2 или новее работающий в AWS
- SSM Agent version 2.2.58.0 или новее
- AWS Tools for Windows PowerShell 3.3.48.0 или новее
- AWS System manager
- IAM
- SNS
- Lambda
Для начала нам нужна роль для сервера. Роль должна разрешать AWS SSM и создание EBS снапшотов.
Заходим в IAM → Policies → Create policy.
Переходим в закладку JSON и вставляем
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ec2:CreateTags", "Resource": "arn:aws:ec2:*::snapshot/*" }, { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:CreateSnapshot" ], "Resource": "*" } ] }
Жмём Review policy в Имя пишем что то типа VssSnapshotPolicy. Сохраняем
Теперь создаём роль.
IAM → Roles → Create Role
Выбираем AWS Service → EC2 и идём в Permissions.
Здесь добавляем AmazonSSMManagedInstanceCore для SMM и нашу полиси которую мы создали ранне VssSnapshotPolicy. При желании присваем таг для нашей роли и даём ей имя допустим VssSnapshotRole.
Затем идём и присваиваем эту роль для желаемых серверов.
Всё теперь ssm может “управлять” этими серверами.
Теперь нам надо на сервера поставить AWSVssComponents. для этого выбираем Run command и жмём Run command ищем AWS-ConfigureAWSPackage.
В Command parameters выбираем Install, Name – AwsVssComponents, Версия последняя.
В Target выбираем системы которые будем бекапить.
Жмём RUN.
После окончания мы можем можем сделать бекап из консоли SSM.
Выбираем Run command, ищем AWSEC2-CreateVssSnapshot. В Target ставим наши сервера. Выбираем параметры как Exclude Boot Volume, Copy Only и No Writers.
Жмём RUN. У нас должны создаться снапшоты.
Для уведомлений о бекапах создадим SNS Topic. И подпишемся на него. Я использую уведомление на почту.
Создаём политику, которая разрешает слать сообщения в нашу очередь
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "sns:Publish", "Resource": "arn:aws:sns:ap-northeast-1:Account ID:Topic Name" } ] }
И создаём роль с этой политикой.
Для автоматизации процесса воспользуемся SSM maintenance window.
Жмём Create maintenance window. Заполняем Name, заполняем Schedule какой душе угодно.
Заходим в созданный maintenance window и добавляем Register RUN command task. Заполняем параметры. В Tag я прописываю тип бекапа (TAG Key=SnapshotType,Value=). У меня это три возможных параметра Day, Week, Month и соответственно три maintenance window. Ставим Enable SNS notifications и указываем нашу роль для sns и topic.
Всё теперь снапшоты будут создаваться по расписанию.
И через некоторое время снапшотов у нас станет слишком много – их надо чистить. Для этого воспользуемся другим сервисом AWS – Lambda.
Для начала создадим роль которая умеет читать и удалять снапшоты.
Для этого в IAM создаём policy
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "logs:DeleteSubscriptionFilter", "ec2:DeleteSnapshot", "ec2:DescribeSnapshots", "logs:DeleteLogStream", "logs:CreateExportTask", "logs:DeleteResourcePolicy", "logs:CreateLogStream", "logs:DeleteMetricFilter", "logs:TagLogGroup", "logs:CancelExportTask", "ec2:DescribeVolumes", "logs:DeleteRetentionPolicy", "logs:DeleteLogDelivery", "logs:AssociateKmsKey", "logs:PutDestination", "logs:DisassociateKmsKey", "logs:UntagLogGroup", "logs:DeleteLogGroup", "logs:PutDestinationPolicy", "ec2:DescribeSnapshotAttribute", "logs:DeleteDestination", "logs:PutLogEvents", "logs:CreateLogGroup", "logs:PutMetricFilter", "logs:CreateLogDelivery", "logs:PutResourcePolicy", "logs:UpdateLogDelivery", "logs:PutSubscriptionFilter", "logs:PutRetentionPolicy" ], "Resource": "*" } ] }
И эту policy вешаем на новую роль.
Идём в lambda и создаём новую python функцию.
import datetime import sys import boto3 def get_volume_snapshots(client, volume_id, SnapshotType): args = { "Filters": [ { "Name": "volume-id", "Values": [volume_id] }, { "Name": "status", "Values": ["completed"] }, { "Name": "tag-key", "Values": ["SnapshotType"]}, { "Name": "tag-value", "Values": [SnapshotType]}, ], "OwnerIds": ["self"] } snapshots = [] while True: resp = client.describe_snapshots(**args) snapshots += resp.get("Snapshots", []) if "NextToken" in resp: args["NextToken"] = resp["NextToken"] else: break return snapshots def delete_snapshot(client, snapshot_id): wait_period = 5 retries = 5 while True: try: client.delete_snapshot(SnapshotId=snapshot_id) return True except Exception as ex: # As the list of snapshot is eventually consistent old snapshots might appear in listed snapshots if getattr(ex, "response", {}).get("Error", {}).get("Code", "") == "'InvalidSnapshot.NotFound": return False # Throttling might occur when deleting snapshots too fast if "throttling" in ex.message.lower(): retries -= 1 if retries == 0: raise ex time.sleep(wait_period) wait_period = min(wait_period + 10 , 30) continue raise ex def lambda_handler(event, context): retentions = {"Day": 5, "Week": 3, "Month": 2} client = boto3.client("ec2") vols = client.describe_volumes() snapshots_deleted = [] for vol in vols['Volumes']: vol_id = vol['VolumeId'] for SnapshotType, retention_count in retentions.items(): snapshots_for_volume = sorted(get_volume_snapshots(client, vol_id, SnapshotType), key=lambda s: s["StartTime"], reverse=True) snapshots_to_delete = [] if retention_count > 0: snapshots_to_delete = [b["SnapshotId"] for b in snapshots_for_volume[retention_count:]] for snapshot_id in snapshots_to_delete: if delete_snapshot(client, snapshot_id): snapshots_deleted.append(snapshot_id) return { "DeletedSnapshots": snapshots_deleted }
Роль используем созданную выше. В качестве триггера используем CloudWatch Event.
эта функция проходит по всем volume, ищет для всех volumes снапшоты которые completed, тегом SnapshotType и удаляет все снапшоты которые больше snapshot retentions. У меня храится 5 последних дневных, 3 недельных и 2 месячных снапшота.
