주:

OpenStack Swift API와 함께 Oracle Cloud Infrastructure Object Storage Service 사용

소개

Oracle Cloud Infrastructure(OCI) Object Storage는 디지털 정보를 객체로 관리하고 구성하는 데이터 스토리지 아키텍처로, 각각 데이터, 메타데이터 및 고유 식별자로 구성됩니다. 기존 파일 또는 블록 스토리지와 달리 OCI Object Storage는 계층 구조에 의존하지 않으므로 방대한 양의 비정형 데이터를 효율적이고 확장 가능한 방식으로 처리할 수 있습니다. 객체는 플랫 주소 공간에 저장되므로 데이터 검색을 단순화하고 원활한 확장이 가능합니다. 이 솔루션은 멀티미디어 컨텐츠 및 백업과 같은 다양한 데이터 유형에 이상적이므로 유연성, 내구성 및 액세스 용이성으로 인해 클라우드 환경, 아카이브 스토리지 및 분산 시스템을 위한 강력한 선택입니다. 사용자는 HTTP 프로토콜을 통해 REST 인터페이스를 사용하여 오브젝트 스토리지 서비스와 상호 작용합니다.

OCI Object Storage 서비스는 Oracle이 관리의 복잡성을 처리하여 신뢰할 수 있고 비용 효율적인 데이터 내구성을 보장하는 클라우드 기반 스토리지 솔루션입니다. 플랫폼 탄력성을 통해 성능 또는 서비스 안정성을 저하시키지 않고도 원활하게 확장할 수 있는 기능으로 점진적으로 시작할 수 있습니다.

OCI Object Storage는 Amazon S3 호환성 API를 통해 OpenStack Swift API 및 Amazon Simple Storage Service(Amazon S3)와의 API 호환성을 제공합니다. 이를 통해 고객은 기존 도구(예: SDK 클라이언트)를 계속 사용하여 애플리케이션을 변경할 필요성을 최소화할 수 있습니다. 자세한 내용은 Amazon S3 호환성 API를 참조하십시오. 이 사용지침서에서는 OCI OpenStack Swift 호환 API 사용을 중점적으로 다룹니다.

OpenStack Swift API에 대해 논의하기 전에 OCI Object Storage에서 사용되는 몇 가지 구성을 명확히 해야 합니다.

OpenStack Swift는 계정, 컨테이너 및 객체의 세 가지 구성을 정의합니다.

이제 OCI Object Storage와 OpenStack Swift API 간에 동등한 리소스를 식별할 수 있습니다.

목표

필요 조건

OCI Swift API 사용

OCI Swift API 지역 엔드포인트는 https://swiftobjectstorage.<region-identifier>.oraclecloud.com의 일관된 URL 형식을 사용합니다. 예를 들어, 미국 동부 지역(US-ashburn-1)의 고유 OCI Swift API 엔드포인트는 https://swiftobjectstorage.US-ashburn-1.oraclecloud.com입니다.

리전 레벨에서 테넌트 레벨 격리를 고려할 때 OCI Swift API 끝점은 https://swiftobjectstorage.<region-identifier>.oraclecloud.com/<tenancy-namespace>가 됩니다. 여기서 <tenancy-namespace>는 저장소를 생성할 테넌시의 자동 생성된 오브젝트 스토리지 네임스페이스 문자열입니다. 자세한 내용은 테넌시 정보 페이지를 참조하십시오.

OCI Swift API에는 구획이라는 개념이 없습니다. 기본적으로 OCI Amazon S3 호환성 API 또는 OCI Swift API를 사용하여 생성되는 버킷은 Oracle Cloud Infrastructure 테넌시의 루트 구획에 생성됩니다. OCI Amazon S3 호환성 API 또는 OCI Swift API에 대해 다른 구획을 지정하여 버킷을 생성할 수 있습니다. 자세한 내용은 테넌시의 Amazon S3 호환성 API 및 Swift API 구획 지정 편집을 참조하십시오.

OCI Swift API는 요청을 인증하는 세 가지 접근 방식을 지원합니다.

접근 방법 1: 기본 인증 헤더 사용

사용자 이름의 형식은 <username>입니다. 예: john.doe@acme.com. 테넌시가 Oracle Identity Cloud Service와 통합된 경우 oracleidentitycloudservice/<username> 형식을 사용합니다.

암호는 사용자에 대해 생성된 인증 토큰입니다. 예: my-auth-token. 자세한 내용은 Getting an Auth Token을 참조하십시오.

OCI Swift API에 대한 각 요청에는 다음 헤더가 포함되어야 합니다.

예를 들어, username이 oracleidentitycloudservice/john.doe@acme.com이고 password가 my-auth-token인 경우 헤더는 다음과 같이 표시됩니다.

공식 설명서에 설명된 API 호출 중 일부를 사용합니다. OpenStack Swift API를 참조하십시오.

