::: IT인터넷 :::

Python으로 MinIO를 사용하는 방법 (3) - 데이터 관리

곰탱이푸우 2022. 4. 18. 08:20
MinIO는 AWS S3와 호환되는 파이썬 라이브러리를 제공한다.
해당 라이브러리를 활용하면 MinIO의 WebUI나 mc (MinIO Client)에서 제공하는 기능의 일부를 파이썬에서 사용할 수 있다.
 
MinIO의 파이썬 라이브러리 소개와 설치 방법은 다음 포스팅을 참고한다.
MinIO의 파이썬 라이브러리로 Bucket을 관리하는 방법은 다음 포스팅을 참고한다.

 

MinIO의 WebUI를 사용하는 방법은 아래 포스팅을 참고한다.
MinIO의  mc (MinIO Client)를 설정하고 사용하는 방법은 아래 포스팅을 참고한다.

 

데이터 관리

자주 사용하는 기능을 중심으로 정리한다.
 
자세한 사항은 아래 문서를 참고한다.

파일 시스템과 다른 폴더 개념

폴더에 대한 개념이 일반적인 파일시스템과 다른 점에 유의한다.
MinIO는 Object Storage로 일반적인 NTFS (윈도우)나 ext4 (우분투)와 같은 파일시스템과 다르다.
 
일반적으로 MinIO의 Object 경로는 다음과 같이 표시된다.
/버킷명/폴더명/.../파일명.확장명
 
MinIO 내부에서 모든 파일 (Object)은 버킷 하위에 동일한 계층에 저장된다.
경로는 WebUI나 CLI에서 파일시스템과 같은 계층적 구조로 표현하기 위한 메타데이터로 사용된다.
 
따라서 MinIO와 S3 같은 Object Storage에서 비어있는 폴더란 존재할 수 없다. 비어있는 버켓만 가능하다.
실제로 특정 폴더의 파일을 전부 삭제하면, MinIO 브라우저에서 보이지 않는다.
해당 폴더 경로를 메타 데이터로 가지는 파일 (Object)이 존재하지 않기 때문이다.
 

업로드 하기

MinIO에 업로드하는 방법은 크게 두 가지로 나뉜다.
파일 자체를 업로드하거나, 데이터를 Object (객체)로 업로드하는 방법이다.
 
데이터를 Object로 업로드하는 것은 문자열이나 바이트스트림을 MinIO에 지정한 Object Name으로 업로드하는 것을 의미한다.
실시간 데이터 스트리밍에서 유용하게 사용 가능하며, compose_object 함수로 단일 Object로 합칠 수도 있다.
이후 해당 Object를 다운로드하면 로컬에서 파일로 사용할 수 있다.
 
파일 업로드
fput_object 함수를 사용한다.
# Uploads data from a file to an object in a bucket.
fput_object(bucket_name, object_name, file_path,
    content_type="application/octet-stream", metadata=None,
    sse=None, progress=None, part_size=0, num_parallel_uploads=3,
    tags=None, retention=None, legal_hold=False)

## Parameters
# 아래 표 참고

## Return
# ObjectWriteResult object - Upload result
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다,
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
object_name
str
 
Object name in the bucket.
file_path
str
 
Name of file to upload.
content_type
str
application
/octet-stream
Content type of the object. (MIME Type)
metadata
dict
None
Any additional metadata to be uploaded along with your PUT request.
sse
Sse
None
Server-side encryption.
progress
threading
None
A progress object.
part_size
int
0
Multipart part size.
num_parallel_uploads
int
3
Num of parallel uploads.
tags
Tags
None
Tags for the object.
retention
Retention
None
Retention configuration.
legal_hold
bool
False
Flag to set legal hold for the object.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

# Upload data.
result = client.fput_object(
    "my-bucket", "my-object", "my-filename")

