Ceph 是一个高性能的PB级分布式文件系统。它能够在一个系统中提供对象存储、块存储和文件存储。对如何加载使用这些存储感兴趣的话可以参考《用容器轻松搭建ceph实验环境》 。它还可以通过RADOSGW来实现S3和OpenStack Swift存储接口。不管RADOSGW还是块存储或文件存储都是基于对象存储来提供服务。本文的主要内容是如何通过RADOSGW来暴露S3和SWIFT接口。由于Docker Registry在2.4版本移除了对rados的支持 ,所以如果使用ceph作为后端存储就需要利用RADOSGW了。
准备工作 我们需要先安装virtualBox 和vagrant 。通过vagrant来驱动virtualBox搭建一个虚拟测试环境。首先在本地任意路径新建一个空文件夹比如test,运行以下命令:
1 2 3 4 mkdir test cd test vagrant init minimum/ubuntu-trusty64-docker vi Vagrantfile
里面应该有一句config.vm.box = "minimum/ubuntu-trusty64-docker",在它的下面添加如下几行代码,相当于给它分配一台IP为192.168.33.111 ,内存为1G的虚拟机。
1 2 3 4 config.vm.network "private_network" , ip: "192.168.33.111" config.vm.provider "virtualbox" do |v | v.memory = 1024 end
这个vagrant镜像已经在ubuntu的基础上帮我们安装了docker,用起来很方便。然后终端运行以下命令启动并连接虚拟机。
搭建环境 首先需要安装一些ceph、radosgw的依赖包,还有python-boto、swift客户端等工具可以用于测试。
1 2 3 4 sudo apt-get updatesudo apt-get -y --force-yes install ceph-common radosgw python-botosudo pip install --upgrade setuptoolssudo pip install --upgrade python-swiftclient
然后就可以启动ceph/demo这个容器来轻松提供ceph服务了:
1 docker run -d --net=host -v /etc/ceph:/etc/ceph -e MON_IP=192.168.33.111 -e CEPH_NETWORK=192.168.33.111/24 --name=ceph ceph/demo
接下来的步骤主要参考的是有一点坑的官方教程 。需要为radosgw生成一个名为gateway的用户:
1 2 sudo ceph auth del client.radosgw.gatewaysudo ceph auth get-or-create client.radosgw.gateway osd 'allow rwx' mon 'allow rwx' -o /etc/ceph/ceph.client.radosgw.keyring
然后需要把这个用户加到ceph.conf配置里,提供端口为9000的FastCGI 服务:
1 2 3 4 5 6 7 8 sudo sed -i $'$a \\\n' /etc/ceph/ceph.confsudo sed -i '$a [client.radosgw.gateway]' /etc/ceph/ceph.confsudo sed -i '$a host = vagrant-ubuntu-trusty-64' /etc/ceph/ceph.confsudo sed -i '$a keyring = /etc/ceph/ceph.client.radosgw.keyring' /etc/ceph/ceph.confsudo sed -i '$a rgw socket path = ""' /etc/ceph/ceph.confsudo sed -i '$a log file = /var/log/radosgw/client.radosgw.gateway.log' /etc/ceph/ceph.confsudo sed -i '$a rgw frontends = fastcgi socket_port=9000 socket_host=0.0.0.0' /etc/ceph/ceph.confsudo sed -i '$a rgw print continue = false' /etc/ceph/ceph.conf
其中第二行的vagrant-ubuntu-trusty-64,必须使用hostname -s得出的结果。如果是按照准备工作 的做法,是不需要变的。另外这里 的第一个回答非常清晰地解释了CGI和FastCGI。 配置完成后就可以重启ceph容器并启动radosgw:
1 2 docker restart ceph sudo /etc/init.d/radosgw start
为了提供HTTP服务,需要安装apache2(Red Hat系是httpd):
1 sudo apt-get -y --force-yes install apache2
接下来创建一个apache2的配置文件,监听80端口并把请求转发到radosgw提供的FastCGI 9000端口上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cat rgw.confServerName localhost DocumentRoot /var/www/html ErrorLog /var/log/apache2/rgw_error.log CustomLog /var/log/apache2/rgw_access.log combined RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] SetEnv proxy-nokeepalive 1 ProxyPass / fcgi://localhost:9000/ EOF sudo mv rgw.conf /etc/apache2/conf-enabled/rgw.conf
由于上述配置需要用到一些apache2默认未加载的模块,所以需要加载并重新启动apache2:
1 2 3 4 sudo a2enmod rewritesudo a2enmod proxy_httpsudo a2enmod proxy_fcgisudo service apache2 restart
测试服务 S3 RADOSGW的基本配置已经完成,现在我们测试一下s3接口。它的存储模型是这样的:用户可以创建和管理多个存储桶(bucket) ,每个存储桶里可以存放无限多个对象(object),每个对象是一个键值对。存储桶的名称与区域无关,全球唯一。
接下来先创建一个s3用户:
1 2 3 docker exec ceph radosgw-admin user create --uid="testuser" --display-name="First User" | tee user.txt export ACCESS_KEY=`sed -n 's/ *"access_key": "\(.*\)",/\1/p' user.txt`export SECRET_KEY=`sed -n 's/ *"secret_key": "\(.*\)"/\1/p' user.txt`
使用以下python代码来测试我们的s3接口是否已经可用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 cat s3test.pyimport boto import boto.s3.connection import os access_key = os.environ["ACCESS_KEY" ] secret_key = os.environ["SECRET_KEY" ] conn = boto.connect_s3( aws_access_key_id = access_key, aws_secret_access_key = secret_key, host = '192.168.33.111' , is_secure=False, calling_format = boto.s3.connection.OrdinaryCallingFormat(), ) bucket = conn.create_bucket('my-new-bucket' ) for bucket in conn.get_all_buckets(): print "{name}\t{created}" .format( name = bucket.name, created = bucket.creation_date, ) EOF python s3test.py
如果显示了my-new-bucket,那就说明测试成功地通过s3接口创建了一个存储桶。可以使用以下命令来获取这个存储桶和实例的信息:
1 2 3 4 docker exec ceph radosgw-admin metadata bucket list docker exec ceph radosgw-admin metadata get bucket:my-new-bucket | tee bucket.txt export BUCKET_ID=`cat bucket.txt | sed -n 's/ *"bucket_id": "\(.*\)"/\1/p' `docker exec ceph radosgw-admin metadata get bucket.instance:my-new-bucket:$BUCKET_ID
还可以修改实例的信息并PUT回去,具体做法可参见《Changing the region of a RGW bucket》 。
Swift 接下来测试swift。对于swift来说,它的存储模型是这样的:一个账号(account)里可以有多个容器(container),容器里可以有许多个键值对,字典里的值称为对象(object)。账号和容器被存储在SQLite数据库里,而对象是以文件方式存储的。
首先需要创建swift用户并生成secret:
1 2 3 docker exec ceph radosgw-admin subuser create --uid=testuser --subuser=testuser:swift --access=full docker exec ceph radosgw-admin key create --subuser=testuser:swift --key-type=swift --gen-secret | tee subuser.txt export PASSWORD=`sed -n '/testuser:swift/{N;p;}' subuser.txt | sed -n 's/ *"secret_key": "\(.*\)"/\1/p' `
然后就可以用以下命令查看swift里所有的容器:
1 swift -A http://192.168.33.111/auth/v1.0 -U testuser:swift -K $PASSWORD list
应该能看到刚才测试s3接口时创建的my-new-bucket,在这里s3的存储桶和swift的容器是同一个概念。接下来我们自己创建容器:
1 2 swift -A http://192.168.33.111/auth/v1.0 -U testuser:swift -K $PASSWORD post qinghua swift -A http://192.168.33.111/auth/v1.0 -U testuser:swift -K $PASSWORD list qinghua
创建成功,里面没有文件。现在可以上传、下载文件试试:
1 2 3 4 5 6 echo Hello World > hw.txtswift -A http://192.168.33.111/auth/v1.0 -U testuser:swift -K $PASSWORD upload qinghua hw.txt swift -A http://192.168.33.111/auth/v1.0 -U testuser:swift -K $PASSWORD list qinghua mv hw.txt hw.bakswift -A http://192.168.33.111/auth/v1.0 -U testuser:swift -K $PASSWORD download qinghua hw.txt cat hw.txt
搞定!