예제:

  1. 다음 필수 환경 변수를 초기화합니다.

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. 계정의 버킷을 나열합니다. 선택한 OCI Swift API 구획의 버킷만 나열됩니다.

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -u "${user}:${password}" | jq
    
  3. Create a bucket.

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -u "${user}:${password}"
    
  4. 파일을 버킷에 업로드합니다.

    echo 'sample file' > ${object_name}
    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X PUT --data-binary "@${object_name}" -u "${user}:${password}"
    
  5. 버킷 콘텐츠를 나열합니다.

    curl -sS -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -u "${user}:${password}" | jq
    
  6. 버킷에서 파일을 인출합니다.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -u "${user}:${password}" -o downloaded_file.txt
    cat downloaded_file.txt
    
  7. 버킷에서 파일을 삭제합니다.

    curl -sS -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X DELETE -u "${user}:${password}"
    
  8. 버킷을 삭제합니다.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X DELETE -u "${user}:${password}"
    

접근 방법 2: v1 인증을 사용한 토큰 기반 인증

해당 지역에 대한 OCI Swift API 권한 부여 엔드포인트를 호출하고 요청에 X-Storage-UserX-Storage-Pass 헤더를 포함해야 합니다. 인증 요청이 성공하면 요청 권한 부여에 사용할 수 있는 X-Storage-Token 헤더와 계정에 대한 OCI Swift API 끝점이 있는 X-Storage-Url 헤더가 포함된 응답을 받게 됩니다.

X-Storage-User 헤더의 형식은 <tenancy-namespace>:<username>입니다.

예를 들어, tenancy-namespaceaxaxnpcrorw5이고 사용자 이름이 Approach 1과 동일한 경우 헤더 값은 axaxnpcrorw5:oracleidentitycloudservice/john.doe@acme.com입니다.

X-Storage-Pass는 생성된 인증 토큰입니다.

예제:

  1. 다음 필수 환경 변수를 초기화합니다.

    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
  2. 토큰을 생성합니다.

    curl -sS -D swift_headers.txt https://swiftobjectstorage.eu-frankfurt-1.oraclecloud.com/auth/v1.0 -H "X-Storage-User: ${tenancy_namespace}:${user}" -H "X-Storage-Pass: ${password}"
    X_Auth_Token=$(cat swift_headers.txt | grep X-Auth-Token | cut -d":" -f 2)
    
  3. 계정의 버킷을 나열합니다. 선택한 OCI Swift API 구획의 버킷만 나열됩니다.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  4. Create a bucket.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X PUT -H "X-Auth-Token: ${X_Auth_Token}"
    
  5. 파일을 버킷에 업로드합니다.

    echo 'sample file' > ${object_name}
    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X PUT --data-binary "@${object_name}" -H "X-Auth-Token: ${X_Auth_Token}"
    
  6. 버킷 콘텐츠를 나열합니다.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -H "X-Auth-Token: ${X_Auth_Token}" | jq
    
  7. 버킷에서 파일을 인출합니다.

    curl -s -D /dev/stderr "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -H "X-Auth-Token: ${X_Auth_Token}" -o downloaded_file.txt
    cat downloaded_file.txt
    
  8. 버킷에서 파일을 삭제합니다.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}/${object_name}" -X DELETE -H "X-Auth-Token: ${X_Auth_Token}"
    
  9. 버킷을 삭제합니다.

    curl -s -i "https://swiftobjectstorage.${region}.oraclecloud.com/v1/${tenancy_namespace}/${bucket_name}" -X DELETE -H "X-Auth-Token: ${X_Auth_Token}"
    

접근 방법 3: v2 인증을 사용한 토큰 기반 인증

OCI Swift API v2 권한 부여 절차를 설명하기 위해 공식 OpenStack Swift API Python 패키지 python-swiftclient 4.5.0과 v2 auth python-keystoneclient 5.4.0에 필요한 종속성을 사용합니다.

예제:

  1. 다음 명령을 실행하여 3.6 이상의 Python 버전에 액세스할 수 있는지 확인합니다. 자세한 내용은 Python 다운로드를 참조하십시오.

    python3 --version
    
  2. 필요한 Python 모듈을 설치합니다.

    python3 -m pip install python-swiftclient python-keystoneclient click
    
  3. 다음 코드를 사용하여 OCI Swift API v2와 상호 작용할 수 있습니다. 실행하기 전에 다음 코드에서 <user>, <password>, <region><tenancy-namespace>의 위치 표시자를 바꿔야 합니다.

    import click
    import os
    
    from swiftclient.client import Connection
    from swiftclient.exceptions import ClientException
    
    user='<username>'
    password='<password>'
    region='<oci-region>'
    tenancy_namespace='<tenancy-namespace>'
    bucket_name='tutorial-bucket'
    object_name='sample.txt'
    
    _authurl = f'https://swiftobjectstorage.{region}.oraclecloud.com/auth/v2.0/'
    _auth_version = '2'
    _user = f'{user}'
    _key = f'{password}'
    _tenant_name = f'{tenancy_namespace}'
    
    conn = Connection(
        authurl=_authurl,
        user=_user,
        key=_key,
        tenant_name=_tenant_name,
        auth_version=_auth_version
    )
    
    @click.group(invoke_without_command=True)
    @click.pass_context
    def main(ctx):
        available_commands = {
            "a": ("List buckets in the account", get_account),
            "b": ("Create a new bucket", put_container),
            "c": ("Upload an object to the bucket", put_object),
            "d": ("List objects in the bucket", get_container),
            "e": ("Download object from the bucket", get_object),
            "f": ("Delete object from the bucket", delete_object),
            "g": ("Delete bucket from the account", delete_container)
        }
        while True:
            click.echo("Available actions")
            for index, command in available_commands.items():
                click.echo(f"{index} - {command[0]}")
            action = click.prompt("Please select an option from the list")
            if action in available_commands.keys():
                ctx.invoke(available_commands[action][1])
            print("###"*10)
    
    @main.command()
    def get_account(conn=conn):
        print("Listing buckets in the account.")
        try:
            resp_headers = conn.get_account()
            for entry in resp_headers[1]:
                print(entry["name"])
        except ClientException as e:
            print(f"Failed to get the buckets in the tenancy. Error: {e}")
            raise
        else:
            print(f"Successfuly listed bucket in the '{_tenant_name}' account.")
    
    @main.command()
    def put_container(conn=conn, bucket_name=bucket_name):
        print(f"Creating a new bucket named {bucket_name}.")
        try:
            resp_headers = conn.put_container(container=bucket_name)
        except ClientException as e:
            print(f"Failed to create the new bucket named {bucket_name} in the tenancy. Error: {e}")
            raise
        else:
            print(f"The '{bucket_name}' was successfuly created.")
    
    @main.command()
    def put_object(conn=conn, bucket_name=bucket_name, object_name=object_name):
        print(f"Uploading a new file, '{object_name}' to the new bucket '{bucket_name}'.")
        try:
            if not os.path.isfile(object_name):
                with open(object_name, "w") as f:
                    f.write("sample file")
            with open(object_name) as f:
                resp_headers = conn.put_object(container=bucket_name, obj=object_name, contents=object_name)
        except ClientException as e:
            print(f"Failed to create a new object named '{object_name}' in the bucket '{bucket_name}'. Error: {e}")
            raise
        else:
            print(f"The '{object_name}' file was successfuly uploaded to '{bucket_name}' bucket.")
    
    @main.command()
    def get_container(conn=conn, bucket_name=bucket_name):
        print(f"List {bucket_name} bucket contents.")
        try:
            resp_headers = conn.get_container(container=bucket_name)
            for entry in resp_headers[1]:
                print(entry["name"])
        except ClientException as e:
            print(f"Failed to list objects in the bucket {bucket_name}. Error: {e}")
            raise
        else:
            print(f"The '{bucket_name}' content was successfuly listed.")
    
    @main.command()
    def get_object(conn=conn, bucket_name=bucket_name, object_name=object_name, dest_file="downloaded_file.txt"):
        print(f"Fetch {object_name} object from the bucket {bucket_name}.")
        try:
            resp_headers = conn.get_object(container=bucket_name, obj=object_name)
            with open(dest_file, "wb") as f:
                f.write(resp_headers[1])
        except ClientException as e:
            print(f"Failed to download {object_name} from {bucket_name} to local file named '{dest_file}'. Error: {e}")
            raise
        else:
            print(f"The '{object_name}' object was saved locally to '{dest_file}'.")
    
    @main.command()
    def delete_object(conn=conn, bucket_name=bucket_name, object_name=object_name):
        print(f"Deleting {object_name} object from the bucket {bucket_name}.")
        try:
            resp_headers = conn.delete_object(container=bucket_name, obj=object_name)
        except ClientException as e:
            print(f"Failed to delete {object_name} from {bucket_name}. Error: {e}")
            raise
        else:
            print(f"The '{object_name}' object was deleted.")
    
    @main.command()
    def delete_container(conn=conn, bucket_name=bucket_name):
        print(f"Deleting the bucket {bucket_name}.")
        try:
            resp_headers = conn.delete_container(container=bucket_name)
        except ClientException as e:
            print(f"Failed to delete {object_name} from {bucket_name}. Error: {e}")
            raise
        else:
            print(f"The '{bucket_name}' bucket was deleted.")
    
    
    if __name__ == "__main__":
        main()
    

확인

추가 학습 자원

docs.oracle.com/learn에서 다른 실습을 살펴보거나 Oracle Learning YouTube 채널에서 더 많은 무료 학습 콘텐츠에 액세스하십시오. 또한 education.oracle.com/learning-explorer를 방문하여 Oracle Learning Explorer가 되십시오.

제품 설명서는 Oracle Help Center를 참조하십시오.