生产环境注意

生产环境中如果要用ceph,一定要非常专业精通、可以troubleshooting才能去用;而且建议二进制安装在服务器上,不要装在k8s中。否则出问题之后因为ceph是分块存储,数据非常难以还原,有极大的丢失风险。

ceph简介

类型

  • ceph是一种开源的分布式的存储系统,包含以下几种存储类型:

  • 块存储(rbd)

    • 块设备可理解成一块硬盘,用户可以直接使用不含文件系统的块设备,也可以将其格式化成特定的文件系统,由文件系统来组织管理存储空间,从而为用户提供丰富而友好的数据操作支持。
    • linux系统中,ls /dev/下有很多块设备文件,这些文件就是我们添加硬盘时识别出来的;
    • rbd就是由Ceph集群提供出来的块设备。可以这样理解,sda是通过数据线连接到了真实的硬盘,而rbd是通过网络连接到了Ceph集群中的一块存储区域,往rbd设备文件写入数据,最终会被存储到Ceph集群的这块区域中;
  • 文件系统(cephfs)

    • 用户可以在块设备上创建xfs、ext4等文件系统,Ceph集群实现了自己的文件系统来组织管理集群的存储空间,用户可以直接将Ceph集群的文件系统挂载到用户机上使用。
    • Ceph有了块设备接口,在块设备上完全可以构建一个文件系统,那么Ceph为什么还需要文件系统接口呢?
    • 主要是因为应用场景的不同,Ceph的块设备具有优异的读写性能,但不能多处挂载同时读写(ReadWriteOnce),目前主要用在OpenStack上作为虚拟磁盘,而Ceph的文件系统接口读写性能较块设备接口差,但具有优异的共享性(ReadWriteMany)。
  • 对象存储(RADOS Fateway)

    • Ceph对象存储使用Ceph对象网关守护进程(radosgw),它是一个用于与Ceph存储集群交互的HTTP服务器。由于它提供与OpenStack Swift和Amazon S3兼容的接口,因此Ceph对象网关具有自己的用户管理。 Ceph对象网关可以将数据存储在用于存储来自Ceph文件系统客户端或Ceph块设备客户端的数据的相同Ceph存储集群中。
    • 使用方式就是通过http协议上传下载删除对象(文件即对象)。
    • 有了块设备接口存储和文件系统接口存储,为什么还整个对象存储呢
    • Ceph的块设备存储具有优异的存储性能但不具有共享性,而Ceph的文件系统具有共享性然而性能较块设备存储差,为什么不权衡一下存储性能和共享性,整个具有共享性而存储性能好于文件系统存储的存储呢,对象存储就这样出现了。

分布式存储的优点:

  • 高可靠:既满足存储读取不丢失,还要保证数据长期存储。在保证部分硬件损坏后依然可以保证数据安全。
  • 高性能:读写速度快。
  • 可扩展:分布式存储的优势就是“分布式”,所谓的“分布式”就是能够将多个物理节点整合在一起形成共享的存储池,节点可以线性扩充,这样可以源源不断的通过扩充节点提升性能和扩大容量,这是传统存储阵列无法做到的。

核心组件

在ceph集群中,不管你是想要提供对象存储,块设备存储,还是文件系统存储,所有Ceph存储集群部署都是从设置每个Ceph节点,网络和Ceph存储开始的。 Ceph存储集群至少需要一个Ceph Monitor,Ceph Manager和Ceph OSD(对象存储守护进程)。运行Ceph Filesystem客户端时也需要Ceph元数据服务器。

  • Monitors:
  • Ceph监视器(ceph-mon)维护集群状态的映射,包括监视器映射,管理器映射,OSD映射和CRUSH映射。这些映射是Ceph守护进程相互协调所需的关键集群状态。监视器还负责管理守护进程和客户端之间的身份验证。冗余和高可用性通常至少需要三个监视器。
  • Managers:
  • Ceph Manager守护程序(ceph-mgr)负责跟踪运行时指标和Ceph集群的当前状态,包括存储利用率,当前性能指标和系统负载。 Ceph Manager守护进程还托管基于python的模块来管理和公开Ceph集群信息,包括基于Web的Ceph Dashboard和REST API。高可用性通常至少需要两名Managers。
  • Ceph OSD:
  • Ceph OSD(对象存储守护进程,ceph-osd)存储数据,处理数据复制,恢复,重新平衡,并通过检查其他Ceph OSD守护进程来获取心跳,为Ceph监视器和管理器提供一些监视信息。冗余和高可用性通常至少需要3个Ceph OSD。
  • MDS:
  • Ceph元数据服务器(MDS,ceph-mds)代表Ceph文件系统存储元数据(即,Ceph块设备和Ceph对象存储不使用MDS)。 Ceph元数据服务器允许POSIX文件系统用户执行基本命令(如ls,find等),而不会给Ceph存储集群带来巨大负担。

