Stein 오픈스택 클라우드 서버 구축(13) - Swift 서비스를 활용한 오브젝트 스토리지 구성하기

blog post 

 

오픈스택의 Swift를 활용하면 다양한 방식으로 오브젝트 스토리지를 구성할 수 있습니다. 어떻게 구성하느냐에 따라 기존 Cinder서비스와 연동하여 블록 스토리지의 백업 서버로 활용할 수도 있고, Glance 이미지 저장 공간으로 활용할 수도 있습니다. 이번 포스트에서는 이 Swift 컴포넌트를 활용하여 사용자의 비정형 데이터를 저장할 수 있는 스토리지를 구축해 보도록 하겠습니다.

 

 

전체 구성

 

 

전체 구성은 아래와 같습니다.

 

 

 

기존 구성에서 네트워크 노드와 3개의 오브젝트 스토리지가 사용됩니다.

 

우선 컨트롤러 노드에는 swift 관련 별다른 패키지는 설치하지 않습니다. 다만 keystone을 통해, user, endpoint 등의 정보로만 swift를 등록해둠으로써, 컨트롤러는 swift 서비스를 관리하는 역할만 담당합니다.

 

네트워크 노드에서는 swift 프록시 서버가 동작합니다. 컨트롤러노드에서 동작하도록 구성할 수도 있으나, 본 구성에서는 기존 네트워크 노드를 swift 프록시 노드로 활용하도록 구성합니다.  프록시 노드는 사용자로부터 데이터 저장 요청을 전달받으면 분산된 3개의 스토리지 노드에 적절하게 데이터를 전달하는 역할을 수행합니다. 

 

실제 데이터를 저장하고 관리할 오브젝트 스토리지 노드는 총 3개의 노드로 구성됩니다. 오브젝트 스토리지 노드는 비정형 데이터를 분산 저장하기 위해 다중 노드로 구성됩니다. 기본 총 3개 이상의 노드를 구성하도록 되어있습니다. 저는 이를 위해 위와 같이 기존 블록 스토리지(Storage@LVM, Storage@NFS)를 각각 Object Storage1,2로 구성해 보도록 하겠습니다. 추가로 Object Storage3의 경우, 별도의 호스트 장비를 1개 추가하여 구성해 보도록 하겠습니다.

 

* 위의 구성에서 ip가 29에서 31로 건너 뛰는 것에는 별다른 의미는 없습니다. 30번 ip는 개인적으로 사용중인 ip이므로 건너뛰었습니다. 참고바랍니다.

 

 

 

컨트롤러 노드 구성

 

 

다른 서비스들과 같이, 마찬가지로 Swift도 사용자, 엔드포인트, url 등의 정보를 시스템에 등록해 줍니다.

 

[root@Controller ~]# openstack user create --domain default --project service --password servicepassword swift                                               
+---------------------+----------------------------------+
| Field               | Value                            |
+---------------------+----------------------------------+
| default_project_id  | 8d3e3541755f454f84dafacd37b4303c |
| domain_id           | default                          |
| enabled             | True                             |
| id                  | 4717d459f56145c09abead2a7be6251d |
| name                | swift                            |
| options             | {}                               |
| password_expires_at | None                             |
+---------------------+----------------------------------+
[root@Controller ~]# openstack role add --project service --user swift admin
[root@Controller ~]# openstack service create --name swift --description "OpenStack Object Storage" object-store                                             
+-------------+----------------------------------+
| Field       | Value                            |
+-------------+----------------------------------+
| description | OpenStack Object Storage         |
| enabled     | True                             |
| id          | 7ff47bcff13a472e817122976cfac710 |
| name        | swift                            |
| type        | object-store                     |
+-------------+----------------------------------+

