ceph对象存储使用总结
大纲
- 基础概念
- 安装对象存储网关RADOS网关
- 配置对象存储网关RADOS网关
- 修改RADOS网关端口
- 修改支持https访问RADOS网关
- 使用s3cmd操作对象存储
- Ceph dashboard管理RADOS网关
- 使用java程序操作对象存储
基础准备
- 操作系统 ubuntu~18.04
- ceph版本 Octopus v15.2.17
- ceph-deploy 2.0.1
- ceph集群搭建见 《ceph安装搭建总结.md》
基础概念
对象存储以对象方式管理数据 。 每一个对象存储如下内容:1数据、2元数据、 3唯一的标识符 。 对象存储不能直接被操作系统当成本地或者远程文件系统访问 (注意 这里与块存储不同 《ceph块使用总结.md》) 。只能在应用程序级别通过API访问 (例如 S3或Swift ,Ceph admin api)
整个对象存储架构如下图
这里假设已经搭建好一个ceph集群。(ceph集群搭建见 《ceph安装搭建总结.md》)。接下来的步骤就是创建RADOS网关
RADOS网关(RGW接口)
RADOS网关的作用就是提供对象存储接口,主要使用了librgw 与 librados库,并且兼容S3 SwiftAPI接口,允许应用程序操作Ceph对象存储
生产环境部署:
建议使用专用的服务器上配置RGW ,如果对象存储工作负载不大,可以使用任意一台MON作为RGW节点
安装RADOS网关
将使用搭建集群时安装ceph-deploy的机器ceph1作为跳板机去到rgw机器上安装 RADOS网关
主机ceph1 上 ceph-deploy 版本2.01
ceph-deploy --version
主机rgw 上未安装任何ceph相关软件
step1 配置网络和ssh免密登录
配置网络
修改主机ceph-controller host文件 添加
vi /etc/hosts
192.168.0.73 ceph-rgw
网络已经ping通
ssh免密登录
因为在创建集群的时候已经生成了ssh 公私钥所以可以不再执行ssh-keygen命令
直接使用ssh-copy-id命令复制秘钥
ssh root@rgw
到此基础网络与ssh配置完成
step2 安装ceph相关软件
ceph-deploy install ceph-rgw
注意 ceph-rgw主机可能需要安装python (apt install python)
安装完成后会自动安装radosgw,登录到ceph-rgw主机可以看到
radosgw -v
dpkg -l |grep radosgw
到此rgw主机上搭建RADOS网关的相关软件已经安装完成
step3 部署RADOS网关服务
在ceph-controller主机上执行
格式 ceph-deploy rgw create 【主机名称】
ceph-deploy --overwrite-conf rgw create ceph-rgw
–overwrite-conf 参数含义:
以当前主机ceph-deploy的ceph.conf配置为准,替换掉ceph-rgw节点上的/etc/ceph.conf (如果没有就新建)
可以看到rgw对应的服务
systemctl start ceph-radosgw@rgw.ceph-rgw
systemctl enable ceph.target
浏览器上访问 http://192.168.0.73:7480/ 可以看到信息
到此RADOS网关服务安装成功
RADOS网关服务服务部署成功后可以看到生成对应的osd池
default.rgw.control #控制器信息
default.rgw.meta #记录元数据
default.rgw.log #日志信息
default.rgw.buckets.index #为rgw的bucket信息
default.rqw.buckets.data #是实际存储的数据信息
RADOS网关服务配置
RADOS网关守护进程内部就由Civeweb实现,通过对Civeweb的配置可以完成对RADOS网关的基本管理
服务的格式为: ceph-radosgw@rgw.<rgw服务器主机名称>
例如刚才创建的RADOS网关服务器主机名称为rgw 所以服务名称为 ceph-radosgw@rgw.ceph-rgw
查看服务状态
systemctl status ceph-radosgw@rgw.ceph-rgw
journalctl -fu ceph-radosgw@rgw.ceph-rgw
修改配置有两种方法
- 1 在跳板机ceph-controller 上执行ceph-deploy config push
- 2 在RADOS网关机器上修改 /etc/ceph/{cluster}.conf文件
端口配置
这里使用在跳板机ceph-controller 上执行ceph-deploy config push 方法
ceph-deploy config push命令操作的是当前文件夹下的ceph.conf文件
修改ceph.conf文件加入
[client.rgw.ceph-rgw]
rgw_host = ceph-rgw
rgw_frontends = "civetweb port=8080 num_threads=500 request_timeout_ms=60000"
配置说明
-
rgw_host:对应的RRADOS网关名称或者IP地址
-
rgw_frontends:配置一些选项信息
num_threads:最大并发连接数,默认为50,根据需求调整,通常在生产集群环境中此值应该更大。
request_timeout_ms:发送与接收超时时长,以ms为单位,默认为30000。
access_log_file:访问日志路径,默认为空。
error_log_file:错误日志路径,默认为空。
在ceph.conf文件所在文件夹执行push命令把配置推送到对应的ceph-rgw主机上
ceph-deploy --overwrite-conf config push ceph-rgw
注意使用--overwrite-conf 参数覆盖已存在的配置
进入ceph-rgw主机上查看配置文件,已经被修改
重启ceph-radosgw@rgw.ceph-rgw 服务
systemctl restart ceph-radosgw@rgw.ceph-rgw
浏览器访问端口已经改变
https配置
这里使用在RADOS网关机器上修改 /etc/ceph/{cluster}.conf文件方法
直接使用已经存在的证书与私钥,将证书与私钥合并成pem文件
cat medcrab.com.key medcrab.com.crt > medcrab.pem
修改/etc/ceph/ceph.conf 文件
[client.rgw.ceph-rgw]
rgw_host = ceph-rgw
rgw_frontends = "civetweb port=8080+443s ssl_certificate=/etc/ceph/PKI/medcrab.pem num_threads=500 request_timeout_ms=60000"
rgw_dns_name = oss.medcrab.com
配置说明:
- port:如果是https端口,需要在端口后面加一个s 这里使用+号表示同时开启http8080端口 和https 443端口
- ssl_certificate:指定证书的路径。
- rgw_dns_name:证书配置了域名 这里使用证书对应的域名
重启ceph-radosgw@rgw.ceph-rgw 服务
systemctl restart ceph-radosgw@rgw.ceph-rgw
使用Switchhost修改自己电脑的host映射,将oss.medcrab.com域名映射到192.168.0.73IP
浏览器访问发现已经可以支持https了
http8080端口也可以继续访问
使用s3cmd操作对象存储
使用ceph对象存储,不能直接被操作系统当成本地或者远程文件系统访问,只能在应用程序级别通过API访问
ceph RADOS网关兼容AmazonS3 所以可以使用s3cmd来操作ceph对象存储
https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/Welcome.html
step1 创建radosgw用户
使用 radosgw-admin命令创建radosgw用户 (在ceph1跳板机上)
radosgw-admin user create --uid="oss-user-1" --display-name="oss-user1"
创建后可以 access_key 与 secret_key (注意access_key 与 secret_key 后续的s3cmd配置时需要使用)
"keys": [
{
"user": "oss-user-1",
"access_key": "2ANNU4UIHQ7HHOPC3MEM",
"secret_key": "UAVJ5gtzGrOZu4jGtU23WBWDYZYb1Am2sE8wY2BS"
}
],
可以使用 radosgw-admin user --uid=“oss-user-1” info 查看用户信息
step2 安装s3cmd
apt install s3cmd
安装完成后首先使用 s3cmd --configure 配置s3cmd
s3cmd --configure
到此 s3cmd安装配置完成
step3 使用s3cmd
s3cmd 常用的使用命令
创建Buckets(桶)桶的格式是s3://【桶的名称】
s3cmd mb s3://oss-bucket1
列出所有Buckets(桶)
s3cmd ls
保存数据到指定的桶
s3cmd put 1.txt s3://oss-bucket1 单个文件上传
s3cmd put *zip s3://oss-bucket1 批量匹配上传
列出桶中的数据
s3cmd ls s3://oss-bucket1
下载数据
s3cmd get s3://oss-bucket1/1.txt 1.txt 单个文件下载
s3cmd get s3://oss-bucket1//* ./ 批量文件下载
查看桶的空间
s3cmd du -H s3://oss-bucket1
删除文件
s3cmd del s3://oss-bucket1/1.txt
匿名访问数据
目前匿名方式还无法访问文件
浏览器匿名访问数据的请求格式为 http://rgw服务器IP:端口/Buckets(桶)名称/文件名称
例如访问
https://oss.medcrab.com/oss-bucket1/1.txt
使用s3cmd setpolicy 修改s3://oss-bucket1 的访问权限
s3cmd setpolicy oss-policy.json s3://oss-bucket1
oss-policy.json内容如下
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": ["arn:aws:s3:::oss-bucket1/*"]
}
]
}
Resources:指定对应的Buckets。必填
Actions:要授予的动作,CreateBucket、DeleteObject、GetObject、PubObject。必填
Effect:要授予的操作效果是允许(allow)还是拒绝(deny),默认为拒绝访问所有的资源,必填。
Principal: 要授权的目的账号,必填 可以使用* 代表所有
https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/example-bucket-policies.html
再次访问 https://oss.medcrab.com/oss-bucket1/1.txt
Ceph dashboard管理RADOS网关
Ceph dashboard 的安装搭建参考 ceph安装搭建总结
点击Object Gateway菜单还暂时无法操作
需要创建一个用户,并配置Ceph dashboard 指定RRADOS网关
step1 创建用户
radosgw-admin user create --uid=rgw --display-name=rgw --system
准备 access_key ,secret_key两个文件,内容就是创建用户时access_key 与secret_key的内容
step2 配置Ceph dashboard
#指定access_key
ceph dashboard set-rgw-api-access-key -i access_key
#指定secret_key
ceph dashboard set-rgw-api-secret-key -i secret_key
# 关闭https
ceph dashboard set-rgw-api-ssl-verify False
# 指定rgw-api-host
ceph dashboard set-rgw-api-host 192.168.0.72
# 指定rgw-api-端口
ceph dashboard set-rgw-api-port 8080
# 使用http
ceph dashboard set-rgw-api-scheme http
# 指定用户
ceph dashboard set-rgw-api-user-id rgw
刷新 Object Gateway菜单可以看到内容
使用java程序操作对象存储
项目pom.xml文件中添加依赖
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-core</artifactId>
<version>1.12.381</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.12.381</version>
</dependency>
java代码
package com.my.study.th3.ceph.aws;
import java.io.File;
import java.util.List;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.BucketPolicy;
import com.amazonaws.services.s3.model.S3Object;
import com.my.study.utils.DateUtil;
/**
* 此代码对应 《ceph使用总结.md》
* @author liuyijiang
*
*/
public class TestCephByAwsS3 {
/** * 【你的 access_key】 */
private static final String AWS_ACCESS_KEY = "6W4L0AZJZY92ZZO93MMT";
/** * 【你的 aws_secret_key】 */
private static final String AWS_SECRET_KEY = "gJslyAsEtYHYtlwUV6pcvrlGsQl9OI2aeQB7WBBK";
/** * 【你的 endpoint】 */
private static final String ENDPOINT = "http://192.168.0.124:7480";
public void test1() {
System.out.println("===============");
// 已经作废的创建 AmazonS3 客户端方法
// AWSCredentials awsCredentials = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
// ClientConfiguration clientConfig = new ClientConfiguration();
// clientConfig.setProtocol(Protocol.HTTP);
// AmazonS3 conn = new AmazonS3Client(awsCredentials, clientConfig);
// conn.setEndpoint(ENDPOINT);
AmazonS3ClientBuilder clientBuilder = AmazonS3ClientBuilder.standard();
ClientConfiguration config = new ClientConfiguration();
config.setProtocol(com.amazonaws.Protocol.HTTP);
config.setConnectionTimeout(10000);
config.setSignerOverride("S3SignerType");
config.setRequestTimeout(10000);
//配置账号密码
AWSCredentials acre = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY);
AWSCredentialsProvider acrep = new AWSStaticCredentialsProvider(acre);
AwsClientBuilder.EndpointConfiguration econfig = new AwsClientBuilder.EndpointConfiguration(ENDPOINT, null);
clientBuilder.setClientConfiguration(config);
clientBuilder.setCredentials(acrep);
clientBuilder.setEndpointConfiguration(econfig);
AmazonS3 client = clientBuilder.build();
boolean needCreate = true;
/**
* 查看access_key对应用户创建的 所有的bucket
*
* 对应命令 s3cmd ls
*/
List<Bucket> buckets = client.listBuckets();
for (Bucket bucket : buckets) {
System.out.println("名称:" + bucket.getName() + " 所属人:" + bucket.getOwner() + " 创建时间:" + DateUtil.dateToString(bucket.getCreationDate())); // StringUtils.fromDate(bucket.getCreationDate())
if(bucket.getName().equals("static-prod")) {
needCreate = false;
}
//获取策略
BucketPolicy policy = client.getBucketPolicy(bucket.getName());
System.out.println(policy.getPolicyText());
}
/**
* 创建buckets
*
* 对应命令 s3cmd mb s3://static-prod
*/
String bucketName = "static-prod";
if(needCreate) {
client.createBucket(bucketName);
System.out.println("===创建成功===");
//设置buckets策略
//注意 Version 各式2012-10-17
String policyText = "{\r\n"
+ " \"Version\": \"2012-10-17\",\r\n"
+ " \"Statement\": [\r\n"
+ " {\r\n"
+ " \"Effect\": \"Allow\",\r\n"
+ " \"Principal\": \"*\",\r\n"
+ " \"Action\": \"s3:GetObject\",\r\n"
+ " \"Resource\": [\"arn:aws:s3:::static-prod/*\"] }]\r\n"
+ "}";
client.setBucketPolicy(bucketName, policyText); // 创建策略测试失败
System.out.println("===策略更新完成===");
//可指定分区 适合亚马逊的对象存储 操作ceph不需要
// String region = "";
// CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName,region);
// client.createBucket(createBucketRequest);
}
/**
* 删除buckets
*
* s3cmd rb s3://static-prod
*/
//client.deleteBucket(bucketName);
String key = "p1.png";
boolean hasObj = false;
try {
/**
* 注意 这里如果没有数据会404会抛异常
*
* http://192.168.0.124:7480/static-prod/p1.png
*/
S3Object obj = client.getObject(bucketName, key);
System.out.println(obj.getKey() + " TaggingCount" + obj.getTaggingCount() + " Location:" + obj.getRedirectLocation());
hasObj = true;
} catch(Exception e) {
}
if(!hasObj) {
File file = new File("D:\\giteecode\\my-study-demo\\src\\main\\java\\com\\my\\study\\th3\\ceph\\aws\\p1.png");
client.putObject(bucketName, key, file);
System.out.println("保存文件 p1.png");
}
}
public static void main(String[] args) {
TestCephByAwsS3 t = new TestCephByAwsS3();
t.test1();
}
}