Backups mit Amazon Glacier
Amazon Glacier ein Dienst für langfristige Backups. Die Daten werden auf Tapes archiviert, was beim Abruf zu einer etwas längeren Wartezeit führt, da die Daten zunächst vom Band auf eine Festplatte kopiert werden. Dafür ist Glacier geradezu spottbillig (etwa $0.0045 pro GB, bei S3 wären es etwa $0.0245). Hinzu kommen, ebenfalls geringe, Kosten für bestimmte Operationen. Die konkreten Preise unterscheiden sich je nach AWS-Region, eine Übersicht findet sich unter: https://aws.amazon.com/de/glacier/pricing/
Die Einrichtung ist einfach und beginnt damit sich einen AWS-Account anzulegen, wer bereits ein Amazon-Konto hat kann dieses nutzen: https://aws.amazon.com/de/
Anschließend wählt man die gewünschte Region aus, in der die Glacier-Daten gespeichert werden sollen und legt einen (oder mehrere) Glacier-Vault(s) an. Wenn die Daten in Frankfurt liegen sollen lautet die URL hierfür: https://eu-central-1.console.aws.amazon.com/glacier/home?region=eu-central-1#/vaults
Damit man auf Glacier zugreifen kann sind außerdem noch entsprechende Credentials nötig. Dies erfolgt unter: https://console.aws.amazon.com/iam/home?region=eu-central-1#/users
Der Access-Type sollte Programmatic access sein, als Permission reicht AmazonGlacierFullAccess aus. Ist der Vorgang erfolgreich ausgeführt erhält man eine Access-ID und einen Access-Key.
Um mit dem Vault arbeiten zu können benötigt man entsprechende Tools. Neben der Python-Library https://github.com/boto/boto, auf der viele Tools aufbauen, stellt auch Amazon selbst mit awscli ein Kommandozeilentool zur Verfügung:
pip install --user virtualenv
virtualenv ~/awscli
source ~/awscli/bin/activate
pip install --upgrade awscli
aws --version
Mit dem Befehl aws configure
können jetzt Default-Credentials hinterlegt werden. Alternativ kann man aber die Dateien ~/.aws/config
und ~/.aws/credentials
aber auch einfach per Hand anlegen:
[default]
region = eu-central-1
[default]
aws_access_key_id = <BACKUPUSER-ACCESS-ID>
aws_secret_access_key = <BACKUPUSER-ACCESS-KEY>
Alle Daten die auf Glacier abgelegt werden sollten zuvor verschlüsselt werden (z.B. mit ccrypt
), als Archivformat kann z.B. tar genutzt werden. Ein kleines Script könnte wie folgt aussehen:
#!/bin/bash
echo -n "`# Init"
target_dir=/backup # local backup storage
source_dir=/docker # path to back up
crypt_key=/root/ccrypt.key # password file for ccrypt, generate it with "pwgen -1 -s 4096 > /path/filename.key
mail=mail@example.com # email recipient
date=$(date +"%Y%m%d") # change this value if you create more than one daily backup
result=0 # do not change
echo " [OK]"
echo -n "`# Housekeeping"
apt-get install tar ccrypt -y --force-yes
mkdir -p ${target_dir}
result=${result}$?
rm -f ${target_dir}/*.cpt
result=${result}$?
echo " [OK]"
echo -n "`# Create Tarball"
/bin/tar -cpf ${target_dir}/data.tar.gz --directory=${source_dir}/ .
result=${result}$?
echo " [OK]"
echo -n "`# Crypt Tarballs"
/usr/bin/ccrypt -e -f -k ${crypt_key} ${target_dir}/data.tar.gz
result=${result}$?
echo " [OK]"
echo "`# Upload Tarball to Glacier"
/usr/local/bin/aws glacier create-vault --account-id - --vault-name ${date}
result=${result}$?
/usr/local/bin/aws glacier upload-archive --account-id - --vault-name ${date} --archive-description data.tar.gz.cpt --body ${target_dir}/data.tar.gz.cpt
result=${result}$?
if [[ ${result} =~ ^[0]+$ ]]; then
/usr/local/bin/aws glacier list-vaults --account-id - | mail -s "BACKUP SUCCESS" ${mail}
echo "Success: ${result}"
exit 0
else
echo "Backup Error: ${result}" | mail -s "BACKUP ERROR" ${mail}
echo "There was an error..."
exit 128
fi
Das Script legt für jeden Tag einen neuen Vault an (YYYYMMDD
) um die Verwaltung zu vereinfachen und die Dateiliste kurz zu halten. Nach dem Upload dauert es einige Zeit (mehrere Stunden) bis ein Inventar für den Vault von Amazon angelegt wurde. Sobald dies erfolgt ist kann man die Anzahl der hochgeladenen Archive und deren Speicherverbrauch auf der AWS-Website oder mit dem Befehl aws glacier list-vaults --account-id -
anzeigen lassen.
{
"VaultList": [
{
"SizeInBytes": 365896732,
"VaultARN": "arn:aws:glacier:eu-central-1:XXXXXXXXXXXX:vaults/XXXXXX",
"LastInventoryDate": "2017-05-06T09:31:41.195Z",
"VaultName": "XXXXXX",
"NumberOfArchives": 3,
"CreationDate": "2017-05-05T23:33:24.247Z"
}
]
}
Ein Backup ist natürlich nichts wert, wenn nicht auch der Restore funktioniert. Hierzu kann der Befehl aws glacier initiate-job --account-id - --vault-name $NAME--job-parameters "{\"Type\": \"inventory-retrieval\"}"
genutzt werden. Der Prozess dauert einige Stunden (~6
). Den Status des erzeugten Jobs kann man mit aws glacier list-jobs --account-id - --vault-name $NAME
abgefragt werden:
{
"JobList": [
{
"InventoryRetrievalParameters": {
"Format": "JSON"
},
"VaultARN": "arn:aws:glacier:eu-central-1:XXXXXXXXXXXX:vaults/XXXXXX",
"Completed": false,
"JobId": "phNiXdUvEuv0H0ODlnaiookFe87P4_UKsZs7yX9l5DmzTXPkC8OdwDBbFKfiFhHLYn9wPF8xncmQ9u3cHmf_KwEpXgzK",
"Action": "InventoryRetrieval",
"CreationDate": "2017-05-06T10:35:49.565Z",
"StatusCode": "InProgress"
}
]
}
Die Job-Parameter können auch in eine Datei geschrieben werden und dann mit --job-parameters file:///path/filename
übergeben werden. Wenn der Job fertig ausgeführt wurde kann mittels aws glacier get-job-output --account-id - --job-id phNiXdUvEuv0H0ODlnaiookFe87P4_UKsZs7yX9l5DmzTXPkC8OdwDBbFKfiFhHLYn9wPF8xncmQ9u3cHmf_KwEpXgzK --vault-name $NAME list.json
eine Liste mit dem Inhalt des Vaults angefordert werden. Die Liste wird als list.json abgelegt. In dieser finden sich die IDs für die abgelegten Daten.
{
"VaultARN":"arn:aws:glacier:us-east-1:49xxxxxxxxxx:vaults/hetzner",
"InventoryDate":"2015-03-23T13:14:02Z","ArchiveList":[
{"ArchiveId":"9OAW7ZgSHjEhwYdh4FoPde2fg2rYFr_SlPwdOqJDoLjr-y59jvXwyW_aLUjmu5ozgZI_37nYiKb7OoWSBShSQfye39nNg8sP6jDm4iDwCIleGdfbLMjsAS38Qb-qmadFhJwPuvtbog",
"ArchiveDescription":"
{\"Path\":\"data.tar.gz.cpt\",
\"UTCDateModified\":\"20140828T034400Z\"]",
"CreationDate":"2015-03-23T01:37:33Z",
"Size":317105197,
"SHA256TreeHash":"054686e6cba818ed125df9184aeeeff34f6078aa4ecba95f741d807116ba852b"},
Diese ID kann dann genutzt werden um die Dateien anzufordern:
aws glacier initiate-job --account-id - --vault-name hetzner --job-parameters "{\"Type\": \"archive-retrieval\",\"ArchiveId\":\"9OAW7ZgSHjEhwYdh4FoPde2fg2rYFr_SlPwdOqJDoLjr-y59jvXwyW_aLUjmu5ozgZI_37nYiKb7OoWSBShSQfye39nNg8sP6jDm4iDwCIleGdfbLMjsAS38Qb-qmadFhJwPuvtbog\",\"Tier\":\"Bulk\"}"
Auch hier dauert es dann wieder einige Stunden (~12
) bis die Aktion ausgeführt wurde. Der Status kann wie gehabt mit aws glacier list-jobs --account-id - --vault-name $NAME
abgefragt werden. Um sich automatisch über einen Job-Status informieren zu lassen kann SNS (Simple Notification Service) genutzt werden: https://docs.aws.amazon.com/amazonglacier/latest/dev/configuring-notifications.html
Zunächst besorgt man sich noch einmal die Joblist mit dem Befehl aws glacier list-jobs --account-id - --vault-name $NAME
:
{
"JobList": [
{
"CompletionDate": "2017-05-08T17:30:33.257Z",
"VaultARN": "arn:aws:glacier:us-east-1:49xxxxxxxxxx:vaults/hetzner",
"RetrievalByteRange": "0-345896991",
"Tier": "Bulk",
"SHA256TreeHash": "9a882b4dd5a0df01499ff45fdef68f0701b4bd35919bcbe8a5bcca220285f3d4",
"Completed": true,
"JobId": "XXXXXX-NXOCpJbGYBHN34NXepAtJUn6ywwwTgcea6M_Q-2Fj7Ah5OtEFAMjoPwq8ie6Z-crgqfsNH5peoP1lh5TvEmPa",
"ArchiveId": "9OAW7ZgSHjEhwYdh4FoPde2fg2rYFr_SlPwdOqJDoLjr-y59jvXwyW_aLUjmu5ozgZI_37nYiKb7OoWSBShSQfye39nNg8sP6jDm4iDwCIleGdfbLMjsAS38Qb-qmadFhJwPuvtbog",
"ArchiveSizeInBytes": 345896992,
"Action": "ArchiveRetrieval",
"ArchiveSHA256TreeHash": "9a882b4dd5a0df01499ff45fdef68f0701b4bd35919bcbe8a5bcca220285f3d4",
"CreationDate": "2017-05-08T12:24:12.980Z",
"StatusMessage": "Succeeded",
"StatusCode": "Succeeded"
}
}
Mit der entsprechenden JobId kann man dann die eigentliche Datei anfordern:
aws glacier get-job-output --account-id - --vault-name hetzner --job-id XXXXXX-NXOCpJbGYBHN34NXepAtJUn6ywwwTgcea6M_Q-2Fj7Ah5OtEFAMjoPwq8ie6Z-crgqfsNH5peoP1lh5TvEmPa data.tar.gz.cpt
Wie man sieht ist der Restore-Prozess, zumindest mit awscli
nicht ganz so komfortabel, funktioniert aber zuverlässig und darauf kommt es ja an. Den sehr günstigen Preis erkauft man mit längeren Wartezeiten. Wenn man die Daten schneller benötigt kann man anstelle von Bulk auch Expedited-Abrufe veranlassen, diese sind teurer, aber dafür stehen die Daten nach wenigen Minuten zur Verfügung. Die wieder hergestellten Daten stehen für 24 Stunden zum Download zur Verfügung. Generell ist es umständlich und zeitaufwändig zu prüfen, ob die gemachten Backups bei einem Restore halten, was sie versprechen. Außerdem verursacht ein Restore zusätzliche Kosten.
Etwas einfacher wird er Prozess z.B. mit https://github.com/uskudnik/amazon-glacier-cmd-interface, hier sollte man aber beachten dass für neue Benutzer die Amazon SimpleDB wohl nicht mehr zur Verfügung steht und die damit verbundenen Funktionen nicht mehr nutzbar sind.
Archive können jederzeit gelöscht werden, ein Vault kann erst dann gelöscht werden, wenn nicht kürzlich in ihn geschrieben wurde. Existiert ein Archiv/Vault weniger als 3 Monate wird eine (geringe) Löschgebühr erhoben, nach Ablauf der Frist ist das Löschen kostenfrei. Beim Download sind 10 GB/Monat kostenfrei.
Weitere Infos finden sich unter: https://docs.aws.amazon.com/amazonglacier/latest/dev/api-initiate-job-post.html und https://docs.aws.amazon.com/amazonglacier/latest/dev/api-job-output-get.html