通过源码运行Swift
作者:张华 发表于:2012-4-8
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明
( http://blog.csdn.net/quqi99 )
Proxy Node,对于每个客户端的请求,它将在Ring中查询Account、Container或Object的位置,并且相应地转发请求。
Storage Server, 有三类存储服务器: Account, Container和Object
Ring, Ring是Swift最重要的组件,用于记录存储对象与物理位置间的映射关系。在涉及查询Account、Container、Object信息时,就需要查询集群的Ring信息。 Ring使用Zone、Device、Partition和Replica来维护这些映射信息。Ring中每个Partition在集群中都(默认)有3个Replica。每个Partition的位置由Ring来维护,并存储在映射中。Ring文件在系统初始化时创建,之后每次增减存储节点时,需要重新平衡一下Ring文件中的项目,以保证增减节点时,系统因此而发生迁移的文件数量最少。
Zone, 如果所有的Node都在一个机架或一个机房中,那么一旦发生断电、网络故障等,都将造成用户无法访问。因此需要一种机制对机器的物理位置进行隔离,以满足分区容忍性(CAP理论中的P)。因此,Ring中引入了Zone的概念,把集群的Node分配到每个Zone中。其中同一个Partition的Replica不能同时放在同一个Node上或同一个Zone内。注意,Zone的大小可以根据业务需求和硬件条件自定义,可以是一块磁盘、一台存储服务器,也可以是一个机架甚至一个IDC。
我的一点理论理解:
普通的哈希算法(一般是对象的哈希对物理结点总数取模,就可以将对象映射到相应的物理结点上)存在这样的问题:
1)可能有的物理结点分配的多,有的物理结点分配的少,数据分布的不平均
2)如果有一台新物理结点加进来,可能需要从其他很多结点往新的移动数据,抖动太大
所以这时候出现了一致性哈希算法,其核心思想是:
1)将哈希空间可看作一个环(Ring).
2)首先求出设备节点(就是一块硬盘)的哈希,这样设备的哈希可以在Ring就是一个点
3)然后就可以再将数据的哈希按顺时针映射到Ring上最近的点,这要的话,每个设备节点只需要处理落在它和它的前驱节点之间的数据
4)添加新设备结点时,新设备结点的哈希又在Ring映射了一个点,这样只需要将离它最近的数据迁移,抖动小
5)可将物理结点再划分更小的虚拟结点以平衡不同性能间物理机器的权重
6)上面第4)步,Ring上直接映射虚拟结点的哈希与对象的哈希,虽然抖动小,但毕竟还得移动数据,所以我们再他们的中间再抽象一个数据分区(Partion)的概念,比如说Ring上有S个虚拟结点,
将其划分成Q个等份,每个等份称为一个数据分区(Partion),并且满足Q>>S,则每个虚拟节点对应的分区数Partion=Q/S,这样的话,就不需要移动数据了,直接将Partion的哈希在新结点重新映射就行了。(Zone -> Device Node -> Virtual Node -> Partion -> Object)
但是有的设备节点的硬盘大比如说200G,有的设备节点硬盘小比较100G,所以我们可以在物理节点上面再抽象一个虚拟结点以分担其权重。
注意:可理解成虚拟结点是所有这些之上的抽象( 硬盘(disk drive),一个server,一个机架(cabinet),一个交换机(switch),甚至是一个数据中心(datacenter)
所有的数据需要冗余备份多份(replica),一般replica=3,因为虚拟节点本来就是环上的点,所以备份时,只需要再将该虚拟节点上的数据同步到它顺时针之后的两个虚拟结点即可。
但是进行数据冗余备份的时候,我们也应该考虑地区的分布,所以我们可以在虚拟结点中再引入一个分区(Zone)的字段,这个字段由初始建Ring时指定,即数据只能按时针replica到具有不同Zone值的虚拟结点上(通过linux里的rsync命令同步,这样同时该虚拟结点还能检测与它通信的结点的心跳)。
Swift中有三种Ring, accounts, containers, objects都有各自的环
Objects, 就是对象了,Swift是分布式对象系统,不同于HDFSg一样的分布式文件系统(文件系统需支持标准的文件接口如NFS,Swift只能用它自己的REST cliet)
Containers, Objects的list, 类似于S3里的桶的概念
Accounts, 是上在Containers的list
抽象成三个Ring的目的是不至于让一个环太大(因为环要直接放到内存里的,不能内存溢出哦)
上面3个环分别都有对应的Object Server, Container Server, Account Server三个进程维护着3个数据库,Proxy Server在有数据查询或存储请求时,再请求这三个服务,它们返回应该上哪个物理结点去管理数据,然后Proxy Server就直接和这个物理结点打交道存储数据了,存储完了,还要更新3个服务里的元数据。
1) 配置swift用户
useradd -mk /home/swift/ -s /bin/bash swiftpasswd swift #为swift用户添加密码,在此我将其设为了swift
编辑/etc/sudoer文件,在文件末尾添加如下代码
swift ALL=(ALL) NOPASSWD:ALL
2)下载swift代码
sudo apt-get install build-essential git python-dev python-setuptools python-pip libxml2-dev libxslt-dev memcached
git clone https://github.com/openstack/swift
git clone https://github.com/openstack/keystone.git
切换到swift用户进入swift目录执行;
su swift
sudo pip install -r requirements.txt
sudo pip install -r test-requirements.txt
sudo python setup.py install
3) 配置
mkdir /etc/swift & sudo chown -R swift:swift /etc/swift/
cp -r /bak/openstack/swift/etc/* /etc/swift/
cd /etc/swift
mv proxy-server.conf-sample proxy-server.conf
mv account-server.conf-sample account-server.conf
mv memcache.conf-sample memcache.conf
mv container-server.conf-sample container-server.conf
mv object-server.conf-sample object-server.conf
mv rsyncd.conf-sample rsyncd.conf
mv swift.conf-sample swift.conf
a, 首先生成随机数: md5sum swift.conf, 将swift.conf中swift_hash_path_suffix 与 swift_hash_path_prefix的值用得到的随机数替换如下
swift_hash_path_suffix = 6bcfdc800aca43cec7979cde8dc3819a
swift_hash_path_prefix = 221d17a3ddbec73528400a12d6d29fe6
b, rsync配置, sudo cp /etc/swift/rsyncd.conf /etc/rsyncd.conf
On fedora,vi /etc/xinetd.d/rsync
disable = noservice xinetd restart
On Ubuntu vi /etc/default/rsync
RSYNC_ENABLE=true
sudo service rsync restart
c, 修改proxy-server.conf
bind_ip = 172.16.1.1
bind_port = 8888 #因为我机器默认的8080端口已被占用
[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
identity_uri = http://172.16.1.1:35357/
auth_uri = http://172.16.1.1:5000/
admin_tenant_name = service
admin_user = swift
admin_password = password
记得将[pipeline:main]中pipeline里的tempauth改成authtoken而使用keytonne
d, 修改memcached.conf
memcache_servers = 127.0.0.1:11211
sudo service rsyslog restart
sudo service memcached restart
e, 修改account-server.conf与container-server.conf与object-server.conf
bind_ip = 172.16.1.1
devices = /srv/node
3, 磁盘及目录, swift的三个Ring使用的是xfs文件系统。
-
dd if=/dev/zero of=/bak/images/swift/swift.img bs=1024 count=0 seek=1000000 #创建10G
mkfs.xfs -i size=1024 /bak/images/swift/swift.img
mkdir -p /srv/node/sdb1
chmod a+w /etc/fstab
echo “/bak/images/swift/swift.img /srv/node/sdb1 xfs noatime,nodiratime,nobarrier,logbufs=8 0 0” >> /etc/fstab
mount /srv/node/sdb1
sudo chown -R swift:swift /srv/node/sdb1
chmod a+w -R /srv/node/sdb1
4 , 配置节点信息
生成ring文件,为这个存储节点配置了2^18个partition
cd /etc/swift
# swift-ring-builder <builder_file> create <part_power> <replicas><min_part_hours>
swift-ring-builder account.builder create 18 1 1
swift-ring-builder container.builder create 18 1 1
swift-ring-builder object.builder create 18 1 1
在ring基础上生成zone,在这里仅以一个节点为例,
# swift-ring-builder <builder_file> add z<zone>-<ip>:<port>/<device_name>_<meta> <weight>
swift-ring-builder account.builder add z1-172.16.1.1:6012/sdb1 100
swift-ring-builder container.builder add z1-172.16.1.1:6011/sdb1 100
swift-ring-builder object.builder add z1-172.16.1.1:6010/sdb1 100
验证ring文件的正确性,
swift-ring-builder account.builder
swift-ring-builder container.builder
swift-ring-builder object.builder
生成最终的ring,
swift-ring-builder account.builder rebalance
swift-ring-builder container.builder rebalance
swift-ring-builder object.builder rebalance
5、增加、删除节点时。
swift-ring-builder account.builder add z1-172.16.1.1:6012/sdb1 100
swift-ring-builder container.builder add z1-172.16.1.1:6011/sdb1 100
swift-ring-builder object.builder add z1-172.16.1.1:6010/sdb1 100
swift-ring-builder account.builder add z2-172.16.1.2:6012/sdb1 100
swift-ring-builder container.builder add z2-172.16.1.2:6011/sdb1 100
swift-ring-builder object.builder add z2-172.16.1.2:6010/sdb1 100
在rebalance后,复制account.ring.gz、container.ring.gz、object.ring.gz到集群的各节点的/etc/swift目录下。这样我们就完成了Ring的重平衡(rebalance)。
sudo iptables -A INPUT -p tcp -m multiport --dports 6000,6001,6002,873 -m comment --comment "001 swift storage incoming" -j ACCEPT
6, 难证,测试以前的swift是否能够跑通 (鉴权方式并非keystone的时候)
sudo chown -R swift:swift /var/run/swift
swift-init main start
curl -v -H 'X-Storage-User: test:tester' -H 'X-Storage-Pass: testing' http://127.0.0.1:8080/auth/v1.0
7, 与keystone集成
sudo apt-get install build-essential git python-dev python-setuptools python-pip libxml2-dev libxslt-dev
sudo apt-get install mysql-server mysql-client python-mysqldb
git clone https://github.com/openstack/keystone.git
切换到keystone目录执行;
sudo pip install -r requirements.txt
sudo pip install -r test-requirements.txt
sudo python setup.py install
a, 配置文件
sudo chown -R swift:swift /etc/keystone/
sudo cp /bak/openstack/keystone/etc/* /etc/keystone/
mv keystone.conf.sample keystone.conf
mv logging.conf.sample logging.conf
mysql -u root -ppassword -h172.16.1.1
create database keystone;
grant all on keystone.* to 'keystone'@'%' identified by 'password';
quit
/bak/openstack/keystone/bin/keystone-manage db_sync
vi keystone.conf
[database]
connection = mysql://keystone:password@172.16.1.1/keystone
b, 启动keystone
keystone-all -d
e, 测试
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN tenant-create --name test --description "Test Tenant" --enabled true
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN tenant-list
curl -d '{"auth": {"tenantName": "admin", "passwordCredentials":{"username": "admin", "password": "password"}}}' -H "Content-type: application/json" http://127.0.0.1:35357/v2.0/tokens | python -mjson.tool
8, swift与keystone集成
a, 在/etc/swift/proxy-server.conf中有如下配置,说明使用swift的用户应该具有admin或者 swiftoperator这个角色
operator_roles = admin, swiftoperator
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN role-create --name admin
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN tenant-create --name service
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN user-create --name swift --tenant_id ca8d1edcc98140f797030b027decbb1c --pass password --email admin@cn.ibm.com --enabled true
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN user-role-add --user_id user-id --tenant_id tenant-id --role_id role-id
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN service-create --name swift --type object-store --description 'OpenStack Storage Service'
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN service-create --name keystone --type identity --description 'OpenStack Identity Service'
#为两个服务创建endpoint,注意swift服务的endpoint需要AUTH_<tenant-id>以这样的内容作为后缀,其中AUTH_后面的是tenant_id,注意到是下面的id需要以自己系统生成的为准,照搬这里的命令肯定会出错。
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN endpoint-create --region RegionOne --service_id <keystone-service-id> --publicurl 'http://172.16.1.1:5000/v2.0' --adminurl 'http://172.16.1.1:35357/v2.0' --internalurl 'http://172.16.1.1:5000/v2.0'
keystone --os-endpoint http://172.16.1.1:35357/v2.0 --os-token ADMIN endpoint-create --region RegionOne --service_id <swift-service-id> --publicurl 'http://172.16.1.1:8888/v1/AUTH_ca8d1edcc98140f797030b027decbb1c' --adminurl 'http://172.16.1.1:8888/v1' --internalurl 'http://172.16.1.1:8888/v1/AUTH_ca8d1edcc98140f797030b027decbb1c'
//开启swift
sudo chown -R swift:swift /var/cache/swift
swift-init proxy start
swift-init all start
curl -d '{"auth": {"tenantName": "service", "passwordCredentials":{"username": "swift", "password": "password"}}}' -H "Content-type: application/json" http://172.16.1.1:5000/v2.0/tokens | python -mjson.tool
swift -A http://172.16.1.1:5000/v2.0 -U service:swift -K password stat -V 2 # 记得将[pipeline:main]中pipeline里的tempauth改成authtoken而使用keytonne
9, swift命令演示:
OS_USERNAME=swift
OS_TENANT_NAME=service
OS_PASSWORD=password
ST_AUTH=http://172.16.1.1:5000/v2.0
ST_USER=service:swift
ST_KEY=password
swift post testcontainer
swift list testcontainer
swift stat testcontainer
touch testfile && swift upload testcontainer testfile
swift download testcontainer testfile
swift stat -v
10, 采用juju快速安装
swift-proxy:
num_units: 1
charm: cs:~openstack-charmers-next/swift-proxy
constraints: mem=1G
options:
zone-assignment: manual
replicas: 3
swift-hash: fdfef9d4-8b06-11e2-8ac0-531c923c8fae
swift-storage-z1:
num_units: 1
charm: cs:~openstack-charmers-next/swift-storage
constraints: mem=1G
options:
zone: 1
block-device: vdb
overwrite: "true"
swift-storage-z2:
num_units: 1
charm: cs:~openstack-charmers-next/swift-storage
constraints: mem=1G
options:
zone: 2
block-device: vdb
overwrite: "true"
swift-storage-z3:
num_units: 1
charm: cs:~openstack-charmers-next/swift-storage
constraints: mem=1G
options:
zone: 3
block-device: vdb
overwrite: "true"
- [ swift-proxy, keystone ]
- [ swift-proxy, swift-storage-z1 ]
- [ swift-proxy, swift-storage-z2 ]
- [ swift-proxy, swift-storage-z3 ]
参考:
[1], http://codefine.co/swift-%E5%92%8C-keystone%E5%8D%95%E6%9C%BA%E5%AE%89%E8%A3%85%E6%80%BB%E7%BB%93/
[2], http://codefine.co/?s=swift&searchsubmit=Search
[3], http://www.cnblogs.com/yuxc/archive/2012/06/22/2558312.html
[4], https://swiftstack.com/docs/integration/keystone.html
[5], http://docs.openstack.org/developer/swift/development_saio.html