使用快照复制 Azure Blob
Copy Azure Blob With Snapshots
我正在尝试备份一些 blob 存储以防止意外删除容器,我可以使用 PowerShell 和 start-CopyAzurBlog 或从命令行使用 AZCopy 来很好地复制 blob,但是这些 blob 有一些快照(用作版本控制过程的一部分),每当我复制时,它都不会带走快照。
我知道您可以将 /snapshot 命令与 AZCopy 一起使用,但这会为每个快照创建一个全新的 blob,我需要它们成为单个 blob 的一部分。
反正有没有完整地复制这些?理想情况下,这将在 PowerShell 中进行,这样我就可以使用 Azure 自动化,但如果需要的话,我很乐意在 C# 中做一些事情。
我必须指出,您要求的功能很难实现。
Snapshot Blob API 只支持为当前的blob数据创建快照。因此,为了备份快照,我们需要在目标中创建与第一个快照具有相同数据的 blob,然后创建快照;并用与第二个快照相同的数据覆盖目标 blob,然后创建一个快照; ...;继续这样做,直到在目标中创建所有快照,最后用与当前源 blob 相同的数据覆盖目标 blob。
由于源 blob 的容量实际上并不是所有快照和当前 blob 的总和,如果您想在备份后也保存目的地的价格,您必须区分两个快照或最后一个快照和当前 blob,并且在每一步只覆盖不同的 blocks/pages,这可能会带来更多的复杂性。
这是符合赵兴路逻辑的代码。该方法是首先列出源 blob 的快照,根据快照在目标中创建 blob 并拍摄该 blob 的快照。最后,您会将基本 blob 复制到目标 blob。
static void CopyBlobAndSnapshots()
{
var sourceAccountName = "<source-account-name>";
var sourceAccountKey = "<source-account-key>";
var sourceContainerName = "<source-container-name>";
var targetAccountName = "<target-account-name>";
var targetAccountKey = "<target-account-key>";
var targetContainerName = "<target-container-name>";
var blobName = "<source-blob-name>";
var sourceAccount = new CloudStorageAccount(new StorageCredentials(sourceAccountName, sourceAccountKey), true);
var targetAccount = new CloudStorageAccount(new StorageCredentials(targetAccountName, targetAccountKey), true);
var sourceBlobClient = sourceAccount.CreateCloudBlobClient();
var sourceContainer = sourceBlobClient.GetContainerReference(sourceContainerName);
var sourceBlob = sourceContainer.GetBlockBlobReference(blobName);
var targetBlobClient = targetAccount.CreateCloudBlobClient();
var targetContainer = targetBlobClient.GetContainerReference(targetContainerName);
targetContainer.CreateIfNotExists();
//Create a SAS Token on source blob with read permissions that is valid for 2 weeks.
var sasToken = sourceBlob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = new DateTimeOffset(DateTime.UtcNow.AddDays(14))
});
//List blob snapshots first
var baseBlobAndSnapshots = sourceContainer.ListBlobs(blobName, true, BlobListingDetails.Snapshots).ToList();
//Since the list contains both base blob and snapshots, we should remove the base blob from this list.
var blobSnapshots = baseBlobAndSnapshots.Where(b => ((CloudBlockBlob)b).SnapshotTime != null).ToList();
//Now we should arrange them in reverse chronological order
blobSnapshots.Reverse();
CloudBlockBlob targetBlob = null;
string sourceBlobUrl = string.Empty;
foreach (var blob in blobSnapshots)
{
var blockBlob = (CloudBlockBlob) blob;
Console.WriteLine("Copying blob snapshot. Snapshot date/time = " + blockBlob.SnapshotTime);
sourceBlobUrl = string.Format("{0}&{1}", blockBlob.SnapshotQualifiedUri, sasToken.Substring(1));
targetBlob = targetContainer.GetBlockBlobReference(blobName);
targetBlob.StartCopy(new Uri(sourceBlobUrl));
//Check the status;
targetBlob.FetchAttributes();
do
{
var copyState = targetBlob.CopyState;
if (copyState.Status == CopyStatus.Pending)
{
Thread.Sleep(1000);//Copy not completed. Wait for it to complete.
targetBlob.FetchAttributes();
}
else
{
break;
}
}
while (true);
Console.WriteLine("Copying blob snapshot complete. Snapshot date/time = " + blockBlob.SnapshotTime);
Console.WriteLine("----------------------------");
//Now take the blob snapshot
Console.WriteLine("Taking blob snapshot....");
targetBlob.Snapshot();
Console.WriteLine("Blob snapshot taken....");
Console.WriteLine("----------------------------");
}
Console.WriteLine("Copying base blob.");
sourceBlobUrl = string.Format("{0}{1}", sourceBlob.Uri, sasToken);
targetBlob = targetContainer.GetBlockBlobReference(blobName);
targetBlob.StartCopy(new Uri(sourceBlobUrl));
//Check the status;
targetBlob.FetchAttributes();
do
{
var copyState = targetBlob.CopyState;
if (copyState.Status == CopyStatus.Pending)
{
Thread.Sleep(1000);//Copy not completed. Wait for it to complete.
targetBlob.FetchAttributes();
}
else
{
break;
}
}
while (true);
Console.WriteLine("Blob with snapshot copy completed!");
}
我正在尝试备份一些 blob 存储以防止意外删除容器,我可以使用 PowerShell 和 start-CopyAzurBlog 或从命令行使用 AZCopy 来很好地复制 blob,但是这些 blob 有一些快照(用作版本控制过程的一部分),每当我复制时,它都不会带走快照。
我知道您可以将 /snapshot 命令与 AZCopy 一起使用,但这会为每个快照创建一个全新的 blob,我需要它们成为单个 blob 的一部分。 反正有没有完整地复制这些?理想情况下,这将在 PowerShell 中进行,这样我就可以使用 Azure 自动化,但如果需要的话,我很乐意在 C# 中做一些事情。
我必须指出,您要求的功能很难实现。
Snapshot Blob API 只支持为当前的blob数据创建快照。因此,为了备份快照,我们需要在目标中创建与第一个快照具有相同数据的 blob,然后创建快照;并用与第二个快照相同的数据覆盖目标 blob,然后创建一个快照; ...;继续这样做,直到在目标中创建所有快照,最后用与当前源 blob 相同的数据覆盖目标 blob。
由于源 blob 的容量实际上并不是所有快照和当前 blob 的总和,如果您想在备份后也保存目的地的价格,您必须区分两个快照或最后一个快照和当前 blob,并且在每一步只覆盖不同的 blocks/pages,这可能会带来更多的复杂性。
这是符合赵兴路逻辑的代码。该方法是首先列出源 blob 的快照,根据快照在目标中创建 blob 并拍摄该 blob 的快照。最后,您会将基本 blob 复制到目标 blob。
static void CopyBlobAndSnapshots()
{
var sourceAccountName = "<source-account-name>";
var sourceAccountKey = "<source-account-key>";
var sourceContainerName = "<source-container-name>";
var targetAccountName = "<target-account-name>";
var targetAccountKey = "<target-account-key>";
var targetContainerName = "<target-container-name>";
var blobName = "<source-blob-name>";
var sourceAccount = new CloudStorageAccount(new StorageCredentials(sourceAccountName, sourceAccountKey), true);
var targetAccount = new CloudStorageAccount(new StorageCredentials(targetAccountName, targetAccountKey), true);
var sourceBlobClient = sourceAccount.CreateCloudBlobClient();
var sourceContainer = sourceBlobClient.GetContainerReference(sourceContainerName);
var sourceBlob = sourceContainer.GetBlockBlobReference(blobName);
var targetBlobClient = targetAccount.CreateCloudBlobClient();
var targetContainer = targetBlobClient.GetContainerReference(targetContainerName);
targetContainer.CreateIfNotExists();
//Create a SAS Token on source blob with read permissions that is valid for 2 weeks.
var sasToken = sourceBlob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = new DateTimeOffset(DateTime.UtcNow.AddDays(14))
});
//List blob snapshots first
var baseBlobAndSnapshots = sourceContainer.ListBlobs(blobName, true, BlobListingDetails.Snapshots).ToList();
//Since the list contains both base blob and snapshots, we should remove the base blob from this list.
var blobSnapshots = baseBlobAndSnapshots.Where(b => ((CloudBlockBlob)b).SnapshotTime != null).ToList();
//Now we should arrange them in reverse chronological order
blobSnapshots.Reverse();
CloudBlockBlob targetBlob = null;
string sourceBlobUrl = string.Empty;
foreach (var blob in blobSnapshots)
{
var blockBlob = (CloudBlockBlob) blob;
Console.WriteLine("Copying blob snapshot. Snapshot date/time = " + blockBlob.SnapshotTime);
sourceBlobUrl = string.Format("{0}&{1}", blockBlob.SnapshotQualifiedUri, sasToken.Substring(1));
targetBlob = targetContainer.GetBlockBlobReference(blobName);
targetBlob.StartCopy(new Uri(sourceBlobUrl));
//Check the status;
targetBlob.FetchAttributes();
do
{
var copyState = targetBlob.CopyState;
if (copyState.Status == CopyStatus.Pending)
{
Thread.Sleep(1000);//Copy not completed. Wait for it to complete.
targetBlob.FetchAttributes();
}
else
{
break;
}
}
while (true);
Console.WriteLine("Copying blob snapshot complete. Snapshot date/time = " + blockBlob.SnapshotTime);
Console.WriteLine("----------------------------");
//Now take the blob snapshot
Console.WriteLine("Taking blob snapshot....");
targetBlob.Snapshot();
Console.WriteLine("Blob snapshot taken....");
Console.WriteLine("----------------------------");
}
Console.WriteLine("Copying base blob.");
sourceBlobUrl = string.Format("{0}{1}", sourceBlob.Uri, sasToken);
targetBlob = targetContainer.GetBlockBlobReference(blobName);
targetBlob.StartCopy(new Uri(sourceBlobUrl));
//Check the status;
targetBlob.FetchAttributes();
do
{
var copyState = targetBlob.CopyState;
if (copyState.Status == CopyStatus.Pending)
{
Thread.Sleep(1000);//Copy not completed. Wait for it to complete.
targetBlob.FetchAttributes();
}
else
{
break;
}
}
while (true);
Console.WriteLine("Blob with snapshot copy completed!");
}