搭建ceph集群准备工作

配置3台主机静态IP

  • master1-admin是管理节点 :192.168.40.7
  • node1-monitor是监控节点:192.168.40.8
  • node2-osd是对象存储节点:192.168.40.9
#修改/etc/sysconfig/network-scripts/ifcfg-ens33文件,变成如下:
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
IPADDR=192.168.40.200
NETMASK=255.255.255.0
GATEWAY=192.168.40.2
DNS1=192.168.40.2
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
DEVICE=ens33
ONBOOT=yes

#修改配置文件之后需要重启网络服务才能使配置生效,重启网络服务命令如下:
service network restart

配置主机名

hostnamectl set-hostname master1-admin && bash
hostnamectl set-hostname node1-monitor && bash
hostnamectl set-hostname node2-osd && bash

配置hosts文件

#3台机器上/etc/hosts中增加:
192.168.40.7   master1-admin  
192.168.40.8   node1-monitor  
192.168.40.9   node2-osd  

配置互相ssh登录

#设置root密码
passwd root
Aa111111111
#以master1-admin为例
ssh-keygen -t rsa
ssh-copy-id master1-admin
ssh-copy-id node1-monitor
ssh-copy-id node2-osd 

关闭防火墙

#3台都执行
systemctl stop firewalld && systemctl disable firewalld

关闭selinux

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

配置ceph源

#3台都执行
yum install -y yum-utils 
yum-config-manager --add-repo https://dl.fedoraproject.org/pub/epel/7/x86_64/ 
yum install --nogpgcheck -y epel-release
rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 
rm /etc/yum.repos.d/dl.fedoraproject.org*
vim /etc/yum.repos.d/ceph.repo

