使用Ajax的PUT方法将文件PUT致Aws S3或Ceph RGW

在为吉致汽车金融服务的过程中,对方的外包人员遇到了无法通过Ajax PUT文件到Ceph RGW的情况,经过分析是他的data指向了一个FormData对象,将文件内容append到了FormData中,Key值为file,
如下:
var formData = new FormData();
formData.append(“file”, document.getElementById(“file1”).files[0]);

这样RGW是无法解析的 ajax的data项应该直接为文件内容,故而修改如下:

$.ajax({
      type: 'PUT',
      url: "<YOUR_PRE_SIGNED_UPLOAD_URL_HERE>",
      contentType: 'binary/octet-stream',//如不确认类型,可以False,填写了则必须与服务端相匹配
      processData: false, //关键
      data: $("#file1").get()[0].files[0],
    })
    .success(function() {
      alert('File uploaded');
    })
    .error(function() {
      alert('File NOT uploaded');
      console.log( arguments);
});

调试成功~

解决Nginx+Ceph RGW跨域问题

在给吉致气车金融做Ceph驻场顾问时,遇到跨域PUT object到返回CORS的错误,经过抓包和日志分析后,发现是其Nginx的配置问题,记录一下
原始的配置

upstream ceph_radosgw_zone {
        server 10.10.100.101:9999 weight=1 max_fails=2 fail_timeout=5;
        server 10.10.100.102:9999 weight=1 max_fails=2 fail_timeout=5;
}

server {
        listen  80;
        location / {
            proxy_pass http://ceph_radosgw_zone;
            proxy_buffering    off;
            client_max_body_size   0;
        }
}

在这样的配置下,由于通过web中间件进行PUT操作,就会产生如下错误

Access to XMLHttpRequest at 'http://10.10.100.100/cbpdev/2019030210121212?x-amz-acl=public-read&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20190222T073759Z&X-Amz-SignedHeaders=host&X-Amz-Expires=29999&X-Amz-Credential=EDEOOIR47GEQ3W3HGCCN%2F20190222%2Fus-east-1%2Fs3%2Faw' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field lang is not allowed by Access-Control-Allow-Headers in preflight response.

错误写的很明确了,header中需要Access-Control-Allow-Headers就像普通的跨域问题
Nginx中加入对应的header应该就可以解决。

server {
        listen  80;
        location / {
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, HEAD, PUT';
            add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

            proxy_pass http://ceph_radosgw_zone;
            proxy_buffering    off;
            client_max_body_size   0;
        }
}

测试发现,普通的GET请求是支持跨域了但在PUT文件是依然反悔跨域错误。经过分析发现PUT过程分为OPTIONS和PUT两个Request Method, 只需要在OPTIONS时解决跨域,PUT method时将Header传入Proxy即可
再次修改

server {
        listen  80;
        location / {
            if ($request_method = 'OPTIONS') {
                add_header Access-Control-Allow-Origin *;
                add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, HEAD, PUT';
                add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
            }
            proxy_pass http://ceph_radosgw_zone;
            proxy_pass_header Server;
            proxy_buffering    off;
            proxy_redirect     off;
            proxy_set_header   Host             $host:$server_port;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            client_max_body_size   0;
        }
}

完美解决

Centos7下配置ceph,包括object storage和cephfs

Centos7的配置方法找了很多,也尝试了好多次,发现每一家的方法都有残缺,最后自己汇总一下

  • 我的环境

两台机器,一台做admin,一台做storage

都安装好了centos7并配置了IP保证两台机器间可以互相ping通

 

  • 两个节点上都要执行的命令

安装NTP client同步时间

yum -y install ntpdate
ntpdate time.windows.com

 

配置hosts,后以简化后面的命令

echo "10.4.10.233 storage">> /etc/hosts #for storage
echo "10.4.10.234 admin">> /etc/hosts #for admin

 

修改hostname为对应的节点名字,centos7比较方便,直接改/etc/hostname就可以了,改好后需重新login

vi /etc/hostname

 

禁用 SELINUX

setenforce 0
sed -i s'/SELINUX.*=.*enforcing/SELINUX=disabled'/g /etc/selinux/config

 

允许防火墙ceph对应端口

firewall-cmd --zone=public --add-port=6789/tcp --permanent
firewall-cmd --zone=public --add-port=6800-7100/tcp --permanent
firewall-cmd --reload

#也可以关闭防火墙

systemctl stop firewalld.service

 

添加ceph用户

useradd -m ceph
passwd ceph #Set password for ceph user

 

赋予ceph sudoer权限,用visudo命令在最尾处添加如下内容

Defaults:ceph !requiretty #To be able to run commands as superuser without tty
ceph ALL=(ALL) NOPASSWD:ALL #Allow this user to run commands as superuser without password

 

 

  • 在admin节点上用root账号执行以下命令

添加YUM源

rpm -Uhv http://ceph.com/rpm-giant/el7/noarch/ceph-release-1-0.el7.noarch.rpm

