AzCopyAzure_00

Kopiowanie plików na Azure Storage przy pomocy AzCopy

Jednym z podstawowych zadań z jakimi musimy się zmierzyć pracując z Azure jest umieszczenie przeróżnych plików w Azure BLOB Storage lub Azure Data Lake Storage Gen 2. Niezależnie od tego czy są to pliki kopii zapasowych, multimediów czy też pliki przeznaczone do analizy to musimy poznać metody i narzędzia służące do transferu tyche do Azure. Narzędzi czy też metod do wykonania tego typu zadania naprawdę dużo są to m.in:

  • Azure portal  – po zalogowaniu się na portalu mamy odpowiednie opcja pozwalające na wrzucenie plików poprzez prosty mechanizm uploadu,
  • Azure Storage Explorer – dedykowane oprogramowanie, które podobnie jak w powyższym przypadku pozwala nam na bezproblemowe wrzucenie plików (pod spodem wykonywana jest komenda AzCopy ale o tym później).
  • Azure API/SDK – narzędzia programistyczne posiadające zestaw metod i komend pozwalających na manipulowanie transferem danych z i na Azure Storage,
  • Azure Data Factory – skalowalny serwis pozwalający na przerzucanie i transformowanie danych m.in na BLOBa.

Oprócz wyżej wymienionych narzędzi jest jeszcze  bohater dzisiejszego artykułu czyli AzCopy. Jest to narzędzie linii komend, które w niezwykle prosty sposób pozwala nam wrzucać i pobierać dane z Azure Storage. Dodatkowo posiada wbudowane możliwości związane z równoległością, wykorzystaniem wątków czy też dekompresją skompresowanych plików. W ramach dzisiejszego artykułu chciałbym zrobić proste wprowadzenie do tego narzędzia tak więc serdecznie zapraszam do lektury.

Pierwszym krokiem jaki musimy wykonać jest pobranie samego narzędzia ze strony Microsoftu (link). Narzędzie jest w pełni darmowe i działa zarówno pod Windowsem, Linuksem jak i MacOs. Jedyne co musimy zrobić to ściągnąć i wypakować archiwum w którym znajduje się plik wykonywalny. Umieściłem ten plik w następującej lokalizacji (używam oczywiście Powershella z poziomu Visual Studio Code):

Set-Location C:\Tools

Możliwości uwierzytelnienia do chmury jest co najmniej kilka – na pierwszy rzut użyjemy prostego okna logowania, które wywołamy następującą komendą:

./azcopy.exe login

Spowodowało to wyświetlenie następującego komunikatu:

PS C:\Tools> ./azcopy.exe login
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code DPEQSS56 to authenticate.

