Rotina de transferir Blob do tipo Page de uma Storage Account GPV1 para a Storage Account Blob com access tier Cool

Hoje vamos falar sobre uma rotina que iremos criar em nosso ambiente para poder economizar com armazenamento de nossos backups.

Relembrando, o nosso cenário é o seguinte:

  • Backup sendo realizados diretamente para um Storage General Porpose V1(GPV1);
  • O Blob está indo com o tipo “page”;
  • Temos que reter esses backups durante 3 meses;
  • Passar o Blob do tipo Page do  GPV1 para Storage Account “Blob” e acces tier Cool.

Como que realizaremos esses procedimentos, sendo que a Storage Account do tipo Blob não aceita o blobs do tipo“Page”?

Aqui eu tento passar o backup de um blob storage para outro através do “Microsoft Azure Storage Explorer”, porém é me retornado o erro:

Obs.: a stgcomunidadesqlserver1 é a storage account do tipo GPV1 e a stgcomunidadesqlserver0 é do tipo Blob.

Ao tentar passar via powershell com o comando “Start-AzureStorageBlobCopy” me retorna o mesmo erro e agora? Como que faço?

 

Simples! Basta converter o tipo do blob para block antes remove-lo, certo?

NO!

A gente especifica o tipo do blob quando o criamos e após isto, não é possível modificá-lo.

Fonte: https://docs.microsoft.com/en-us/rest/api/storageservices/Understanding-Block-Blobs–Append-Blobs–and-Page-Blobs?redirectedfrom=MSDN

Desta forma, a solução seria utilizar o AZCopy para baixar este arquivo para meu servidor e depois realizar o Download novamente.

Aqui não irei detalhar sobre o AZCopy, mas para quem nunca o utilizou pode ter todos os detalhes no link: https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azcopy

Login-AzureRmAccount #Passar as credenciais para acessar o Azure

Set-AzureRmContext -SubscriptionName "SubscriptionName"

#Preenche as variáveis para pegar os arquivos do Storage stgcomunidadesqlserver1
$SubscriptionName = "SubscriptionName"
$ResourceName = "ComunidadeSQLServer"
#Aqui eu coloco o nome do diretório para qual quero baixar meus backups
$destFile = "E:\RotinaAzCopy"
#storage account de origem
$srcStorageAccount = "stgcomunidadesqlserver1"
#Aqui estou pegando a access key da storage account para acessá-la
$srcStorageKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceName -StorageAccountName $srcStorageAccount).Value[0]
$srcContext = New-AzureStorageContext -StorageAccountName $srcStorageAccount -StorageAccountKey $srcStorageKey
#Conteiner de origem
$srcContainer = "backup"
$srcBlob = (Get-AzureStorageBlob -context $srcContext -Container $srcContainer)
$srcBlob2 = $srcBlob.name

#Muda de pasta para usar o AzCopy
Set-Location "C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy"

.\AzCopy.exe  /Source:https://stgcomunidadesqlserver1.blob.core.windows.net/backup /Dest:$destFile /SourceKey:$srcStorageKey /Pattern:$srcBlob2 /Y 

Resultado:

E para passar o Blob da pasta local para o Storage Account do tipo Blob basta executar:

#Aqui começa a parte de enviar os arquivos para o storage cold
$coldStorageAccount = "stgcomunidadesqlserver0"
$coldStorageKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceName -StorageAccountName $coldStorageAccount).Value[0]
$coldContext = New-AzureStorageContext -StorageAccountName $coldStorageAccount -StorageAccountKey $coldStorageKey


.\AzCopy.exe /Source:$destFile /Dest:https://stgcomunidadesqlserver0.blob.core.windows.net/rotinamove /DestKey:$coldStorageKey /Y /S

Resultado:

Podemos observar que o “Access Tier” e o “Blob Type” já estão alterados. Isso porque nesta Storage Account o Access Tier padrão é o cool (configurei assim) e quando enviamos algum arquivo via AZCopy, o padrão dele é do tipo Block . Caso você queira mudar o tipo do blob ao fazer o upload dele, basta passar o parâmetro: /BlobType:”TipoDoBlob” , mas neste caso, não necessitamos de passar este parâmetro.

Então, juntando os dois, o comando completo ficaria assim:

Login-AzureRmAccount #Passar as credenciais para acessar o Azure

Set-AzureRmContext -SubscriptionName "SubscriptonName"

#Preenche as variáveis para pegar os arquivos do Storage stgcomunidadesqlserver1
$SubscriptionName = "SubscriptonName"
$ResourceName = "ComunidadeSQLServer"
#Aqui eu coloco o nome do diretório para qual quero baixar meus backups
$destFile = "E:\RotinaAzCopy"
#storage account de origem
$srcStorageAccount = "stgcomunidadesqlserver1"
#Aqui estou pegando a access key da storage account para acessá-la
$srcStorageKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceName -StorageAccountName $srcStorageAccount).Value[0]
$srcContext = New-AzureStorageContext -StorageAccountName $srcStorageAccount -StorageAccountKey $srcStorageKey
#Conteiner de origem
$srcContainer = "backup"
$srcBlob = (Get-AzureStorageBlob -context $srcContext -Container $srcContainer)
$srcBlob2 = $srcBlob.name

#Muda de pasta para usar o AzCopy
Set-Location "C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy"

.\AzCopy.exe  /Source:https://stgcomunidadesqlserver1.blob.core.windows.net/backup /Dest:$destFile /SourceKey:$srcStorageKey /Pattern:$srcBlob2 /Y 



#Aqui começa a parter de enviar os arquivos para o storage cold
$coldStorageAccount = "stgcomunidadesqlserver0"
$coldStorageKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceName -StorageAccountName $coldStorageAccount).Value[0]
$coldContext = New-AzureStorageContext -StorageAccountName $coldStorageAccount -StorageAccountKey $coldStorageKey


.\AzCopy.exe /Source:$destFile /Dest:https://stgcomunidadesqlserver0.blob.core.windows.net/rotinamove /DestKey:$coldStorageKey /Y /S

Porém, desta forma, estamos baixando somente um arquivo e se eu tiver vários arquivos a serem transferidos e com uma data de corte?

Nesta mesma lógica que utilizamos o AzCopy, vamos acrescentar o loop FOR e o Where-Object:

E o script vai ficar assim:

Login-AzureRmAccount #Passar as credenciais para acessar o Azure

Set-AzureRmContext -SubscriptionName "SubscriptionName"

#Preenche as variáveis para pegar os arquivos do Storage stgcomunidadesqlserver1
$SubscriptionName = "SubscriptionName"
$ResourceName = "ComunidadeSQLServer"

#Aqui eu coloco o nome do diretório para qual quero baixar meus backups
$destFile = "E:\RotinaAzCopy"
$srcStorageAccount = "stgcomunidadesqlserver1"

#Aqui estou pegano a access key da storage account para acessá-la
$srcStorageKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceName -StorageAccountName $srcStorageAccount).Value[0]
$srcContext = New-AzureStorageContext -StorageAccountName $srcStorageAccount -StorageAccountKey $srcStorageKey

#Conteiner de origem
$srcContainer = "backup"

#colocar aqui a data de corte dos backups que deseja passar para o storage Cool. 
#Neste exemplo estamos passando a data com -7 dias
$dataExclusao = (Get-Date).AddDays(-7) 

#Aqui acrescentaremos o Where-Object a data de corte que passamos na vareável anterior
#Obs.: Para exemplo, comentei a parte do Where-Object, pois quis passar todos os backups do conteiner
$srcBlob = (Get-AzureStorageBlob -context $srcContext -Container $srcContainer) | Where-Object {$_.LastModified -lt $dataExclusao}

#Aqui estamos pegando somente o nome do blob, descartando as demais informações
$srcBlob2 = $srcBlob.name



#Aqui começa a parte de enviar os arquivos para o storage cood (Destino)
$coldStorageAccount = "stgcomunidadesqlserver0"
$coldStorageKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $ResourceName -StorageAccountName $coldStorageAccount).Value[0]
$coldContext = New-AzureStorageContext -StorageAccountName $coldStorageAccount -StorageAccountKey $coldStorageKey



#Muda de pasta para usar o AzCopy
Set-Location "C:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy"

