Microsoft MVP성태의 닷넷 이야기
개발 환경 구성: 496. Azure - Blob Storage Account의 Location 이전 방법 [링크 복사], [링크+제목 복사]
조회: 282
글쓴 사람
정성태 (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://docs.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://docs.microsoft.com/ko-kr/azure/data-factory/connector-azure-blob-storage

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

Get started with AzCopy
; https://docs.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://docs.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://docs.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 서버의 경우 발생하는 성능 하락" 글에서와 유사하게 지연 시간이 없어졌습니다.

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




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





[최초 등록일: ]
[최종 수정일: 7/22/2020 ]

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

비밀번호

댓글 쓴 사람
 




[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
12350정성태9/25/2020112Windows: 175. 윈도우 환경에서 클라이언트 소켓의 최대 접속 수파일 다운로드1
12349정성태9/25/202053Linux: 32. Ubuntu 20.04 - docker를 위한 tcp 바인딩 추가
12348정성태9/25/202033오류 유형: 658. 리눅스 docker - Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
12347정성태9/25/202085Windows: 174. WSL 2의 네트워크 통신 방법
12346정성태9/25/202033오류 유형: 657. IIS - http://localhost 방문 시 Service Unavailable 503 오류 발생
12345정성태9/25/202030오류 유형: 656. iisreset 실행 시 "Restart attempt failed." 오류가 발생하지만 웹 서비스는 정상적인 경우
12344정성태9/25/202042Windows: 173. 서비스 관리자에 "IIS Admin Service"가 등록되어 있지 않다면?
12343정성태9/24/2020174.NET Framework: 945. C# - 닷넷 응용 프로그램에서 메모리 누수가 발생할 수 있는 패턴
12342정성태9/25/2020130디버깅 기술: 171. windbg - 인스턴스가 살아 있어 메모리 누수가 발생하고 있는지 확인하는 방법
12341정성태9/23/2020171.NET Framework: 944. C# - 인스턴스가 살아 있어 메모리 누수가 발생하고 있는지 확인하는 방법파일 다운로드1
12340정성태9/23/202095.NET Framework: 943. WPF - WindowsFormsHost를 담은 윈도우 생성 시 메모리 누수
12339정성태9/21/202070오류 유형: 655. 코어 모드의 윈도우는 GUI 모드의 윈도우로 교체가 안 됩니다.
12338정성태9/21/202042오류 유형: 654. 우분투 설치 시 "CHS: Error 2001 reading sector ..." 오류 발생
12337정성태9/21/202044오류 유형: 653. Windows - Time zone 설정을 바꿔도 반영이 안 되는 경우
12336정성태9/21/2020152.NET Framework: 942. C# - WOL(Wake On Lan) 구현
12335정성태9/21/202054Linux: 31. 우분투 20.04 초기 설정 - 고정 IP 및 SSH 설치
12334정성태9/21/202034오류 유형: 652. windbg - !py 확장 명령어 실행 시 "failed to find python interpreter"
12333정성태9/20/2020102.NET Framework: 941. C# - 전위/후위 증감 연산자에 대한 오버로딩 구현 (2)
12332정성태9/18/202090.NET Framework: 940. C# - Windows Forms ListView와 DataGridView의 예제 코드파일 다운로드1
12331정성태9/24/202081오류 유형: 651. repadmin /syncall - 0x80090322 The target principal name is incorrect.
12330정성태9/20/2020231.NET Framework: 939. C# - 전위/후위 증감 연산자에 대한 오버로딩 구현 [2]파일 다운로드1
12329정성태9/16/2020116오류 유형: 650. ASUS 메인보드 관련 소프트웨어 설치 후 ArmouryCrate.UserSessionHelper.exe 프로세스 무한 종료 현상
12328정성태9/16/202089VS.NET IDE: 150. TFS의 이력에서 "Get This Version"과 같은 기능을 Git으로 처리한다면?
12327정성태9/12/2020148.NET Framework: 938. C# - ICS(Internet Connection Sharing) 제어파일 다운로드1
12326정성태9/12/2020138개발 환경 구성: 516. Azure VM의 Network Adapter를 실수로 비활성화한 경우
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...