Microsoft MVP성태의 닷넷 이야기
개발 환경 구성: 496. Azure - Blob Storage Account의 Location 이전 방법 [링크 복사], [링크+제목 복사]
조회: 11796
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

Azure - Blob Storage Account의 Location 이전 방법

지난 글에도 언급했지만,

Azure - Location이 다른 웹/DB 서버의 경우 발생하는 성능 하락
; https://www.sysnet.pe.kr/2/0/12273

Azure는 Location 이전을 수작업으로 해야 합니다. 이에 대해 방법을 찾아보면 아래의 문서가 나오는데,

Azure Storage 계정을 다른 지역으로 이동
; https://learn.microsoft.com/ko-kr/azure/storage/common/storage-account-move?tabs=azure-portal

기존 Storage의 template을 내보내는 방법과 신규 Storage에서 가져오는 방법을 설명하는 것으로, 이것은 해당 Storage에 설정한 환경을 복사하는 것일 뿐 데이터를 마이그레이션하는 작업은 하지 않습니다. 즉, 데이터 이전은 별도로, 수작업으로 해야 합니다. ^^;

또한 "Azure Storage 계정을 다른 지역으로 이동" 문서의 마지막에 보면 "Azure Data Factory"를 사용하여 데이터를 이동할 수도 있습니다. 직관적인 사용자 인터페이스를 제공합니다."라는 설명으로 "Azure Data Factory"를 이용하면 왠지 간단한 절차만으로 해결될 것 같지만 해당 문서를 보면,

Copy and transform data in Azure Blob storage by using Azure Data Factory
; https://learn.microsoft.com/ko-kr/azure/data-factory/connector-azure-blob-storage

그냥 azcopy로 처리하는 것이 더 낫겠다는 생각을 (10초도 안되어서) 하게 될 것입니다. ^^; AzCopy의 사용법은,

Get started with AzCopy
; https://learn.microsoft.com/ko-kr/azure/storage/common/storage-use-azcopy-v10?toc=/azure/storage/blobs/toc.json

Transfer data with AzCopy and Blob storage
; https://learn.microsoft.com/ko-kr/azure/storage/common/storage-use-azcopy-blobs

그나마 직관적입니다. 일단, Azure Blob Storage에서 로컬로 복사한다면 다음과 같은 형식으로 실행할 수 있습니다.

azcopy copy 'https://<source-storage-account-name>.blob.core.windows.net/<container-name><SAS-token>' '<local-file-path>' --recursive

예를 들어,

source-storage-account-name == udb.blob.core.windows.net
local-file-path == d:\temp

위의 조건이라면 다음과 같이 실행할 수 있습니다.

azcopy copy "https://udb.blob.core.windows.net?...[SAS-token]..." "d:\temp" --recursive

여기서 아직 구하지 못한 것이 SAS(Shared access signature) token 값인데, 이것은 Azure Portal에서 다음의 화면을 통해,

sas_token_1.png

구할 수 있습니다. 예를 들어, SAS Token의 값이 다음과 같이 구해졌다면,

?sv=2019-10-10&ss=bfqt&srt=sco&sp=rwdlacupx&se=2020-07-18T14:51:29Z&st=2020-07-16T06:51:29Z&sip=168.126.144.30&spr=https&sig=QijTJGThP%3BEi3tSEgCnVZQylMY162FrIg9wafuuFU8E%3D

최종적으로 이렇게 실행하면 됩니다.

azcopy copy "https://udb.blob.core.windows.net?sv=2019-10-10&ss=bfqt&...[생략]..." "d:\temp" --recursive

만약, 전체 Storage가 아니라 하위 Container만 특정하고 싶다면 URL에 덧붙여 실행할 수 있습니다. 가령, 여러분들의 Storage에 "images"라는 이름의 container가 있다면 이렇게 실행할 수 있습니다.

azcopy copy "https://udb.blob.core.windows.net/images?sv=2019-10-10&ss=bfqt&...[생략]..." "d:\temp" --recursive

SAS Token 관련해서 좀 더 자세한 사항은 다음의 문서에서 확인할 수 있습니다.

Grant limited access to Azure Storage resources using shared access signatures (SAS)
; https://learn.microsoft.com/ko-kr/azure/storage/common/storage-sas-overview

How to Generate an Azure SAS Token to Access Storage Accounts
; https://adamtheautomator.com/azure-sas-token/




반대로 로컬의 디렉터리를 Azure Stroage에 넣는 것은 인자 값의 순서만 바꾸면 됩니다.

azcopy copy '<local-directory-path>\*' 'https://<storage-account-name>.<blob or dfs>.core.windows.net/<container-name>/<directory-path>'

단지, 다운로드할 때와는 달리 전체 blob을 올릴 수는 없습니다. 제가 방법을 모르는 걸 수도 있지만, 아래와 같이 오류가 발생합니다. (혹시, 방법을 아시는 분은 덧글 부탁드립니다. ^^)

C:\>azcopy copy  "d:\temp" "https://...[대상_stroage]....blob.core.windows.net?sv=2019-10-1...[생략]..." --recursive
INFO: Scanning...

failed to perform copy command due to error: cannot transfer individual files/folders to the root of a service. Add a container or directory to the destination URL

대신, 하위 Container 별로 올릴 수 있는데, 이때 미리 Container를 생성해 두어야 합니다. 그렇지 않고 실행하면 이번에도 실패합니다.

// 대상 storage에 "temp" container가 만들어져 있지 않은 경우

C:\> azcopy copy  "d:\temp" "https://...[대상_stroage]....blob.core.windows.net/temp?sv=2019-10-10&ss=bfqt&srt=sco&sp=rwdlacupx&se=2020-07-19T22:23:20Z&st=2020-07-17T14:23:20Z&spr=https&sig=wSw3VBfT%2FAmvSBVPNXhCNFOJ6eShzXewQIl%2BMb0qfNQ%3D" --recursive
INFO: Scanning...
INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support

Job 92ee7705-2dfb-de48-6401-c71ddeb7c900 has started
Log file is located at: C:\Users\testusr\.azcopy\92ee7705-2dfb-de48-6401-c71ddeb7c900.log

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

Job 92ee7705-2dfb-de48-6401-c71ddeb7c900 summary
Elapsed Time (Minutes): 0.0334
Number of File Transfers: 56
Number of Folder Property Transfers: 0
Total Number of Transfers: 56
Number of Transfers Completed: 0
Number of Transfers Failed: 56
Number of Transfers Skipped: 0
TotalBytesTransferred: 0
Final Job Status: Failed

따라서, 예를 들어, "d:\temp\images"의 하위 폴더/파일들을 업로드하고 싶다면 그 blob들이 위치할 container도 미리 생성해 놓고 실행해야 합니다. 대개의 경우, 이전에 "images" 컨테이너에 있던 내용들이라면 그 이름 그대로 옮기고 싶을 것이므로 이런 식으로 처리할 수 있습니다.

azcopy copy  "d:\temp\images\*" "https://...[대상_stroage]....blob.core.windows.net/images?sv=2019-10-10...[생략]..." --recursive

(위의 예에서 "*" 문자를 빼면, Azure Storage의 images 컨테이너 하위에 다시 "images" 폴더가 생성되고 그 하위에 파일 및 서브 디렉터리가 올라갑니다.)

자, 그럼 Azure Storage를 옮기는 방법은 다음과 같이 정리할 수 있습니다.

1. 원본 Storage에서 "azcopy copy ..."로 로컬에 모두 다운로드
2. 대상 Storage에 원본의 컨테이너들을 미리 생성해 놓고, 개별 컨테이너마다 "azcopy copy ..."로 업로드




위에서 로컬을 경유한 방법을 소개했지만, 사실 전체 Storage를 옮기는 것이라면 다음의 명령어 하나로 해결할 수 있습니다.

azcopy copy 'https://<source-storage-account-name>.blob.core.windows.net/<SAS-token>' 'https://<destination-storage-account-name>.blob.core.windows.net/' --recursive

문서 상으로는 위와 같이 SAS-token을 source-storage-account 측에만 제공하지만, 제가 해본 결과로는 destination-storage-account 측에도 지정해야 했었습니다. (아마 같은 storage 내에서라면 필요 없겠지만 다른 storage라면 필요할 것입니다. 그렇긴 한데 제가 이거저거 너무 테스트를 많이 해봐서 확실치 않습니다. ^^;) 어쨌든, 다음과 같은 명령어 하나로 storage 이전을 간단하게 마무리했습니다.

D:\temp\blob> azcopy copy "https://...source....blob.core.windows.net?sv=2019-10-10...[소스측_sas_token]..." "https://...dest....blob.core.windows.net?sv=2019-10-10...[목적지측_sas_token]..." --recursive
INFO: Scanning...
INFO: Any empty folders will not be processed, because source and/or destination doesn't have full folder support

Job 54c45f3e-5bc6-ae47-7e87-9a9dc3d575c4 has started
Log file is located at: C:\Users\testusr\.azcopy\54c45f3e-5bc6-ae47-7e87-9a9dc3d575c4.log

100.0 %, 9851 Done, 0 Failed, 6 Pending, 0 Skipped, 9857 Total, 2-sec Throughput (Mb/s): 7.7693

Job 54c45f3e-5bc6-ae47-7e87-9a9dc3d575c4 summary
Elapsed Time (Minutes): 25.3103
Number of File Transfers: 9857
Number of Folder Property Transfers: 0
Total Number of Transfers: 9857
Number of Transfers Completed: 9857
Number of Transfers Failed: 0
Number of Transfers Skipped: 0
TotalBytesTransferred: 2141323772
Final Job Status: Completed




참고로, azcopy 명령어 사용 전 login 작업은 해야 합니다.

C:\temp> azcopy login --tenant-id 9F848C20-BBDF-413D-B9AC-117390503A2E
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code DCNCEVAMF to authenticate.

INFO: Login succeeded.

C:\temp>

위에서 --tenant-id 값은 해당 서비스가 속해있는 azure 구독과 관련한 AAD의 tenant-id를 입력하면 됩니다. 이 값은 프로그램으로도 구할 수 있지만 Azure Portal 내의 "Azure Active Directory"에서도 구할 수 있습니다.

sas_token_2.png




지난 글과 마찬가지로,

Azure - Location이 다른 웹/DB 서버의 경우 발생하는 성능 하락
; https://www.sysnet.pe.kr/2/0/12273

Storage 역시 그것을 액세스하는 측과 같은 Location에 있는 것이 성능상 (당연하겠지만) 좋습니다. 이를 위해 다음과 같은 소스 코드로 측정을 해봤는데요.

using Azure.Storage.Blobs;
using System;
using System.Diagnostics;
using System.IO;

namespace ConsoleApp2
{

    // (deprecated)
    // Install-Package WindowsAzure.Storage

    // or

    // Install-Package Microsoft.Azure.Storage.Common
    // Install-Package Microsoft.Azure.Storage.Blob

    // or

    // .NETStandard,Version=v2.0
    // .NET Framework 4.6.1 or later
    // Install-Package Azure.Storage.Blobs
    class Program
    {
        static void Main(string[] args)
        {
            string blobConnectionString = "DefaultEndpointsProtocol=...[생략]...";

            Action<int, BlobClient, Action<int, BlobClient>> action = (loopCount, blobClient, work) =>
            {
                Stopwatch st = new Stopwatch();
                st.Start();

                work(loopCount, blobClient);

                st.Stop();

                Console.WriteLine(st.ElapsedMilliseconds);
            };

            BlobServiceClient bsc = new BlobServiceClient(blobConnectionString);

            BlobContainerClient bcc = bsc.GetBlobContainerClient("images");
            BlobClient bc = bcc.GetBlobClient("test.png");

            action(1, bc, RunCommand);
            action(1, bc, RunCommand);
            action(1, bc, RunCommand);
        }

        private static void RunCommand(int loopCount, BlobClient blobClient)
        {
            MemoryStream ms = new MemoryStream();
            blobClient.DownloadTo(ms);
        }
    }
}

Location이 달랐을 때는,

C:\temp\perf>ConsoleApp2.exe
805
41
41

C:\temp\perf>ConsoleApp2.exe
693
43
44

40ms 이상의 고정적인 지연 시간이 발생하지만 같은 Location에 있을 때는,

C:\temp\perf>ConsoleApp2.exe
573
4
2

C:\temp\perf>ConsoleApp2.exe
396
3
2

"Azure - Location이 다른 웹/DB 서버의 경우 발생하는 성능 하락" 글에서와 유사하게 지연 시간이 없어졌습니다.

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 1/4/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2021-02-18 10시33분
본문에서 "Azure Data Factory"를 언급하며 문서의 압박으로 인해 실습하진 않았는데요, 반면 아래의 강좌를 보면 상당히 절차가 간단하다는 것을 알 수 있습니다. (참고로 데모 작업을 곁들인 설명은 3번째 동영상에 있습니다.)

ETL의 끝판왕, 애저 데이터 팩토리 | ep0. 인트로 | 애저듣보잡
; https://www.youtube.com/watch?v=4GwCz7K-8qo

ETL의 끝판왕, 애저 데이터 팩토리 | ep1. 소개 | 애저듣보잡
; https://www.youtube.com/watch?v=B2ay3OlLq0k

ETL의 끝판왕, 애저 데이터 팩토리 | ep2. 데모 | 애저듣보잡
; https://www.youtube.com/watch?v=24zgXpTv-BI

