文章目录
- 一、Ceph理论知识
- 1、Ceph简介
- 2、Ceph分布式存储的优点
- 3、Ceph核心组件
- 二、部署Ceph高可用集群
- 1、服务器环境信息
- 2、部署前环境准备工作
- 3、部署Ceph监控服务Monitor
- 4、激活Ceph存储服务OSD
- 三、K8S对接Ceph存储
- 1、K8S对接Ceph RBD实现数据持久化
- 2、基于Ceph RBD生成PV
- 3、基于Storageclass动态生成PV
- 4、K8S对接CephFS实现数据持久化
- 四、所遇问题记录
- 1、激活OSD失败
一、Ceph理论知识
1、Ceph简介
Ceph 是一个开源的分布式存储系统,用于提供高性能、高可靠性的对象存储、块存储和文件系统,它通过去中心化的架构,自动处理数据复制和恢复,旨在提供弹性扩展和容错能力。Ceph官方网址:
Ceph包含一下几种存储类型:
(1)块存储(RBD):
-
用途: 提供了高性能的块级存储,类似于传统的磁盘驱动器。通常用于虚拟机的存储或数据库的存储。
-
接口: 通过 Ceph 的 RADOS(Reliable Autonomic Distributed Object Store)接口提供块设备。
-
架构: 在 Ceph 集群中,每个块设备映射到一个 RADOS 对象,支持动态分配和快照功能。
-
扩展性: 可以根据需求动态增加或减少存储容量。
-
缺点:块设备具有优异的读写性能,但不能多处挂载同时读写,目前主要用在OpenStack上作为虚拟磁盘。
-
总结:块设备可理解成一块硬盘,用户直接使用不含文件系统的块设备,也可以将其格式化成特定的文件系统,由文件系统来组织管理存储空间,从而为用户提供丰富而友好的数据操作支持。
(2)文件系统(CephFS):
- 用途: 提供一个完整的分布式文件系统,用于支持标准的文件操作和目录结构,适用于需要 POSIX 兼容的应用程序。
- 接口: 提供标准的 POSIX 文件系统接口,允许通过传统的文件系统工具和应用程序访问存储的数据。
- 架构: CephFS 构建在 Ceph 的对象存储之上,通过元数据服务器(MDS)来管理文件和目录的元数据。
- 扩展性: 支持横向扩展,能够处理大量的文件和目录操作。
- 缺点:文件系统接口读写性能较块设备接口差,但具有优异的共享性。
(3)对象存储(Object Gateway):
-
用途: 主要用于存储大量的非结构化数据,如照片、视频、备份和日志文件。
-
接口: 提供了兼容 Amazon S3 和 OpenStack Swift 的 RESTful API,方便与现有的云服务和应用程序集成。
-
架构: 数据以对象的形式存储,每个对象由数据、元数据和唯一标识符(Object ID)组成。
-
扩展性: 对象存储可以通过增加更多的存储节点来横向扩展,适合大规模数据存储需求。
问题:有了块设备接口存储和文件系统接口存储,为什么还整个对象存储呢?
答:Ceph的块设备存储具有优异的存储性能但不具有共享性,而Ceph的文件系统具有共享性然而性能较块设备存储差,为什么不权衡一下存储性能和共享性,整个具有共享性而存储性能好于文件系统存储的存储呢,对象存储就这样出现了。
2、Ceph分布式存储的优点
- 弹性扩展: 可以无缝添加更多的存储节点,以支持增长的存储需求,而不会影响系统的性能。
- 高可用性: 数据自动复制到多个节点,确保在硬件故障时数据不会丢失。
- 高性能:读写速度快。
- 去中心化: 没有单点故障,提升了系统的可靠性和容错能力。
- 灵活性: 支持对象存储、块存储和文件系统等多种存储类型,满足不同的需求。
3、Ceph核心组件
- Monitors:监视器,负责维护集群状态的映射,包括监视器映射,管理器映射,OSD映射和CRUSH映射。这些映射是Ceph守护进程相互协调所需的关键集群状态。监视器还负责管理守护进程和客户端之间的身份验证。冗余和高可用性通常至少需要三个监视器。
- Managers:负责跟踪运行时指标和Ceph集群的当前状态,包括存储利用率,当前性能指标和系统负载。 Ceph Manager守护进程还托管基于python的模块来管理和公开Ceph集群信息,包括基于Web的Ceph Dashboard和REST API。高可用性通常至少需要两名Managers。
- Ceph OSD:负责存储数据,处理数据复制,恢复,重新平衡,并通过检查其他Ceph OSD守护进程来获取心跳,为Ceph监视器和管理器提供一些监视信息。冗余和高可用性通常至少需要3个Ceph OSD。
- MDS:元数据服务器,代表Ceph文件系统存储元数据(即,Ceph块设备和Ceph对象存储不使用MDS)。 Ceph元数据服务器允许POSIX文件系统用户执行基本命令(如ls,find等),而不会给Ceph存储集群带来巨大负担。
二、部署Ceph高可用集群
1、服务器环境信息
注意:由于我本次仅仅只是实验所以我把Ceph集群与K8S集群部署到了一起,如果生产环境需要多申请三台服务器,单独部署Ceph集群!
序号 | IP地址 | 主机名 | 磁盘 | 安装服务 | 别名 |
---|---|---|---|---|---|
1 | 16.32.15.200 | master-1 | sdb-20G | K8S-Master、ceph、ceph-deploy | K8S管理节点、Ceph管理节点 |
2 | 16.32.15.201 | node-1 | sdb-20G | K8S-Node-1、ceph | |
3 | 16.32.15.202 | node-2 | sdb-20G | K8S-Node-2、ceph |
2、部署前环境准备工作
PS:所有主机中执行
1、配置阿里云Ceph安装源
cat >> /etc/yum.repos.d/ceph.repo << EOF
[Ceph]
name=Ceph packages for \$basearch
baseurl=http://mirrors.aliyun.com/ceph/rpm-jewel/el7/x86_64/
enabled=1
gpgcheck=0
type=rpm-md
gpgkey=https://mirrors.aliyun.com/ceph/keys/release.asc
priority=1
[Ceph-noarch]
name=Ceph noarch packages
baseurl=http://mirrors.aliyun.com/ceph/rpm-jewel/el7/noarch/
enabled=1
gpgcheck=0
type=rpm-md
gpgkey=https://mirrors.aliyun.com/ceph/keys/release.asc
priority=1
[ceph-source]
name=Ceph source packages
baseurl=http://mirrors.aliyun.com/ceph/rpm-jewel/el7/SRPMS/
enabled=1
gpgcheck=0
type=rpm-md
gpgkey=https://mirrors.aliyun.com/ceph/keys/release.asc
priority=1
EOF
2、安装基础包,平时排查问题需要用到
yum install -y yum-utils device-mapper-persistent-data lvm2 wget net-tools nfs-utils lrzsz gcc gcc-c++ make cmake libxml2-devel openssl-devel curl curl-devel unzip sudo ntp libaio-devel wget vim ncurses-devel autoconf automake zlib-devel python-devel epel-release openssh-server socat ipvsadm conntrack ntpdate telnet deltarpm
3、添加hosts本地解析
vim /etc/hosts
16.32.15.200 master-1
16.32.15.201 node-1
16.32.15.202 node-2
4、修改主机名(对应主机执行)
hostnamectl set-hostname master-1 && bash
hostnamectl set-hostname node-1 && bash
hostnamectl set-hostname node-2 && bash
5、配置内网免密登入
ssh-keygen
ssh-copy-id master-1
ssh-copy-id node-1
ssh-copy-id node-2
6、配置NTP时间同步
yum -y install ntpdate
ntpdate ntp1.aliyun.com
添加定时任务,每天凌晨1点自动同步时间
echo "0 1 * * * ntpdate ntp1.aliyun.com" >> /var/spool/cron/root
3、部署Ceph监控服务Monitor
1、安装ceph-deploy(Ceph管理节点执行)
yum install python-setuptools ceph-deploy -y
2、安装ceph(所有主机执行)
yum install ceph ceph-radosgw -y
3、查看ceph版本
ceph --version
4、创建Monitor(Ceph管理节点执行)
创建一个目录,用于保存 ceph-deploy 生成的配置文件信息的
cd /etc/ceph
ceph-deploy new master-1 node-1 node-2
查看当前生成的文件:
ls -1 /etc/ceph
ceph.conf # Ceph配置文件
ceph-deploy-ceph.log # 日志文件
ceph.mon.keyring # Monitor密钥
5、修改ceph配置文件(Ceph管理节点执行)
vim /etc/ceph/ceph.conf
[global]
fsid = 8797ef39-fcb3-4e82-bf49-a068cfc72eae
mon_initial_members = master-1, node-1, node-2
mon_host = 16.32.15.200,16.32.15.201,16.32.15.202
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
# 新增配置如下:
osd_pool_default_size = 2 # 2个osd也能达到active+clean状态
mon clock drift allowed = 0.500 # 监视器间允许的时钟漂移量默认值0.05
mon clock drift warn backoff = 10 # 时钟偏移警告的退避指数。默认值5
注意:Ceph对每个mon之间的时间同步延时默认要求在0.05s之间,这个时间有的时候太短了。所以如果ceph集群如果出现clock问题就检查ntp时间同步或者适当放宽这个误差时间。
6、配置初始Monitor、收集所有的密钥(Ceph管理节点执行)
cd /etc/ceph
ceph-deploy mon create-initial
等待收集完成后,查看收集到的key
ls -1 /etc/ceph/*.keyring
4、激活Ceph存储服务OSD
注意:以下操作均在,Ceph管理节点执行!!
1、准备OSD
cd /etc/ceph/
ceph-deploy osd prepare master-1:/dev/sdb
ceph-deploy osd prepare node-1:/dev/sdb
ceph-deploy osd prepare node-2:/dev/sdb
2、激活OSD
ceph-deploy osd activate master-1:/dev/sdb1
ceph-deploy osd activate node-1:/dev/sdb1
ceph-deploy osd activate node-2:/dev/sdb1
3、查看OSD状态
ceph-deploy osd list master-1 node-1 node-2
三、K8S对接Ceph存储
注意1:在K8S集群中如果使用Ceph存储,需要再K8S各个节点中安装ceph-common
工具,安装命令如下:
yum install ceph-common -y
注意2:如果K8S集群和Ceph集群不在相同服务器中,需要把Ceph集群中的 /etc/ceph
目录拷贝到K8S各个节点下!!
1、K8S对接Ceph RBD实现数据持久化
PS:以下操作均在,Ceph管理节、K8S管理节点中执行!!
1、创建RBD
ceph osd pool create k8srbd 16
rbd create rbda -s 1024 -p k8srbd
rbd feature disable k8srbd/rbda object-map fast-diff deep-flatten # 禁用无用特性
2、查看RBD状态信息
ceph osd pool ls # 列出所有pool
ceph osd pool stats k8srbd # 查看状态
3、创建Pod,使用RBD挂载
apiVersion: v1
kind: Pod
metadata:
name: test-rbd
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: testrbd
mountPath: /opt
volumes:
- name: testrbd
rbd:
monitors: # 监视器IP:Port
- '16.32.15.200:6789'
- '16.32.15.201:6789'
- '16.32.15.202:6789'
pool: k8srbd # pool名称
image: rbda # image名称
fsType: xfs
readOnly: false
user: admin
keyring: /etc/ceph/ceph.client.admin.keyring
3、执行apply并查看Pod状态
kubectl apply -f pod.yaml
kubectl get pods
注意:RBD类型只能挂载一个,如果再创建一个Pod,使用相同的RBD,则会创建失败!
2、基于Ceph RBD生成PV
PS:以下操作均在,Ceph管理节、K8S管理节点中执行!!
1、创建Ceph secret对象
Secret对象用于K8S Volume插件访问Ceph集群,获取client.admin
的keyring值,(ceph管理节点):
ceph auth get-key client.admin | base64
QVFDVHljbG1hU3JnSnhBQSt0eUpmcVRjNEs2SHdrZUcxdjJVblE9PQ==
2、创建Ceph的Secret资源(K8S Master节点操作):
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret
data:
key: QVFBWk0zeGdZdDlhQXhBQVZsS0poYzlQUlBianBGSWJVbDNBenc9PQ==
kubectl apply -f ceph-secret.yaml
3、创建pool池
ceph osd pool create k8srbd1 16
rbd create rbda -s 1024 -p k8srbd1
rbd feature disable k8srbd1/rbda object-map fast-diff deep-flatten
4、创建PV、PVC
apiVersion: v1
kind: PersistentVolume
metadata:
name: ceph-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadOnlyMany
rbd:
monitors:
- '16.32.15.200:6789'
- '16.32.15.201:6789'
- '16.32.15.202:6789'
pool: k8srbd1
image: rbda
user: admin
secretRef:
name: ceph-secret
fsType: xfs
readOnly: false
persistentVolumeReclaimPolicy: Recycle
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: ceph-pvc
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi
kubectl apply -f ceph-pv-pvc.yaml
查看PVC是否绑定PV:
kubectl get pvc ceph-pvc
5、创建Deployment资源,使用PVC
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/ceph-data"
name: ceph-data
volumes:
- name: ceph-data
persistentVolumeClaim:
claimName: ceph-pvc
kubectl apply -f deployment.yaml
注意:Ceph RBD块存储能在同一个Node上跨pod以使用ReadWriteOnce共享挂载,但不支持跨Node使用。
问题:结合Ceph RBD共享挂载的特性,发现一个问题:
由于Deployment触发更新,为了保证服务的可用性,Deployment要先创建一个Pod并运行正常之后,再去删除老Pod。而如果新创建的Pod和老Pod不在一个node,就会导致此故障。
解决办法:
- 使用能支持跨node和pod之间挂载的共享存储,例如CephFS,GlusterFS等。
- 给Node添加Label,只允许Deployment所管理的Pod调度到一个固定的Node上。(不建议,Node节点宕机,服务也就宕机了)
3、基于Storageclass动态生成PV
注意:K8S1.20版本之后如果需要使用自动生成PV,需要修改kube-apiserver配置,进行兼容:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 添加这一行:
- --feature-gates=RemoveSelfLink=false
重启kubelet生效
systemctl restart kubelet
注意:我这边两套集群v1.26.2
版本修改此配置后,导致集群起不来,而v1.23.0
版本修改后可以正常启动,建议现在测试环境添加此配置,如果没有问题,在添加生产环境!!
1、执行赋权操作(所有K8S集群、Ceph集群中执行)
chmod 777 -R /etc/ceph/*
mkdir /root/.ceph/
cp -ar /etc/ceph/ /root/.ceph/
cp -ar /etc/ceph/* /root/.ceph/
2、创建RBD的供应商Provisioner
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rbd-provisioner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
- apiGroups: [""]
resources: ["services"]
resourceNames: ["kube-dns","coredns"]
verbs: ["list", "get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: rbd-provisioner
subjects:
- kind: ServiceAccount
name: rbd-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: rbd-provisioner
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: rbd-provisioner
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rbd-provisioner
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: rbd-provisioner
subjects:
- kind: ServiceAccount
name: rbd-provisioner
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rbd-provisioner
spec:
selector:
matchLabels:
app: rbd-provisioner
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: rbd-provisioner
spec:
containers:
- name: rbd-provisioner
image: quay.io/xianchao/external_storage/rbd-provisioner:v1
imagePullPolicy: IfNotPresent
env:
- name: PROVISIONER_NAME
value: ceph.com/rbd
serviceAccount: rbd-provisioner
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: rbd-provisioner
kubectl apply -f rbd-provisioner.yaml
3、创建Ceph Secret
ceph osd pool create k8srbd2 16
ceph auth get-key client.admin | base64
apiVersion: v1
kind: Secret
metadata:
name: ceph-secret-1
type: "ceph.com/rbd"
data:
key: QVFDVHljbG1hU3JnSnhBQSt0eUpmcVRjNEs2SHdrZUcxdjJVblE9PQ==
kubectl apply -f ceph-secret-1.yaml
4、创建Storageclass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: k8s-rbd
provisioner: ceph.com/rbd # 与provisioner对应
parameters:
monitors: 16.32.15.200:6789,16.32.15.201:6789,16.32.15.202:6789
adminId: admin
adminSecretName: ceph-secret-1
pool: k8srbd2
userId: admin
userSecretName: ceph-secret-1
fsType: xfs
imageFormat: "2"
imageFeatures: "layering"
kubectl apply -f storageclass.yaml
4、创建PVC,自动生成PV
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi
storageClassName: k8s-rbd
kubectl apply -f rbd-pvc.yaml
kubectl get pvc
5、创建Pod,挂载PVC
apiVersion: v1
kind: Pod
metadata:
labels:
test: rbd-pod
name: ceph-rbd-pod
spec:
containers:
- name: ceph-rbd-nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: ceph-rbd
mountPath: /mnt
readOnly: false
volumes:
- name: ceph-rbd
persistentVolumeClaim:
claimName: rbd-pvc
kubectl apply -f pod-sto.yaml
4、K8S对接CephFS实现数据持久化
PS:以下操作均在,Ceph管理节、K8S管理节点中执行!!
1、创建MDS
ceph-deploy mds create master-1 node-1 node-2
2、创建存储池
一个CephFS至少要求两个librados存储池,一个为data,一个为metadata。当配置这两个存储池时,需要注意以下两点:
- 为metadata pool设置较高级别的副本级别,因为metadata的损坏可能导致整个文件系统不用。
- 建议metadata pool使用低延时存储,比如SSD,因为metadata会直接影响客户端的响应速度。
ceph osd pool create cephfs_data 128
ceph osd pool create cephfs_metadata 128
pg_num 取值是强制性的,因为不能自动计算。下面是几个常用的值:
- 少于 5 个 OSD 时可把 pg_num 设置为 128
- OSD 数量在 5 到 10 个时,可把 pg_num 设置为 512
- OSD 数量在 10 到 50 个时,可把 pg_num 设置为 4096
当OSD 数量大于 50 时,得理解权衡方法、以及如何自己计算 pg_num 取值
自己计算 pg_num 取值时可借助 pgcalc 工具
随着 OSD 数量的增加,正确的 pg_num 取值变得更加重要,因为它显著地影响着集群的行为、以及出错时的数据持久性(即灾难性事件导致数据丢失的概率)
3、创建文件系统
ceph fs new k8sfs cephfs_metadata cephfs_data
4、查看
ceph fs ls # 查看创建后的cephfs
ceph mds stat # 查看mds节点状态
ceph -s # 查看集群信息
5、创建目录,将CephFS挂载到此目录
cat /etc/ceph/ceph.client.admin.keyring |grep key|awk -F" " '{print $3}' > /etc/ceph/admin.secret
mkdir /data/ceph_data -p
mount -t ceph 16.32.15.201:6789:/ /data/ceph_data -o name=admin,secretfile=/etc/ceph/admin.secret
df -hT /data/ceph_data
6、在CephFS挂载目录中,创建子目录,作为存储挂载
mkdir -p /data/ceph_data/qinzt
chmod 0777 /data/ceph_data/qinzt
7、创建Secret,用于K8S连接Ceph
将/etc/ceph/ceph.client.admin.keyring里面的key的值转换为base64,否则会有问题
cat /etc/ceph/ceph.client.admin.keyring|awk NR==2'{print $NF}'|base64
QVFCbExNcG11Q215TEJBQVdWTzlEY2h1T2Zham5GQWxmV1dESFE9PQo=
apiVersion: v1
kind: Secret
metadata:
name: cephfs-secret
data:
key: QVFCbExNcG11Q215TEJBQVdWTzlEY2h1T2Zham5GQWxmV1dESFE9PQo=
kubectl apply -f cephfs-secret.yaml
8、创建PV、PVC
apiVersion: v1
kind: PersistentVolume
metadata:
name: cephfs-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
cephfs:
monitors:
- '16.32.15.200:6789'
- '16.32.15.201:6789'
- '16.32.15.202:6789'
path: /qinzt # 挂载目录(Ceph根下的qinzt目录 > /data/ceph_data/qinzt)
user: admin
readOnly: false
secretRef:
name: cephfs-secret
persistentVolumeReclaimPolicy: Recycle
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: cephfs-pvc
spec:
accessModes:
- ReadWriteMany
volumeName: cephfs-pv
resources:
requests:
storage: 1Gi
kubectl apply -f cephfs-pv-pvc.yaml
kubectl get pvc cephfs-pvc
9、创建Pods,挂载CephFS
apiVersion: apps/v1
kind: Deployment
metadata:
name: cephfs-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
env: dev
template:
metadata:
labels:
app: nginx
env: dev
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: cephfs
mountPath: /mnt
volumes:
- name: cephfs
persistentVolumeClaim:
claimName: cephfs-pvc
kubectl apply -f cephfs-deployment.yaml
10、验证,Pod中创建文件,本地查看是否存在
# 进入Pod1创建5个文件
kubectl exec -it cephfs-deployment-6f66847599-2hd9s -- /bin/bash
touch pod1{1..5}.txt /mnt/
# 进入Pod2查看创建的文件
kubectl exec -it cephfs-deployment-6f66847599-cggzm -- /bin/bash
ls /mnt/*
# 查看本地目录
ls /data/ceph_data/qinzt/
pod11.txt pod12.txt pod13.txt pod14.txt pod15.txt
通过验证,可以确认容器内挂载目录是共享的,并且Pod写入的数据已经存储到了CephFS中了
四、所遇问题记录
1、激活OSD失败
报错信息:ERROR: error creating empty object store in /var/lib/ceph/tmp/mnt.QdHa3y: (13) Permission denied
解决方案:
chown ceph:ceph /dev/sdb*