Swift で簡単に分散オブジェクトストレージ

最近、OpenStack にどっぷり浸かってる @jedipunkz です。

Folsom がリリースされて Quantum を理解するのにめちゃ苦労して楽しい真っ最中なのだけど、 今日は OpenStack の中でも最も枯れているコンポーネント Swift を使ったオブジェクトストレー ジ構築について少し書こうかなぁと思ってます。

最近は OpenStack を構築・デプロイするのに皆、Swift 入れてないのね。仲間はずれ 感たっぷりだけど、一番安定して動くと思ってる。

これを読んで、自宅にオブジェクトストレージを置いちゃおぅ。

構成は ?…

                        +--------+
                        | client |
                        +--------+
                             |
                      +-------------+
                      | swift-proxy |
                      +-------------+ 172.16.0.10
                             |
         +-------------------+-------------------+ 172.16.0.0/24
         |                   |                   |
+-----------------+ +-----------------+ +-----------------+
| swift-storage01 | | swift-storage02 | | swift-storage03 |
+-----------------+ +-----------------+ +-----------------+
172.16.0.11         172.16.0.12         172.16.0.13

となる。IP アドレスは…

  • client : 172.16.0.0/24 のどこか
  • swift-proxy : 172.16.0.10
  • swift-storage01 : 172.16.0.11
  • swift-storage02 : 172.16.0.12
  • swift-storage03 : 172.16.0.13

これはサンプル。自宅の環境に合わせて読み替えてください。

全て同じネットワークセグメントに。なので上の図は概念的な図です。通信の流れだけ 把握出来ればいいなぁと。向き書いてないけど..。四角で囲まれているのがノード (サー バ) です。物理サーバでも仮想マシンでも大丈夫!

マシンの準備

Ubuntu Server 12.04 もしくは 12.10 を用意。swift-storage のマシン3台だけは /dev/sda6 など Disk デバイスを swift 用に用意してあげてください。普通にハード ディスクのパーティションを切ってあげるだけでいいです。高価な Disk を使うまでも ないので。それが分散ストレージの良いところ! Disk ・ノードが壊れてもデータが失 われないんです!

swift-proxy の構築

今回は簡易認証機能の tempauth を使います。Keystone を使った構成を説明しようか 迷ったのだけど、Keystone の構築だけで一つ記事が書けるくらいになるので..、諦め ました。tempauth は Swift 本体に実装されていますよ。

構築は簡単、まず下記をコピペしてください。

apt-get update
apt-get install swift python-swift
apt-get install python-keystoneclient python-keystone 
mkdir /etc/swift
chown -R swift:swift /etc/swift
export PROXY_LOCAL_NET_IP=10.200.4.133
export POUND_NET=10.200.4.138
apt-get install swift-proxy memcached
perl -pi -e "s/-l 127.0.0.1/-l $PROXY_LOCAL_NET_IP/" /etc/memcached.conf
service memcached restart
cat >/etc/swift/proxy-server.conf <<EOF
[DEFAULT]
#cert_file = /etc/swift/cert.crt
#key_file = /etc/swift/cert.key
bind_port = 8080
workers = 8
user = swift

[pipeline:main]
pipeline = healthcheck cache tempauth proxy-server

[app:proxy-server]
use = egg:swift#proxy
allow_account_management = true
account_autocreate = true

[filter:tempauth]
use = egg:swift#tempauth
user_system_root = testpass .admin
https://$PROXY_LOCAL_NET_IP:8080/v1/AUTH_system

[filter:healthcheck]
use = egg:swift#healthcheck

[filter:cache]
use = egg:swift#memcache
memcache_servers = $PROXY_LOCAL_NET_IP01:11211
EOF

次に swift.conf とリング情報 (バランシングのための情報) を swift-proxy 上に用意します。これらは、 あとで各すべてのノードに配置するので重要です。これもコピペしてください。