更新系统并安装ceph-deploy工具

yum update -y && yum install ceph-deploy -y

 

  • 在admin节点上用ceph账号执行以下命令

创建并复制SSH KEY允许其它节点直接访问

ssh-keygen -t rsa -P ''
ssh-keygen -t rsa -f .ssh/id_rsa -P ''
ssh-copy-id ceph@storage

 

修改~/.ssh/config,添加以下信息,用以指定SSH连接storage节点时使用ceph用户,注意这个文件的权限需要为600

Host storage
Hostname storage
User ceph

创建临时目录,用以存放ceph配置过程的临时文件,这个目录名可以随意

mkdir ~/ceph-cluster && cd ~/ceph-cluster

初始化ceph配置

ceph-deploy new storage

执行完上面的命令后,当前所以目录中会生成一些文件,编辑其中的ceph.conf,并在尾部添加以下内容,以允许外网访问

osd pool default size = 1
public network = 10.4.10.0/24

安装ceph,ceph-deploy会自动在指定的节点上安装,这个命令只需在admin节点上执行一次即可

ceph-deploy install admin storage

初始化monitor

ceph-deploy mon create-initial

同步storage节点的Key

ceph-deploy gatherkeys storage

 

#查看当前系统中的磁盘,为安装成功,请先删数据库上的分区

ceph-deploy disk list storage

当这个命令看到/dev/sdc unknown等字样时就可以了

 

初始化数据盘

ceph-deploy disk zap storage:sdb
ceph-deploy disk zap storage:sdc

 

准备OSD存储设备

ceph-deploy osd prepare storage:sdc:/dev/sdb

这个代表sdc是数据盘,sdb做为sdc的journal盘

当然你也可以执行

ceph-deploy osd prepare storage:sdc

这样的话,sdc会指定自己为自己的journal盘,但这样会严重影响性能

 

激活osd

ceph-deploy osd activate storage:/dev/sdc1:/dev/sdb1

 

分发配置信息到各节点

ceph-deploy admin admin storage

该命中会把配置文件复制到/etc/ceph目录下

设置正确的权限

sudo chmod +r /etc/ceph/ceph.client.admin.keyring

 

创建mds

ceph-deploy mds create storage

 

查看状态

ceph -s

没有出现

HEALTH_ERROR就OK了
一般为HELTH_OK

 

  • 配置对象存储

创建数据池,poolname可以自行指定

ceph osd pool create poolname 128

 

就这么简单,测试一下

#PUT
echo "I am YQ:)" > test.txt
rados put test test.txt --pool=poolname

#LS
rados ls --pool=poolname

#GET
rm testfile.txt 
rados get --pool=poolname testfile testfile.txt
cat testfile.txt

#REMOVE
rados rm testfile --pool=poolname

 

#如何删除pool呢?

ceph osd pool delete poolname poolname --yes-i-really-really-mean-it

 

  • 配置cephfs

对于cephfs,也需要做一些创建工作,不然直接mount当前状态的ceph会报error=5 input/output error
创建两个数据池,分别作为cephfs的一般数据池和元数据池

ceph osd pool create cephfs_data 128
ceph osd pool create cephfs_metadata 128

 

创建cephfs

ceph fs new cephfs cephfs_metadata cephfs_data

 

查看各状态

ceph mds stat

显示e5: 1/1/1 up {0=storage=up:active}

ceph -s

cluster c89d8b75-0ade-499d-b472-923a6d5671af
health HEALTH_WARN
too many PGs per OSD (448 > max 300)
monmap e1: 1 mons at {storage=10.4.10.233:6789/0}
election epoch 1, quorum 0 storage
mdsmap e5: 1/1/1 up {0=storage=up:active}
osdmap e18: 1 osds: 1 up, 1 in
pgmap v37: 448 pgs, 4 pools, 1978 bytes data, 21 objects
37444 kB used, 1862 GB / 1862 GB avail
448 active+clean
client io 546 B/s wr, 2 op/s

ceph osd tree

ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 1.81999 root default
-2 1.81999 host storage
0 1.81999 osd.0 up 1.00000 1.00000
ssh-keygen -t rsa -P ”
ssh-keygen -t rsa -f .ssh/id_rsa -P ”
这时任何一台支持cephfs的客户端机器就可以通过以下命令mount这个cephfs,

mkdir /mnt/cephfs
mount -t ceph storage:6789:/ /mnt/cephfs -o name=admin,secret=AQABV4BVkn66AhAAdvNPjWuf9o1IZSYKMelT6Q==

secret的值取自/etc/ceph/ceph.client.admin.keyring

原生的centos7 kernel并没有打开cephfs,需要重编
但如果你想直接在某个节点上进行mount测试的话还是比较方便的,由于我们前面安装ceph时会下载kernel只需grub2-set-default 0再重启系统即会使用新的kernel该kernel默认打开了cephf