
Setup Openstack Swift on Ubuntu 14.04
Openstack Swift เป็น Object Storage ของค่าย Openstack ถูกใช้โดยบริษัทใหญ่ๆจำนวนมาก ช่วยให้เราสามารถสร้าง object storage คล้ายๆ S3 ใน datacenter ของเราได้ไม่ยาก…
Openstack Swift เป็น Object Storage ของค่าย Openstack ถูกใช้โดยบริษัทใหญ่ๆจำนวนมาก ช่วยให้เราสามารถสร้าง object storage คล้ายๆ S3 ใน datacenter ของเราได้ไม่ยาก
Install dependencies
ลง ubuntu 14.04 แบบเปล่าๆ เลือกเพิ่มเพียง basic server และ openssh เท่านั้น จากนั้นทำการ update package ซะก่อน
apt-get update
apt-get upgrade
ทุกเครื่องเวลาจะต้อง sync กันไม่งั้นจะมีปัญหากับการคำนวน ในขั้นตอนการทำงานของ swift ดังนั้นเราจำเป็นต้องเซ็ตให้มี ntp ด้วย และ set timezone ให้ทุกเครื่องตรงกัน
apt-get install ntp ntpdate
dpkg-reconfigure tzdata
swift จะแนะนำให้เราใช้ xfs เป็น file system ของ harddisk ซึ่งโดยปกติแล้ว ubuntu จะไม่ได้ลง xfs มาให้ด้วย จึงจำเป็นที่จะต้องติดตั้งก่อน ด้วยคำสั่ง
apt-get install xfsprogs
ต่อไปเป็นการลง library พื้นฐานของ python ที่จำเป็นต้องใช้ ซึ่งจะมีสองส่วนคือ ส่วนที่ใช้ในการเซ็ตอัพและcompile ต่างๆ
apt-get install curl gcc memcached rsync sqlite3 git-core libffi-dev python-setuptools
และ library ที่จำเป็นต้องใช้ใน swift
apt-get install python-coverage python-dev python-nose python-simplejson python-xattr python-eventlet python-greenlet python-pastedeploy python-netifaces python-pip python-dnspython python-mock
Setup Storage Disk
ในขั้นตอนนี้คือการที่เราจะ format disk ที่เราจะให้ swift ใช้ทุกให้เป็น xfs นะครับ ถ้าหากเรามี disk ที่เป็น physical disk อยู่แล้ว ก็สามารถใช้คำสั่ง fdisk ดูได้เลยว่ามี drive อะไรอยู่บ้าง และในการทำงาน swift นั้นไม่จำเป็นต้องแบ่ง partition disk ก็ได้
โดยใช้คำสั่ง
# เพื่อดูว่ามี disk อะไรอยู่บ้าง
fdisk -l
# ทำการ format เป็น xfs และใส่ label ด้วยเพื่อให้จำง่าย
mkfs.xfs -f -L o1 -i size=1024 /dev/sda
mkfs.xfs -f -L o2 -i size=1024 /dev/sdb
# Note : ตาม recommend ที่ได้อ่านมา xfs โดย default จะอยู่ที่ 256 ซึ่งค่อนข้างจะเล็กเกินไป เลยขนาดขนาดของ inode เป็น 1024
# สร้าง folder mount point และทำการ mount จากนั้นก็ใส่ลงไปใน /etc/fstab เพื่อให้ทำการ mount ตอน boot
# Note : เมื่อก่อนเราใช้ o1 กับ o2 แต่หลังจากใช้งานจริงชื่อ o1 จะไปซ้ำซ้อนกับเวลาเรียก index ใน swift นะครับ ซึ่ง swift จะเข้าใจว่า o1 คือ disk ที่ index 1 ด้วย จึงควรหลีกเลี่ยงการใช้
mkdir -p /srv/node/o1
mkdir -p /srv/node/o2
echo '/dev/sda /srv/node/o1 xfs noatime,nodiratime,nobarrier,logbufs=8 0 0' >> /etc/fstab
echo '/dev/sdb /srv/node/o2 xfs noatime,nodiratime,nobarrier,logbufs=8 0 0' >> /etc/fstab
mount -a
Install Swift CLI (python-swiftclient)
เพื่อให้เป็นระบบเบียบเราเลยจะเก็บ code ทั้งหมดไว้ใน opt โดยการทำงานคือเราไปที่ folder opt จากนั้นทำการ clone code ของ client ทั้งหมดมาไว้ แล้วก็ลง package ที่จำเป็นของ python จากนั้นก็สั่ง install
cd /opt
git clone https://github.com/openstack/python-swiftclient.git
cd /opt/python-swiftclient
pip install -U -r requirements.txt
python setup.py install
หลังจากการอัพเดทตรงนี้แล้วใครที่รันแล้ว error cannot import name IncompleteRead น่าจะเกิดจากการที่ update package request แล้ว error นะครับ
ลองดูรายละเอียดปัญหานี้ใน pip stops with ImportError for request-Modul
ส่วนวิธีแก้แบบง่ายๆคือมีสองทางคือ
ทำการลง package request ใหม่ด้วย easy_installเพื่อเป็นการลง request ทับลงไปใหม่
easy_install requests==2.2.1
หรืออีกวิธีคือ ทำการลง pip ใหม่เลยเพื่อป้องกันปัญหานี้ในอนาคต
apt-get remove python-pip
easy_install pip
Install Swift
ขั้นตอนจะเหมือนกันกับตอนที่เราลง cli คือ ไปที่ folder opt จากนั้นทำการ clone code ของ client ทั้งหมดมาไว้ แล้วก็ลง package ที่จำเป็นของ python จากนั้นก็สั่ง install
cd /opt
git clone https://github.com/openstack/swift.git
cd /opt/swift
pip install -U -r requirements.txt
python setup.py install
Basic Swift Configuration
เริ่มด้วยการสร้าง folder ไว้สำหรับเก็บ config ของ swift ทั้งหมดจากนั้น copy file ตัวอย่างการ config ไปวางไว้
mkdir -p /etc/swift
cd /opt/swift/etc
cp account-server.conf-sample /etc/swift/account-server.conf
cp container-server.conf-sample /etc/swift/container-server.conf
cp object-server.conf-sample /etc/swift/object-server.conf
cp proxy-server.conf-sample /etc/swift/proxy-server.conf
cp drive-audit.conf-sample /etc/swift/drive-audit.conf
cp swift.conf-sample /etc/swift/swift.conf
cp container-reconciler.conf-sample /etc/swift/container-reconciler.conf
cp object-expirer.conf-sample /etc/swift/object-expirer.conf
ถึงตรงนี้โปรแกรม Swift จะสามารเริ่มทำงานได้แล้ว เราสามารถทดลองรันได้ด้วยคำสั่ง
swift-init -h
ต่อไปเราจะสร้าง user ชื่อ swift ขึ้นมาเพื่อใช้ในการรัน process และจัดการไฟล์ต่างๆ และกำหนดสิทธิในการเข้าถึงข้อมูล
useradd swift
chown -R swift:swift /srv/node
# สร้าง folder ไว้เพื่อให้ swift ทำงาน
mkdir -p /var/run/swift
mkdir -p /var/cache/swift
chown -R swift:swift /var/run/swift
chown -R swift:swift /var/cache/swift
storage policies
การกำหนด storage policies โดยเข้าไปแก้ไขไฟล์ /etc/swift/swift.conf เนื่องจากไฟล์นี้เราได้ copy มาจากไฟล์ตัวอย่าง จึงจะมี config ตัวอย่างมาให้แล้วในไฟล์นะครับ
vim /etc/swift/swift.conf
ในเนื้อไฟล์จะมีส่วนที่ต้องแก้ไขดังนี้คือ
- swift_hash_path_suffix และ swift_hash_path_prefix : คือชุดของ string ที่เราจะใช้ประกอบกับข้อมูล path เวลา gen hash ข้อมูลชุดนี้สามารถเป็นอะไรก็ได้ ที่ต้องใส่เพื่อที่จะป้องกันไม่ให้คนสามารถเดา hash ของเราออก และไม่สามารถทำการโจมตีระบบได้
ถ้าหากนึกไม่ออกว่าจะใช้รหัสอะไรดี สามารถเจนด้วยคำสั่งhead -c 32 /dev/urandom | base64เพื่อสร้าง string ความยาว 32 ตัวอักษรขึ้นมาสองชุดก็ได้แล้วนำไปใช้ แต่ถ้าใช้ base64 จะมีอักขระพิเศษอยู่ใน string และมี “=” ต่อท้าย ถ้าหากต้องการเป็น alphanumeric ให้ใช้เป็นcat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1จะได้เฉพาะ string แทน
คำสั่ง
/dev/urandomหรือคำสั่ง/dev/randomบางครั้งในการรันเราจะไม่ได้ผลลัพธ์อะไรออกมา นั่นเป็นเพราะว่าทั้งสองคำสั่งนั้นใช้ entropy pool ซึ่งถ้าหาก pool ว่างอยู่คำสั่งก็จะทำการรอจนกว่า pool จะเต็มจึงคืนค่าออกมา
- storage-policy:N : ตัวกำหนดค่า policy ของ object ต่างๆใน swift
โดยพื้นฐานแล้วทุก object ใน swift จะต้องอยู่กับ policy อันใดอันหนึ่งเสมอ ซึ่งโดย default จะมี policy-0 อยู่ที่เป็น default แต่ถ้าหากเราต้องการสร้างใหม่เราก็สามารถกำหนดอันอื่นเป็น default ได้เช่นกัน
รูปแบบการกำหนดค่าจะแทนที่ตัว N ด้วยตัวเลขไล่เรียงกันไป ซึ่งตรงส่วนนี้เราจะต้องใช้อีกในตอนเลือก Policy ให้ object ตอนสร้าง ring
ในตัวอย่างข้างล่างคือสร้าง policy ใหม่ขึ้นมา 1 ตัว และกำหนดให้เป็น default แทน policy เดิม
...
[swift-hash]
swift_hash_path_suffix = ib4sewhU+QyIK7GM5RtXdsUHsL1B1nwdP0bWFwXvoME=
swift_hash_path_prefix = iBH2dIYApMLkUpP/3bRuUbDp2NwQtmW86sjZvtKfQC4=
...
[storage-policy:0]
name = Policy-0
#default = yes
...
[storage-policy:1]
name = p1
default = yes
policy_type = replication
...
ring builder
ส่วนสำคัญอันต่อไปของ swift คือการสร้าง ring ซึ่งตัว ring นี้จะเป็นส่วนหลักในการกำนหดว่าไฟล์ไหนจะอยู่ที่ใดบ้าง และเป็นสิ่งที่ทำให้ swift มีการเก็บและกระจายข้อมูลแบบ ==as unique as possible==
คำสั่งในการสร้าง ring คือ swift-ring-builder โดยมี argument ดังนี้
swift-ring-builder (account|container|object|object-n).builder create <part_power> <replicas> <min_part_hours>
ตัวคือ
(account|container|object|object-n).builderเป็นประเภทของ ring ว่าจะสร้าง ring ของ account , container , object หรือ object policy ไหน<part_power>คือจำนวน partition ทั้งหมดที่จะมีในระบบ ตัวอย่างการคำนวน เช่นหากเราต้องการให้ disk ทุกลูกมีจำนวน 100 partition ก็จะได้สูตรเป็น
partition power = log2 (100 × [max expected number of disk])
ถ้าเรามี disk เครื่องละ 15 ลูกมี cluster ขนาด 10 เครื่อง ก็จะได้เป็น partition power = log2(100x15x10) = 13.872 ≈ 14 ผลลัพธ์ที่ได้ ถ้าไม่ลงตัวจะปัดขึ้นหรือลงก็ได้ แต่ถ้าให้แนะนำการปัดขึ้นจะได้ประสิทธิภาพที่ดีกว่า<replicas>จำนวน copy ของไฟล์ที่จะมีในระบบ<min_part_hours>เพื่อเป็นการป้องกันไม่ให้มีการโยกย้ายไฟล์บ่อยเกินไป และเพื่อให้มั่นใจว่า จะมีอย่างน้อย 1 copy เสมอที่พร้อมใช้งาน จึงให้มีการกำนหดค่านี้ขึ้น เพื่อเป็นการ lock file ไว้ไม่ให้มีการเคลื่อนย้ายในช่วงเวลาที่กำหนด
เพื่อให้ทุกไฟล์อยู่ในที่เดียวกัน เพราะงั้นเราจึงจะรันคำสั่งนี้ใน folder /etc/swift นะครับ ซึ่งตอนรันคำสั่ง builder จะได้ไฟล์ .builder ขึ้นมาตามประเภทที่เราสั่ง
cd /etc/swift
swift-ring-builder account.builder create 14 2 1
swift-ring-builder container.builder create 14 2 1
swift-ring-builder object.builder create 14 2 1
swift-ring-builder object-1.builder create 14 2 1
เมื่อรันเสร็จก็จะมีไฟล์ account.builder, container.builder, object.builder, object-1.builder เกิดขึ้นใน folder
ถ้าเราต้องการดูรายละเอียดของแต่ละไฟล์เราสามารถใช้คำสั่ง
swift-ring-builder account.builder
และจะได้ผลลัพธ์เป็น
account.builder, build version 0
16384 partitions, 2.000000 replicas, 0 regions, 0 zones, 0 devices, 0.00 balance, 0.00 dispersion
The minimum number of hours before a partition can be reassigned is 1
The overload factor is 0.00% (0.000000)
จะเห็นว่าจะมีข้อมูลเบื้องต้นตามที่เราได้ config ไปแต่ว่าจะยังไม่มีข้อมูลของเครื่องหรือ disk อยู่ในนี้ เนื่องจากเรายังไม่ได้ทำการ add disk เข้ามาใน ring
หรืออีกวิธีที่ใช้ในการดูข้อมูลของ file builder คือใช้ python ในการเปิดอ่าน เนื่องจาก .builder นั้นเป็น pickle file ของ python เพราะงั้นเราสามารถใช้ python ในการเปิดอ่านได้เลย
# python
>>> import pickle
>>> print pickle.load(open('object.builder'))
{
'devs': [],
'_replica2part2dev': None,
'replicas': 2.0, '_dispersion_graph': {},
'min_part_hours': 1,
'_last_part_gather_start': 0,
'parts': 16384,
'overload': 0.0,
'part_power': 6,
'dispersion': 0.0,
'devs_changed': False,
'version': 0,
'_last_part_moves_epoch': None,
'_last_part_moves': None, '_remove_devs': []
}
การเพิ่ม device ไปยัง builder file
คำสั่งในการเพิ่ม device ไปยัง ring คือ
swift-ring-builder add account.builder <region><zone>-<IP>:6002/<device> <weight>
swift-ring-builder add container.builder <region><zone>-<IP>:6001/<device> <weight>
swift-ring-builder add object.builder <region><zone>-<IP>:6000/<device> <weight>
swift-ring-builder add object-n.builder <region><zone>-<IP>:6000/<device> <weight>
<region><zone>เป็นการแบ่งเพื่อกำหนดขอบเขตของการ failure ที่อาจจะเกิดขึ้นได้ ซึ่งจะกำหนดให้ region หรือ zone ใหญ่แค่ไหนนั้นขึ้นอยู่กับว่า ขนาดของ cluster เราใหญ่เพียงใด เช่น
ถ้าหาก cluster เราอยู่ใน datacenter เดียวกัน ก็อาจจะให้ region คือ ตู้ rack และ zone คือ 1/4 rack หรือ แต่ละเครื่องคือ 1zone เลยก็ได้
หรือถ้า cluster เรามีขนาดใหญ่มาก แต่ละประเทศอาจจะเป็น region และแต่ละ datacenter เป็นแต่ละ zone ก็ได้
การกำหนดนี้เพื่อทำให้ข้อมูลเรา ==as unique as possible== เท่านั้น<IP>ip ของเครื่องที่ device ที่ต้องการอยู่port6002,6001,6000 คือ port default ของ ring แต่ละประเภท ซึ่งค่า default นี้สามารถแก้ไขได้ในไฟล์(account,container,object)-server.conf<device>เราจะใช้เพียงชื่อ folder ของ device เท่านั้นในการเขียน เช่น folder ที่เราได้สร้างตอนแรกชื่อ/srv/node/o1,/srv/node/o2ตอนที่เราระบุค่า device ก็จะใช้เพียงo1และo2เท่านั้น ที่เราไม่ต้องระบุ/srv/nodeนั้นเป็นเพราะค่านี้เป็นค่า default ใน config file(account,container,object)-server.confอยู่แล้วdevices = /srv/nodeซึ่ง swift จะเข้าไปอ่านใน folder นี้โดยอัตโนมัติ<weight>คือค่าการกระจายข้อมูล เพื่อให้ง่าย อาจจะใช้ค่าเป็นขนาดของ disk เลยก็ได้เช่น disk ขนาด 3TB ก็ใช้ 3000 สำหรับ weight จะทำให้ disk แต่ละตัวถูกระจายข้อมูลไปตามขนาดของ disk ที่ถูกเพิ่มเข้ามา หรือถ้าต้องการให้ทุกลูกมีไฟล์เท่ากันก็สามารถใช้ค่าเท่ากันหมดโดยไม่เกี่ยวกับขนาดก็ได้
ตัวอย่างการ add disk 2ลูกของเครื่อง 1 เครื่องไปยัง ring
swift-ring-builder account.builder add r1z1-10.0.0.2:6002/o1 600
swift-ring-builder container.builder add r1z1-10.0.0.2:6001/o1 600
swift-ring-builder object.builder add r1z1-10.0.0.2:6000/o1 600
swift-ring-builder object-1.builder add r1z1-10.0.0.2:6000/o1 600
swift-ring-builder account.builder add r1z1-10.0.0.2:6002/o2 600
swift-ring-builder container.builder add r1z1-10.0.0.2:6001/o2 600
swift-ring-builder object.builder add r1z1-10.0.0.2:6000/o2 600
swift-ring-builder object-1.builder add r1z1-10.0.0.2:6000/o2 600
ตอนนี้เราได้ add device สอง drive เข้าไปยัง ring ลองดูผลลัพธ์ด้วยการรัน
swift-ring-builder object.builder
จะได้ผลลัพธ์มี device เพิ่มมาสองบรรทัดตามที่เราได้ add เข้าไป
object.builder, build version 2
16384 partitions, 2.000000 replicas, 1 regions, 1 zones, 2 devices, 100.00 balance, 0.00 dispersion
The minimum number of hours before a partition can be reassigned is 1
The overload factor is 0.00% (0.000000)
Devices: id region zone ip address port replication ip replication port name weight partitions balance meta
0 1 1 10.0.0.2 6000 10.0.0.2 6000 o1 600.00 0 -100.00
1 1 1 10.0.0.2 6000 10.0.0.2 6000 o2 600.00 0 -100.00
ถ้าสังเกตุตรงค่า balance จะเห็นว่ามีค่าเป็น -100 เพราะว่าเราพึ่งจะทำการ add disk เข้าไปและยังไม่ได้ทำการ rebalance จึงมีค่าเป็น -100 คือจะไม่มีข้อมูลใดๆมากเขียนลงใน device นี้
เมื่อเรา add เสร็จแล้วและต้องการที่จะเริ่มการใช้งานจึงต้องทำการ rebalance เสียก่อนโดยคำสั่ง
cd /etc/swift
swift-ring-builder account.builder rebalance
swift-ring-builder container.builder rebalance
swift-ring-builder object.builder rebalance
swift-ring-builder object-1.builder rebalance
ลองรัน swift-ring-builder object.builder อีกครั้งเพื่อดูผลลัพธ์
# swift-ring-builder object.builder
object.builder, build version 2
16384 partitions, 2.000000 replicas, 1 regions, 1 zones, 2 devices, 0.00 balance, 0.00 dispersion
The minimum number of hours before a partition can be reassigned is 1
The overload factor is 0.00% (0.000000)
Devices: id region zone ip address port replication ip replication port name weight partitions balance meta
0 1 1 10.0.0.2 6000 10.0.0.2 6000 o1 600.00 64 0.00
1 1 1 10.0.0.2 6000 10.0.0.2 6000 o2 600.00 64 0.00
จะได้ค่า balance เป็น 0 คือ ทุก drive มีการกระจายข้อมูลเท่าเทียมกัน ในกรณีที่เรามีการแบ่ง weight ไม่เท่ากัน ค่านี้อาจจะมีค่ามากกว่า 0 ค่าอื่นได้ กระจายตาม weight ที่เราแบ่งไป
การตั้งค่า log
โดย defalut ใน (account,container,object)-server.conf จะส่งค่า log ออกไปยัง local0 ในชื่อ swift อยู่แล้ว
log_name = swift
log_facility = LOG_LOCAL0
log_level = INFO
log_address = /dev/log
ดังนั้นเราสามารถตั้งค่า rsyslog ให้ทำการรับ Log ที่เกิดขึ้นนี้ไปเขียนยังไฟล์ได้เลย
mkdir -p /var/log/swift
chown -R syslog.adm /var/log/swift
chmod -R g+w /var/log/swift
# all log in single file. Not a good practice
echo 'local0.* /var/log/swift/all.log' > /etc/rsyslog.d/0-swift.conf
service rsyslog restart
สร้าง TempAuth user เพื่อทดสอบระบบ
TempAuth คือระบบ auth แบบง่ายๆที่ติดมากับ swift เพื่อใช้ในการสร้าง user ขึ้นมาทดสอบระบบนะครับ วิธีการ config ก็จะอยู่ในไฟล์ /etc/swift/proxy-server.conf เราลองเพิ่ม user เข้าไปใหม่โดย
vim /etc/swift/proxy-server.conf
ส่วนของ config ที่เราจะเพิ่มเข้าไปคือส่วนที่อยู่ใต้ [filter:tempauth] โดยมี format การเพิ่ม user คือ
user_$SWIFTACCOUNT_$SWIFTUSER = $KEY [group] [group] [...] [storage_url]
$SWIFTACCOUNTaccount ใน swift ซึ่ง account ใน swift นี้จะไม่ได้หมายถึง user ที่ใช้งาน แต่หมายถึงหน่วยใหญ่สุดของข้อมูล หรือมองง่ายๆว่าเป็น folder อันหนึ่งก็ได้ ใน folder account ก็จะมีหลาย folder container ใน container ก็ถึงจะมี object อีกทีนึง$SWIFTUSERอันนี้ถึงจะเป็น user ที่จะใช้ในการเข้าถึงระบบจริงๆ ใน 1 account สามารถมีกี่ user ก็ได้$KEYpassword ของ user นี้[group](ใส่หรือไม่ก็ได้) กลุ่มของ user นี้ใช้ในการระบุสิทธิของ user นี้ด้วยว่าทำอะไรได้บ้าง ชื่อกลุ่มจะมี . นำหน้า เช่น .admin[storage_url](ใส่หรือไม่ก็ได้) url ของ storage ที่จะทำการ authen เข้าไป ปกติจะไม่จำเป็นต้องใส่ นอกจากเราจะมีการ config จำเพาะบางอย่าง
และเพื้่อให้มันทำงานได้ เราต้องตั้ง allow_account_management และ account_autocreate ให้มีค่าเป็น True ด้วย เพื่อให้สร้าง account ใหม่จาก config ได้เลย และเพิ่มลบ user ได้
ตัวอย่าง จะเพิ่ม user me ลงใน account ชื่อ myaccount โดยให้เป็น admin และ reseller_admin ด้วยก็จะได้เป็น
[app:proxy-server]
...
allow_account_management = true
account_autocreate = true
...
[filter:tempauth]
...
user_myaccount_me = secretpassword .admin .reseller_admin
...
สุดท้ายเพื่อให้ tempauth ทำงานได้ จำเป็นที่จะต้อง enable memcache ไว้ด้วย ถ้าหายังไม่ได้ทำการ start ไว้ก็ใช้คำสั่ง
service memcached start
ตั้งค่า Consistency Processes
เนื่องจาก swift ใช้ rsync ในการเป็น data transfer channel เราจึงต้องมาตั้งค่าของ rsync สำหรับการใช้งานของเราด้วย
เริ่มด้วยการแก้ไขไฟล์ /etc/default/rsync แล้วแก้ RSYNC_ENABLE จาก false เป็น true
RSYNC_ENABLE=true
จากนั้นทำการแก้ไขหรือสร้าง ไฟล์ /etc/rsyncd.conf
uid = swift
gid = swift
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
[account]
max connections = 5
path = /srv/node/
read only = false
lock file = /var/lock/account.lock
[container]
max connections = 5
path = /srv/node/
read only = false
lock file = /var/lock/container.lock
[object]
max connections = 5
path = /srv/node/
read only = false
lock file = /var/lock/object.lock
path จะต้องตรงกับ path ที่อยู่ในไฟล์ (account,container,object)-server.conf ที่เราตั้งไว้
ทำการ restart service
service rsync start
เราสามารถตรวจสอบว่าทำงานได้ถูกต้องหรือไม่ด้วยการสั่ง
rsync localhost::
rsync localhost::account
rsync localhost::container
rsync localhost::object
ควรจะได้ผลลัพธ์เป็น
# rsync localhost::
account
container
object
# rsync localhost::account
drwxr-xr-x 4,096 2015/06/02 09:58:25 .
drwxr-xr-x 36 2015/06/03 03:00:20 o1
drwxr-xr-x 36 2015/06/03 03:00:20 o2
# rsync localhost::container
drwxr-xr-x 4,096 2015/06/02 09:58:25 .
drwxr-xr-x 36 2015/06/03 03:00:20 o1
drwxr-xr-x 36 2015/06/03 03:00:20 o2
# rsync localhost::object
drwxr-xr-x 4,096 2015/06/02 09:58:25 .
drwxr-xr-x 36 2015/06/03 03:00:20 o1
drwxr-xr-x 36 2015/06/03 03:00:20 o2
เริ่มการทำงาน Swift
ตอนนี้ทุกอย่างพร้อมเริ่มทำงานแล้ว เราสามารถ เริ่มการทำงานได้โดยคำสั่ง จะ start ทั้งหมดพร้อมกันก็ได้
swift-init all start
หรือจะ start ทีละส่วนก็ได้
swift-init proxy start
swift-init account start
swift-init container start
swift-init object start
swift-init account-replicator start
swift-init container-replicator start
swift-init object-replicator start
...
ทดสอบการใช้งาน
ทดสอบต่อ login
curl -v -H 'X-Auth-User: myaccount:me' -H 'X-Auth-Key: secretpassword' http://localhost:8080/auth/v1.0/
จะได้ผลลัพธ์เป็น
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /auth/v1.0/ HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
> X-Auth-User: myaccount:me
> X-Auth-Key: secretpassword
>
< HTTP/1.1 200 OK
< X-Storage-Url: http://localhost:8080/v1/AUTH_myaccount
< X-Auth-Token: AUTH_tk048752659a5d475d9b947de718c64f43
< Content-Type: text/html; charset=UTF-8
< X-Storage-Token: AUTH_tk048752659a5d475d9b947de718c64f43
< Content-Length: 0
< X-Trans-Id: tx07f11ae1905644bbab570-00556eae51
< Date: Wed, 03 Jun 2015 07:35:45 GMT
<
* Connection #0 to host localhost left intact
ทดสอบใช้ token ในการเรียกข้อมูล
curl -v -H 'X-Storage-Token: AUTH_tk048752659a5d475d9b947de718c64f43' http://localhost:8080/v1/AUTH_myaccount/
เราสามารถเรียกโดยใช้เพียง token ที่ได้มาจากการ auth ก็จะได้ผลลัพธ์เช่นกัน
* Hostname was NOT found in DNS cache
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /v1/AUTH_myaccount/ HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
> X-Storage-Token: AUTH_tk048752659a5d475d9b947de718c64f43
>
< HTTP/1.1 204 No Content
< Content-Type: text/plain; charset=utf-8
< X-Account-Object-Count: 0
< X-Timestamp: 1433316971.86943
< X-Account-Bytes-Used: 0
< X-Account-Container-Count: 0
< X-Put-Timestamp: 1433316971.86943
< Content-Length: 0
< X-Trans-Id: tx8822o29b2c704303802fa-00556eae6b
< Date: Wed, 03 Jun 2015 07:36:11 GMT
<
* Connection #0 to host localhost left intact
แต่ตอนนี้เรายังไม่มีข้อมูลอะไร จึงขึ้น 204 No Content
สร้าง container ใหม่
curl -v -H 'X-Storage-Token: AUTH_tk048752659a5d475d9b947de718c64f43' -X PUT http://localhost:8080/v1/AUTH_myaccount/mycontainer
จะได้ผลลัพธ์ออกมาเป็น 201 Created
< HTTP/1.1 201 Created
< Content-Length: 0
< Content-Type: text/html; charset=UTF-8
< X-Trans-Id: tx2e939o1830f347o1b07b7-00556eaee7
< Date: Wed, 03 Jun 2015 07:38:15 GMT
<
ลองไปดูสิ่งที่เกิดขึ้นหลังจากสร้าง container
ls /srv/node/o1
# accounts containers objects objects-1 tmp
จะเห็นว่ามี folder account กับ containers โผล่ขึ้นมา
ซึ่งหาก ลองดูใน folder account จะมี folder ย่อยๆ ตาม hash ขึ้นมาอีก ซึ่งลักษณะของโครงสร้าง folder นี้แต่ละคนจะแตกต่างกันตาม hash ที่คำนวนได้ และตามโครงสร้าง ring ที่ได้กำหนดไว้ เช่น
cd /srv/node/o1/accounts
ls
# 39
cd 39/2d3/9fa47b61fcba8266f00887d5c1ef62d3/
ls
# 9fa47b61fcba8266f00887d5c1ef62d3.db
# 9fa47b61fcba8266f00887d5c1ef62d3.db.pending
อย่างในกรณีตัวอย่างนี้ เราพึ่งสร้าง account ขึ้นมา 1 อันและได้ container ขึ้นมา 1 อัน จึงมีไฟล์ sqlite3 เกิดขึ้นมา 1 ไฟล์ ซึ่งในนี้ถ้าเราลองเปิดดู โดยสั่ง
sqlite3 9fa47b61fcba8266f00887d5c1ef62d3.db
จะได้หน้า console ของ sqlite3 มาให้เราเรียกดูข้อมูลได้
SQLite version 3.8.2 2013-12-06 14:53:30
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .tables
account_stat container incoming_sync outgoing_sync policy_stat
sqlite> select * from container;
3|mycontainer|1433317095.91114|0|0|0|0|1
sqlite> .quit
เมื่อลองสั่ง .tables ดูจะเห็นว่าในข้อมูลของ account ก็จะมี table ชื่อ container อยู่ ซึ่งเอาไว้ lookup ดูว่ามี container ชื่ออะไรบ้าง มีค่าเป็นอะไรบ้าง
ต่อมาเราลองสั่ง select * from container เพื่อดูข้อมูลใน container ก็จะเห็นว่ามีอยู่ 1 container ชื่อ mycontainer ที่เราพึ่งได้สร้างไป
ทั้ง account และ container เป็นเพียง sqlite3 table ที่เอาไว้ lookup ข้อมูลลงไปว่าข้อมูลที่ต้องการอยู่ตรงไหนบ้าง
ทดลองใช้ swift client
อัพโหลดไฟล์
swift -A http://localhost:8080/auth/v1.0/ -U myaccount:me -K secretpassword upload mycontainer some_file
อัพโหลดไฟล์ขนาดใหญ่
เนื่องจาก swift มีการจำกัดขนาดของ object ไว้ที่ 5GB (เปลี่ยนได้ แต่อาจจะมีผลกับประสิทธิภาพการทำงาน) ถ้าหากต้องการอัพโหลดไฟล์ขนาดใหญ่ จำต้องทำการส่งอไปเป็น chunk ย่อย ๆ
swift -A http://127.0.0.1:8080/auth/v1.0/ -U myaccount:me -K secretpassword upload mycontainer -S 1073741824 largefile
สร้าง tempurl
ต้องสร้าง key ขึ้นมาเพื่อใช้เป็น secret ในการสร้าง temp url ก่อน โดยใส่ค่า key ลงใน meta ชื่อ Temp-URL-Key
swift post -m "Temp-URL-Key:mykey" -A http://127.0.0.1:8080/auth/v1.0/ -U myaccount:me -K secretpassword
จากนั้นจึงใช้ key นั้นในการสร้าง tempurl เช่นถ้าเราจะสร้าง ให้ไปเรียกไฟล์ test โดยให้เรียก GET ได้อย่างเดียว และมีอายุ 60 วินาที
swift-temp-url GET 60 /v1/AUTH_myaccount/mycontainer/test mykey
จะได้ temp url ออกมาเป็น
/v1/AUTH_myaccount/mycontainer/test?temp_url_sig=2b382a99495a9o172ff427d94e34070841d7o1f9&temp_url_expires=1433318527
ซึ่ง url นี้จะเรียกได้โดย ไม่ต้องมี username password ใดๆ
curl 'http://localhost:8080/v1/AUTH_myaccount/mycontainer/test?temp_url_sig=2b382a99495a9o172ff427d94e34070841d7o1f9&temp_url_expires=1433318527'
# Test Data!!!
และเมื่อหมดอายุแล้วเรียกใหม่จะได้
curl 'http://localhost:8080/v1/AUTH_myaccount/mycontainer/test?temp_url_sig=2b382a99495a9o172ff427d94e34070841d7o1f9&temp_url_expires=1433318527'
# 401 Unauthorized: Temp URL invalid
ที่มา/อ้างอิง :
- SAIO - Swift All In One การติดตั้งแบบครบจาก doc ของ swift เอง
- หนังสือดีๆของ Swiftstack เขียนดีมาก ๆ ครับ โดยเฉพาะเล่ม Object Storage with Swift by Joe Arnold and the SwiftStack team อ่านเล่มเดียวอยู่เลย