#Na primeira execução, esta parte retornará um erro, pois os arquivos ainda não existirão
#Estes arquivos criei para verificar se minha rotina foi com sucesso ou não
Remove-Item E:\ResultadoRotinaAzCopy\resultadoQuente.txt -recurse -Confirm:$false   
Remove-Item E:\ResultadoRotinaAzCopy\resultadoFrio.txt -recurse -Confirm:$false   


#Aqui estpu pegando somente a quantidade de arquivos e logando 
$srcBlob2.Count | Out-File E:\ResultadoRotinaAzCopy\resultadoQuente.txt -append

#Utilizaremos esta data para futuras verificações
#Importante lembrar que a timezone do servidor deverá ser a mesma do azure, pois aqui estamos usando a data como filtro
$DataInicio = (Get-Date)

#Cria um loop para baixar somente os arquivos que eu quero
for ($i=0; $i -lt $srcBlob2.Count; $i++) {
    #Nas duas próximas linhas passo o arquivo na posição do array, jogo na variável e depois logo no meu arquivo .txt
    $file = $srcBlob2[$i]
    $file | Out-File E:\ResultadoRotinaAzCopy\resultadoQuente.txt -append

    #Aqui começo o procedimento do download do meu backup e logo novamente o resultado. 
    #Observar que desta vez estamos passando o parâmetro /Pattern: , pois queremos pegar somente um arquivo.
    .\AzCopy.exe  /Source:https://stgcomunidadesqlserver1.blob.core.windows.net/backup /Dest:$destFile /SourceKey:$srcStorageKey /Pattern:$file /Y | Out-File E:\ResultadoRotinaAzCopy\resultadoQuente.txt -append
    $file  | Out-File E:\ResultadoRotinaAzCopy\resultadoFrio.txt -append
   
    #Aqui começo o meu upload para o blob de destino
    .\AzCopy.exe /Source:$destFile /Dest:https://stgcomunidadesqlserver0.blob.core.windows.net/rotinamove /DestKey:$coldStorageKey /Y | Out-File E:\ResultadoRotinaAzCopy\resultadoFrio.txt -append
    Remove-Item $destFile -recurse -Confirm:$false   
}

#Importante lembrar que a timezone do servidor deverá ser a mesma do azure, pois aqui estamos usando a data como filtro 
$ResultadoCold = (Get-AzureStorageBlob -context $coldContext -Container "rotinamove" | Where-Object  {$_.LastModified -ge $DataInicio})
$resultadoCold2 = $resultadoCold.name

$TamanhoCold = $resultadoCold2.Count
$tamanhoHot = $srcBlob2.Count

#Aqui realizaremos uma simples verificação se todos os blobs do período que quis passar foram com sucesso.
#Caso positivo, os blobs da origem serão excluídos
IF($TamanhoCold -eq $tamanhoHot) {

    Get-AzureStorageBlob -context $srcContext -Container $srcContainer | Where-Object {$_.LastModified -le $dataExclusao} | Remove-AzureStorageBlob | Out-file F:\Resultado\ErroDelete.txt

}


Blob de Origem:

Blob de destino:

Ficando com a nossa arquitetura final:

Para completar, como queremos deixar isso automático, podemos criar um job no Agent (isso mesmo, dentro do SQL Server) para que todos os dias as “X” horas essa rotina é executada. A única diferença é que no comando  Login-AzureRmAccount  já tenhamos que passar as credenciais. Talvez isso seja uma “falha” se segurança, mas levando em consideração que somente pessoas autorizadas terão acesso aos jobs, e que a conta que será configurada tiver somente o acesso restrito à movimentação de arquivos entre as storage accounts, certamente não teremos problemas com segurança!

Acrescentando o código assim:

$Usuario = "sqlazure@seudominio.onmicrosoft.com"
$secpasswd = ConvertTo-SecureString "senha" -AsPlainText -Force
$mycreds = New-Object -typename System.Management.Automation.PSCredential -ArgumentList $Usuario,$secpasswd

#Loga no Azure
Login-AzureRmAccount -Credential $mycreds

Desta forma, espero que não tenha ficado confuso os scripts (ainda tenho que melhorar e muito em minhas documentações de códigos rsrs), mas qualquer dúvida estou disponível para responder.

Até o próximo post: “Limitações/Erros (Access Key Credential)”

Anúncios