[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

配置时间同步

service ntpd stop
ntpdate cn.pool.ntp.org

crontab -e
* */1 * * * /usr/sbin/ntpdate   cn.pool.ntp.org

service crond restart

安装基础软件包

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

安装ceph集群

安装ceph

#master1-admin上执行,安装ceph-deploy
yum install python-setuptools ceph-deploy -y
#3台上都执行,安装ceph
yum install ceph ceph-radosgw  -y
#确认ceph版本
ceph --version

创建monitor节点

#master1-admin上创建一个目录,用于保存 ceph-deploy 生成的配置文件信息
cd /etc/ceph
ceph-deploy new master1-admin node1-monitor node2-osd
ls
#生成了如下配置文件,Ceph配置文件、一个monitor密钥环和一个日志文件
#ceph.conf  ceph-deploy-ceph.log  ceph.mon.keyring

安装ceph-monitor

#把ceph.conf配置文件里的默认副本数从3改成1 。把osd_pool_default_size = 2 加入[global]段,这样只有2个osd也能达到active+clean状态:
vim /etc/ceph/ceph.conf
[global]
fsid = c617a513-0b8e-40a4-ba5a-741bbc9a13d8
mon_initial_members = master1-admin, node1-monitor, node2-osd
mon_host = 192.168.40.7,192.168.40.8,192.168.40.9
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
osd_pool_default_size = 2
mon clock drift allowed = 0.500 
mon clock drift warn backoff = 10

#mon clock drift allowed ,监视器间允许的时钟漂移量,默认值0.05
#这个设置定义了在发出警告之前,监视器的时间漂移必须超过 mon clock drift allowed 的多少倍。这意味着,如果 mon clock drift allowed 是0.500秒,那么只有当监视器的时间漂移超过5秒时,才会发出警告。
#初始化monitor,收集所有密钥
#master1-admin上
cd /etc/ceph
ceph-deploy mon create-initial
ls *.keyring

部署osd服务

#准备osd,在master1-admin上
cd /etc/ceph/
ceph-deploy osd prepare master1-admin:/dev/sdc
ceph-deploy osd prepare node1-monitor:/dev/sdc 
ceph-deploy osd prepare node2-osd:/dev/sdc

#激活osd,在master1-admin上
ceph-deploy osd activate master1-admin:/dev/sdc1
ceph-deploy osd activate node1-monitor:/dev/sdc1
ceph-deploy osd activate node2-osd:/dev/sdc1

#查看状态:
ceph-deploy osd list master1-admin node1-monitor node2-osd

创建ceph文件系统

  • 要使用Ceph文件系统,你的Ceph的存储集群里至少需要存在一个Ceph的元数据服务器(mds)。

创建mds

#master1-admin上
ceph-deploy mds create master1-admin node1-monitor node2-osd
#查看ceph当前文件系统
ceph fs ls   

一个cephfs至少要求两个librados存储池,一个为data,一个为metadata。当配置这两个存储池时,注意:

  1. 为metadata pool设置较高级别的副本级别,因为metadata的损坏可能导致整个文件系统不可用。
  2. 建议metadata pool使用低延时存储,比如SSD,因为metadata会直接影响客户端的响应速度。

创建osd存储池

#master1-admin上
ceph osd pool create cephfs_data 128
ceph osd pool create cephfs_metadata 128

上面的128是pg_num的值,确定 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 取值变得更加重要,因为它显著地影响着集群的行为、以及出错时的数据持久性(即灾难性事件导致数据丢失的概率)。

创建文件系统

ceph fs new hangtestfs cephfs_metadata cephfs_data
#查看创建后的cephfs
ceph fs ls
#查看mds节点状态
ceph mds stat 
#查看存储集群状态信息
ceph -s

测试k8s集群挂载ceph rbd

安装前置软件

# kubernetes要想使用ceph,需要在k8s的每个node节点安装ceph-common的驱动  。
#把ceph节点上的ceph.repo文件拷贝到k8s各个节点/etc/yum.repos.d/目录下,然后在k8s的各个节点yum install ceph-common -y
scp /etc/yum.repos.d/ceph.repo 192.168.40.4:/etc/yum.repos.d/
scp /etc/yum.repos.d/ceph.repo 192.168.40.5:/etc/yum.repos.d/
scp /etc/yum.repos.d/ceph.repo 192.168.40.6:/etc/yum.repos.d/
#每个k8s节点上安装
yum install ceph-common -y
#在ceph的master1-admin上把ceph配置文件拷贝到k8s node上
scp /etc/ceph/* 192.168.40.4:/etc/ceph/
scp /etc/ceph/* 192.168.40.5:/etc/ceph/
scp /etc/ceph/* 192.168.40.6/etc/ceph/

配置rbd

#master1-admin上
#创建ceph rbd
ceph osd pool create k8srbd1 6 #创建pool,pgnum是6
rbd create rbda -s 1024 -p k8srbd1 #创建1G大小的块设备
rbd feature disable k8srbd1/rbda object-map fast-diff deep-flatten

创建pod挂载ceph rbd

apiVersion: v1
kind: Pod
metadata:
  name: po-testrbd
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent
      volumeMounts:
      - name: testrbd
        mountPath: /mnt
  volumes:
    - name: testrbd #注意: k8srbd1下的rbda被pod挂载了,那其他pod就不能占用这个k8srbd1下的rbda了
      rbd:
        monitors:
        - '192.168.40.7:6789'
        - '192.168.40.8:6789'
        - '192.168.40.9:6789'
        pool: k8srbd1
        image: rbda
        fsType: xfs
        readOnly: false
        user: admin
        keyring: /etc/ceph/ceph.client.admin.keyring
  • 注意:rbd设备不能同时被多个pod挂载。例如,创建一个deploy,2个pod挂载同一个rbd设备
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dep-cephrbd
spec:
  replicas: 2
  selector:
    matchLabels:
      storage: ceph
  template:
    metadata:
      labels:
        storage: ceph
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: testrbd
          mountPath: /mnt/
      volumes:
      - name: testrbd #注意: k8srbd1下的rbda被pod挂载了,那其他pod就不能占用这个k8srbd1下的rbda了
        rbd:
          monitors:
          - '192.168.40.7:6789'
          - '192.168.40.8:6789'
          - '192.168.40.9:6789'
          pool: k8srbd1
          image: rbda
          fsType: xfs
          readOnly: false
          user: admin
          keyring: /etc/ceph/ceph.client.admin.keyring
  • 如果是按照前面直接挂载的方式,两个pod只有1个pod能起来,另一个会提示MountVolume.WaitForAttach failed for volume "testrbd" : rbd image k8srbd1/rbda is still being used。即使设置调度到同一pod也不行。

基于ceph rbd生成pv

创建secret

#创建ceph-secret这个k8s secret对象,这个secret对象用于k8s volume插件访问ceph集群,获取client.admin的keyring值,并用base64编码,在master1-admin(ceph管理节点)操作
ceph auth get-key client.admin | base64
#创建ceph的secret,在k8s的控制节点操作:
cat secret-ceph.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret
data:
  key: QVFCVFJwdGx4Z2VoTFJBQW9QVkpsb3NvZDl1ZFBTYXRZbThDUGc9PQ== #<上一步生成的key>

kubectl apply -f ceph-secret.yaml

创建osd pool

#创建ceph rbd
ceph osd pool create k8srbd1 6 #创建pool,pgnum是6
rbd create rbda -s 1024 -p k8srbd1 #创建1G大小的块设备
rbd feature disable k8srbd1/rbda object-map fast-diff deep-flatten

创建pv

apiVersion: v1 
kind: PersistentVolume 
metadata: 
  name: ceph-pv 
spec:   
   capacity:     
     storage: 1Gi   
   accessModes:     
   - ReadWriteOnce   
   rbd:     
         monitors:       
         - '192.168.40.7:6789'
         - '192.168.40.8:6789'
         - '192.168.40.9:6789'    
         pool: k8srbd1     
         image: rbda     
         user: admin     
         secretRef:       
           name: ceph-secret     
         fsType: xfs     
         readOnly: false   
   persistentVolumeReclaimPolicy: Recycle

创建pvc

kind: PersistentVolumeClaim 
apiVersion: v1 
metadata:   
  name: ceph-pvc 
spec:   
  accessModes:     
  - ReadWriteOnce   
  resources:     
   requests:       
    storage: 1Gi

挂载pvc

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
     app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template: # create pods using pod definition in this template
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
          - name: ceph-data
            mountPath: "/ceph-data"
      volumes:
      - name: ceph-data
        persistentVolumeClaim:
          claimName: ceph-pvc
  • 做成pv来挂载,就允许同一node上的多pod挂载了:ceph rbd块存储能在同一个node上跨pod以ReadWriteOnce共享挂载;ceph rbd块存储能在同一个node上同一个pod多个容器中以ReadWriteOnce共享挂载
  • ceph rbd块存储不能跨node以ReadWriteOnce共享挂载
  • 如果一个使用ceph rdb的pod所在的node挂掉,这个pod虽然会被调度到其它node,但是由于rbd不能跨node多次挂载和挂掉的pod不能自动解绑pv的问题,这个新pod不会正常运行

  • 解决办法:

1,使用能支持跨node和pod之间挂载的共享存储,例如cephfs,GlusterFS等

2,给node添加label,只允许deployment所管理的pod调度到一个固定的node上。(不建议,这个node挂掉的话,服务就故障了)

基于storage class动态生成pv

ceph配置文件授权

#3台ceph节点和3台k8s节点都执行。sc需要用到。
chmod 777  -R  /etc/ceph/*
mkdir /root/.ceph/
cp -ar /etc/ceph/ /root/.ceph/

安装rbd供应商

#事先上传镜像
docker load -i 
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: 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

创建ceph secret

#创建ceph-secret这个k8s secret对象,这个secret对象用于k8s volume插件访问ceph集群,获取client.admin的keyring值,并用base64编码,在master1-admin(ceph管理节点)操作
ceph auth get-key client.admin | base64
#创建ceph的secret,在k8s的控制节点操作:
apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret-sc
type: "ceph.com/rbd" #secret的type除了可以用内置的,也可以自定义一个string。
data:
  key: QVFCVFJwdGx4Z2VoTFJBQW9QVkpsb3NvZDl1ZFBTYXRZbThDUGc9PQ== #<上一步生成的key>
#创建ceph pool,只需要创建pool即可,rbd设备会被sc来自动创建
ceph osd pool create k8stest1 6 #创建pool,pgnum是6

创建sc

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: k8s-rbd
provisioner: ceph.com/rbd #要用provisioner里面env定义的name
parameters:
  monitors: 192.168.40.8:6789,192.168.40.7:6789,192.168.40.9:6789
  adminId: admin
  adminSecretName: ceph-secret-sc
  pool: k8stest1
  userId: admin
  userSecretName: ceph-secret-sc
  fsType: xfs
  imageFormat: "2" #指定了RBD镜像的格式。"2"表示使用第二版的RBD镜像格式,这是一种新的、更加灵活的格式,支持更多的特性,如快照、克隆和层次化存储等
  imageFeatures: "layering" #这个参数指定了RBD镜像的特性。"layering"表示启用了层次化存储特性。层次化存储允许镜像共享相同的数据块,可以节省存储空间,并且可以更快地创建新的镜像和快照。

K8s 1.20版本兼容问题

k8s1.20版本通过rbd provisioner动态生成pv会报错:

kubectl logs rbd-provisioner-685746688f-8mbz

E0418 15:50:09.610071 1 controller.go:1004] provision "default/rbd-pvc" class "k8s-rbd": unexpected error getting claim reference: selfLink was empty, can't make reference

  • 报错原因是1.20版本禁用了selfLink,解决方法如下;

  • 编辑/etc/kubernetes/manifests/kube-apiserver.yaml,在这里:

spec:
 containers:
 - command:
   - kube-apiserver

添加这一行:

- --feature-gates=RemoveSelfLink=false

重启kubelet

systemctl restart kubelet

创建pvc

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: rbd-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi
  storageClassName: k8s-rbd

在Kubernetes的PersistentVolumeClaim(PVC)定义中,pvc.spec.volumeMode字段用于指定所请求的存储卷的访问模式。

volumeMode字段有两个可能的取值:

  1. Filesystem:这是默认的模式。在这种模式下,Kubernetes会在卷上创建一个文件系统,然后将这个文件系统挂载到Pod中的容器上。
  2. Block:在这种模式下,卷作为裸设备(raw block device)提供给Pod。也就是说,卷不会被格式化,也不会被挂载到Pod中的容器上。而是直接作为块设备提供给容器使用。

这两种模式的选择取决于你的应用需求。一般来说,大多数应用都会使用Filesystem模式,但是一些需要高性能IO或者特殊的文件系统特性的应用可能会选择Block模式。

创建pod挂载pvc

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: rbd-pod
  name: ceph-rbd-pod
spec:
  containers:
  - name: ceph-rbd-nginx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: ceph-rbd
      mountPath: /mnt
      readOnly: false
  volumes:
  - name: ceph-rbd
    persistentVolumeClaim:
      claimName: rbd-pvc

k8s挂载cephfs

创建ceph子目录

ceph fs ls
#为了别的地方能挂载cephfs,先创建一个secretfile,在master1-admin上
cat /etc/ceph/ceph.client.admin.keyring |grep key|awk -F" " '{print $3}' > /etc/ceph/admin.secret

#挂载cephfs的根目录(192.168.40.8:6789:/)到集群mon节点下的一个目录,比如/mnt/k8s_data/,因为挂载后,我们就可以直接在k8s_data下面用Linux命令创建子目录了。
mkdir /mnt/k8s_data/
mount -t ceph 192.168.40.8:6789:/ /mnt/k8s_data -o name=admin,secretfile=/etc/ceph/admin.secret
df -h

#在cephfs的根目录里面创建了一个子目录podtest,k8s以后就可以挂载这个目录 
cd /mnt/k8s_data/
mkdir podtest -p
chmod 0777 podtest/ 

创建secret

#将/etc/ceph/ceph.client.admin.keyring里面的key的值转换为base64
cat /etc/ceph/ceph.client.admin.keyring | base64
W2NsaWVudC5hZG1pbl0KCWtleSA9IEFRQlRScHRseGdlaExSQUFvUFZKbG9zb2Q5dWRQU2F0WW04Q1BnPT0K
#创建secret
apiVersion: v1
kind: Secret
metadata:
  name: cephfs-secret
data:
  key: W2NsaWVudC5hZG1pbl0KCWtleSA9IEFRQlRScHRseGdlaExSQUFvUFZKbG9zb2Q5dWRQU2F0WW04Q1BnPT0K

创建pv

apiVersion: v1
kind: PersistentVolume
metadata:
  name: cephfs-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  cephfs:
    monitors:
      - 192.168.40.8:6789
    path: /podtest
    user: admin
    readOnly: false
    secretRef:
        name: cephfs-secret
  persistentVolumeReclaimPolicy: Recycle  

创建pvc

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: cephfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  volumeName: cephfs-pv
  resources:
    requests:
      storage: 1Gi

pod挂载pvc

apiVersion: v1
kind: Pod
metadata:
  name: cephfs-pod-1
spec:
  containers:
    - image: nginx
      name: nginx
      imagePullPolicy: IfNotPresent
      volumeMounts:
      - name: test-v1
        mountPath: /mnt
  volumes:
  - name: test-v1
    persistentVolumeClaim:
      claimName: cephfs-pvc

基于Rook部署ceph集群

安装ceph

参考:Rook Quickstart Guide

unzip rook-master.zip
cd rook-master/deploy/examples/
vim operator.yaml
#修改镜像地址:registry.k8s.io访问速度慢。可以使用阿里云的镜像源:registry.cn-hangzhou.aliyuncs.com/google_containers。
##把下面的镜像地址修改成阿里云的##
# ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.7.2"
# ROOK_CSI_REGISTRAR_IMAGE: "registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.7.0"
# ROOK_CSI_RESIZER_IMAGE: "registry.k8s.io/sig-storage/csi-resizer:v1.7.0"
# ROOK_CSI_PROVISIONER_IMAGE: "registry.k8s.io/sig-storage/csi-provisioner:v3.4.0"
# ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.k8s.io/sig-storage/csi-snapshotter:v6.2.1"
# ROOK_CSI_ATTACHER_IMAGE: "registry.k8s.io/sig-storage/csi-attacher:v4.1.0"
##改完之后变成如下##
ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.7.2"
ROOK_CSI_CEPH_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/cephcsi:v3.7.2"   ROOK_CSI_REGISTRAR_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-node-driver-registrar:v2.7.0"
ROOK_CSI_RESIZER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-resizer:v1.7.0"
ROOK_CSI_PROVISIONER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-provisioner:v3.4.0"
ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-snapshotter:v6.2.1"
ROOK_CSI_ATTACHER_IMAGE: "registry.cn-hangzhou.aliyuncs.com/google_containers/csi-attacher:v4.1.0"
#修改以下字段:
ROOK_ENABLE_DISCOVERY_DAEMON: "true"
#Rook的一个环境变量,用于控制是否启用发现守护程序。发现守护程序是Rook集群中的一个组件,用于检测新的存储设备并将其添加到Rook集群中。
  • 安装rook
kubectl apply -f crds.yaml -f common.yaml -f operator.yaml
kubectl get pods -n rook-ceph

创建ceph集群

  • 修改cluster.yaml文件(在/rook-master/deploy/examples/路径下)
storage:
  useAllNodes: false
  useAllDevices: false
  #deviceFilter:
  config:
    nodes:
      - name: "master1"
        devices:
        - name: "sdb"
      - name: "node1"
        devices:
        - name: "sdb"
      - name: "node2"
        devices:
        - name: "sdb"
#部署
kubectl apply -f cluster.yaml

字段说明:

  • useAllNodes
  • true: Rook 会在所有可用的 Kubernetes 节点上启动存储服务。这意味着每一个 Kubernetes 节点(服务器或虚拟机)都会被用来运行 Ceph 存储服务,从而使整个 Kubernetes 集群的所有节点都参与到存储服务中。
  • false: Rook 只会在指定的 Kubernetes 节点上启动存储服务。这意味着只有你明确选择的节点会被用来运行 Ceph 存储服务,而不是整个集群的所有节点。
  • useAllDevices:
  • true: Rook 会在所有可用的存储设备上启动存储服务。这意味着每一个被检测到的存储设备(如硬盘、SSD)都会被用来存储数据,从而充分利用所有可用的存储资源。
  • false: Rook 只会在你指定的存储设备上启动存储服务。这意味着只有你明确选择的存储设备会被用来存储数据,而不是所有可用的存储设备。
  • -name:”sdb”: 采用裸盘,即未格式化的磁盘。其中master1, node1, node2新加磁盘sdb,建议最少三个节点,否则后面的试验可能会出现问题

安装ceph客户端工具

kubectl apply -f toolbox.yaml -n rook-ceph
#等待pod running
kubectl -n rook-ceph exec -it rook-ceph-tools-6adffg7qzsvg-adv -- bash
ceph status
ceph osd status
ceph df

安装ceph dashboard

  • 默认情况下,ceph dashboard已经创建好了,可以在ceph dashboard前面创建一个nodePort类型的Service暴露pod
tee dashboard.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
  labels:
    app: rook-ceph-mgr
    ceph_daemon_id: a
    rook_cluster: rook-ceph
  name: rook-ceph-mgr-dashboard
  namespace: rook-ceph
spec:
  ports:
  - name: http-dashboard
    port: 7000
    protocol: TCP
    targetPort: 7000
  selector:
    app: rook-ceph-mgr
    ceph_daemon_id: a
    rook_cluster: rook-ceph
  sessionAffinity: None
  type: NodePort
EOF
  • 任意节点IP:Nodeport即可查看ceph dashboard

  • username: admin

  • password:

kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo