目录
[Ceph 块存储RBD](#Ceph 块存储RBD)
[CephFS 文件存储详解](#CephFS 文件存储详解)
[MDS 高可用配置](#MDS 高可用配置)
[RGW 对象存储](#RGW 对象存储)
[Ceph 集群运维](#Ceph 集群运维)
[PG 状态速查指南](#PG 状态速查指南)
[CephX 是什么?](#CephX 是什么?)
[Ceph RBD 使用详解](#Ceph RBD 使用详解)
[K8s 为什么需要 Ceph?](#K8s 为什么需要 Ceph?)
Ceph 块存储RBD
[一、什么是 RBD?](#一、什么是 RBD?)
[二、创建 RBD 存储池](#二、创建 RBD 存储池)
[四、客户端使用 RBD](#四、客户端使用 RBD)
一、什么是 RBD?
RBD(RADOS Block Device)即块存储设备,可以为 KVM、OpenStack、Kubernetes 等提供高性能、可无限扩展的存储后端。客户端通过 librbd 库即可把 Ceph 集群当硬盘用。不过,用于 rbd 的存储池需要事先启用rbd 功能并进行初始化。
二、创建 RBD 存储池
1. 创建存储池
ceph osd pool create myrbd1 64 64
64 64:PG 和 PGP 数量,通常设为相同值 pool 'myrdb1' created
2. 启用 RBD 功能
ceph osd pool application enable myrbd1 rbd
3. 初始化存储池
rbd pool init -p myrbd1
三、创建映像(Image)
存储池不能直接使用,需要先在里面创建映像文件,映像才是真正的"虚拟磁盘"。
# 创建 5G 映像(默认特性)
rbd create myimg1 --size 5G --pool myrbd1
# 创建 3G 映像(只开启 layering,兼容低版本内核)
rbd create myimg2 --size 3G --pool myrbd1 --image-format 2 --image-feature layering
rbd create 创建一个 RBD 映像
myimg1 映像名称,可以随意起
--size 5G 虚拟磁盘大小 5GB
--pool myrbd1 存放在 myrbd1 这个存储池里
--image-format 2 使用第二版映像格式(支持更多高级特性)
--image-feature layering 只开启 layering(分层)这一个特性,其他全部关闭
Ceph RBD 支持很多高级特性:
| 特性 | 作用 | 低版本内核支持? |
|---|---|---|
layering |
支持快照分层/克隆 | ✅ 支持 |
exclusive-lock |
排他锁,防止多客户端同时写 | ❌ 不支持 |
object-map |
对象位图,加速 resize/flatten 操作 | ❌ 不支持 |
fast-diff |
快速计算增量 | ❌ 不支持 |
deep-flatten |
深度扁平化 | ❌ 不支持 |
查看映像:
bash
rbd ls --pool myrbd1 # 列出所有映像
rbd --image myimg1 --pool myrbd1 info # 查看映像详情
四、客户端使用 RBD
1. 安装客户端工具
yum install -y ceph-common
2. 同步认证文件
scp ceph.conf ceph.client.admin.keyring root@客户端IP:/etc/ceph/
3. 映射映像为本地磁盘
rbd -p myrbd1 map myimg2
# 成功:/dev/rbd0
rbd map 把 RBD 映像映射为本地块设备
-p myrbd1 指定存储池名称
myimg2 映像名称
4. 格式化并挂载
mkfs.ext4 /dev/rbd0
mount /dev/rbd0 /data
5. 写入测试
dd if=/dev/zero of=/data/test-file bs=1MB count=300
五、常见问题
映射时报错:feature set mismatch
原因:映像的特性(如 object-map、fast-diff、deep-flatten)需要高版本内核支持,客户端内核太旧不支持。
解决:创建映像时只开启兼容特性:
rbd create myimg2 --size 3G --pool myrbd1 --image-feature layering
或者关闭已有映像的不兼容特性:
rbd feature disable myrbd1/myimg1 object-map fast-diff deep-flatten
六、删除数据后空间不释放?
在 RBD 块存储上删除文件后,ceph df 查看会发现空间没有被回收。
原因:删除操作只是在文件系统层面做了"已删除"标记,并没有通知底层 Ceph 集群释放这些块。
解决方法(二选一)
方法 1:手动触发空间回收
fstrim -v /data
-
fstrim:告诉底层存储"这些块已经不用了,收回去吧" -
-v:显示回收了多少空间
方法 2:挂载时开启自动回收
mount -o discard /dev/rbd0 /data
discard选项会让文件系统在删除文件时自动通知 底层存储回收空间,不用手动执行fstrim
CephFS 文件存储详解
[一、CephFS 概述](#一、CephFS 概述)
[二、部署 MDS 服务](#二、部署 MDS 服务)
[1. 安装 MDS](#1. 安装 MDS)
[2. 部署 MDS 节点](#2. 部署 MDS 节点)
[3. 验证 MDS 状态](#3. 验证 MDS 状态)
[1. 创建普通用户(推荐,不要直接用 admin)](#1. 创建普通用户(推荐,不要直接用 admin))
[2. 验证账户](#2. 验证账户)
[3. 导出认证文件](#3. 导出认证文件)
[1. 安装客户端软件](#1. 安装客户端软件)
[2. 同步认证文件到客户端](#2. 同步认证文件到客户端)
[3. 验证权限](#3. 验证权限)
[六、客户端挂载 CephFS](#六、客户端挂载 CephFS)
[安装 ceph-fuse](#安装 ceph-fuse)
[CephFS 通过 NFS-Ganesha 导出](#CephFS 通过 NFS-Ganesha 导出)
[1. 安装](#1. 安装)
[2. 配置 /etc/ganesha/ganesha.conf](#2. 配置 /etc/ganesha/ganesha.conf)
[3. 启动服务](#3. 启动服务)
[4. 客户端挂载](#4. 客户端挂载)
[CephFS 配额(Quota)](#CephFS 配额(Quota))
一、CephFS 概述
CephFS 是 Ceph 提供的文件存储接口,类似 NFS,多台客户端可以同时挂载读写同一个目录,支持 POSIX 标准文件操作。
架构特点:
-
元数据分离 :文件元数据(文件名、权限、目录结构)存放在独立的
cephfs-metadata池中,基于多副本保证高可用 -
MDS 缓存:专用 MDS 服务器在内存中缓存元数据,提升读写响应速度
-
数据分离 :实际文件内容存放在
cephfs-data池中
数据读写流程:
-
读数据:客户端请求 MDS → MDS 从 metadata 池加载元数据缓存到内存 → 返回给客户端 → 客户端直接去 OSD 读数据
-
写数据:客户端请求 MDS → MDS 缓存元数据并同步到 metadata 池 → 客户端数据写入 data 池
二、部署 MDS 服务
1. 安装 MDS
Ubuntu:
apt-cache madison ceph-mds
apt install ceph-mds=16.2.5-1bionic
CentOS:
yum install ceph-mds -y
2. 部署 MDS 节点
ceph-deploy mds create ceph-mgr1
3. 验证 MDS 状态
ceph mds stat
# 初始输出:, 1 up:standby (备用状态,需分配存储池后才变为 active)
三、创建存储池并初始化文件系统
# 1. 创建元数据池(存文件名、权限等)
ceph osd pool create cephfs-metadata 32 32
# 2. 创建数据池(存实际文件内容)
ceph osd pool create cephfs-data 64 64
# 3. 创建文件系统
ceph fs new mycephfs cephfs-metadata cephfs-data
# 4. 验证
ceph fs ls # 列出所有文件系统
ceph mds stat # 状态变为 active
# 输出:mycephfs-1/1/1 up {0=ceph-mgr1=up:active}
ceph fs status mycephfs # 查看指定文件系统运行状态
四、创建客户端账户与认证文件
1. 创建普通用户(推荐,不要直接用 admin)
ceph auth add client.yanyan mon 'allow r' mds 'allow rw' osd 'allow rwx pool=cephfs-data'
权限说明:
-
mon 'allow r':允许读取 Monitor(查看集群状态) -
mds 'allow rw':允许通过 MDS 读写文件 -
osd 'allow rwx pool=cephfs-data':只允许操作数据池,不能碰其他池
2. 验证账户
ceph auth get client.yanyan
3. 导出认证文件
# 导出完整 keyring 文件
ceph auth get client.yanyan -o ceph.client.yanyan.keyring
# 仅导出密钥字符串(用于 mount 命令的 secret 参数)
ceph auth print-key client.yanyan > yanyan.key
# 查看内容
cat ceph.client.yanyan.keyring
五、客户端安装与配置
1. 安装客户端软件
yum install epel-release -y
yum install https://mirrors.aliyun.com/ceph/rpm-octopus/el7/noarch/ceph-release-1-1.el7.noarch.rpm -y
yum install ceph-common -y
2. 同步认证文件到客户端
scp ceph.conf ceph.client.yanyan.keyring yanyan.key root@172.31.6.203:/etc/ceph/
3. 验证权限
ceph --user yanyan -s
能正常显示集群状态即表示认证成功。
六、客户端挂载 CephFS
方式一:内核空间挂载(推荐,性能好)
通过 key 文件挂载
mkdir /data
mount -t ceph 172.31.6.104:6789,172.31.6.105:6789,172.31.6.106:6789:/ /data -o name=yanyan,secretfile=/etc/ceph/yanyan.key
通过 key 字符串挂载
mount -t ceph 172.31.6.104:6789,172.31.6.105:6789,172.31.6.106:6789:/ /data -o name=yanyan,secret=密钥字符串
测试读写
cp /etc/issue /data/
dd if=/dev/zero of=/data/testfile bs=1M count=100
查看挂载状态
stat -f /data/
# Type 显示为 ceph 即成功
开机自动挂载
编辑 /etc/fstab:
172.31.6.104:6789,172.31.6.105:6789,172.31.6.106:6789:/ /data ceph defaults,name=yanyan,secretfile=/etc/ceph/yanyan.key,_netdev 0 0
验证配置:
mount -a
方式二:用户空间挂载(ceph-fuse,兼容性好)
安装 ceph-fuse
yum install ceph-fuse -y
挂载
mkdir /data
ceph-fuse --name client.yanyan -m 172.31.6.104:6789,172.31.6.105:6789,172.31.6.106:6789 /data
开机自动挂载
编辑 /etc/fstab:
none /data fuse.ceph ceph.id=yanyan,ceph.conf=/etc/ceph/ceph.conf,_netdev,defaults 0 0
两种挂载方式对比
| 挂载方式 | 命令 | 性能 | 依赖 |
|---|---|---|---|
| 内核挂载 | mount -t ceph |
高 | 需内核支持 ceph 模块 |
| 用户空间挂载 | ceph-fuse |
稍低 | 只需安装 ceph-fuse |
CephFS 通过 NFS-Ganesha 导出
当前 CephFS 章节只讲了本地挂载,补充 NFS 导出可以让非 Linux 客户端或无法安装 ceph 模块的机器也能访问。
1. 安装
apt install nfs-ganesha-ceph -y # Ubuntu
2. 配置 /etc/ganesha/ganesha.conf
cat > /etc/ganesha/ganesha.conf << 'EOF'
NFS_CORE_PARAM {
Enable_NLM = false; # 关闭文件锁(兼容问题)
Enable_RQUOTA = false; # 关闭配额报告
Protocols = 4; # 只用 NFSv4
}
EXPORT_DEFAULTS {
Access_Type = RW; # 默认读写权限
}
EXPORT {
Export_Id = 1; # 导出编号,多个导出要不重复
Path = "/"; # 把 CephFS 的根目录共享出去
FSAL {
name = CEPH; # 告诉 Ganesha 后端是 CephFS
hostname = "172.31.6.104"; # 你的 MON 节点 IP 之一
}
Squash = "No_root_squash"; # 允许客户端 root 保持 root 权限
Pseudo = "/magedu"; # 客户端挂载时看到的路径名
SecType = "sys"; # 使用系统用户认证
}
LOG {
Default_Log_Level = WARN; # 日志级别
}
EOF
Path = "/":把 CephFS 的根目录共享出去,也可以改成 /data 等子目录。
Pseudo = "/magedu":客户端挂载时用的 NFS 路径,比如 mount -t nfs 服务器IP:/magedu /本地目录。
hostname:填你 Ceph 集群 MON 节点的 IP,Ganesha 会通过它连接 Ceph 集群。
3. 启动服务
systemctl restart nfs-ganesha
4. 客户端挂载
mount -t nfs 172.31.6.104:/magedu /data
Windows 客户端:
打开“此电脑” → 映射网络驱动器
文件夹填 \\172.31.6.104\magedu
完成,就能在 Windows 里直接读写 CephFS 的文件。
CephFS 配额(Quota)
CephFS 支持对目录设置容量或文件数限制,便于多租户隔离。
# 设置容量限制
setfattr -n ceph.quota.max_bytes -v 10737418240 /mnt/cephfs/dir
setfattr:设置文件扩展属性(extended attributes),Linux 文件系统都支持这个机制。
-n ceph.quota.max_bytes:要设置的属性名,CephFS 定义的特殊属性,表示“最大字节数”。
-v 10737418240:属性值,单位是字节,这里是 10GB(10 × 1024 × 1024 × 1024)。
/mnt/cephfs/dir:要限制的目录路径(这个目录必须已经存在)
# 设置文件数限制
setfattr -n ceph.quota.max_files -v 10000 /mnt/cephfs/dir
# 查看配额
getfattr -n ceph.quota.max_bytes /mnt/cephfs/dir
研发组在 /data/rd 里放了一个 6GB 的大文件
dd if=/dev/zero of=/data/rd/bigfile bs=1G count=6
# 写到最后会报错:Disk quota exceeded
MDS 高可用配置
[1. 为什么要高可用?](#1. 为什么要高可用?)
[2. 添加更多 MDS 节点](#2. 添加更多 MDS 节点)
[3. 设置活跃主节点数量](#3. 设置活跃主节点数量)
[4. 配置专属备节点(可选但推荐)](#4. 配置专属备节点(可选但推荐))
[5. 分发配置并重启](#5. 分发配置并重启)
[6. 验证](#6. 验证)
1. 为什么要高可用?
MDS 是 CephFS 的元数据管家,如果只有一台 MDS,它一挂,所有客户端都无法找到文件,CephFS 整个瘫痪。
2. 添加更多 MDS 节点
# 在新增节点上安装
apt install ceph-mds -y
# 部署
ceph-deploy mds create ceph-mgr2
ceph-deploy mds create ceph-mon2
ceph-deploy mds create ceph-mon3
3. 设置活跃主节点数量
# 设置最多 2 个主 MDS 同时工作
ceph fs set mycephfs max_mds 2
此时 4 个 MDS 中,2 个变 active(主),2 个变 standby(备)。
4. 配置专属备节点(可选但推荐)
编辑 ceph.conf:
[mds.ceph-mgr2]
mds_standby_for_name = ceph-mgr1 # 只给 ceph-mgr1 当备胎
mds_standby_replay = true # 实时同步主节点元数据
[mds.ceph-mon3]
mds_standby_for_name = ceph-mon2
mds_standby_replay = true
关键参数解释:
-
mds_standby_for_name:指定专属备份哪个主 MDS -
mds_standby_replay = true:备节点内存中实时保持元数据副本,主挂了毫秒级切换
5. 分发配置并重启
ceph-deploy --overwrite-conf config push ceph-mgr1 ceph-mgr2 ceph-mon2 ceph-mon3
systemctl restart ceph-mds@ceph-mgr1.service
systemctl restart ceph-mds@ceph-mgr2.service
systemctl restart ceph-mds@ceph-mon2.service
systemctl restart ceph-mds@ceph-mon3.service
6. 验证
ceph fs status
ceph fs get mycephfs
RGW 对象存储
[什么是 RGW?](#什么是 RGW?)
[部署 RGW 服务](#部署 RGW 服务)
[创建 RGW 用户与认证](#创建 RGW 用户与认证)
[Bucket 核心概念](#Bucket 核心概念)
[客户端工具 s3cmd](#客户端工具 s3cmd)
[RGW 高可用](#RGW 高可用)
[HTTPS 配置](#HTTPS 配置)
[Bucket 版本控制](#Bucket 版本控制)
[总结对比 Ceph 三种存储](#总结对比 Ceph 三种存储)
什么是 RGW?
RGW(RADOS Gateway)提供 RESTful API 接口,客户端通过 HTTP 与 Ceph 交互,完成数据的上传、下载、删除等操作。兼容 S3 和 Swift 协议,适合图片、视频、备份归档等场景。
如果用 RBD(块存储)或 CephFS(文件存储),可以不启用 RGW。
部署 RGW 服务
# 1. 安装软件
apt install -y radosgw
# 2. 部署 RGW
ceph-deploy --overwrite-conf rgw create ceph-mgr1
# 3. 验证进程
ps aux | grep radosgw
RGW 自动创建的存储池
部署完成后,ceph osd pool ls 会多出以下池:
| 存储池 | 作用 |
|---|---|
.rgw.root |
RGW 根配置(zone 等) |
default.rgw.control |
控制信息,通知其它 RGW 更新缓存 |
default.rgw.meta |
元数据:用户信息、Bucket 映射、密钥等 |
default.rgw.log |
各类操作日志 |
default.rgw.buckets.index |
Bucket 到对象的索引 |
default.rgw.buckets.data |
实际对象数据,默认三副本 |
创建 RGW 用户与认证
# 创建用户
radosgw-admin user create --uid="user1" --display-name="user1"
# 输出 access_key 和 secret_key,供客户端使用
# 创建只读用户
radosgw-admin user create --uid="readonly" --display-name="readonly" --max-buckets=0
# 修改用户配额
radosgw-admin quota set --quota-scope=user --uid=user1 --max-size=10G
radosgw-admin quota set --quota-scope=user --uid=user1 --max-objects=10000
用户权限基于 Bucket,可设置 read、write、readwrite、full-control。
Bucket 核心概念
-
Bucket 是存储对象的容器,扁平结构,不可嵌套。
-
只能包含小写字母、数字、短横线
- -
必须以小写字母或数字开头和结尾
-
长度 3-63 字节
-
不能使用 IP 地址格式
-
可设置访问控制、生命周期、跨域等。
客户端工具 s3cmd
安装与配置
apt install s3cmd -y
s3cmd --configure
Access Key: JIJX25OFEJ40JEBECDZV
Secret Key: vBa23pj4AhGk9GPeSrhL9NLaldShudVfjQ4AC90E
Default Region [US]: (直接回车)
S3 Endpoint [s3.amazonaws.com]: rgw.magedu.net:9900
DNS-style bucket+hostname:port template: rgw.magedu.net:9900/%(bucket)s
Encryption password: (回车跳过)
Path to GPG program [/usr/bin/gpg]: (回车)
Use HTTPS protocol [Yes]: No
Test access with supplied credentials? [Y/n] y
Save settings? [y/N] y
# 输入 Access Key、Secret Key、Endpoint(如 rgw.magedu.net:9900)
s3cmd常用命令
s3cmd mb s3://mybucket # 创建 Bucket
s3cmd put file.jpg s3://mybucket/ # 上传文件
s3cmd ls s3://mybucket/ # 列出对象
s3cmd get s3://mybucket/file.jpg /local/ # 下载
s3cmd rm s3://mybucket/file.jpg # 删除对象
s3cmd rb s3://mybucket # 删除空 Bucket
RGW 高可用
部署多台 RGW(至少两台),使用 HAProxy 做 TCP 反向代理: 转发 443 到后端 9443
listen ceph-rgw
bind 172.31.6.201:80
mode tcp
server rgw1 172.31.6.104:9900 check
server rgw2 172.31.6.105:9900 check
listen ceph-rgw-https
bind 172.31.6.201:443
mode tcp
server rgw1 172.31.6.104:9443 check
server rgw2 172.31.6.105:9443 check
客户端访问 VIP,实现故障转移。
# 在客户端挂载或测试时,停掉其中一台 RGW
systemctl stop ceph-radosgw@rgw.ceph-mgr1
# 客户端继续上传下载,服务不中断
s3cmd put test.jpg s3://mybucket/
# 恢复
systemctl start ceph-radosgw@rgw.ceph-mgr1
HTTPS 配置
生成自签名证书:
mkdir /etc/ceph/certs
cd /etc/ceph/certs
openssl genrsa -out civetweb.key 2048
openssl req -new -x509 -key civetweb.key -out civetweb.crt -subj "/CN=rgw.magedu.net"
cat civetweb.key civetweb.crt > civetweb.pem
修改 ceph.conf:
[client.rgw.ceph-mgr1]
rgw_frontends = "civetweb port=9900+9443s ssl_certificate=/etc/ceph/certs/civetweb.pem"
重启服务后,通过 https://rgw.magedu.net:9443 访问。负载均衡器可相应转发 443 端口。
常用管理命令
| 命令 | 说明 |
|---|---|
radosgw-admin user list |
列出所有用户 |
radosgw-admin bucket list |
列出所有 Bucket |
radosgw-admin bucket stats --bucket=xxx |
查看 Bucket 统计 |
radosgw-admin usage show --uid=user1 |
查看用户用量 |
ceph osd pool ls |
查看 RGW 相关存储池 |
radosgw-admin user info --uid=user1 |
查看用户详细信息 |
radosgw-admin user modify --uid=user1 --max-buckets=20 |
修改用户属性 |
radosgw-admin bucket list --uid=user1 |
查看某用户的所有 Bucket |
Bucket 版本控制
默认情况下,如果你往 Bucket 里上传了一个同名文件,旧文件会被直接覆盖,再也找不回来。
开启版本控制后,每次上传同名文件,Ceph 不会删除旧文件,而是给它打上一个版本号保留起来。你可以随时找回任意一个历史版本。
类比
就像 Word 文档的"修订历史",你改了 10 次,每次的版本都留着,随时可以恢复到 3 天前那个版本。
开启版本控制:
s3cmd setbucketversioning s3://mybucket enabled
验证是否开启:
s3cmd info s3://mybucket
输出里会看到 Versioning: Enabled。
实际效果演示:
# 1. 上传第一个版本
echo "版本1的内容" > test.txt
s3cmd put test.txt s3://mybucket/
# 2. 修改后再次上传(覆盖)
echo "版本2的内容" > test.txt
s3cmd put test.txt s3://mybucket/
# 3. 再次修改上传
echo "版本3的内容" > test.txt
s3cmd put test.txt s3://mybucket/
# 4. 查看所有版本
s3cmd ls --list-md5 s3://mybucket/test.txt
你会发现虽然只有一个文件 test.txt,但它保留了三个历史版本。你可以指定某个版本下载回来。
关闭版本控制(不再保留新版本,但旧版本还在):
s3cmd setbucketversioning s3://mybucket suspended
生命周期规则
自动清理 Bucket 里的旧文件,节省存储空间。比如"只要超过 90 天的文件,自动删除"。
你不需要手动去删,Ceph 会定时检查并执行。
类比
就像手机相册的"自动清理 30 天前的截图",到时间了系统自己删。
第一步:写一个 XML 规则文件
创建一个 lifecycle.xml 文件,内容如下:
<LifecycleConfiguration>
<Rule>
<ID>delete-old-files</ID> <!-- 规则名字,随便起 -->
<Filter></Filter> <!-- 作用于 Bucket 内所有文件 -->
<Status>Enabled</Status> <!-- 启用这条规则 -->
<Expiration>
<Days>90</Days> <!-- 超过 90 天的文件自动删除 -->
</Expiration>
</Rule>
</LifecycleConfiguration>
参数解释:
-
<ID>:给这条规则起个名字,方便以后管理 -
<Filter>:过滤条件,空的表示对 Bucket 里所有文件 生效。也可以指定前缀,比如<Prefix>logs/</Prefix>表示只对logs/目录下的文件生效 -
<Days>90</Days>:文件创建后超过 90 天就自动删除
第二步:应用规则到 Bucket
s3cmd setlifecycle lifecycle.xml s3://mybucket
第三步:验证规则是否生效
s3cmd getlifecycle s3://mybucket
会输出刚才设置的 XML 内容。
删除生命周期规则:
s3cmd dellifecycle s3://mybucket
两个功能组合使用的场景
假设你的监控系统每天产生大量截图,上传到 s3://monitor-screenshots:
-
开启版本控制:防止有人误删或覆盖重要截图
-
设置生命周期:90 天前的截图自动删除,不然磁盘很快就满了
这样既安全又省空间。
总结对比 Ceph 三种存储
| 存储类型 | 访问方式 | 典型场景 |
|---|---|---|
| RBD | 映射为本地磁盘,格式化挂载 | 虚拟机磁盘、数据库 |
| CephFS | mount 成目录,POSIX 操作 | 共享文件系统 |
| RGW | HTTP API(S3/Swift) | 对象存储、网盘、备份 |
Ceph 集群运维
[四、删除 OSD 或服务器](#四、删除 OSD 或服务器)
[五、Ceph 配置文件(ceph.conf)](#五、Ceph 配置文件(ceph.conf))
[六、Ceph Dashboard 开启与使用](#六、Ceph Dashboard 开启与使用)
[七、存储池、PG 与 CRUSH 核心概念](#七、存储池、PG 与 CRUSH 核心概念)
[三、PG 与 PGP](#三、PG 与 PGP)
[四、PG 数量计算(重要)](#四、PG 数量计算(重要))
[五、验证 PG 分布](#五、验证 PG 分布)
[八、CRUSH map 手动编辑与自定义规则](#八、CRUSH map 手动编辑与自定义规则)
[最简单的方法(不用手写 map)](#最简单的方法(不用手写 map))
[手动编辑 map 的流程(机架感知等复杂场景)](#手动编辑 map 的流程(机架感知等复杂场景))
一、通过套接字进行单机管理
什么是套接字(Socket)管理? 每个 Ceph 服务(OSD、MON)启动后,会在 /var/run/ceph/ 下生成一个 .asok 文件,管理员可以通过这个文件直接和本机上的单个守护进程交互,不经过集群网络。
查看套接字文件:
# OSD 节点
ll /var/run/ceph/
# 输出:ceph-osd.0.asok, ceph-osd.1.asok ...
# MON 节点
ll /var/run/ceph/
# 输出:ceph-mon.mon01.asok ...
使用方式:
ceph --admin-socket /var/run/ceph/ceph-osd.0.asok --help
常用操作:
# 查看 MON 状态 输出这个 MON 节点的内部状态
ceph --admin-daemon /var/run/ceph/ceph-mon.mon01.asok mon_status
# 查看当前配置 这个进程当前生效的全部配置参数
ceph --admin-daemon /var/run/ceph/ceph-mon.mon01.asok config show
这种管理方式不依赖集群网络,当集群异常时仍可操作本机进程。
二、集群的停止与重启
核心原则 :关闭前设置 noout,防止 OSD 被踢出导致数据无谓迁移。
关闭顺序(从外到内):
# 1. 设置 noout
ceph osd set noout t #关闭服务前设置 noout noout is set
# 2. 停止客户端(断开挂载、映射)
# 3. 停止 RGW(如使用)
# 4. 停止 CephFS MDS
# 5. 停止 OSD
# 6. 停止 MGR
# 7. 停止 MON
启动顺序(从内到外):
# 1. 启动 MON
# 2. 启动 MGR
# 3. 启动 OSD
# 4. 启动 MDS
# 5. 启动 RGW
# 6. 启动客户端
# 7. 取消 noout
ceph osd unset noout
三、添加服务器
# 1. 配置软件源
# 2. 安装 Ceph 软件
ceph-deploy install --release pacific 新节点名
# 3. 擦除磁盘
ceph-deploy disk zap 新节点名 /dev/sdb
# 4. 创建 OSD
ceph-deploy osd create 新节点名 --data /dev/sdb
四、删除 OSD 或服务器
删除单个 OSD:
# 1. 踢出集群
ceph osd out 1
# 2. 等待数据迁移完成
# 3. 停止进程
systemctl stop ceph-osd@1
# 4. 删除 OSD
ceph osd rm 1
删除整台服务器:
# 1. 逐一把该主机所有 OSD 按上述步骤删除
# 2. 从 CRUSH 移除主机
ceph osd crush rm 主机名
五、Ceph 配置文件(ceph.conf)
加载优先级(从高到低):
1. $CEPH_CONF 环境变量
2. -c 参数指定的位置
3. /etc/ceph/ceph.conf
4. ~/.ceph/ceph.conf
5. ./ceph.conf
配置段:
| 段名 | 作用 | 示例 |
|---|---|---|
[global] |
全局配置 | fsid、mon_host |
[osd] |
所有 OSD 通用 | 也可写 [osd.1] 指定单个 |
[mon] |
所有 MON 通用 | 也可写 [mon.mon01] 指定单个 |
[client] |
客户端配置 | 挂载、映射默认参数 |
六、Ceph Dashboard 开启与使用
Ceph Dashboard 是一个 Web 管理界面 ,打开浏览器就能看到集群状态、存储用量、OSD 健康度、性能曲线。不用每次都敲 ceph -s。
# 启用 dashboard 模块 在 active MGR 节点上加载 dashboard 模块
ceph mgr module enable dashboard
# 创建自签名证书
ceph dashboard create-self-signed-cert
# 创建管理员用户
ceph dashboard ac-user-create admin <password> administrator
admin:用户名
密码:自己设置
administrator:角色,表示管理员权限
# 查看访问地址
ceph mgr services
{
"dashboard": "https://172.31.6.104:8443"
}
浏览器访问 https://<mgr-ip>:8443 即可。如果打不开
-
确认 MGR 节点 IP 是对的
-
确认防火墙允许 8443 端口
-
确认
ceph mgr stat显示有 active MGR
七、存储池、PG 与 CRUSH 核心概念
一、两种存储池类型
| 类型 | 原理 | 冗余方式 | 磁盘占用 | 适用场景 |
|---|---|---|---|---|
| 副本池(replicated) | 一主多备,默认 3 副本 | 1 份数据存 3 份 | 3 倍 | RBD、CephFS、RGW 均支持 |
| 纠删码池(erasure code) | 数据分块 + 校验块,如 8+4 | 12 块中允许坏 4 块 | 1.5 倍 | 默认仅 RGW 可用;从 Luminous**(v12.2.x,2017年发布)** 版本起,开启 allow_ec_overwrites 后 RBD 和 CephFS 也可使用(元数据需存放于副本池) |
纠删码参数解读:
-
k=2:数据块数,对象被切成 k 份 -
m=2:校验块数,最多允许坏 m 个 OSD -
默认配置
k=2, m=2,生产常用k=8, m=4 -
优点:节省磁盘空间(3 副本需要 300% 空间,8+4 只需 150%)
-
缺点:读写时要编解码计算,CPU 开销更高
创建纠删码池示例:
ceph osd pool create erasure-testpool 16 16 erasure
ceph osd erasure-code-profile get default
rados put -p erasure-testpool testfile1 /var/log/syslog
rados get -p erasure-testpool testfile1 /tmp/testfile1
二、副本池读写流程
读数据(只读主 OSD):
客户端 → 主 OSD → 从本地磁盘读 → 返回数据
写数据(主 OSD 协调,等所有副本写完才确认):
客户端 → 主 OSD → 同时发给副本 OSD1、OSD2
→ 副本写完回复主 OSD
→ 主 OSD 回复客户端"写完"
纠删码读写:
-
写:主 OSD 先把数据编码成 k+m 个块,再分发写入各 OSD
-
读:从各 OSD 收集数据块后解码还原;有块丢失时自动用校验块重建
三、PG 与 PGP
PG(归置组 Placement Group):
-
存储池的虚拟子单元,夹在对象和 OSD 之间
-
对象先映射到 PG,PG 再映射到 OSD
-
好处:数据迁移以 PG 为单位,效率高
PGP(PG for Placement):
-
PG 到 OSD 的组合排列关系
-
创建池时通常 PG = PGP
数据定位全流程:
对象 → (哈希) → PG → (CRUSH 算法) → 具体 OSD
四、PG 数量计算(重要)
核心公式:
总 PG 数 = (OSD 总数 × 100) ÷ 副本数
单池 PG = 总 PG 数 ÷ 存储池数量 → 取最接近的 2 的 N 次幂
计算示例:100 个 OSD,3 副本,5 个存储池
总 PG = 100 × 100 ÷ 3 ≈ 3333
单池 PG = 3333 ÷ 5 ≈ 666 → 取 512
数量参考:
| 集群规模 | 每 OSD 建议 PG 数 |
|---|---|
| < 50 个 OSD | 100-150 |
| > 50 个 OSD | 50-100 |
| 大型集群 | 100-200 |
关键约束:
-
PG 数必须是 2 的 N 次幂(8、16、32、64、128、256、512...)
-
每个 OSD 的 PG 不超过 250 个
-
PG 太少:数据分布不均,同步时网络负载集中
-
PG 太多:CPU 和内存开销过大
五、验证 PG 分布
# 查看某池的 PG 状态
ceph pg ls-by-pool mypool | awk '{print $1,$2,$15}'
# 查看所有 PG 状态
ceph pg stat
awk '{print $1,$2,$15}' 输出各列含义:
-
$1:PG ID -
$2:对象数量 -
$15:该 PG 分布在哪些 OSD 上(ACTING 列)
八、CRUSH map 手动编辑与自定义规则
场景:
你有 4 台存储节点,每台上面插了 1 块 SSD (480G)和 2 块 HDD(2T)。现在你想实现:
-
高性能池
ssd-pool的数据只存到 SSD 上 -
备份池
backup-pool的数据只存到 HDD 上
最简单的方法(不用手写 map)
# 1. 创建一条仅选 SSD 的规则
ceph osd crush rule create-replicated ssd_rule default host ssd
# 2. 创建存储池时指定这条规则
ceph osd pool create ssd-pool 32 32 ssd_rule
- `ssd_rule`:规则名字,自己起
- `default`:从哪个 root 开始(默认的就行)
- `host`:故障域级别,保证同一数据的不同副本在不同主机上
- `ssd`:设备类别,只选标记为 SSD 的 OSD
这条命令执行完,ssd-pool 里的数据就只会落在 SSD 上。
手动编辑 map 的流程(机架感知等复杂场景)
如果上面的命令行方式满足不了(比如你要机架感知),才需要手动编辑:
# 1. 导出当前 CRUSH map
ceph osd getcrushmap -o /tmp/crush.bin
# 2. 转为可编辑文本
crushtool -d /tmp/crush.bin -o /tmp/crush.txt
# 3. 用 vim 编辑
vim /tmp/crush.txt
文本文件里的结构你可以理解为四个部分:
a) 设备清单(devices):列出所有 OSD
device 0 osd.0 class ssd # ← class 决定它属于 ssd 还是 hdd
device 1 osd.1 class hdd
device 2 osd.2 class hdd
b) 类型定义(types):不用改
c) 桶(bucket):把 OSD 按物理拓扑组织
host store01 { # 一台主机叫 store01
item osd.0 weight 0.48 # 里面放这块 SSD
item osd.1 weight 1.95 # 和这块 HDD
item osd.2 weight 1.95
}
host store02 { ... }
root default { # 所有主机的总集合
item store01 weight ...
item store02 weight ...
}
d) 规则(rule):定义怎么选 OSD
rule ssd_rule {
id 10
type replicated
step take default # 从 default 这个 root 开始
step chooseleaf firstn 0 type host # 选不同主机,每个主机选一个 OSD
step emit
}
编辑完后:
# 4. 转回二进制
crushtool -c /tmp/crush.txt -o /tmp/crush-new.bin
# 5. 导入(立即生效,危险!)
ceph osd setcrushmap -i /tmp/crush-new.bin
# 6. 验证
ceph osd crush rule ls
ceph osd pool create test-pool 32 32 ssd_rule
实际上如果你只是想分 SSD/HDD,用第一段里的命令行方式就够了,不用手动写 map。
九、常见故障诊断命令速查
ceph health detail # 查看健康详情
ceph pg dump_stuck inactive # 卡住的 PG
ceph pg dump_stuck unclean
ceph pg dump_stuck stale
ceph daemon osd.X status # 某 OSD 实时状态
ceph pg <pgid> query # 某 PG 详细信息
ceph log last 50 # 最近集群日志
ceph osd perf # 各 OSD 延迟
十、性能基准测试命令
# RADOS 性能测试(写)
rados bench -p <pool> 10 write --no-cleanup
# RADOS 性能测试(读)
rados bench -p <pool> 10 seq
# RBD 性能测试(FIO)
fio --filename=/dev/rbd0 --rw=randwrite --bs=4k --size=1G ...
PG 状态速查指南
[1. 正常基准状态](#1. 正常基准状态)
[2. 数据同步与恢复状态 (PG内部工作流)](#2. 数据同步与恢复状态 (PG内部工作流))
[3. 降级与警告状态 (影响冗余度,但IO通常不断)](#3. 降级与警告状态 (影响冗余度,但IO通常不断))
[4. 严重故障状态 (导致IO中断)](#4. 严重故障状态 (导致IO中断))
[5. 维护状态](#5. 维护状态)
PG (Placement Group) 是 Ceph 数据分布与管理的核心单元。一个健康的 PG 状态为 active+clean,任何故障都会导致状态变化。
1. 正常基准状态
-
Active: PG 可以正常处理客户端的读写请求。
-
Clean : PG 内的所有副本数据一致,且数量等于存储池设定的副本数(如3副本)。
Active+Clean是完美状态。
2. 数据同步与恢复状态 (PG内部工作流)
这类状态通常出现在OSD重启、扩容或故障恢复时,数据正在重新同步。
-
Peering : 正在协商。同一个PG内的OSD正在互相通信,就数据状态达成一致,是恢复流程的第一步。
-
Recovering : 正在增量恢复。基于日志(PGLog)同步少量差异数据。通常OSD短暂离线后会出现。
-
Backfilling : 正在全量恢复。当OSD离线太久,日志无法增量同步时,会从主OSD全量拷贝整个PG数据。数据量大,耗时长。
-
Remapped : 重新映射。CRUSH算法为PG分配了新的OSD组合(如扩容时),数据开始从旧组合迁移到新组合。在此期间,客户端仍由旧组合中的主OSD处理请求,IO不断。
3. 降级与警告状态 (影响冗余度,但IO通常不断)
-
Degraded : 降级状态。PG发现某个副本数据不一致需要修复,或者当前可用的副本数少于规定数量。客户端IO通常不中断,但数据冗余度降低。
-
Undersized : 副本数不足 。当前在线的PG副本数低于存储池设定的
min_size值。如果min_size配置合理,PG仍可处理IO。 -
Stale : 主OSD失联。主OSD没有按时向MON汇报PG状态(网络问题、进程卡死等)。此时,MON无法得知该PG的真实状态。
-
Peered : 已协商,但副本不足 。PG内OSD已完成协商,但由于在线副本数少于
min_size,PG暂时不能响应IO请求,IO会阻塞 。一旦副本数恢复或手动降低min_size,即可恢复。
4. 严重故障状态 (导致IO中断)
-
Down : 瘫痪状态 。PG检测到在某个关键时期内,在线的OSD数量不足以完成数据修复。通常发生在"数据丢在旧OSD上,且旧OSD离线的同时,其他副本也全挂"的连环故障中。IO会完全阻塞。
-
Incomplete : 协商失败 。在Peering过程中,PG发现无法选出权威日志,或选出的OSD组合无法完成数据修复。这通常是灾难性故障的前兆,如多副本同时永久损坏。IO阻塞。
-
Inconsistent : 数据不一致。深度清理(Deep Scrub)时,发现副本间的对象数据内容不匹配。这是数据损坏的明确信号,需立即干预。
5. 维护状态
- Scrubbing / Deep: PG正在执行数据一致性扫描(轻量或深度)。这是正常的后台维护操作,深度扫描时PG会暂时处于此状态。
一句话总结 :处理PG故障时,只要抓住 Active 和 Clean 两个核心。没了 Active,IO就会挂起 ;没了 Clean,数据冗余度就处于风险中 。结合 ceph -s 和 ceph health detail,锁定故障PG,按上述状态逻辑排查,是运维的关键。
数据读写流程与存储池管理
[1. 创建存储池](#1. 创建存储池)
[2. 列出存储池](#2. 列出存储池)
[3. 查看存储池统计](#3. 查看存储池统计)
[4. 重命名存储池](#4. 重命名存储池)
[5. 删除存储池](#5. 删除存储池)
[6. 存储池配额](#6. 存储池配额)
[7. 存储池常用参数](#7. 存储池常用参数)
[8. 清理(Scrub)参数](#8. 清理(Scrub)参数)
一、数据读写流程
整体步骤:
APP 请求(对象名 + 存储池名)
↓
客户端对对象名做哈希,取模得到 PG 编号
↓
客户端对存储池名做哈希,与 PG 编号组合成完整 PG ID(如 3.23)
↓
客户端从 MON 获取最新 cluster map
↓
CRUSH 算法根据 PG ID + cluster map 计算出主 OSD 和备 OSD
↓
客户端直接向主 OSD 发起读写请求
↓(写操作)
主 OSD 同步数据到备 OSD,全部写完才确认
核心要点:
-
客户端不需要知道对象存哪,全靠 CRUSH 算法实时计算
-
不需要查中心元数据表,因此无瓶颈、可无限扩展
-
写操作由主 OSD 协调,等所有副本写完才返回成功
✅ 此流程自 Ceph 诞生至今基本未变,核心原理仍然适用。
二、存储池管理
1. 创建存储池
ceph osd pool create <poolname> <pg_num> <pgp_num> {replicated|erasure}
示例:
ceph osd pool create mypool 32 32
⚠️ 变化提示 :现代 Ceph 已支持 PG 自动扩缩容,创建时给一个初始 PG 数即可,后续集群会自动调整:
ceph osd pool set mypool pg_autoscale_mode on
2. 列出存储池
ceph osd pool ls # 只显示名称
ceph osd lspools # 显示名称和 ID
ceph osd pool ls detail # 显示详细信息
3. 查看存储池统计
ceph osd pool stats mypool # 查看单个池
rados df # 查看所有池用量
4. 重命名存储池
ceph osd pool rename old-name new-name
5. 删除存储池
删除存储池会永久删除所有数据,Ceph 设置了两道防线:
防线一:nodelete 标志(默认为 false,可直接删)
ceph osd pool get mypool nodelete # 查看
ceph osd pool set mypool nodelete true # 禁止删除
ceph osd pool set mypool nodelete false # 允许删除
防线二:集群级 mon_allow_pool_delete 参数(默认 false,需临时打开)
# 临时允许删除
ceph tell mon.* injectargs --mon-allow-pool-delete=true
# 执行删除(注意要写两遍存储池名)
ceph osd pool rm mypool mypool --yes-i-really-really-mean-it
# 恢复禁止删除
ceph tell mon.* injectargs --mon-allow-pool-delete=false
6. 存储池配额
限制存储池的最大空间或对象数量:
# 查看配额
ceph osd pool get-quota mypool
# 限制对象数
ceph osd pool set-quota mypool max_objects 1000
# 限制容量
ceph osd pool set-quota mypool max_bytes 10737418240 # 10G
7. 存储池常用参数
| 参数 | 含义 | 默认值 | 查看/设置命令 |
|---|---|---|---|
size |
副本数 | 3 | ceph osd pool get mypool size |
min_size |
最小服务副本数 | 2 | ceph osd pool get mypool min_size |
pg_num |
PG 数量 | 创建时指定 | ceph osd pool get mypool pg_num |
crush_rule |
CRUSH 规则 | replicated_rule | ceph osd pool get mypool crush_rule |
nodelete |
禁止删除标志 | false | ceph osd pool get mypool nodelete |
nopgchange |
禁止修改 PG 数 | false | ceph osd pool get mypool nopgchange |
nosizechange |
禁止修改配额 | false | ceph osd pool get mypool nosizechange |
noscrub |
关闭轻量清理 | false | ceph osd pool get mypool noscrub |
nodeep-scrub |
关闭深度清理 | false | ceph osd pool get mypool nodeep-scrub |
修改 PG 数量:
ceph osd pool set mypool pg_num 64
关闭/开启清理扫描(临时解决高 I/O 问题):
ceph osd pool set mypool noscrub true # 暂停轻量清理
ceph osd pool set mypool nodeep-scrub true # 暂停深度清理
ceph osd pool set mypool noscrub false # 恢复
8. 清理(Scrub)参数
Scrub 是 Ceph 的数据一致性检查机制:
| 参数 | 默认值 | 含义 |
|---|---|---|
osd_scrub_min_interval |
86400 秒(1 天) | 轻量清理最小间隔 |
osd_scrub_max_interval |
604800 秒(7 天) | 轻量清理最大间隔 |
osd_deep_scrub_interval |
604800 秒(7 天) | 深度清理间隔 |
osd_max_scrubs |
1 | 每个 OSD 同时进行的 scrub 数量 |
通过套接字查看当前 OSD 的 scrub 配置:
ceph daemon osd.3 config show | grep scrub
存储池快照与数据压缩
[1. 创建快照](#1. 创建快照)
[2. 查看快照列表](#2. 查看快照列表)
[3. 回滚对象(基于快照恢复单个文件)](#3. 回滚对象(基于快照恢复单个文件))
[4. 删除快照](#4. 删除快照)
存储池快照
快照用于对存储池中的数据进行备份与还原 。注意:这是存储池级别的快照,与 RBD 映像快照不同。
⚠️ 实际使用提示 :生产环境中更常用的是 RBD 映像快照 (
rbd snap),存储池快照主要用于 rados 对象级别的操作,日常使用场景较少。
1. 创建快照
# 方式一
ceph osd pool mksnap mypool mypool-snap
# 方式二
rados -p mypool mksnap mypool-snap2
2. 查看快照列表
rados lssnap -p mypool
1 mypool-snap 2026.4.03 16:12:56
2 mypool-snap2 2026.4.03 16:13:40
3. 回滚对象(基于快照恢复单个文件)
# 上传文件
rados -p mypool put testfile /etc/hosts
# 创建快照
ceph osd pool mksnap mypool mypool-snapshot001
# 删除文件
rados -p mypool rm testfile
# 从快照回滚该文件
rados rollback -p mypool testfile mypool-snapshot001
# 文件已恢复,可正常操作
rados -p mypool rm testfile
4. 删除快照
# 删除指定快照
ceph osd pool rmsnap mypool mypool-snap
# 验证
rados lssnap -p mypool
数据压缩
如果使用 Bluestore 存储引擎,Ceph 支持实时数据压缩 (边压缩边写入),有助于节省磁盘空间。默认不开启压缩。
✅ 此功能在现代 Ceph 中依然有效,配置方式基本不变。
1. 设置压缩算法
ceph osd pool set mypool compression_algorithm snappy
常用算法对比:
| 算法 | CPU 消耗 | 压缩比 | 推荐场景 |
|---|---|---|---|
snappy |
低 | 中等 | 默认推荐,通用场景 |
lz4 |
低 | 中等 | 与 snappy 类似 |
zstd |
中 | 高 | 磁盘空间紧张时 |
zlib |
高 | 高 | 不推荐,CPU 开销过大 |
none |
无 | 无 | 关闭压缩 |
2. 设置压缩模式
ceph osd pool set mypool compression_mode aggressive
模式说明:
| 模式 | 含义 |
|---|---|
none |
不压缩 |
passive |
仅当写操作带有可压缩提示时才压缩 |
aggressive |
除非写操作带有不可压缩提示,否则都压缩 |
force |
强制压缩,忽略所有提示 |
3. 查看压缩设置
ceph osd pool get mypool compression_algorithm
ceph osd pool get mypool compression_mode
4. 压缩相关参数
存储池级别参数:
| 参数 | 含义 | 默认值 |
|---|---|---|
compression_algorithm |
压缩算法 | snappy |
compression_mode |
压缩模式 | none |
compression_required_ratio |
压缩后/压缩前的比值上限 | .875 |
全局参数(配置于 ceph.conf):
| 参数 | 含义 | 默认值 |
|---|---|---|
bluestore_compression_algorithm |
全局压缩算法 | - |
bluestore_compression_mode |
全局压缩模式 | - |
bluestore_compression_min_blob_size |
小于此值不压缩 | 0 |
bluestore_compression_max_blob_size |
大于此值拆块后压缩 | 0 |
bluestore_compression_min_blob_size_ssd |
SSD 最小压缩块 | 8K |
bluestore_compression_max_blob_size_ssd |
SSD 最大压缩块 | 64K |
bluestore_compression_min_blob_size_hdd |
HDD 最小压缩块 | 128K |
bluestore_compression_max_blob_size_hdd |
HDD 最大压缩块 | 512K |
5. 在节点上验证压缩配置
ceph daemon osd.11 config show | grep compression
快照 vs 压缩 使用建议
| 功能 | 适用场景 | 注意事项 |
|---|---|---|
| 存储池快照 | rados 对象级别回滚 | 生产更常用 RBD 快照(rbd snap) |
| 数据压缩 | 节省磁盘空间 | CPU 与空间之间的权衡,建议 snappy/lz4 + aggressive |
CephX 是什么?
[CephX 的两个限制](#CephX 的两个限制)
[Profile 能力(预定义组合)](#Profile 能力(预定义组合))
[1. 列出所有用户](#1. 列出所有用户)
[2. 查看指定用户](#2. 查看指定用户)
[3. 添加用户](#3. 添加用户)
[4. 修改用户权限](#4. 修改用户权限)
[5. 删除用户](#5. 删除用户)
[1. 导出用户到密钥环文件(备份)](#1. 导出用户到密钥环文件(备份))
[2. 从密钥环文件恢复用户](#2. 从密钥环文件恢复用户)
[3. 合并多个用户到同一个密钥环](#3. 合并多个用户到同一个密钥环)
CephX 是 Ceph 内置的身份认证和授权协议,所有与 MON 通信的请求都必须通过认证。
两个关键点:
-
可以在 MON 节点关闭认证,但关闭后任何访问都被允许,数据无安全性
-
CephX 只负责认证授权 ,不负责数据加密传输
二、认证流程
客户端 → MON:我有密钥,给我一个 session key
MON → 客户端:验证通过,返回 session key(用客户端密钥加密)
客户端 → MON:用 session key 请求服务 ticket
MON → 客户端:发放 ticket
客户端 → OSD:出示 ticket
OSD:MON 和 OSD 共享同一个 secret,信任 MON 发的 ticket,放行
-
ticket 有有效期,过期自动重新发放
-
多个 MON 节点共同认证,无单点故障和性能瓶颈
关键设计思想
| 设计点 | 原因 |
|---|---|
| 每个 MON 都能认证 | 无单点故障,无性能瓶颈 |
| session key 用客户端密钥加密 | 网络被监听也无法解密 |
| MON 和 OSD 共享 secret | OSD 信任 MON 的 ticket,不用每次读写都问 MON |
| ticket 有有效期 | ticket 泄露影响是暂时的 |
CephX 的两个限制
| 限制 | 说明 |
|---|---|
| 不能扩展到非 Ceph 组件 | 只对 Ceph 内部有效,不能认证外部应用 |
| 不能加密传输数据 | 只管"你是谁",不管"数据在路上是否被偷看" |
三、访问流程
无论客户端是块设备、对象存储还是文件系统,Ceph 在存储池中把所有数据都存为对象。
-
用户必须有存储池访问权限,才能读写数据
-
用户必须有执行权限(x) ,才能使用
ceph管理命令
四、用户类型
Ceph 用户格式:TYPE.ID
| 类型 | 说明 | 示例 |
|---|---|---|
client |
管理员或应用程序 | client.admin |
osd |
OSD 守护进程 | osd.0 |
mds |
MDS 守护进程 | mds.ceph-mgr1 |
mgr |
MGR 守护进程 | mgr.ceph-mgr1 |
管理员管理的用户都属于
client类型。MON/OSD/MDS 是系统组件用户。
五、能力(Capabilities/Caps)
Ceph 通过 caps 描述用户对 MON/OSD/MDS 的授权范围。
语法格式 :daemon-type 'allow caps' [...]
基础能力
| 能力 | 含义 |
|---|---|
r |
读权限(如检索 CRUSH 运行图) |
w |
写权限(写入对象) |
x |
执行权限(调用类方法、执行 auth 操作) |
* |
全部权限(读、写、执行 + 管理命令) |
class-read |
类读取(x 的子集) |
class-write |
类写入(x 的子集) |
Profile 能力(预定义组合)
| Profile | 用途 |
|---|---|
profile osd |
OSD 间通信、状态上报、心跳检测 |
profile mds |
MDS 间通信 |
profile bootstrap-osd |
引导初始化新 OSD |
profile bootstrap-mds |
引导初始化新 MDS |
六、典型权限示例
# admin 用户:全部权限
[client.admin]
caps mds = "allow *"
caps mgr = "allow *"
caps mon = "allow *"
caps osd = "allow *"
# OSD 用户:OSD 间通信权限
[osd.10]
caps mgr = "allow profile osd"
caps mon = "allow profile osd"
caps osd = "allow *"
# 自定义受限用户:只能读 MON,只能读写 mypool 这个存储池
[client.tom]
caps mon = "allow r"
caps osd = "allow rwx pool=mypool"
七、用户管理命令
1. 列出所有用户
ceph auth list #查看所有用户的名单及其权限和密钥
ceph auth list -o output.keyring # 导出到文件
2. 查看指定用户
ceph auth get client.admin
ceph auth get osd.10
3. 添加用户
| 命令 | 是否创建 | 返回内容 | 适用场景 |
|---|---|---|---|
add |
必须不存在 | 无输出 | 严格新建 |
get-or-create |
不存在则创建 | 完整 keyring 格式 | 最常用 |
get-or-create-key |
不存在则创建 | 只返回密钥字符串 | 脚本/自动化 |
print-key |
不创建 | 只返回密钥字符串 | 查看已有密钥 |
# 方式一:add(已存在会报错)
ceph auth add client.tom mon 'allow r' osd 'allow rwx pool=mypool'
# 方式二:get-or-create(推荐)
已存在就直接获取。会输出或导出完整的密钥文件
ceph auth get-or-create client.jack mon 'allow r' osd 'allow rwx pool=mypool' -o jack.keyring
# 方式三:只返回密钥字符串 没有多余信息,很适合在脚本里用
ceph auth get-or-create-key client.jack mon 'allow r' osd 'allow rwx pool=mypool'
# 方式四:查看已有用户密钥
ceph auth print-key client.jack
4. 修改用户权限
注意 :ceph auth caps 是完全覆盖,必须同时带上旧权限和新权限。
# 仅查看当前权限
ceph auth get client.jack
# 修改权限(覆盖)
ceph auth caps client.jack mon 'allow r' osd 'allow rw pool=mypool'
5. 删除用户
ceph auth del client.tom
八、密钥环(Keyring)管理
密钥环文件(.keyring)保存用户的认证信息,客户端需要此文件才能访问 Ceph。
密钥环文件优先级:
/etc/ceph/<$cluster>.<type>.<id>.keyring # 单用户
/etc/ceph/cluster.keyring # 多用户
/etc/ceph/keyring # 多用户
/etc/ceph/keyring.bin # 二进制格式
1. 导出用户到密钥环文件(备份)
# 创建空 keyring 文件
ceph-authtool --create-keyring ceph.client.user1.keyring
ceph-authtool 是一个专门管理密钥环文件的工具。
--create-keyring 就是让它生成一个新的、空的密钥环文件。
ceph.client.user1.keyring 是这个文件的文件名,通常命名为 ceph.用户名.keyring,一看就知道是谁的卡。
# 导出用户认证信息
ceph auth get client.user1 -o ceph.client.user1.keyring
ceph auth get client.user1 是从 Ceph 集群里查询 client.user1 这个用户的密钥和权限。
-o ceph.client.user1.keyring 是把查询结果输出并覆盖到第一步创建的文件里。
# 验证
cat ceph.client.user1.keyring
2. 从密钥环文件恢复用户
# 误删用户
ceph auth del client.user1
# 从备份导入恢复
ceph auth import -i ceph.client.user1.keyring
# 验证
ceph auth get client.user1
3. 合并多个用户到同一个密钥环
# 创建空文件
ceph-authtool --create-keyring ceph.client.user.keyring
# 导入 admin 用户
ceph-authtool ./ceph.client.user.keyring --import-keyring ./ceph.client.admin.keyring
# 再导入其他用户
ceph-authtool ./ceph.client.user.keyring --import-keyring ./ceph.client.user1.keyring
# 查看合并后的内容
ceph-authtool -l ./ceph.client.user.keyring
九、权限配置场景速查
| 场景 | 权限配置 |
|---|---|
| 集群管理员 | caps mon/osd/mgr/mds = "allow *" |
| RBD 客户端 | caps mon = "allow r" + caps osd = "allow rwx pool=存储池名" |
| 只读监控 | caps mon = "allow r" + caps osd = "allow r pool=存储池名" |
十、命令速查表
| 操作 | 命令 |
|---|---|
| 列出所有用户 | ceph auth list |
| 查看某用户 | ceph auth get client.admin |
| 创建用户 | ceph auth get-or-create client.xxx mon 'allow r' osd 'allow rwx pool=xxx' |
| 只获取密钥 | ceph auth print-key client.xxx |
| 修改权限 | ceph auth caps client.xxx mon 'allow r' osd 'allow rw pool=xxx' |
| 删除用户 | ceph auth del client.xxx |
| 导出到文件 | ceph auth get client.xxx -o xxx.keyring |
| 从文件导入 | ceph auth import -i xxx.keyring |
| 合并 keyring | ceph-authtool target.keyring --import-keyring source.keyring |
Ceph RBD 使用详解
[一、RBD 概述](#一、RBD 概述)
[二、创建 RBD 存储池](#二、创建 RBD 存储池)
[三、创建与管理 RBD 镜像](#三、创建与管理 RBD 镜像)
[1. 创建镜像](#1. 创建镜像)
[2. 查看镜像详细信息](#2. 查看镜像详细信息)
[3. 镜像特性说明与启用/禁用](#3. 镜像特性说明与启用/禁用)
[四、客户端挂载 RBD](#四、客户端挂载 RBD)
[1. 安装客户端软件](#1. 安装客户端软件)
[2. 同步认证文件(以 admin 为例)](#2. 同步认证文件(以 admin 为例))
[3. 映射镜像为本地块设备](#3. 映射镜像为本地块设备)
[4. 普通用户挂载示例](#4. 普通用户挂载示例)
[1. 卸载镜像](#1. 卸载镜像)
[2. 删除镜像(谨慎操作)](#2. 删除镜像(谨慎操作))
[1. 快照命令概览](#1. 快照命令概览)
[2. 创建快照](#2. 创建快照)
[3. 回滚快照](#3. 回滚快照)
[4. 删除快照](#4. 删除快照)
[5. 快照数量限制](#5. 快照数量限制)
[6.RBD 镜像克隆与 flatten](#6.RBD 镜像克隆与 flatten)
[为什么需要 flatten](#为什么需要 flatten)
一、RBD 概述
RBD(RADOS Block Device)是 Ceph 提供的块存储 ,可以简单理解为从 Ceph 集群里划分出来的"虚拟硬盘"。它的典型使用场景是:
-
给虚拟机当磁盘(比如 OpenStack、KVM 虚机直接挂载 RBD 镜像当系统盘或数据盘)。
-
给物理服务器或容器 提供额外的持久化存储(通过映射成本地
/dev/rbd设备,格式化后直接挂载目录使用)。 -
数据库、中间件等需要裸盘性能 和快照、克隆、扩容、高可用特性的场景。
它的好处是:
-
可以随时扩容,不停机增加磁盘大小。
-
可以快照/回滚,出了问题秒级恢复到某个时间点。
-
可以克隆,快速复制出一份数据给开发测试。
-
数据多副本分布在集群里,坏了硬盘也不丢数据。
二、创建 RBD 存储池
# 创建存储池
ceph osd pool create rbd-data1 32 32
# 查看存储池列表
ceph osd pool ls
# 在存储池上启用 RBD 应用
ceph osd pool application enable rbd-data1 rbd
# 初始化 RBD 池
rbd pool init -p rbd-data1
三、创建与管理 RBD 镜像
1. 创建镜像
# 创建两个镜像:data-img1(3G)和 data-img2(5G)
rbd create data-img1 --size 3G --pool rbd-data1 --image-format 2 --image-feature layering
rbd create data-img2 --size 5G --pool rbd-data1 --image-format 2 --image-feature layering
参数说明:
--image-format 2:使用第二代镜像格式(支持更多高级特性,现在都推荐用 2)。
--image-feature layering:开启分层快照特性,这样以后才能对镜像做快照,并从快照克隆出新的镜像。
创建好之后,它们还不直接能用,需要像挂盘一样映射到客户端、格式化、挂载到目录,然后就能跟本地硬盘一样读写文件了。
# 查看镜像列表
rbd ls --pool rbd-data1
# 查看镜像详细信息(含大小、格式等)
rbd ls --pool rbd-data1 -l
# 以 JSON 格式输出
rbd ls --pool rbd-data1 -l --format json --pretty-format
2. 查看镜像详细信息
rbd --image data-img2 --pool rbd-data1 info
rbd image 'data-img2':
size 5 GiB in 1280 objects
order 22 (4 MiB objects) #对象大小,每个对象是 2^22/1024/1024=4MiB
id: d42b6b8b4567 #镜像 id
block_name_prefix: rbd_data.d42b6b8b4567 #size 里面的 1280 个对象名称前缀
format: 2 #镜像文件格式版本
features: layering #特性,layering 支持分层快照以写时复制
op_features:
flags:
create_timestam
3. 镜像特性说明与启用/禁用
常见特性
-
layering:支持分层快照,写时复制(COW)。 -
striping:条带化 V2,提高顺序读写性能。 -
exclusive-lock:独占锁,限制同一镜像仅能被一个客户端使用。 -
object-map:对象映射(依赖独占锁),加速导入导出与空间统计。 -
fast-diff:快速计算镜像与快照差异(依赖 object-map)。 -
deep-flatten:快照扁平化,解除克隆对父镜像的依赖。 -
journaling:日志记录(依赖独占锁),可恢复数据但增加 IO 开销。
启用特性
rbd feature enable exclusive-lock --pool rbd-data1 --image data-img1
rbd feature enable object-map --pool rbd-data1 --image data-img1
rbd feature enable fast-diff --pool rbd-data1 --image data-img1
# 验证特性已开启
rbd --image data-img1 --pool rbd-data1 info
禁用特性
rbd feature disable fast-diff --pool rbd-data1 --image data-img1
# 验证特性已关闭
rbd --image data-img1 --pool rbd-data1 info
四、客户端挂载 RBD
1. 安装客户端软件
# 配置 YUM 源
yum install epel-release
yum install https://mirrors.aliyun.com/ceph/rpm-octopus/el7/noarch/ceph-release-1-1.el7.noarch.rpm -y
# 安装 ceph-common
yum install ceph-common
2. 同步认证文件(以 admin 为例)
# 从部署节点拷贝认证文件至客户端
scp ceph.conf ceph.client.admin.keyring root@172.31.6.110:/etc/ceph/
3. 映射镜像为本地块设备
# 若内核不支持某些特性(如 object-map),先禁用
rbd feature disable rbd-data1/data-img1 object-map
# 映射镜像
rbd -p rbd-data1 map data-img1
rbd -p rbd-data1 map data-img2
#Ceph 集群里的 data-img2 镜像就会自动出现在你本机,成为一个新的块设备 map → 多出设备 → 格式化 → 挂载到目录 → 正常使用
# 查看映射的设备
lsblk
4. 普通用户挂载示例
若使用非 admin 用户(如 client.shijie),则需要:
例:
mkfs.xfs /dev/rbd0
mkfs.xfs /dev/rbd1
# 格式化(ext4 举例)
mkfs.ext4 /dev/rbd0
mkdir /data
mount /dev/rbd0 /data/
# 复制文件进行读写测试
cp /var/log/messages /data/
ll /data/
df -TH
管理端可验证锁定状态:
rbd ls -p rbd-data1 -l
# LOCK 列显示 excl,表示镜像已被客户端独占锁定
五、镜像空间扩容
# 把 data-img2 这个虚拟磁盘的容量从原来的 5G 直接拉到 8G。
rbd resize --pool rbd-data1 --image data-img2 --size 8G
#虚拟硬盘”的物理容量就变大了,但你的客户端系统还不知道
# 客户端识别新空间(ext4 文件系统)
resize2fs /dev/rbd0
# 若为 xfs 文件系统,使用:
# xfs_growfs /data/
# 查看扩容结果
fdisk -l /dev/rbd0
六、开机自动挂载
在客户端编辑 /etc/rc.d/rc.local,添加:
rbd --user shijie -p rbd-data1 map data-img2
mount /dev/rbd0 /data/
赋予执行权限:
chmod a+x /etc/rc.d/rc.local
重启后验证:
rbd showmapped
df -TH
七、卸载与删除镜像
1. 卸载镜像
# 卸载文件系统并取消映射
umount /data
rbd --user shijie -p rbd-data1 unmap data-img2
2. 删除镜像(谨慎操作)
直接删除:
rbd rm --pool rbd-data1 --image data-img1
回收站机制(推荐先移入回收站):
删除的镜像数据无法恢复,但是还有另外一种方法可以先把镜像移动到回收站,后期确认删除的时候再从回收站删除即可。
# 查看镜像状态
rbd status --pool rbd-data1 --image data-img2
# 移入回收站
将 data-img2 这个镜像从正常镜像列表里移除,放入池的回收站里。
rbd trash move --pool rbd-data1 --image data-img2
# 查看回收站列表
rbd trash list --pool rbd-data1
# 从回收站还原(需指定镜像 ID)
rbd trash restore --pool rbd-data1 --image data-img2 --image-id d42b6b8b4567
# 确认删除后从回收站永久清除
rbd trash rm --pool rbd-data1 --image-id <id>
八、镜像快照管理
1. 快照命令概览
snap create (snap add) # 创建快照
snap limit set # 设置快照数量上限
snap limit clear # 清除快照数量限制
snap list (snap ls) # 列出快照
snap protect # 保护快照(防止被删除)
snap unprotect # 取消保护
snap purge # 删除所有未保护快照
snap remove (snap rm) # 删除指定快照
snap rename # 重命名快照
snap rollback (snap revert) # 回滚至某快照
2. 创建快照
rbd snap create --pool rbd-data1 --image data-img2 --snap img2-snap-20251215
rbd snap list --pool rbd-data1 --image data-img2
SNAPID NAME SIZE TIMESTAMP
4 img2-snap-20251215 8 GiB Tue Dec
3. 回滚快照
# 客户端需先卸载并取消映射
umount /data
rbd unmap /dev/rbd0 #把映射的本地设备 /dev/rbd0 断开
# 管理端执行回滚
rbd snap rollback --pool rbd-data1 --image data-img2 --snap img2-snap-20251215
rbd snap rollback RBD 快照子命令,执行回滚操作
--pool rbd-data1 指定存储池名称,告诉系统这个镜像在哪个池里
--image data-img2 指定要回滚的镜像名称,即你要恢复哪个“虚拟磁盘”
--snap img2-snap-20251215 指定回滚到哪一个快照点,即你要恢复到哪个时间点的状态
# 客户端重新映射并挂载验证
rbd --user shijie -p rbd-data1 map data-img2
mount /dev/rbd0 /data/
ll /data/
--user shijie 指定连接 Ceph 集群用的认证用户,这里用的是普通用户 client.shijie,而非默认的 admin
-p rbd-data1 指定存储池名称,与 --pool rbd-data1 等价
map data-img2 映射操作,把 data-img2 这个镜像挂载到本机,变成 /dev/rbd0(或 rbd1 等)
4. 删除快照
rbd snap remove --pool rbd-data1 --image data-img2 --snap img2-snap-20201215
rbd snap list --pool rbd-data1 --image data-img2
5. 快照数量限制
# 设置上限
rbd snap limit set --pool rbd-data1 --image data-img2 --limit 30
rbd snap limit set --pool rbd-data1 --image data-img2 --limit 20
rbd snap limit set --pool rbd-data1 --image data-img2 --limit 15
# 清除上限
rbd snap limit clear --pool rbd-data1 --image data-img2
6.RBD 镜像克隆与 flatten
场景:
你们公司要快速部署 50 台云主机的开发环境。传统做法每台云主机都要创建新磁盘、装系统,至少花半小时。
用克隆的方法
-
先手工做一个 5G 的 RBD 镜像,装上 CentOS 系统和开发环境。
-
给这个镜像打快照并保护:
rbd snap create mypool/base-img@v1 rbd snap protect mypool/base-img@v1 -
然后批量克隆:
for i in {1..50}; do rbd clone mypool/base-img@v1 mypool/vm-$i done秒级完成! 因为克隆只是创建一个引用,不实际拷贝数据。
-
50 台云主机分别挂载
mypool/vm-1到mypool/vm-50,直接开机就能用。
为什么需要 flatten
克隆后的子镜像依赖于父快照,你不能删那个父快照。当你想清理空间时:
rbd flatten mypool/vm-1
执行后 vm-1 就把所有父数据复制一份到自己身上,彻底脱离父子关系。之后父快照可以删除。
九、验证内核模块
挂载 RBD 后,内核自动加载 libceph.ko 模块,可用以下命令验证:
lsmod | grep ceph
K8s 为什么需要 Ceph?
[四、理解 K8s 节点上的操作](#四、理解 K8s 节点上的操作)
[方式二:通过 Secret 挂载(推荐)](#方式二:通过 Secret 挂载(推荐))
[base64 编码是干什么的?](#base64 编码是干什么的?)
[七、理解 MySQL 案例](#七、理解 MySQL 案例)
[八、理解 CephFS 案例](#八、理解 CephFS 案例)
K8s 本身的问题
K8s 是用来管理容器的。容器一重启,里面的数据就没了(容器是无状态的)。但很多应用需要持久化存储,比如:
-
MySQL 数据库的文件不能丢
-
Nginx 的网页文件需要多个容器共享
解决方案
K8s 本身不提供存储,它需要外挂存储。Ceph 就是一个完美的外挂存储:
-
提供 RBD(块存储)→ 像一块硬盘,只能被一个 Pod 独享
-
提供 CephFS(文件存储)→ 像 NFS,可以被多个 Pod 同时共享
二、理解第一个操作:创建存储池和镜像
ceph osd pool create laowang-rbd-pool1 32 32
ceph osd pool application enable laowang-rbd-pool1 rbd
rbd pool init -p laowang-rbd-pool1
rbd create laowang-img-img1 --size 3G --pool laowang-rbd-pool1 --image-format 2 --image-feature layering
在 Ceph 集群里准备一块 3GB 的虚拟硬盘,后面给 K8s Pod 用。
每步拆解:
-
创建存储池
laowang-rbd-pool1:在 Ceph 里划出一个"区域" -
启用 RBD:声明这个区域是用来存放块设备的
-
初始化:让这个池准备好接受 RBD 镜像
-
创建镜像
laowang-img-img1:真正创建了一块 3GB 的虚拟硬盘
三、理解第二个操作:创建用户和权限
ceph auth get-or-create client.laowang mon 'allow r' osd 'allow * pool=laowang-rbd-pool1'
创建一个专门给 K8s 用的 Ceph 账号,只允许访问这一个存储池,不能碰其他池。
为什么不用 admin?
admin 是超级管理员,能删所有数据。如果 K8s 里有人搞破坏或配置错误,用 admin 账号可能会把整个 Ceph 集群的数据都毁了。所以创建受限账号最安全。
权限解释:
-
mon 'allow r':只能查看集群状态 客户端地图 -
osd 'allow * pool=laowang-rbd-pool1':只能对laowang-rbd-pool1这个池做任何操作,其他池碰不了
四、理解 K8s 节点上的操作
为什么 K8s 节点要装 ceph-common?
K8s 节点本身不认识 Ceph。安装 ceph-common 后,节点才能:
-
识别
rbd命令 -
能执行
rbd map把 Ceph 镜像映射成本地/dev/rbd0设备 -
然后才能把这个设备挂进容器
为什么要同步认证文件?
ceph.conf 和 .keyring 文件就像身份证。K8s 节点拿着它们才能向 Ceph 集群证明"我是合法用户"。
为什么要配主机名解析?
Ceph 集群内部用主机名通信(比如 ceph-mon1)。K8s 节点如果不认识这些名字,就找不到 Ceph 的 MON 节点,也就连不上集群。
五、理解两种挂载方式
方式一:keyring 文件直接挂载
volumes:
- name: rbd-data1 # 给这个卷起个名字,后面挂载时引用用
rbd: # 指定卷类型为 Ceph RBD(块存储)
monitors: ['172.31.6.104:6789', ...] # MON 节点地址,客户端先连这里获取集群地图
pool: laowang-rbd-pool1 # 存储池名称,虚拟磁盘在这个池里
image: laowang-img-img1 # RBD 映像名称,就是之前 rbd create 的那个
user: client.laowang # Ceph 用户名(对应之前 ceph auth get-or-create 创建的)
keyring: /etc/ceph/ceph.client.laowang.keyring # 密钥文件在宿主机上的路径
大白话 :Pod 的 YAML 里直接写死了宿主机上的 keyring 文件路径。K8s 创建这个 Pod 时,去宿主机上找这个文件,用来认证,然后把 laowang-img-img1 这块虚拟硬盘挂进容器。
缺点:每台 K8s 节点上都必须放这个 keyring 文件。万一某台节点忘了放,Pod 调度到那台节点上就启动失败。
方式二:通过 Secret 挂载(推荐)
# 第一步:把 key 做成 K8s Secret
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret-laowang
type: "kubernetes.io/rbd"
data:
key: QVFCNEw3OWcvaGU3SEJBQXZKUTdzSTN6ZFNzVFVMMjFOeDZ6TFE9PQ==
---
# 第二步:Pod 引用 Secret
volumes:
- name: rbd-data1
rbd:
user: client.laowang
secretRef:
name: ceph-secret-laowang-laowang # 引用了上面创建的 Secret
大白话 :把 Ceph 用户的 key(经过 base64 编码)存成 K8s 的 Secret 对象。Pod 通过 secretRef 引用这个 Secret,K8s 自动把 key 注入到 Pod 的挂载操作中。
优点:
-
不需要在每个节点放 keyring 文件
-
key 只存在 K8s 里,更安全
-
Secret 可以统一管理、更新、轮转
base64 编码是干什么的?
K8s Secret 要求值是 base64 编码的字符串,不是加密,只是把二进制数据转成纯文本。你可以轻松解码:
ceph auth print-key client.laowang
QVFCNEw3OWcvaGU3SEJBQXZKUTdzSTN6ZFNzVFVMMjFOeDZ6TFE9PQ==
echo "QVFCNEw3OWcvaGU3SEJBQXZKUTdzSTN6ZFNzVFVMMjFOeDZ6TFE9PQ==" | base64 -d
# 输出:AQB4L79g/he7HBAAvJQ7sI3zdSsTUL21Nx6zLQ==(就是原始 key)
六、理解"动态存储卷供给"
静态供给 vs 动态供给
| 静态供给 | 动态供给 | |
|---|---|---|
| 操作方式 | 管理员先在 Ceph 手动创建镜像,然后在 YAML 里写死镜像名 | 用户创建 PVC 声明需要多大空间,K8s 自动去 Ceph 创建镜像 |
| 灵活性 | 差,每新增一个应用都要手工先建镜像 | 好,按需自动创建 |
| 适用场景 | 固定数量应用 | 有状态服务(数据库)大量部署 |
动态供给是怎么工作的?
1. 需要一个 admin Secret
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret-admin
type: "kubernetes.io/rbd"
data:
key: <admin-key-base64>
K8s 需要有创建 RBD 镜像的权限,所以要用 client.admin 的 key(因为 admin 可以创建和删除镜像)。
2. 创建 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-storage-class-laowang # 模板名称,PVC 引用用这个
provisioner: kubernetes.io/rbd # 使用 K8s 内置的 RBD 驱动
parameters:
adminId: admin # 用 admin 创建/删除镜像
adminSecretName: ceph-secret-admin # admin 的密钥存在哪个 Secret
pool: laowang-rbd-pool1 # 在哪个 Ceph 池里创建镜像
userId: laowang-laowang # Pod 用这个用户读写
userSecretName: ceph-secret-laowang-laowang # 普通用户的密钥
| 字段 | 含义 | 值如何得来 |
|---|---|---|
provisioner: kubernetes.io/rbd |
告诉 K8s 用内置 RBD 驱动动态分配存储 | 固定写法 |
adminId: admin |
有权限在 Ceph 池里创建镜像的用户 | client.admin |
adminSecretName |
admin 用户的密钥存在哪个 K8s Secret 里 | 上一步创建的 ceph-secret-admin |
pool |
在哪个 Ceph 存储池里创建镜像 | 之前 ceph osd pool create laowang-rbd-pool1 创建的那个池 |
userId: laowang-laowang |
Pod 实际读写数据时用的 Ceph 用户 | 之前 ceph auth get-or-create client.laowang 创建的用户 |
userSecretName |
普通用户的密钥存在哪个 Secret | 上一步创建的 ceph-secret-laowang-laowang |
StorageClass 就像一个模板,定义了"用什么方式创建存储卷"。
3. 用户创建 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data-pvc # PVC 名称,Pod 引用用这个
spec:
accessModes:
- ReadWriteOnce # 只能一个 Pod 读写(块存储限制)
storageClassName: ceph-storage-class-laowang # 引用上面的 StorageClass
resources:
requests:
storage: '5Gi' # 我要 5GB
| 字段 | 含义 |
|---|---|
kind: PersistentVolumeClaim |
资源类型:PVC,表示"我要申请存储" |
accessModes: ReadWriteOnce |
只能被单个节点上的单个 Pod 以读写方式挂载(RBD 块存储的限制) |
storageClassName |
引用 StorageClass,告诉 K8s"用这个模板给我创建磁盘" |
storage: '5Gi' |
申请的磁盘大小,K8s 会自动在 Ceph 里创建一个 5GB 的 RBD 镜像 |
4. 背后发生了什么
-
用户创建 PVC,声明要 5GB
-
K8s 发现 PVC 指向了
ceph-storage-class-laowang这个 StorageClass -
K8s 用 admin Secret 去连接 Ceph,自动执行
rbd create ... --size 5G -
新创建的 RBD 镜像自动绑定到这个 PVC
-
用户在自己的 Pod 里引用这个 PVC,就能用到一块 5GB 的新硬盘
验证:在 Ceph 端能看到自动创建的镜像:
rbd ls --pool laowang-rbd-pool1
# 会多出一个以 "kubernetes-dynamic-pvc-" 开头的镜像名
七、理解 MySQL 案例
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-data-pvc # 引用刚才创建的 PVC
MySQL 的 /var/lib/mysql 目录(存数据库文件的)挂载到了这个 PVC 上。
效果:
-
MySQL Pod 写的数据存在 Ceph RBD 镜像里
-
即使 MySQL Pod 挂了、被删了、被调度到别的节点,数据不会丢
-
新 Pod 启动时挂载同一个 PVC,数据还在
八、理解 CephFS 案例
volumes:
- name: laowang-staticdata-cephfs
cephfs:
monitors: [...] # MON 节点地址
path: / # CephFS 的挂载路径
user: admin # 认证用户
secretRef:
name: ceph-secret-admin # 密钥
和 RBD 的区别
| RBD | CephFS | |
|---|---|---|
| 使用方式 | 像一块硬盘,只能被一个 Pod 挂载(读写模式) | 像一个共享文件夹,可以同时被多个 Pod 挂载 |
| 典型场景 | MySQL 数据库 | Nginx 静态文件、共享配置 |
| 多 Pod 共享 | 不支持(除非只读) | 支持 |
案例中的效果
3 个 Nginx Pod 都挂载同一个 CephFS 目录 /data/nginx/statics。任何一个 Pod 往这个目录写文件,其他两个 Pod 立刻能看到。这就实现了多副本共享数据。
九、整个流程总结
┌─────────────────────────────────────────────────────┐
│ Ceph 集群 │
│ ┌───────────┐ ┌───────────┐ ┌───────────────────┐ │
│ │ 存储池 │ │ 用户/权限 │ │ 镜像(虚拟硬盘) │ │
│ │ rbd-pool1 │ │ laowang │ │ laowang-img-img1 │ │
│ └───────────┘ └───────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────┘
↑
│ 网络(6789端口)
↓
┌─────────────────────────────────────────────────────┐
│ K8s 集群 │
│ ┌──────────────┐ ┌──────────┐ ┌────────────────┐ │
│ │ Secret │ │ PVC/PV │ │ Pod (MySQL) │ │
│ │ (存ceph key) │ │ (5GB) │ │ /var/lib/mysql │ │
│ └──────────────┘ └──────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────┘
1