print( "created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))
# Upload data with content-type.
result = client.fput_object( "my-bucket", "my-object", "my-filename",
    content_type="application/csv")

print("created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))
# Upload data with metadata.
result = client.fput_object( "my-bucket", "my-object", "my-filename",
    metadata={"My-Project": "one"} )

print( "created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))
# Upload data with progress bar.
result = client.fput_object( "my-bucket", "my-object", "my-filename",
    progress=Progress())

print("created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))
 
 
데이터 업로드
put_object 함수를 사용한다.
# Uploads data from a stream to an object in a bucket.
put_object(bucket_name, object_name, data, length,
    content_type="application/octet-stream", metadata=None,
    sse=None, progress=None, part_size=0, num_parallel_uploads=3,
    tags=None, retention=None, legal_hold=False)

## Parameters
# 아래 표 참고

## Return
# ObjectWriteResult object - Upload result
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다,
fput_object와 비교해서 file_path 항목 대신에 data와 lengh 항목이 사용되었다.
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
object_name
str
 
Object name in the bucket.
data
object
 
An object having callable read() returning bytes object.
length
int
 
Data size; -1 for unknown size and set valid part_size.
content_type
str
application
/octet-stream
Content type of the object. (MIME Type)
metadata
dict
None
Any additional metadata to be uploaded along with your PUT request.
sse
Sse
None
Server-side encryption.
progress
threading
None
A progress object.
part_size
int
0
Multipart part size.
num_parallel_uploads
int
3
Num of parallel uploads.
tags
Tags
None
Tags for the object.
retention
Retention
None
Retention configuration.
legal_hold
bool
False
Flag to set legal hold for the object.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

# Upload data
result = client.put_object("my-bucket", "my-object", io.BytesIO(b"hello"), 5)

print("created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))
# Upload unknown sized data.
data = urlopen( "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.81.tar.xz")

result = client.put_object("my-bucket", "my-object", data, length=-1, part_size=10*1024*1024)

print("created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))

# Upload data with content-type
result = client.put_object( "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
    content_type="application/csv")

print("created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))
# Upload data with metadata.
result = client.put_object( "my-bucket", "my-object", io.BytesIO(b"hello"), 5,
    metadata={"My-Project": "one"})

print( "created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))

# Upload data with progress bar.
result = client.put_object("my-bucket", "my-object", io.BytesIO(b"hello"), 5,
    progress=Progress())

print("created {0} object; etag: {1}, version-id: {2}".format(
    result.object_name, result.etag, result.version_id))
 
 

목록 확인하기

특정 버켓과 경로 하위에 어떠한 파일들이 존재하는지 확인하는 방법이다.
 
list_objects 함수를 사용한다.
# Lists object information of a bucket.
list_objects(bucket_name, prefix=None, recursive=False, start_after=None,
    include_user_meta=False, include_version=False,
    use_api_v1=False, use_url_encoding_type=True)

## Parameters
# 아래 표 참고

## Return
# An iterator of Object - List result
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다.
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
prefix
str
None
Object name starts with prefix.
recursive
bool
False
List recursively than directory structure emulation.
start_after
str
None
List objects after this key name.
include_user_meta
bool
False
MinIO specific flag to control to include user metadata.
include_version
bool
False
Flag to control whether include object versions.
use_api_v1
bool
False
Flag to control to use ListObjectV1 S3 API or not.
use_url_encoding_type
bool
True
Flag to control whether URL encoding type to be used or not.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

# List objects information.
objects = client.list_objects("my-bucket")

for obj in objects:
    print(obj)

# List objects information whose names starts with "my/prefix/".
objects = client.list_objects("my-bucket", prefix="my/prefix/")

for obj in objects:
    print(obj)

# List objects information recursively.
objects = client.list_objects("my-bucket", recursive=True)

for obj in objects:
    print(obj)

# List objects information recursively whose names starts with "my/prefix/".
objects = client.list_objects("my-bucket", prefix="my/prefix/", recursive=True)

for obj in objects:
    print(obj)

# List objects information recursively after object name "my/prefix/world/1".
objects = client.list_objects("my-bucket",
    recursive=True, start_after="my/prefix/world/1")

for obj in objects:
    print(obj)
 
 

정보 확인하기

MinIO에 존재하는 파일 (Object)에 대한 정보를 확인하는 방법이다.
확인 가능한 정보는 최종 수정 시간과 파일 (Object)의 크기이다.
 
stat_object 함수를 사용한다.
# Get object information and metadata of an object.
stat_object(bucket_name, object_name,
    ssec=None, version_id=None, extra_query_params=None)

## Parameters
# 아래 표 참고

## Return
# Object information as Object - Status result
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다,
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
object_name
str
 
Object name in the bucket.
ssec
SseCustomerKey
None
Server-side encryption customer key.
version_id
str
None
Version ID of the object.
extra_query_params
dict
None
Extra query parameters for advanced usage.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

# Get object information.
result = client.stat_object("my-bucket", "my-object")

print("last-modified: {0}, size: {1}".format(result.last_modified, result.size))
 

다운로드 하기

MinIO에서 다운로드하는 방법도 업로드와 동일하게 은 크게 두 가지로 나뉜다.
파일 자체를 다운로드하거나,  Object (객체)를 로컬 변수에 데이터로 읽어오는 방법이다.
 
파일 다운로드
fget_object 함수를 사용한다.
# Downloads data of an object to file.
fget_object(bucket_name, object_name, file_path,
    request_headers=None, ssec=None, version_id=None,
    extra_query_params=None, tmp_file_path=None)

## Parameters
# 아래 표 참고

## Return
# Object information as Object - Download result
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다,
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
object_name
str
 
Object name in the bucket.
file_path
str
 
Name of file to download.
request_headers
dict
None
Any additional headers to be added with GET request.
ssec
SseCustomerKey
None
Server-side encryption customer key.
version_id
str
None
Version-ID of the object.
extra_query_params
dict
None
Extra query parameters for advanced usage.
tmp_file_path
str
None
Path to a temporary file.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

# Download data of an object.
client.fget_object("my-bucket", "my-object", "my-filename")

# Download data of an object using a temp path.
client.fget_object("my-bucket", "my-object", "my-filename", tmp_file_path="/path/to/tmp/path")
 
 
데이터 다운로드
Object를 로컬 변수에 데이터로 읽어오는 것은 문자열이나 바이트스트림을 지정한 크기만큼 MinIO에서 가져오는 것을 의미한다.
MinIO에 연결 된 상태이기 때문에 연결을 해제하는 코드를 명시적으로 사용해야 한다.
 
get_object  함수를 사용한다.
# Gets data from offset to length of an object.
# Returned response should be closed after use to release network resources.
# To reuse the connection, it's required to call response.release_conn() explicitly.

get_object(bucket_name, object_name,
    offset=0, length=0, request_headers=None, ssec=None,
    version_id=None, extra_query_params=None)

## Parameters
# 아래 표 참고

## Return
# urllib3.response.HTTPResponse object. - Download result
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다,
fget_object와 비교해서 file_path 항목 대신에 offset과 lengh 항목이 사용되었다.
또한 파일 다운로드가 아니므로 tmp_file_path 항목이 없다.
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
object_name
str
 
Object name in the bucket.
offset
int
0
Start byte position of object data.
length
int
0
Data size; -1 for unknown size and set valid part_size.
request_headers
dict
None
Any additional headers to be added with GET request.
ssec
SseCustomerKey
None
Server-side encryption customer key.
version_id
str
None
Version-ID of the object.
extra_query_params
dict
None
Extra query parameters for advanced usage.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

# Get data of an object.
try:
    response = client.get_object("my-bucket", "my-object")
    # Read data from response.
finally:
    response.close()
    response.release_conn()

# Get data of an object from offset and length.
try:
    response = client.get_object("my-bucket", "my-object", offset=512, length=1024)
    # Read data from response.
finally:
    response.close()
    response.release_conn()
 

복사와 이동하기

파이썬을 이용하여 파일 복사는 가능하지만 파일 이동은 지원하지 않는다.
 
복사하기
copy_object 함수를 사용한다. 지원하는 단일 파일의 최대 크기는 5GB이다.
# Create an object by server-side copying data from another object.
# In this API maximum supported source object size is 5GiB.
copy_object(bucket_name, object_name, source,
    sse=None, metadata=None, tags=None, retention=None,
    legal_hold=False, metadata_directive=None, tagging_directive=None)

## Parameters
# 아래 표 참고

## Return
# ObjectWriteResult object. - Copy result
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다,
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
object_name
str
 
Object name in the bucket.
source
CopySource
 
Source object information.
sse
Sse
None
Server-side encryption of destination object.
metadata
dict
None
Any user-defined metadata to be copied along with destination object.
tags
Tags
None
Tags for destination object.
retention
Retention
None
Retention configuration.
legal_hold
bool
False
Flag to set legal hold for destination object.
metadata_directive
str
None
Directive used to handle user metadata for destination object.
tagging_directive
str
None
Directive used to handle tags for destination object.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

from datetime import datetime, timezone
from minio.commonconfig import REPLACE, CopySource

# copy an object from a bucket to another.
result = client.copy_object(
    "my-bucket",
    "my-object",
    CopySource("my-sourcebucket", "my-sourceobject"),
)
print(result.object_name, result.version_id)

# copy an object with condition.
result = client.copy_object(
    "my-bucket",
    "my-object",
    CopySource(
        "my-sourcebucket",
        "my-sourceobject",
        modified_since=datetime(2014, 4, 1, tzinfo=timezone.utc),
    ),
)
print(result.object_name, result.version_id)

# copy an object from a bucket with replacing metadata.
metadata = {"test_meta_key": "test_meta_value"}
result = client.copy_object(
    "my-bucket",
    "my-object",
    CopySource("my-sourcebucket", "my-sourceobject"),
    metadata=metadata,
    metadata_directive=REPLACE,
)
print(result.object_name, result.version_id)
 
이동하기
파이썬을 이용한 파일 이동은 지원하지 않는다.
필요한 경우 copy_object와 아래에서 다룰 remove_object를 조합하여 사용하면 된다.
 
 

삭제하기

MinIO에서 파이썬을 사용한 파일 삭제는 단일 삭제와 다중 삭제 등 두 가지 방법을 제공한다 .
 
단일 삭제
remove_object 함수를 사용한다.
# Remove an object.
remove_object(bucket_name, object_name, version_id=None)

## Parameters
# 아래 표 참고

## Return
# None
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다,
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
object_name
str
 
Object name in the bucket.
version_id
str
None
Version ID of the object.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

# Remove object.
client.remove_object("my-bucket", "my-object")

# Remove version of an object.
client.remove_object(
    "my-bucket", "my-object",
    version_id="dfbd25b3-abec-4184-a4e8-5a35a5c1174d",
)
 
다중 삭제
remove_objects 함수를 사용한다.
# Remove multiple objects.
remove_objects(bucket_name, delete_object_list,
    bypass_governance_mode=False)

## Parameters
# 아래 표 참고

## Return
# An iterator containing :class:DeleteError <DeleteError> object - Delete Error
 
전달하는 인자는 다음과 같다.
연하게 표시한 부분은 사용 빈도가 떨어지는 옵션이거나 기본 값을 사용하는 부분이다,
Param
Type
Default
Description
bucket_name
str
 
Name of the bucket.
delete_object_list
iterable
 
An iterable containing :class:DeleteObject <DeleteObject> object.
bypass_governance_mode
bool
False
Bypass Governance retention mode.
 
예제 코드는 다음과 같다.
# client는 위에서 정의한 MinIO 클래스의 인스턴스이다.

# Remove list of objects.
errors = client.remove_objects(
    "my-bucket",
    [
        DeleteObject("my-object1"),
        DeleteObject("my-object2"),
        DeleteObject("my-object3", "13f88b18-8dcd-4c83-88f2-8631fdb6250c"),
    ],
)
for error in errors:
    print("error occured when deleting object", error)

# Remove a prefix recursively.
delete_object_list = map(
    lambda x: DeleteObject(x.object_name),
    client.list_objects("my-bucket", "my/prefix/", recursive=True),
)
errors = client.remove_objects("my-bucket", delete_object_list)
for error in errors:
    print("error occured when deleting object", error)
 
 
태그 사용하기
MinIO에서 특정 파일(Object)에 대한 정보를 표시하기 위해 태그 (Tag)를 사용한다.
태그는 일반적으로 AWS S3와 같은 클라우드 스토리지 서비스에서 목적과 사용 빈도 구분을 위해 사용한다.
 
S3의 경우 활용 빈도에 따라 Standard, Infrequent Access, One Zone, Glacier 등으로 구분하여 서비스를 제공한다.
활용 빈도가 거의 없지만 보관이 필요한 경우 Glacier로 옮기면 아주 저렴한 가격에 보관이 가능하다.
집안 정리하면서 활용 빈도가 적은 물건들을 창고로 옮기는 것과 같은 개념이다.
 
물론 스토리지 영역이 바뀌는 것이므로 이동하는 비용은 추가된다.
미리 데이터에 태그를 설정해 놓으면 스토리지 등급을 바꿀 때 빠르게 진행할 수 있다.
 
그러나 MinIO를 로컬 환경에 온프레미스 (On-premise)로 구축하여 사용하는 경우는 조금 다르다.
일반적으로 불필요한 데이터는 삭제하거나, 디스크를 추가하여 저장 공간을 확장하는 방법이 더 많이 사용된다.
또는 별도의 MinIO 서버를 구축하여 백업 전용으로 사용하기도 한다.
클라우드 서비스는 데이터의 업로드 시작부터 사용료가 발생하지만, 온프레미스는 최초 구축 비용만 발생하기 때문이다.
 
데이터의 목적은 주로 저장 경로에 표현되기 때문에, 로컬에 온프레미스로 구축한 경우 태그 활용도가 떨어진다.
약 3년간 데이터 엔지니어로 업무를 수행하면서 MinIO에서 태그 기능을 활용하지 않은 것도 그 때문이다.
 
따라서 태그 사용은 별도로 하지 않고 간략하게 소개만 한다.
  • set_object_tags - 특정 파일 (Object)에 태그를 지정하는 함수
  • get_object_tags - 특정 파일 (Object)에 지정 된 태그를 확인하는 함수
  • delete_object_tags - 특정 파일 (Object)에 지정 된 태그를 삭제하는 함수
구체적인 사용법은 다음 문서를 참고한다.