//이번 포스트에서 Swift 프록시 서비스는 Network 노드에서 동작하도록 구성될 예정입니다.
//따라서 아래와 같이 swift_proxy url 정보를 Network 노드인 10.0.0.27로 등록해줍니다.
//(물론 컨트롤러 노드에서 프록시 서비스를 동작하도록 구성할 경우, 아래 ip를 해당 노드의 ip로 변경해 주면 됩니다.)
[root@Controller ~]# export swift_proxy=10.0.0.27
[root@Controller ~]# openstack endpoint create --region RegionOne object-store public http://$swift_proxy:8080/v1/AUTH_%\(tenant_id\)s
+--------------+---------------------------------------------+
| Field        | Value                                       |
+--------------+---------------------------------------------+
| enabled      | True                                        |
| id           | df75f657c8c14b709e4d657a32d0e9a6            |
| interface    | public                                      |
| region       | RegionOne                                   |
| region_id    | RegionOne                                   |
| service_id   | 7ff47bcff13a472e817122976cfac710            |
| service_name | swift                                       |
| service_type | object-store                                |
| url          | http://10.0.0.27:8080/v1/AUTH_%(tenant_id)s |
+--------------+---------------------------------------------+
[root@Controller ~]# openstack endpoint create --region RegionOne object-store internal http://$swift_proxy:8080/v1/AUTH_%\(tenant_id\)s
+--------------+---------------------------------------------+
| Field        | Value                                       |
+--------------+---------------------------------------------+
| enabled      | True                                        |
| id           | 59b97bf96ae44035a1da3d918385685f            |
| interface    | internal                                    |
| region       | RegionOne                                   |
| region_id    | RegionOne                                   |
| service_id   | 7ff47bcff13a472e817122976cfac710            |
| service_name | swift                                       |
| service_type | object-store                                |
| url          | http://10.0.0.27:8080/v1/AUTH_%(tenant_id)s |
+--------------+---------------------------------------------+
[root@Controller ~]# openstack endpoint create --region RegionOne object-store admin http://$swift_proxy:8080/v1
+--------------+----------------------------------+
| Field        | Value                            |
+--------------+----------------------------------+
| enabled      | True                             |
| id           | 0d916e27833c45dcbee0c6bf761f14b4 |
| interface    | admin                            |
| region       | RegionOne                        |
| region_id    | RegionOne                        |
| service_id   | 7ff47bcff13a472e817122976cfac710 |
| service_name | swift                            |
| service_type | object-store                     |
| url          | http://10.0.0.27:8080/v1         |
+--------------+----------------------------------+

 

 

네트워크(프록시) 노드 구성

 

 

Swift 프록시 서비스 제공에 필요한 패키지를 설치해 줍니다.

[root@Network ~]# yum install openstack-swift-proxy python-memcached openssh-clients

 

Swift 프록시 서버 관련 정보를 설정해 줍니다.

[root@Network ~]# vim /etc/swift/proxy-server.conf

...생략...

//memcache 정보를 설정해줍니다. memcache 서비스는 현재 컨트롤러 노드에서 동작하고 있으므로 컨트롤러 노드의 ip를 입력합니다.
[filter:cache]
use = egg:swift#memcache
#memcache_servers = 127.0.0.1:11211
memcache_servers = 10.0.0.26:11211

//paste.filter_factory를 제외한 기존 정보는 주석처리합니다.
[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
#admin_tenant_name = %SERVICE_TENANT_NAME%
#admin_user = %SERVICE_USER%
#admin_password = %SERVICE_PASSWORD%
#auth_host = 127.0.0.1
#auth_port = 35357
#auth_protocol = http
#signing_dir = /tmp/keystone-signing-swift

//컨트롤러 노드의 ip로 입력하고, 앞서 컨트롤러 노드에서 입력한 swift user의 패스워드를 지정해줍니다.
www_authenticate_uri = http://10.0.0.26:5000
auth_url = http://10.0.0.26:5000
memcached_servers = 10.0.0.26:11211
auth_type = password
project_domain_name = default
user_domain_name = default
project_name = service
username = swift
password = servicepassword
delay_auth_decision = true

 

swift 설정파일을 아래와 같이 주석처리 및 추가해 줍니다.

[root@Network ~]# vim /etc/swift/swift.conf

[swift-hash]
#swift_hash_path_suffix = %SWIFT_HASH_PATH_SUFFIX%
swift_hash_path_suffix = swift_shared_path
swift_hash_path_prefix = swift_shared_path

 

추후 클러스터링할 오브젝트 스토리지를 위해 아래와 같이 링(Ring) 정보를 생성해 줍니다.

참고(오픈스택 공식 문서): https://docs.openstack.org/liberty/ko_KR/install-guide-ubuntu/swift-initial-rings.html

 

  • 링: 클러스터링 된 오브젝트 스토리지 중, 사용자 요청에 따라 데이터를 저장해야할 때, 어떤 스토리지에 데이터를 저장할지 선택하는 역할을 수행.

ring을 create, add하는 과정에서 사용되는 포맷이 있습니다. 각 포맷이 의미하는 바는 아래와 같습니다.

  • swift-ring-builder *.builder create 명령의 12 3 1 의미: 
    • 12: 한 클러스터 스토리지에서 생성 가능한 파티션 수. 2^12 = 4096. 즉 12는 거듭제곱(power) 수를 의미.
    • 3: 오브젝트 복사 수. 스토리지 장치의 수를 의미하기도 함. 기본이 3.
    • 1:  데이터 이동, 복제, 파티션 이동 등이 진행될 때 잠기는 최소 시간. 데이터 손실을 방지하기 위한 기능.
  • swift-ring-builder *.builder add 명령의 r0z0, r1z1, r2z2 의미: 
    • r과 z: 각각 region, zone을 의미
    • 숫자 0,1,2: 각 스토리지가 속하는 region과 zone의 번호를 의미

위의 정보를 참고하여 아래와 같이 account, container, object를 생성합니다.

//builder 생성
[root@Network ~]# swift-ring-builder /etc/swift/account.builder create 12 3 1 
[root@Network ~]# swift-ring-builder /etc/swift/container.builder create 12 3 1 
[root@Network ~]# swift-ring-builder /etc/swift/object.builder create 12 3 1

//각 builder에 region과 zone을 추가.
//Storage1 관련
[root@Network ~]# swift-ring-builder /etc/swift/account.builder add r0z0-10.0.0.28:6202/device0 100 
Device d0r0z0-10.0.0.28:6202R10.0.0.28:6202/device0_"" with 100.0 weight got id 0
[root@Network ~]# swift-ring-builder /etc/swift/container.builder add r0z0-10.0.0.28:6201/device0 100 
Device d0r0z0-10.0.0.28:6201R10.0.0.28:6201/device0_"" with 100.0 weight got id 0
[root@Network ~]# swift-ring-builder /etc/swift/object.builder add r0z0-10.0.0.28:6200/device0 100 
Device d0r0z0-10.0.0.28:6200R10.0.0.28:6200/device0_"" with 100.0 weight got id 0

//Storage2 관련
[root@Network ~]# swift-ring-builder /etc/swift/account.builder add r1z1-10.0.0.29:6202/device1 100 
Device d1r1z1-10.0.0.29:6202R10.0.0.29:6202/device1_"" with 100.0 weight got id 1
[root@Network ~]# swift-ring-builder /etc/swift/container.builder add r1z1-10.0.0.29:6201/device1 100 
Device d1r1z1-10.0.0.29:6201R10.0.0.29:6201/device1_"" with 100.0 weight got id 1
[root@Network ~]# swift-ring-builder /etc/swift/object.builder add r1z1-10.0.0.29:6200/device1 100 
Device d1r1z1-10.0.0.29:6200R10.0.0.29:6200/device1_"" with 100.0 weight got id 1

//Storage3 관련
[root@Network ~]# swift-ring-builder /etc/swift/account.builder add r2z2-10.0.0.31:6202/device2 100 
Device d2r2z2-10.0.0.31:6202R10.0.0.31:6202/device2_"" with 100.0 weight got id 2
[root@Network ~]# swift-ring-builder /etc/swift/container.builder add r2z2-10.0.0.31:6201/device2 100 
Device d2r2z2-10.0.0.31:6201R10.0.0.31:6201/device2_"" with 100.0 weight got id 2
[root@Network ~]# swift-ring-builder /etc/swift/object.builder add r2z2-10.0.0.31:6200/device2 100 
Device d2r2z2-10.0.0.31:6200R10.0.0.31:6200/device2_"" with 100.0 weight got id 2

//위의 정보를 실제 builder에 반영
[root@Network ~]# swift-ring-builder /etc/swift/account.builder rebalance 
Reassigned 12288 (300.00%) partitions. Balance is now 0.00. Dispersion is now 0.00
[root@Network ~]# swift-ring-builder /etc/swift/container.builder rebalance 
Reassigned 12288 (300.00%) partitions. Balance is now 0.00. Dispersion is now 0.00
[root@Network ~]# swift-ring-builder /etc/swift/object.builder rebalance 
Reassigned 12288 (300.00%) partitions. Balance is now 0.00. Dispersion is now 0.00

 

다음으로 swift 관련 파일의 소유권을 변경해 줍니다.

[root@Network ~]# chown swift. /etc/swift/*.gz 

 

 프록시 서비스를 시작합니다.

[root@Network ~]# systemctl start openstack-swift-proxy 
[root@Network ~]# systemctl enable openstack-swift-proxy 

 

시스템에서 방화벽이 동작 중이라면 필요한 포트 정보를 허용해 줍니다.

[root@Network ~]# firewall-cmd --add-port=8080/tcp --permanent 
success
[root@Network ~]# firewall-cmd --reload 
success

 

 

 

 

스토리지 노드 구성

 

 

사용될 모든 스토리지(본 포스트에서는 Object Storage 1,2,3)에서 실제 데이터를 저장하고 관리하기 위한 작업을 진행합니다.

 

우선 스토리지 별로 비정형 데이터를 저장하기 위한 물리 볼륨을 시스템에 추가해주고 마운트해야 합니다. 본 포스트에서는 오브젝트 스토리지를 위한 추가 볼륨(아래 예시에서는 /dev/sdb1)을 추가해주었고, 오픈스택 파운데이션에서도 새로운 볼륨을 추가해 주는 것으로 매뉴얼에 소개되어 있습니다. 따라서 새로운 볼륨 추가 없이, 기존 루트 파티션의 볼륨(아마도 /dev/sda)과 공유하여 사용할 수 있을지는 확실치 않습니다. 이 부분은 나중에 기회가 되면 실험해 보도록 하겠습니다.

 

저는 각 오브젝트 스토리지 1,2,3에 20GB 물리 디스크를 추가해 주었습니다. 이후 fdisk 명령을 통해 /dev/sdb 디스크를 통해 /dev/sdb1을 생성하는 작업까지 진행을 마쳤습니다. 아래 작업은 이 이후 과정부터 각 노드별 작업 및 공통 작업으로 나누어 설명합니다.

 

 

Object Storage1 

 

 

오브젝트 스토리지1은 앞서 설계와 같이, 기존에 이미 cinder 서비스가 동작하는 노드입니다. 따라서 기본적인 네트워크, 시간 동기화, openstack stein 레포지토리 설정 등은 이미 구성을 마친 노드입니다. 만약 이러한 구성이 안되어 있는 경우, 아래 "Object Storage2"를 참고하여 진행하시기 바랍니다.

 

아래와 같이 /dev/sdb1의 파일시스템을 xfs로 지정합니다.

 

[root@Storage1 ~]# mkfs.xfs -i size=1024 -s size=4096 /dev/sdb1
meta-data=/dev/sdb1              isize=1024   agcount=4, agsize=1310656 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=5242624, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

 

device0 디렉토리를 생성하고 해당 디렉토리에 sdb1 볼륨을 마운트합니다. 마운트 된 디렉토리의 소유권도 swift로 변경함으로써, 이후 swift 서비스가 접근할 수 있도록 합니다.

[root@Storage1 ~]# mkdir -p /srv/node/device0
[root@Storage1 ~]# mount -o noatime,nodiratime,nobarrier /dev/sdb1 /srv/node/device0
[root@Storage1 ~]# chown -R swift. /srv/node 

 

재부팅 할 경우를 대비하여 위에서 생성한 볼륨을 fstab에 등록합니다.

[root@Storage1 ~]# vim /etc/fstab
/dev/sdb1               /srv/node/device0       xfs     noatime,nodiratime,nobarrier 0 0

 

 

 

Object Storage2

 

 

Storage2는 기존에 NFS기반으로 Storage1의 Cinder 서비스와 함께 스토리지 서비스를 제공중인 노드입니다. 하지만 Cinder 서비스나 오픈스택 stein이 설치되어 있지는 않았습니다. 따라서 아래와 같이 stein 버전을 설치하고 레포지토리를 지정해 줍니다.

[root@Storage2 ~]# yum -y install centos-release-openstack-stein 
[root@Storage2 ~]# sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/CentOS-OpenStack-stein.repo 

 

다음으로 시간동기화도 진행합니다. 시간 동기화는 해당 포스트를 참고하여 진행합니다(4번 참고): 

Stein 오픈스택 클라우드 서버 구축(2) - 시스템 구성 (update 2020.01.28)

 

다음으로, 앞서 진행한 Storage1과 같이 sdb1 디스크의 파일시스템을 xfs로 지정하고 디렉토리 생성, 마운트, 소유권 변환을 진행합니다. 

 

* 중요: 디렉토리 번호는 Storage1의 device0과 같으면 안됩니다.

[root@Storage2 ~]# mkfs.xfs -i size=1024 -s size=4096 /dev/sdb1
...메시지생략...
[root@Storage2 ~]# mkdir -p /srv/node/device1
[root@Storage2 ~]# mount -o noatime,nodiratime,nobarrier /dev/sdb1 /srv/node/device1
[root@Storage2 ~]# chown -R swift. /srv/node 

 

마지막으로 fstab에 볼륨을 등록해 둡니다.

[root@Storage2 ~]# vim /etc/fstab
/dev/sdb1               /srv/node/device1       xfs     noatime,nodiratime,nobarrier 0 0

 

 

 

Object Storage3

 

 

Storage3 역시 Storage2와 마찬가지로 현재 오픈스택 stein 버전이 설치되어 있지 않으므로, 아래와 같이 설치해줍니다.

[root@Storage3 ~]# yum -y install centos-release-openstack-stein 
[root@Storage3 ~]# sed -i -e "s/enabled=1/enabled=0/g" /etc/yum.repos.d/CentOS-OpenStack-stein.repo 

 

다음으로 시간동기화도 진행합니다. 시간 동기화는 해당 포스트를 참고하여 진행합니다(4번 참고): 

Stein 오픈스택 클라우드 서버 구축(2) - 시스템 구성 (update 2020.01.28)

 

 

다음으로, 앞서 진행한 Storage1과 같이 sdb1 디스크의 파일시스템을 xfs로 지정하고 디렉토리 생성, 마운트, 소유권 변환을 진행합니다.

 

* 중요: 디렉토리 번호는 Storage1,2의 device0,1과 같으면 안됩니다.

[root@Storage3 ~]# mkfs.xfs -i size=1024 -s size=4096 /dev/sdb1
...메시지생략...
[root@Storage3 ~]# mkdir -p /srv/node/device2
[root@Storage3 ~]# mount -o noatime,nodiratime,nobarrier /dev/sdb1 /srv/node/device2
[root@Storage3 ~]# chown -R swift. /srv/node 

 

재부팅을 위해 볼륨을 fstab에 등록합니다.

[root@Storage3 ~]# vim /etc/fstab
/dev/sdb1               /srv/node/device2       xfs     noatime,nodiratime,nobarrier 0 0

 

 

노드 공통

 

 

Storage 1,2,3에 모두 아래와 같이 swift 서비스를 설치합니다.

[root@Storage ~]# yum install openstack-swift-account openstack-swift-container openstack-swift-object xfsprogs rsync openssh-clients

 

 
네트워크 노드에 있는 swift 관련 파일을 복사해 옵니다.

[root@Storage ~]# scp root@Network:/etc/swift/*.gz /etc/swift/
[root@Storage ~]# chown swift. /etc/swift/*.gz

 

다음으로 스토리지 노드의 swift 설정을 진행합니다.

[root@Storage ~]# vi /etc/swift/swift.conf
[swift-hash]
#swift_hash_path_suffix = %SWIFT_HASH_PATH_SUFFIX%
swift_hash_path_suffix = swift_shared_path
swift_hash_path_prefix = swift_shared_pat

 


 

account, container, object 관련 설정을 진행합니다.

//각 노드에서 account, container, object의 bind ip, port 설정
[root@Storage ~]# vi /etc/swift/account-server.conf
bind_ip = 0.0.0.0
bind_port = 6202

[root@Storage ~]# vi /etc/swift/container-server.conf
bind_ip = 0.0.0.0
bind_port = 6201

[root@Storage ~]# vi /etc/swift/object-server.conf
bind_ip = 0.0.0.0
bind_port = 6200

[root@Storage ~]# vi /etc/rsyncd.conf
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log
uid = swift
gid = swift

// 현재 노드의 ip
address = 10.0.0.28

[account]
path            = /srv/node
read only       = false
write only      = no
list            = yes
incoming chmod  = 0644
outgoing chmod  = 0644
max connections = 25
lock file =     /var/lock/account.lock

[container]
path            = /srv/node
read only       = false
write only      = no
list            = yes
incoming chmod  = 0644
outgoing chmod  = 0644
max connections = 25
lock file =     /var/lock/container.lock

[object]
path            = /srv/node
read only       = false
write only      = no
list            = yes
incoming chmod  = 0644
outgoing chmod  = 0644
max connections = 25
lock file =     /var/lock/object.lock

[swift_server]
path            = /etc/swift
read only       = true
write only      = no
list            = yes
incoming chmod  = 0644
outgoing chmod  = 0644
max connections = 5
lock file =     /var/lock/swift_server.lock

 

만약 selinux가 동작중이라면, 아래와 같이 관련 서비스를 허용해 줍니다.

[root@Storage ~]# semanage fcontext -a -t swift_data_t /srv/node/device0 
[root@Storage ~]# restorecon /srv/node/device0

 

방화벽을 사용중이라면 관련 포트를 허용해줍니다.

[root@Storage ~]# firewall-cmd --add-port={873/tcp,6200/tcp,6201/tcp,6202/tcp} --permanent 
success
[root@Storage ~]# firewall-cmd --reload 
success

 

모든 스토리지에서 swift 관련 서비스를 재시작해 줍니다.

[root@Storage ~]# systemctl restart rsyncd openstack-swift-account-auditor openstack-swift-account-replicator openstack-swift-account openstack-swift-container-auditor openstack-swift-container-replicator openstack-swift-container-updater openstack-swift-container openstack-swift-object-auditor openstack-swift-object-replicator openstack-swift-object-updater openstack-swift-object
[root@Storage ~]# systemctl enable rsyncd openstack-swift-account-auditor openstack-swift-account-replicator openstack-swift-account openstack-swift-container-auditor openstack-swift-container-replicator openstack-swift-container-updater openstack-swift-container openstack-swift-object-auditor openstack-swift-object-replicator openstack-swift-object-updater openstack-swift-object

 

 

테스트

 

 

앞서 모든 과정이 진행되었다면, 정상적으로 기능이 동작하는지 확인해 봅니다. cli로 확인할 수도 있겠으나, 저는 대시보드에서 확인해 보겠습니다.

 

우선 http 서비스를 재시작 합니다.

[root@Controller ~]# systemctl restart httpd

 

대시보드 접속 후, 아래와 같이 "프로젝트->오브젝트 스토리지" 메뉴가 있는지 확인해 봅니다. 이후 "컨테이너"로 들어가 봅니다.

 

"컨테이너" 페이지에서 "+컨테이너" 클릭 후, 아래와 같이 이름 입력 후 컨테이너를 생성해 봅니다. 

"test"라는 이름의 컨테이너가 생성되는지 확인해 봅니다.

해당 컨테이너에 파일이 업로드 되는지 확인해 봅니다. 아래와 같이 업로드 버튼(화살표모양)을 클릭 후, "파일선택"을 클릭하여 아무 파일이나 선택하고 "파일 업로드"를 클릭해봅니다.

정상적으로 파일이 업로드 되는 것이 보이면 시스템 구축을 성공적으로 진행했다고 볼 수 있습니다.

 

이로써, 우리가 잘 알고 있는 네이버 클라우드, 구글 드라이브와 같은 형태로 오픈스택을 사용할 수 있게 되었습니다.

 

TAGS.

Comments