IT/Big Data

Ceph Object Storage구성 및 접속해보기

yeTi 2020. 7. 14. 14:10

안녕하세요. yeTi입니다.
오늘은 Ceph을 활용해서 S3와 같은 Object Storage를 사용할 수 있는 환경을 구성해보겠습니다.

Ceph Object Storage

Ceph Object Storagelibrgwlibrados상에서 제공하는 object storage interface입니다.


위의 그림에서와 같이 Ceph Object Storage는 두가지 인터페이스를 제공합니다.

  1. S3-compatible: Amazon S3의 RESTful API와 호환되는 인터페이스를 사용하여 객체 스토리지 기능을 제공합니다.
  2. Swift-compatible: OpenStack Swift API와 호환되는 인터페이스를 사용하여 객체 스토리지 기능을 제공합니다.

Object Storage 설치

Rook Docs에서 제공하는 절차에 따라서 Object Storage를 설치합니다. Yaml파일들은 Rook - GitHub에서 제공합니다.

CephObjectStorespec을 다운받은 후 설치합니다.

~$ wget -O object.yaml https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/object.yaml
~$ kc create -f object.yaml

다음과 같이 서비스가 구성된것을 확인할 수 있습니다.

~$ kubectl -n rook-ceph get all -l app=rook-ceph-rgw
NAME                                           READY   STATUS    RESTARTS   AGE
pod/rook-ceph-rgw-my-store-a-f56487895-t69qb   1/1     Running   0          2m56s

NAME                             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/rook-ceph-rgw-my-store   ClusterIP   10.100.216.1   <none>        80/TCP    3m43s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/rook-ceph-rgw-my-store-a   1/1     1            1           2m56s

NAME                                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/rook-ceph-rgw-my-store-a-f56487895   1         1         1       2m56s

Ceph에서 발생하는 WARNING을 해결하기 위해 pool 크기를 조절합니다.

[/]# ceph osd pool set .rgw.root size 1
set pool 47 size to 1
[/]# ceph osd pool set my-store.rgw.buckets.data size 1
set pool 48 size to 1
[/]# ceph osd pool set my-store.rgw.buckets.index size 1
set pool 45 size to 1
[/]# ceph osd pool set my-store.rgw.buckets.non-ec size 1
set pool 46 size to 1
[/]# ceph osd pool set my-store.rgw.control size 1
set pool 42 size to 1
[/]# ceph osd pool set my-store.rgw.log size 1
set pool 44 size to 1
[/]# ceph osd pool set my-store.rgw.meta size 1
set pool 43 size to 1

Object Storage에 접근할 사용자를 생성합니다.

$ wget -O object-user.yaml https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/object-user.yaml
$ kubectl create -f object-user.yaml
cephobjectstoreuser.ceph.rook.io/my-user created

Object Storage에 접근시 필요한 보안토큰들을 조회합니다.

$ kubectl -n rook-ceph describe secret rook-ceph-object-user-my-store-my-user
Name:         rook-ceph-object-user-my-store-my-user
Namespace:    rook-ceph
Labels:       app=rook-ceph-rgw
              rook_cluster=rook-ceph
              rook_object_store=my-store
              user=my-user
Annotations:  <none>

Type:  kubernetes.io/rook

Data
====
AccessKey:  20 bytes
SecretKey:  40 bytes

$ kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user -o yaml | grep AccessKey | head -1 | awk '{print $2}' | base64 --decode
12324u4389jfdh

$ kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user -o yaml | grep SecretKey | head -1 | awk '{print $2}' | base64 --decode
djfhgdityh98456htjkfhngkljdf

간단한 접속 테스트를 위해 ceph-tool에서 s3cmd를 사용합니다. 파일 입력 테스트를 진행하는 데 버킷을 생성하지 않으므로 ERROR: S3 error: 404 (NoSuchBucket) 오류가 발생합니다.

~$ kubectl exec -it pod/rook-ceph-tools-7bb5797c8-x5h86 -n rook-ceph -- /bin/bash
# s3cmd --configure
New settings:
  Access Key: [입력한 Key]
  Secret Key: [입력한 Key]
  Default Region: US
  S3 Endpoint: [입력한 Endpoint]
  DNS-style bucket+hostname:port template for accessing a bucket: %(bucket)s.s3.amazonaws.com
  Encryption password:
  Path to GPG program: /usr/bin/gpg
  Use HTTPS protocol: True
  HTTP Proxy server name:
  HTTP Proxy server port: 0

# s3cmd put /tmp/rookObj --no-ssl --host-bucket=  s3://rookbucket
ERROR: S3 error: 404 (NoSuchBucket)

결과적으로 Object Storage에 접근한것을 확인할 수 있습니다.

Client 예제

외부에서 접근을 해보도록 하겠습니다. 우선 NodePort를 설정합니다.

$ wget -O rgw-external.yaml https://raw.githubusercontent.com/rook/rook/master/cluster/examples/kubernetes/ceph/rgw-external.yaml

Python기반 예제는 Python S3 Example에서 제공하는 절차대로 진행했습니다.

boto 라이브러리를 설치합니다.

$ cat "boto==2.49.0" > requirements.txt
$ pip install requirements.txt

다음과 같이 접속테스트 및 bucket, key를 사용해 봅니다.

import boto
import boto.s3.connection

access_key = '[키 값]'
secret_key = '[키 값]'

conn = boto.connect_s3(
        aws_access_key_id = access_key,
        aws_secret_access_key = secret_key,
        host = '[host]',
        port = [port],
        is_secure=False,               # uncommmnt if you are not using ssl
        calling_format = boto.s3.connection.OrdinaryCallingFormat(),
        )
print('Create connection')

print('Get bucket size:', len(conn.get_all_buckets()))
print('Bucket List ===')
for bucket in conn.get_all_buckets():
    print("{name}\t{created}".format(name = bucket.name, created = bucket.creation_date))
print('===')

bucket = conn.create_bucket('my-new-bucket')
print('Create bucket:', bucket.name)

key = bucket.new_key('hello.txt')
key.set_contents_from_string('Hello World!')
print('Create Key:', key.name)

print('Ket List ===')
for key in bucket.list():
        print("{name}\t{size}\t{modified}".format(
                name = key.name,
                size = key.size,
                modified = key.last_modified,
                ))
print('===')

bucket.delete_key(key.name)
print('Delete key:', key.name)

conn.delete_bucket(bucket.name)
print('Delete buket:', bucket.name)