INFO: Logging in under the "Common" tenant. This will log the account in under its home tenant.
INFO: If you plan to use AzCopy with a B2B account (where the account's home tenant is separate from the tenant of the target storage account), please sign in under the target tenant with --tenant-id

Logowałem się spoza sieci i zostałem poproszony o podanie kodu na stronie Microsoftu gdzie musiałem się zalogować w standardowy sposób używając konta domenowego i podać kod zwrócony przez narzędzie. Pokazuje cały ten proces ponieważ różni się on nieco od logowania ze zwykłym promptem jaki dostajemy chociażby w REST API Power BI.

Po zalogowaniu wywołałem pomoc aby zapoznać się z dostępnymi przełącznikami narzędzia:

./azcopy.exe --help

Moim oczom ukazała się cała gama informacji o narzędziu w tym kilka dostępnych opcji:

  • bench,
  • copy,
  • doc,
  • env,
  • help,
  • jobs,
  • list,
  • login.

Dwa z nich już poznaliśmy tj. help oraz login. Pokażemy sobie jeszcze kilka dodatkowych gdzie najbardziej istotnym jest oczywiście komenda copy wykonująca rzeczywistą operację kopiowania.

Na potrzeby naszej prezentacji stworzyłem Storage Account zawierający BLOB Storage o nazwie prtdevsa, a w ramach niego utworzyłem kontener o nazwie azcopytest do którego wrzuciłem kilka plików csv. Zanim zaczniemy przeglądać pliki na BLOBie wyloguje się ponieważ będziemy się uwierzytelniać używając Shared Access Signature:

.\azcopy logout

Efekty naszych działań będziemy podglądać w Azure Storage Explorer. O tym jak skonfigurować to narzędzie i stworzyć Storage Account pisałem w ramach artykułu o odpytywaniu Azure BLOB Storage z poziomu OPENROWSET, który znajdziecie tutaj. Wszystko mam gotowe dlatego też wygeneruje sobie SAS dla całego kontenera z interfejsu graficznego:

Konfiguracja sygnatury jest oczywiście czasowa tak więc będzie ona aktywna tylko przez kilka godzin – dla uproszczenia nadał wszystkie możliwe uprawnienia:

Po kliknięciu Create dostaniemy pełne URI do zasobu wraz z parametrem sygnatury:

Uri będzie dla nas o tyle istotne, że będziemy go używać jako odnośnika w ramach AzCopy – poniższa komenda listuje wszystkie pliki znajdujące się na BLOBie:

.\azcopy.exe list "https://prtdevsa.blob.core.windows.net/azcopytest?sv=2019-10-10&st=2020-09-13T16%3A12%3A13Z&se=2020-09-13T18%3A12%3A00Z&sr=c&sp=racwdxl&sig=tMRiS%2B0QYjGEzExNCy15o4f7GtSXH6QRr1G9Nrm43WQ%3D"

W rezultacie otrzymałem listę plików znajdujących się w danym kontenerze wraz z ich rozmiarem:

Widzimy, że kontener na BLOB Storage zawiera kilka plików tak więc spróbujmy je teraz ściągnąć na lokalny dysk. W tym wypadku wystarczy wywołać komendę AzCopy Copy gdzie jako pierwszy parametr podajemy źródło, a drugi to miejsce docelowe:

.\azcopy.exe copy "https://prtdevsa.blob.core.windows.net/azcopytest?sv=2019-10-10&st=2020-09-13T16%3A12%3A13Z&se=2020-09-13T18%3A12%3A00Z&sr=c&sp=racwdxl&sig=tMRiS%2B0QYjGEzExNCy15o4f7GtSXH6QRr1G9Nrm43WQ%3D" 
"C:\temp" --recursive

Dodatkowo powyżej możecie zauważyć przełącznik –recursive, który jest obligatoryjny ponieważ wskazaliśmy cały kontener jako źródło kopiowania (moglibyśmy również użyć wildcarda * wskazującego na wszystkie pliki wewnątrz danej lokalizacji). Jako zwrotkę otrzymaliśmy następujące informacje:

INFO: Scanning...
INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support

Job ca9f748a-1fc7-784a-57bc-c71056226908 has started
Log file is located at: C:\Users\adria\.azcopy\ca9f748a-1fc7-784a-57bc-c71056226908.log

0.0 %, 0 Done, 0 Failed, 6 Pending, 0 Skipped, 6 Total, 


Job ca9f748a-1fc7-784a-57bc-c71056226908 summary
Elapsed Time (Minutes): 0.0334
Number of File Transfers: 6
Number of Folder Property Transfers: 0
Total Number of Transfers: 6
Number of Transfers Completed: 6
Number of Transfers Failed: 0
Number of Transfers Skipped: 0
TotalBytesTransferred: 915199
Final Job Status: Completed

Patrząc na powyższą informację dane powinny zostać pobrane bez większych problemów. Gdy zajrzymy do folderu docelowego pliki znalazły się w odpowiednim miejscu:

Dla celów testowych utworzyłem kopię jednego z plików znajdujących się w moim lokalnym folderze (dbo_test.csv) po to aby wrzucić go na BLOBa – posłuży do tego tak jak powyżej komenda AzCopy Copy z tym, że teraz wskazałem konkretny plik jako źródło i kontener jako miejsce docelowe (SAS nadal użyty jako metoda uwierzytelnienia):

.\azcopy.exe copy "C:\temp\azcopytest\dbo_test - Copy.csv"  
"https://prtdevsa.blob.core.windows.net/azcopytest?sv=2019-10-10&st=2020-09-13T16%3A12%3A13Z&se=2020-09-13T18%3A12%3A00Z&sr=c&sp=racwdxl&sig=tMRiS%2B0QYjGEzExNCy15o4f7GtSXH6QRr1G9Nrm43WQ%3D"

Wszystko powiodło się bez większych komplikacji co widzimy w informacji zwrotnej oraz w Storage Explorer:

INFO: Scanning...
INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support

Job d8ba0fd5-26b9-ad4f-654d-30d5c947a522 has started
Log file is located at: C:\Users\adria\.azcopy\d8ba0fd5-26b9-ad4f-654d-30d5c947a522.log

0.0 %, 0 Done, 0 Failed, 1 Pending, 0 Skipped, 1 Total, 2-sec Throughput (Mb/s): 2.228


Job d8ba0fd5-26b9-ad4f-654d-30d5c947a522 summary
Elapsed Time (Minutes): 0.0667
Number of File Transfers: 1
Number of Folder Property Transfers: 0
Total Number of Transfers: 1
Number of Transfers Completed: 1
Number of Transfers Failed: 0
Number of Transfers Skipped: 0
TotalBytesTransferred: 878604
Final Job Status: Completed

Proste kopiowanie to oczywiście nie wszystko co jest możliwe do osiągnięcia przy pomocy opisywanego narzędzia. Niezwykle przydatny może być przełącznik Sync, który na podstawie daty modyfikacji rozpoznaje które pliki powinny zostać wrzucone do miejsca docelowego. Aby to zobrazować zmodyfikowałem plik dbo_test.csv i użyłem komendy AzCopy Sync w następującej konfiguracji:

.\azcopy.exe sync "C:\temp\azcopytest\"  
"https://prtdevsa.blob.core.windows.net/azcopytest?sv=2019-10-10&st=2020-09-13T16%3A12%3A13Z&se=2020-09-13T18%3A12%3A00Z&sr=c&sp=racwdxl&sig=tMRiS%2B0QYjGEzExy15o4f7GtSXH6QRr1G9Nrm43WQ%3D"

Widzimy, że przetransferowany został jeden plik, który został zmieniony:

INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support

Job 87d67e80-9d94-fe43-4ae5-c9bf7684cadd has started
Log file is located at: C:\Users\adria\.azcopy\87d67e80-9d94-fe43-4ae5-c9bf7684cadd.log

0.0 %, 0 Done, 0 Failed, 1 Pending, 1 Total, 2-sec Throughput (Mb/s): 4.1941

Job 87d67e80-9d94-fe43-4ae5-c9bf7684cadd Summary
Files Scanned at Source: 7
Files Scanned at Destination: 7
Elapsed Time (Minutes): 0.1334
Number of Copy Transfers for Files: 1
Number of Copy Transfers for Folder Properties: 0
Total Number Of Copy Transfers: 1
Number of Copy Transfers Completed: 1
Number of Copy Transfers Failed: 0
Number of Deletions at Destination: 0
Total Number of Bytes Transferred: 2635564
Total Number of Bytes Enumerated: 2635564
Final Job Status: Completed

Oprócz synchronizacji plików pomiędzy środowiskiem on-prem oraz Azure możliwy jest transfer pomiędzy różnymi kontenerami czy też kontami Azure Storage. Wystarczy wskazać URI określonych kont pomiedzy którymi chcemy dokonać transferu.

Przechodząc dalej warto wspomnieć, że każde uruchomienie operacji AzCopy jest rejestrowane jako tzw. job i możemy je podejrzeć wywołując komendę:

.\azcopy.exe jobs list
Existing Jobs
JobId: ea724e85-20d9-314b-7d8a-2ac6f7d487d6
Start Time: Sunday, 13-Sep-20 19:11:00 CEST
Status: Completed
Command: sync C:\temp\azcopytest\ https://prtdevsa.blob.core.windows.net/azcopytest?se=2020-09-13t18%3A12%3A00z&sig=REDACTED&sp=racwdxl&sr=c&st=2020-09-13t16%3A12%3A13z&sv=2019-10-10

To właśnie przy pomocy tej właśnie komendy możemy sprawdzić statusy poszczególnych uruchomień itp.  Każde uruchomione zadanie posiada swój identyfikator i jest w pełni logowane – pliki loga znajdują się domyślnie w folderze z profilem użytkownika uruchamiającego narzędzie i są nazwane według identyfikatora:

Jedną z największych zalet AzCopy jest to, że jesteśmy w stanie uruchomić przerwany proces kopiowania. Na powyższym zrzucie ekranowym możecie zauważyć folder “Plans” – to właśnie tam trzymane są informacje o postępie kopiowania plików. Jeśli z jakiegoś powodu  kopiowanie zostanie przerwane to możemy je wznowić dzięki właśnie folderowi plans.  Zademonstruje to w taki sposób, że najpierw wyczyszczę informacje o jobach które wykonałem:

./azcopy.exe jobs clean

Następnie ustawię zmienną środowiskową w taki sposób aby kopiowany był tylko jeden plik na raz (listę dostępnych zmiennych środowiskowych możecie zobaczyć wykonując komendę azcopy env):

$env:AZCOPY_CONCURRENT_FILES=1

Po uruchomieniu operacji kopiowania (tym razem zamiast przełącznika recursive użyłem *):

 ./azcopy copy "C:\temp\azcopytest\*" 
"https://prtdevsa.blob.core.windows.net/azcopytest?sv=2019-10-10&st=2020-09-13T16%3A12%3A13Z&se=2020-09-13T18%3A12%3A00Z&sr=c&sp=racwdxl&sig=tMRiS%2B0QYjGEzExNCy15o4f7GtSXH6QRr1G9Nrm43WQ%3D"

Następnie w trakcie wykonywania powyższej komendy wyłączyłem sieć i po sprawdzeniu statusu dostałem następujące informacje:

Po zrestartowaniu linii komend i przywróceniu dostępu do internetu status nadal był “InProgress”  więc z całą pewnością coś poszło nie tak. Możemy joba wybudzić z letargu komendą resume:

./azcopy.exe jobs resume "567a8c7f-74cc-154d-5003-f25e05afb470" 
--destination-sas "sv=2019-10-10&st=2020-09-13T16%3A12%3A13Z&se=2020-09-13T18%3A12%3A00Z&sr=c&sp=racwdxl&sig=tMRiS%2B0QYjGEzExNCy15o4f7GtSXH6QRr1G9Nrm43WQ%3D"

Jedynymi przełącznikami jakie musieliśmy ustawić był identyfikator joba oraz  –destination-sas gdzie na nowo musieliśmy podać sygnature SAS ( w tym wypadku w ramach parametru destination sas ale jeśli BLOB Storage byłby użyty jako źródło to mamy również parametr źródła). Po chwili dostaliśmy potwierdzenie, że wszystko jest w porządku:

Job 567a8c7f-74cc-154d-5003-f25e05afb470 has started
Log file is located at: C:\Users\adria\.azcopy\567a8c7f-74cc-154d-5003-f25e05afb470.log

25.8 %, 6 Done, 0 Failed, 1 Pending, 0 Skipped, 7 Total, 2-sec Throughput (Mb/s): 1.236 


Job 567a8c7f-74cc-154d-5003-f25e05afb470 summary
Elapsed Time (Minutes): 0.3001
Number of File Transfers: 7
Number of Folder Property Transfers: 0
Total Number Of Transfers: 7
Number of Transfers Completed: 7
Number of Transfers Failed: 0
Number of Transfers Skipped: 0
TotalBytesTransferred: 3550763
Final Job Status: Completed

Na co wskazują również logi:

Existing Jobs
JobId: 567a8c7f-74cc-154d-5003-f25e05afb470
Start Time: Sunday, 13-Sep-20 19:56:56 CEST
Status: Completed
Command: copy C:\temp\azcopytest\*

Bardzo ciekawy mechanizm pozwalający sprawnie zarządzać transferem plików nawet w przypadku wystąpienia problemów. Wszystkie przykłady, które tutaj przedstawiłem opierały się na BLOB Storage ale AzCopy może również być użyty to kopiowania plików do Azure Data Lake Storage Gen 2.  Dla testów stworzyłem ten typ storage, co możecie zobaczyć na poniższym zrzucie ze Storage Explorera:

Używając intefejsu graficznego narzędzia wrzuciłem tam plik i co ciekawe możemy tam dostrzec dosyć ciekawą opcjęo której wspomniałem we wstępie, a którą możecie dostrzec na poniższym zrzucie ekranowym:

Okazuje się, że “pod spodem” Storage Explorer używa AzCopy do wszelkich operacji transferu plików. Skopiowana komenda wygląda następująco:

$env:AZCOPY_CRED_TYPE = "Anonymous";

./azcopy.exe copy "C:\temp\azcopytest\dbo_DimCustomerStage.csv" 
"https://adlsprt.blob.core.windows.net/demo2/dbo_DimCustomerStage.csv?sv=2019-10-10&se=2020-10-10T18A12%3A56Z&sr=c&sp=rwl&sig=Or53fcDz%2FZdueVoMKjzNMUb9SQVTyG3uVSpd2qM%3D" --overwrite=prompt --from-to=LocalBlob --blob-type BlockBlob --follow-symlinks --put-md5 --follow-symlinks --recursive;

$env:AZCOPY_CRED_TYPE = "";

Mając tą wiedzę możemy podejrzeć działanie poszczególnych operacji AzCopy wygenerowanych z narzędzia – całkiem ciekawe!

Tak więc do ADLSG2 również możemy dostać się przy pomocy sygnatury SAS i skopiować interesujące nas pliki. Możliwości jest całkiem sporo jednakże nie omówiliśmy wszytskich scenariuszy.
Wiemy, że w przypadku ADLS mamy nieco więcej możliwości jak chociażby możliwość oparcia uwierzytelniania o AD.  Aby to zrobić zarejestrujmy naszą aplikację w Azure. Na portalu wyszukujemy App registration:

Po wybraniu App registration wybieramy nową rejestrację (New registration):

Do celów testowych ustawimy naszą aplikację w następujący sposób:

Następnie przypiszemy sobie do appki Secret czyli wybieramy z menu Certificates & secrets:

Następnie wybieramy New client secret oraz nadajemy nazwę i czas po jakim sekret wygaśnie:

Wygenerowane hasło zapisujemy na boku, a w głównym oknie aplikacji dostaniemy dodatkowo Client ID oraz Tenant ID potrzebne w naszym skrypcie:

Rejestrując aplikację możemy nadać jej uprawnienia do ADLS. Metod jest wiele ale w tym demo wybierzemy Manage Access dostępny w menu kontekstowym w Storage Explorer:

Wyszukujemy aplikację po nadanej nazwie. Następnie możemy nadać uprawnienia. Warto zwrócić uwagę na to, że uprawnienie Default spowoduje, że uprawnienie zostanie nadane również elementom wewnątrz kontenera ale tylko które się tam znajdą po nadaniu tych uprawnień! Może to czasem powodować niemałe zamieszanie więc warto o tym pamiętać.

Mając już nadane uprawnienia możemy przejść do skryptu. Najpierw przypisujemy sekret do zmiennej środowiskowej AZCOPY_SPA_CLIENT_SECRET (sekret traktujemy jak hasło i nie wpisujemy go w taki sposób jak poniżej – ja zapisałem go bezpośrednio tylko i wyłącznie w celach demonstracyjnych). Następnie wywołujemy AzCopy z przełącznikiem login oraz –service principal. Dodatkowo musimy podać –application-id oraz –tenant-id o których mówiłem wyżej:

$env:AZCOPY_SPA_CLIENT_SECRET="KOchk344R6.gN5eWd2It_b-~3VAJx2_Sw1"

./azcopy.exe login --service-principal  --application-id "13218857-642d-4c33-90c0-72df3d98496f" --tenant-id="f8be387a6-f648-4s47-aaac-8dsa6c5c6604d"
INFO: If you set an environment variable by using the command line, that variable will be readable in your command line history. Consider clearing variables that contain credentials from your command line history.  To keep variables from appearing in your history, you can use a script to prompt the user for their credentials, and to set the environment variable.
INFO: SPN Auth via secret succeeded.

Po uwierzytelnieniu samo kopiowanie wygląda dokładnie tak samo jak poprzednio:

./azcopy.exe copy "C:\temp\azcopytest\dbo_DimCustomerStage.csv" "https://adlsprt.blob.core.windows.net/demo2"
INFO: Scanning...
INFO: Authenticating to destination using Azure AD
INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support

Job 797615e6-0d6c-044a-6f75-6ebbf409cf9c has started
Log file is located at: C:\Users\adria\.azcopy\797615e6-0d6c-044a-6f75-6ebbf409cf9c.log

0.0 %, 0 Done, 0 Failed, 1 Pending, 0 Skipped, 1 Total, 


Job 797615e6-0d6c-044a-6f75-6ebbf409cf9c summary
Elapsed Time (Minutes): 0.0334
Number of File Transfers: 1
Number of Folder Property Transfers: 0
Total Number of Transfers: 1
Number of Transfers Completed: 1
Number of Transfers Failed: 0
Number of Transfers Skipped: 0
TotalBytesTransferred: 35283
Final Job Status: Completed

Sprawdźmy czy plik, który skopiowaliśmy rzeczywiście znalazł się tam gdzie chcieliśmy:

./azcopy.exe list "https://adlsprt.blob.core.windows.net/demo2"
INFO: Authenticating to destination using Azure AD
INFO: dbo_DimCustomerStage.csv; Content Length: 34.46 KiB

Powyższy funkcjonalności wydają mi się fundamentem jeśli chodzi o używanie AzCopy, największą zagwostką może okazać się sposób uwierzytelnienia ale po jego poznaniu nie powinniśmy mieć już więcej problemów. Jeśli jesteście zainteresowani narzędziem to polecam potrenować jego użycie szczególnie, że jest jeszcze cała masa opcji o których możecie przeczytać w dokumentacji https://docs.microsoft.com/en-us/azure/storage/common/storage-ref-azcopy-copy. Szczególnie polecam zapoznać się z ustawieniami związanymi z wydajnością, które dostosowane do możliwości naszej sieci superwydajnie są w stanie wrzucić nawet ogromne zbiory danych do chmury. Na ten moment to by było na tyle. Jak zwykle zachęcam was do sybskrypcji i życzę udanego dania!

Leave a Reply