强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Ceph 存储运维完全指南 / 07 - 对象存储 RGW

07 - 对象存储 RGW

7.1 RGW 概述

RGW(RADOS Gateway) 是 Ceph 的对象存储网关,提供与 Amazon S3OpenStack Swift 兼容的 RESTful API。

RGW 架构

┌───────────────────────────────────────────┐
│              S3/Swift 客户端              │
│    (boto3 / aws-cli / s3cmd / SDK)        │
└────────────────────┬──────────────────────┘
                     │ HTTP(S)
                     ↓
            ┌────────────────┐
            │     RGW        │
            │  (Civetweb /   │
            │   Beast HTTP)  │
            └───────┬────────┘
                    │ librados
                    ↓
            ┌────────────────┐
            │     RADOS      │
            │  对象 + 元数据  │
            └────────────────┘

适用场景

场景说明
图片/视频存储海量非结构化数据
数据备份配合生命周期策略自动过期
大数据Hadoop/Spark S3A 接口
云存储服务提供 S3 兼容的私有云存储
CDN 源站配合 CDN 提供静态资源

7.2 RGW 部署

# cephadm 方式部署
ceph orch apply rgw myrgw \
    --port=80 \
    --placement="3 node1 node2 node3"

# 查看 RGW 服务
ceph orch ls | grep rgw
ceph orch ps | grep rgw

# 验证 RGW
curl http://node1:80
# 输出: <?xml version="1.0" encoding="UTF-8"?><ListAllMyBucketsResult>...

# 查看 RGW 存储池
ceph osd pool ls | grep rgw

RGW 内部存储池

池名用途
.rgw.rootRGW 根域信息
default.rgw.control控制信息
default.rgw.meta元数据
default.rgw.log日志
default.rgw.buckets.index桶索引
default.rgw.buckets.data桶数据
default.rgw.buckets.non-ec非 EC 桶数据

7.3 RGW 用户管理

# 创建用户
radosgw-admin user create \
    --uid="myuser" \
    --display-name="My Application User" \
    --email="user@example.com"

# 输出关键信息:
# "user_id": "myuser",
# "display_name": "My Application User",
# "keys": [
#     {
#         "user": "myuser",
#         "access_key": "XXXXXXXXXXXXXXXXXXXX",
#         "secret_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
#     }
# ]

# 创建子用户(Swift 兼容)
radosgw-admin subuser create \
    --uid=myuser \
    --subuser=myuser:swift \
    --access=full

# 创建 S3 凭证
radosgw-admin key create --uid=myuser --gen-access-key --gen-secret

# 列出所有用户
radosgw-admin user list

# 查看用户详情
radosgw-admin user info --uid=myuser

# 修改用户配额
radosgw-admin quota set --quota-scope=user --uid=myuser --max-size=100G
radosgw-admin quota set --quota-scope=user --uid=myuser --max-objects=100000
radosgw-admin quota enable --uid=myuser

# 禁用用户
radosgw-admin user suspend --uid=myuser

# 删除用户
radosgw-admin user rm --uid=myuser

7.4 S3 客户端使用

配置 AWS CLI

# 安装
pip install awscli

# 配置
aws configure --profile ceph
# AWS Access Key ID: <access_key>
# AWS Secret Access Key: <secret_key>
# Default region name: us-east-1
# Default output format: json

# 或创建配置文件
cat > ~/.aws/config <<EOF
[profile ceph]
endpoint_url = http://node1:80
region = us-east-1
EOF

cat > ~/.aws/credentials <<EOF
[ceph]
aws_access_key_id = XXXXXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
EOF

基本操作

# 创建桶
aws s3 mb s3://mybucket --profile ceph
# 或
aws --endpoint-url http://node1:80 s3 mb s3://mybucket

# 列出桶
aws --endpoint-url http://node1:80 s3 ls

# 上传文件
aws --endpoint-url http://node1:80 s3 cp myfile.txt s3://mybucket/

# 上传目录
aws --endpoint-url http://node1:80 s3 sync ./mydir s3://mybucket/mydir/

# 下载文件
aws --endpoint-url http://node1:80 s3 cp s3://mybucket/myfile.txt ./downloaded.txt

# 列出桶内对象
aws --endpoint-url http://node1:80 s3 ls s3://mybucket/

# 删除对象
aws --endpoint-url http://node1:80 s3 rm s3://mybucket/myfile.txt

# 删除桶(必须先清空)
aws --endpoint-url http://node1:80 s3 rb s3://mybucket --force

使用 s3cmd

# 安装
sudo apt install -y s3cmd

# 配置
cat > ~/.s3cfg <<EOF
[default]
access_key = XXXXXXXXXXXXXXXXXXXX
secret_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
host_base = node1:80
host_bucket = %(bucket)s.node1:80
use_https = False
EOF

# 操作
s3cmd mb s3://mybucket
s3cmd put myfile.txt s3://mybucket/
s3cmd ls s3://mybucket/

Python boto3 示例

import boto3

s3 = boto3.client(
    's3',
    endpoint_url='http://node1:80',
    aws_access_key_id='XXXXXXXXXXXXXXXXXXXX',
    aws_secret_access_key='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
)