cat > /etc/swift/swift.conf << EOF
[swift-hash]
# random unique string that can never change (DO NOT LOSE)
swift_hash_path_suffix = `od -t x8 -N 8 -A n </dev/random`
EOF
cd /etc/swift
swift-ring-builder account.builder create 18 3 1
swift-ring-builder container.builder create 18 3 1
swift-ring-builder object.builder create 18 3 1
export STORAGE_LOCAL_NET_IP01=172.16.0.11
export STORAGE_LOCAL_NET_IP02=172.16.0.12
export STORAGE_LOCAL_NET_IP03=172.16.0.13
export ZONE01=1
export ZONE02=2
export ZONE03=3
export WEIGHT=100
export DEVICE=sda6
swift-ring-builder account.builder add z$ZONE01-$STORAGE_LOCAL_NET_IP01:6002/$DEVICE $WEIGHT
swift-ring-builder container.builder add z$ZONE01-$STORAGE_LOCAL_NET_IP01:6001/$DEVICE $WEIGHT
swift-ring-builder object.builder add z$ZONE01-$STORAGE_LOCAL_NET_IP01:6000/$DEVICE $WEIGHT
swift-ring-builder account.builder add z$ZONE02-$STORAGE_LOCAL_NET_IP02:6002/$DEVICE $WEIGHT
swift-ring-builder container.builder add z$ZONE02-$STORAGE_LOCAL_NET_IP02:6001/$DEVICE $WEIGHT
swift-ring-builder object.builder add z$ZONE02-$STORAGE_LOCAL_NET_IP02:6000/$DEVICE $WEIGHT
swift-ring-builder account.builder add z$ZONE03-$STORAGE_LOCAL_NET_IP03:6002/$DEVICE $WEIGHT
swift-ring-builder container.builder add z$ZONE03-$STORAGE_LOCAL_NET_IP03:6001/$DEVICE $WEIGHT
swift-ring-builder object.builder add z$ZONE03-$STORAGE_LOCAL_NET_IP03:6000/$DEVICE $WEIGHT
swift-ring-builder account.builder
swift-ring-builder container.builder
swift-ring-builder object.builder
swift-ring-builder account.builder rebalance
swift-ring-builder container.builder rebalance
swift-ring-builder object.builder rebalance

で、起動。

swift-proxy# chown -R swift:swift /etc/swift
swift-proxy# swift-init proxy start

おしまい。

swift-storage 構築

swift-storage の構築は各ノードで下記の内容をコピペしてください。今回は3台分だ けど、マシンが余ってたら4台でも5台でも OK !

apt-get update
apt-get install swift python-swift
mkdir /etc/swift
chown -R swift:swift /etc/swift

export STORAGE_LOCAL_NET_IP=172.16.0.11

apt-get install swift-account swift-container swift-object xfsprogs
mkfs.xfs -i size=1024 /dev/sda6
echo "/dev/sda6 /srv/node/sda6 xfs noatime,nodiratime,nobarrier,logbufs=8 0 0" >> /etc/fstab
mkdir -p /srv/node/sda6
mount /srv/node/sda6
chown -R swift:swift /srv/node
cat >/etc/rsyncd.conf <<EOF
uid = swift
gid = swift
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
address = $STORAGE_LOCAL_NET_IP

[account]
max connections = 2
path = /srv/node/
read only = false
lock file = /var/lock/account.lock

[container]
max connections = 2
path = /srv/node/
read only = false
lock file = /var/lock/container.lock

[object]
max connections = 2
path = /srv/node/
read only = false
lock file = /var/lock/object.lock
EOF
perl -pi -e 's/RSYNC_ENABLE=false/RSYNC_ENABLE=true/' /etc/default/rsync
service rsync start
cat >/etc/swift/account-server.conf <<EOF
[DEFAULT]
bind_ip = $STORAGE_LOCAL_NET_IP
workers = 2

[pipeline:main]
pipeline = account-server

[app:account-server]
use = egg:swift#account

[account-replicator]

[account-auditor]

[account-reaper]
EOF
cat >/etc/swift/container-server.conf <<EOF
[DEFAULT]
bind_ip = $STORAGE_LOCAL_NET_IP
workers = 2

[pipeline:main]
pipeline = container-server

[app:container-server]
use = egg:swift#container

[container-replicator]

[container-updater]

[container-auditor]

[container-sync]
EOF
cat >/etc/swift/object-server.conf <<EOF
[DEFAULT]
bind_ip = $STORAGE_LOCAL_NET_IP
workers = 2

[pipeline:main]
pipeline = object-server

[app:object-server]
use = egg:swift#object

[object-replicator]

[object-updater]

[object-auditor]
EOF

環境変数 ${STORAGE_LOCAL_NET_IP} を3台毎に変えて、各台で流し込んであげたら、 swift-proxy で生成した /etc/swift.conf とリング情報達を各 swift-storage に 配置します。

swift-proxy     # scp /etc/swift/swift.conf /etc/swift/*ring.gz 172.16.0.11:/tmp/
swift-proxy     # scp /etc/swift/swift.conf /etc/swift/*ring.gz 172.16.0.12:/tmp/
swift-proxy     # scp /etc/swift/swift.conf /etc/swift/*ring.gz 172.16.0.13:/tmp/
swift-storage01 # mv /tmp/swift.conf /tmp/*ring.gz /etc/swift/
swift-storage01 # chown -R swift:swift /etc/swift
swift-storage02 # mv /tmp/swift.conf /tmp/*ring.gz /etc/swift/
swift-storage02 # chown -R swift:swift /etc/swift
swift-storage03 # mv /tmp/swift.conf /tmp/*ring.gz /etc/swift/
swift-storage03 # chown -R swift:swift /etc/swift

swift-storage を各台で起動します。

swift-storage01 # swift-init all start
swift-storage02 # swift-init all start
swift-storage03 # swift-init all start

アクセスしてみる

完成したので、swift クライアントでアクセスしてみる。

% swift -A http://172.16.0.10:8080/auth/v1.0 -U system:root -K testpass stat
Account: AUTH_system
Containers: 4
Objects: 15
Bytes: 23866252
Connection: keep-alive
Accept-Ranges: bytes

ファイルをアップロード・ダウンロードしてみる。

% swift -A http://172.16.0.10:8080/auth/v1.0 -U system:root -K testpass upload test /etc/hosts
% swift -A http://172.16.0.10:8080/auth/v1.0 -U system:root -K testpass list
% test
% cd /tmp/
% swift -A http://172.16.0.10:8080/auth/v1.0 -U system:root -K testpass download test
% ls /tmp/etc/hosts

もちろん、HTTP な API なので curl 等の HTTP ブラウザを使ってもアクセスできる!

% curl -k -v -H 'X-Storage-User: system:root' -H 'X-Storage-Pass: testpass' http://172.16.0.10:8080/auth/v1.0
< HTTP/1.1 200 OK
< Server: nginx/1.1.19
< Date: Mon, 03 Sep 2012 04:58:30 GMT
< Content-Length: 0
< Connection: keep-alive
< X-Storage-Url: https://172.16.0.10:8080/v1/AUTH_system
< X-Storage-Token: AUTH_tk8a19f76c9bce4077aee02aef76257020
< X-Auth-Token: AUTH_tk8a19f96c9bce4077aee02aef76257020
<
* Connection #0 to host 172.16.0.10 left intact
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):

得られた X-Auth-Token, X-Storage-Url を使ってアクセスする。

% curl -k -v -H 'X-Auth-Token: <token-from-x-auth-token-above>' <url-from-x-storage-url-above>
< HTTP/1.1 200 OK
< Server: nginx/1.1.19
< Date: Mon, 03 Sep 2012 04:59:47 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 34
< Connection: keep-alive
< X-Account-Object-Count: 15
< X-Account-Bytes-Used: 23866252
< X-Account-Container-Count: 4
< Accept-Ranges: bytes
<
test
* Connection #0 to host 172.16.0.10 left intact
* Closing connection #0
* SSLv3, TLS alert, Client hello (1):

さっき放り込んだ ‘test’ が swift 上にあることが確認できる。

http://cyberduck.ch/ ここにある CyberDuck という GUI なツールを使ってもアクセス出来るよ! HTTPS が必須になるので一工夫する必要があるのだけど、そのあたりは頑張ってみてください。

オンラインでのノードの追加・削除なんてことも出来ます。次回時間があったら解説しますね。

今回は swift-ring-builder コマンドでレプリカ数 ‘3’ を指定したので、アップロー ドしたファイル(オブジェクトと言う) は必ず 3 個配置される。なので 1 台の swift-storage が故障しても大丈夫。ノードを増やせばストレージ全体の容量も増やせ る。また、swift-proxy は単純な HTTP なので負荷分散機・もしくはソフトウェアのロー ドバランサを入れれば swift-proxy 自体の冗長も組めるほか、ストレージ I/O の拡張 にもつながる。pound, nginx などを使って冗長組んでみてください。その時に memcached の内容は共有させてあげる必要があるので、これまた一工夫が必要なのだけ ど。時間があったら今度解説します。

自宅でも簡単に分散オブジェクトストレージが組める swift。使わない手は無いですよぉ。