ETL의 끝판왕, 애저 데이터 팩토리 | ep3. 클로징 | 애저듣보잡
; https://www.youtube.com/watch?v=2J0sEwjZxGA
정성태

... 16  17  18  19  20  21  22  23  24  25  26  27  [28]  29  30  ...
NoWriterDateCnt.TitleFile(s)
12919정성태1/13/20226218Windows: 199. Host Network Service (HNS)에 의해서 점유되는 포트
12918정성태1/13/20226409Linux: 47. WSL - shell script에서 설정한 환경 변수가 스크립트 실행 후 반영되지 않는 문제
12917정성태1/12/20225654오류 유형: 785. C# - The type or namespace name '...' could not be found (are you missing a using directive or an assembly reference?)
12916정성태1/12/20225386오류 유형: 784. TFS - One or more source control bindings for this solution are not valid and are listed below.
12915정성태1/11/20225664오류 유형: 783. Visual Studio - We didn't find any interpreters
12914정성태1/11/20227559VS.NET IDE: 172. 비주얼 스튜디오 2022의 파이선 개발 환경 지원
12913정성태1/11/20228081.NET Framework: 1133. C# - byte * (바이트 포인터)를 FileStream으로 쓰는 방법 [1]
12912정성태1/11/20228720개발 환경 구성: 623. ffmpeg.exe를 사용해 비디오 파일의 이미지를 PGM(Portable Gray Map) 파일 포맷으로 출력하는 방법 [1]
12911정성태1/11/20226046VS.NET IDE: 171. 비주얼 스튜디오 - 더 이상 만들 수 없는 "ASP.NET Core 3.1 Web Application (.NET Framework)" 프로젝트
12910정성태1/10/20226529제니퍼 .NET: 30. 제니퍼 닷넷 적용 사례 (8) - CPU high와 DB 쿼리 성능에 문제가 함께 있는 사이트
12909정성태1/10/20227922오류 유형: 782. Visual Studio 2022 설치 시 "Couldn't install Microsoft.VisualCpp.Redist.14.Latest"
12908정성태1/10/20225749.NET Framework: 1132. C# - ref/out 매개변수의 IL 코드 처리
12907정성태1/9/20226221오류 유형: 781. (youtube-dl.exe) 실행 시 "This app can't run on your PC" / "Access is denied." 오류 발생
12906정성태1/9/20226815.NET Framework: 1131. C# - 네임스페이스까지 동일한 타입을 2개의 DLL에서 제공하는 경우 충돌을 우회하는 방법 [1]파일 다운로드1
12905정성태1/8/20226475오류 유형: 780. Could not load file or assembly 'Microsoft.VisualStudio.TextTemplating.VSHost.15.0, Version=16.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
12904정성태1/8/20228519개발 환경 구성: 623. Visual Studio 2022 빌드 환경을 위한 github Actions 설정 [1]
12903정성태1/7/20227120.NET Framework: 1130. C# - ELEMENT_TYPE_INTERNAL 유형의 사용 예
12902정성태1/7/20227162오류 유형: 779. SQL 서버 로그인 에러 - provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.
12901정성태1/5/20227263오류 유형: 778. C# - .NET 5+에서 warning CA1416: This call site is reachable on all platforms. '...' is only supported on: 'windows' 경고 발생
12900정성태1/5/20228909개발 환경 구성: 622. vcpkg로 ffmpeg를 빌드하는 경우 생성될 구성 요소 제어하는 방법
12899정성태1/3/20228387개발 환경 구성: 621. windbg에서 python 스크립트 실행하는 방법 - pykd (2)
12898정성태1/2/20228939.NET Framework: 1129. C# - ffmpeg(FFmpeg.AutoGen)를 이용한 비디오 인코딩 예제(encode_video.c) [1]파일 다운로드1
12897정성태1/2/20227813.NET Framework: 1128. C# - 화면 캡처한 이미지를 ffmpeg(FFmpeg.AutoGen)로 동영상 처리 [4]파일 다운로드1
12896정성태1/1/202210678.NET Framework: 1127. C# - FFmpeg.AutoGen 라이브러리를 이용한 기본 프로젝트 구성파일 다운로드1
12895정성태12/31/20219170.NET Framework: 1126. C# - snagit처럼 화면 캡처를 연속으로 수행해 동영상 제작 [1]파일 다운로드1
12894정성태12/30/20217160.NET Framework: 1125. C# - DefaultObjectPool<T>의 IDisposable 개체에 대한 풀링 문제 [3]파일 다운로드1
... 16  17  18  19  20  21  22  23  24  25  26  27  [28]  29  30  ...