# 创建桶
s3.create_bucket(Bucket='mybucket')

# 上传文件
s3.upload_file('localfile.txt', 'mybucket', 'remote.txt')

# 下载文件
s3.download_file('mybucket', 'remote.txt', 'downloaded.txt')

# 列出对象
response = s3.list_objects_v2(Bucket='mybucket')
for obj in response.get('Contents', []):
    print(f"{obj['Key']} - {obj['Size']} bytes")

7.5 桶策略(Bucket Policy)

# 设置桶策略(允许指定用户读写)
cat > /tmp/policy.json <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {"AWS": ["arn:aws:iam:::user/myuser"]},
            "Action": ["s3:GetObject", "s3:PutObject"],
            "Resource": ["arn:aws:s3:::mybucket/*"]
        },
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::mybucket"
        }
    ]
}
EOF

aws --endpoint-url http://node1:80 s3api put-bucket-policy \
    --bucket mybucket --policy file:///tmp/policy.json

# 查看桶策略
aws --endpoint-url http://node1:80 s3api get-bucket-policy --bucket mybucket

# 设置桶为公开读
aws --endpoint-url http://node1:80 s3api put-bucket-acl \
    --bucket mybucket --acl public-read

7.6 生命周期管理(Lifecycle)

# 创建生命周期配置
cat > /tmp/lifecycle.json <<EOF
{
    "Rules": [
        {
            "ID": "expire-old-logs",
            "Status": "Enabled",
            "Prefix": "logs/",
            "Expiration": {"Days": 90}
        },
        {
            "ID": "transition-to-lowfreq",
            "Status": "Enabled",
            "Prefix": "archive/",
            "Transitions": [
                {"Days": 30, "StorageClass": "STANDARD_IA"}
            ],
            "Expiration": {"Days": 365}
        },
        {
            "ID": "cleanup-incomplete",
            "Status": "Enabled",
            "Filter": {"Prefix": ""},
            "AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 7}
        }
    ]
}
EOF

# 应用生命周期策略
radosgw-admin lc put --bucket mybucket --lc-conf /tmp/lifecycle.json

# 或使用 AWS CLI
aws --endpoint-url http://node1:80 s3api put-bucket-lifecycle-configuration \
    --bucket mybucket --lifecycle-configuration file:///tmp/lifecycle.json

# 查看生命周期配置
radosgw-admin lc get --bucket mybucket

# 手动触发生命周期处理
radosgw-admin lc process

# 查看生命周期状态
radosgw-admin lc list

7.7 多站点复制

# === 主站点(master zone) ===
radosgw-admin realm create --rgw-realm=myrealm --default
radosgw-admin zonegroup create --rgw-zonegroup=myzonegroup --endpoints=http://node1:80 --master --default
radosgw-admin zone create --rgw-zonegroup=myzonegroup --rgw-zone=master --endpoints=http://node1:80 --master --default
radosgw-admin period update --commit

# === 备站点(slave zone) ===
# 拉取 realm
radosgw-admin realm pull --url=http://master-node:80 --access-key=<access> --secret=<secret>
radosgw-admin zonegroup create --rgw-zonegroup=myzonegroup --endpoints=http://node4:80
radosgw-admin zone create --rgw-zonegroup=myzonegroup --rgw-zone=slave --endpoints=http://node4:80
radosgw-admin period update --commit

7.8 RGW 性能优化

# 调整 RGW 工作线程数
ceph config set client.rgw rgw_thread_pool_size 512

# 启用 Beast HTTP 后端(比 Civetweb 更高效)
ceph config set client.rgw rgw_frontends "beast port=80"

# 启用缓存
ceph config set client.rgw rgw_cache_enabled true
ceph config set client.rgw rgw_cache_lru_size 10000

# 大文件分片上传配置
ceph config set client.rgw rgw_max_chunk_size 4194304        # 4MB
ceph config set client.rgw rgw_multipart_min_part_size 5242880  # 5MB

7.9 业务场景:数据备份

# 创建备份专用桶
aws --endpoint-url http://node1:80 s3 mb s3://backups

# 设置生命周期:90 天后自动删除
cat > /tmp/backup-lifecycle.json <<EOF
{
    "Rules": [{
        "ID": "auto-delete-90d",
        "Status": "Enabled",
        "Filter": {"Prefix": ""},
        "Expiration": {"Days": 90}
    }]
}
EOF

aws --endpoint-url http://node1:80 s3api put-bucket-lifecycle-configuration \
    --bucket backups --lifecycle-configuration file:///tmp/backup-lifecycle.json

# 数据库备份脚本示例
#!/bin/bash
DATE=$(date +%Y%m%d)
mysqldump --all-databases | gzip > /tmp/db-backup-$DATE.sql.gz
aws --endpoint-url http://node1:80 s3 cp /tmp/db-backup-$DATE.sql.gz s3://backups/mysql/
rm /tmp/db-backup-$DATE.sql.gz

扩展阅读

  1. RGW 官方文档
  2. S3 API 兼容性
  3. RGW 多站点复制
  4. AWS S3 文档

下一章08 - CRUSH Map 深入 — 学习 CRUSH Map 的完整结构、桶类型、自定义规则和故障域设计。