一、存储分类

存储一般分为三类:

  • 文件存储:一些数据可能需要被多个节点使用,比如用户的头像、用户上传的文 件等,实现方式:NFS、NAS、FTP、CephFS等。
  • 块存储:一些数据只能被一个节点使用,或者是需要将一块裸盘整个挂载使用, 比如数据库、Redis等,实现方式:Ceph、GlusterFS、公有云。
  • 对象存储:由程序代码直接实现的一种存储方式,云原生应用无状态化常用的实 现方式,实现方式:一般是符合S3协议的云存储,比如AWS的S3存储、Minio、七 牛云等。

二、使用Ceph块存储

块存储一般用于一个 Pod 挂载一块存储使用,相当于一个服务器新挂了一个盘,只给一个应用使用。

2.1 先决条件

  • 有一个 Rook 集群
  • 在 Rook 可以配置存储之前,需要创建StorageClass和CephBlockPool
  • 每个 OSD 必须位于不同的节点上,因为 被failureDomain设置为host且 被replicated.size设置为3

2.2 创建StorageClass和CephBlockPool

1.根据自己需要修改storageclass.yaml(下面的文件是去掉注释进行展示)

$ cd /root/rook/deploy/examples/csi/rbd
$ vim storageclass.yaml
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
  name: replicapool
  namespace: rook-ceph
spec:
  failureDomain: host
  replicated:
    size: 3
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
  clusterID: rook-ceph # namespace:cluster
  pool: replicapool
  imageFormat: "2"
  imageFeatures: layering
  csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
  csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
  csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
  csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
  csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
  csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
  csi.storage.k8s.io/fstype: ext4
allowVolumeExpansion: true
reclaimPolicy: Delete

上面参数说明:

  • name: 定义了一个名为replicapool的块池
  • namespace: 属于rook-ceph命名空间
  • failureDomain: 使用主机作为故障域(failureDomain: host
  • replicated:3个副本的复制块池
  • provisioner: 指定用于创建和管理卷的 CSI(Container Storage Interface)插件的提供者,这里使用 Rook-Ceph RBD CSI 插件来创建和管理与该 StorageClass 关联的持久卷。
  • parameters:指定了一些特定于Rook-Ceph的参数
  • clusterID: 指定要使用的Ceph集群的名称。在示例中,设置为rook-ceph表示使用名为rook-ceph的Ceph集群。
  • pool: 指定要使用的Ceph块池的名称。在示例中,设置为replicapool表示使用名为replicapool的Ceph块池
  • imageFormat: 指定创建的RBD镜像的格式。在示例中,设置为2表示使用RBD镜像格式版本2
  • imageFeatures: 指定RBD镜像的特性。在示例中,设置为layering表示启用镜像分层特性
  • csi.storage.k8s.io/provisioner-secret-name: 指定CSI插件使用的用于存储Ceph凭据的Kubernetes Secret的名称
  • csi.storage.k8s.io/provisioner-secret-namespace: 指定包含上述凭据的Kubernetes Secret所在的命名空间
  • csi.storage.k8s.io/controller-expand-secret-name: 指定CSI插件使用的用于扩展卷时的控制器凭据的Kubernetes Secret的名称
  • csi.storage.k8s.io/controller-expand-secret-namespace: 指定包含上述控制器凭据的Kubernetes Secret所在的命名空间
  • csi.storage.k8s.io/node-stage-secret-name: 指定CSI插件使用的用于节点级别挂载卷时的凭据的Kubernetes Secret的名称
  • csi.storage.k8s.io/node-stage-secret-namespace: 指定包含上述节点凭据的Kubernetes Secret所在的命名空间
  • csi.storage.k8s.io/fstype: 指定要在挂载卷时使用的文件系统类型。在示例中,设置为ext4表示使用ext4文件系统
  • allowVolumeExpansion: 指定是否允许卷进行扩展。在示例中,设置为true表示允许扩展卷的大小
  • reclaimPolicy: 指定在卷被释放后如何处理底层存储资源。在示例中,设置为Delete表示删除底层存储资源

说明:我这里没有做修改,可以根据自己的需求进行修改

如果已将 Rook 运算符部署在“rook-ceph”以外的命名空间中,需要更改配置程序中的前缀以匹配目前使用的命名空间。例如,如果 Rook 操作符在名称空间“my-namespace”中运行,则配置程序值应为“my-namespace.rbd.csi.ceph.com”。

provisioner: my-namespace.rbd.csi.ceph.com

2.创建StorageClass和CephBlockPool

$ cd /root/rook/deploy/examples/csi/rbd
$ k create -f  storageclass.yaml

3.查看创建的 cephblockpool 和 storageClass

[root@k8s-master01 rbd]# k get cephblockpool -n rook-ceph
NAME          PHASE
replicapool   Ready

[root@k8s-master01 rbd]# k get sc
NAME              PROVISIONER                  RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
rook-ceph-block   rook-ceph.rbd.csi.ceph.com   Delete          Immediate           true                   3m12s

4.登录Ceph的Dashboard查看新创建的 cephblockpool ,观察到已成功创建

使用ceph块存储-1

2.3 挂载测试

这里针对Deployment 和Statefulset分别进行演示。

2.3.1 Deployment无状态部署

创建一个示例应用程序来使用 Rook 通过经典的 wordpress 和 mysql 应用程序配置的块存储。这两个应用程序都将利用 Rook 提供的块卷。

1.修改mysql.yaml ,设置请求存储大小为5G,设置镜像为国内镜像,即将mysql:5.6修改为registry.cn-hangzhou.aliyuncs.com/abroad_images/mysql:5.6

$ cd /root/rook/deploy/examples
$ vim mysql.yaml

挂载测试-1

2.修改mysql.yaml ,设置请求存储大小为5G,设置镜像为国内镜像,即将wordpress:4.6.1-apache修改为registry.cn-hangzhou.aliyuncs.com/abroad_images/wordpress:4.6.1-apache

挂载测试-2

3.启动 mysql 和 wordpress

$ cd /root/rook/deploy/examples
$ k create -f mysql.yaml -f wordpress.yaml

4.查看PVC

[root@k8s-master01 examples]# k get pvc
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
mysql-pv-claim   Bound    pvc-8133aa82-b1a8-48bc-a4e7-8a195f8d72bd   5Gi        RWO            rook-ceph-block   5m16s
wp-pv-claim      Bound    pvc-04730a5e-6d78-46fd-aba8-3133f9b1a83e   5Gi        RWO            rook-ceph-block   5m16s

5.等待这两个Pod完全起来后,获取 wordpress 应用程序的集群 IP

[root@k8s-master01 examples]# kubectl get po
NAME                               READY   STATUS      RESTARTS        AGE
wordpress-54f687fd7c-ppbwk         1/1     Running     0               8m31s
wordpress-mysql-64c9849bd6-6jqls   1/1     Running     0               8m31s

[root@k8s-master01 examples]# kubectl get svc wordpress
NAME        TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
wordpress   LoadBalancer   10.0.99.72   <pending>     80:30458/TCP   9m35s

说明:这里因为没有外部IP地址访问wordpress,所以不做验证

2.3.2 Statefulset有状态部署

上面的演示类型为deployment,如果是 statefulset,只需要将 volumeTemplateClaim 里面的 Claim 名称改为 StorageClass 名称即可动态创建 Pod。在 StatefulSet 的 YAML 文件中,将 volumeClaimTemplatesClaim 名称改为 StorageClass 的名称。

1.定义一个yaml

$ vim sts-sc.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # 必须匹配 .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # 默认值是 1
  minReadySeconds: 10 # 默认值是 0
  template:
    metadata:
      labels:
        app: nginx # 必须匹配 .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "rook-ceph-block"
      resources:
        requests:
          storage: 1Gi

注意:这里的名称应该与步骤3.2中创建的 StorageClass 的名称保持一致。

2.创建该应用

$ k create -f sts-sc.yaml

3.查看应用创建情况

[root@k8s-master01 ~]# k get po -l app=nginx
NAME                     READY   STATUS    RESTARTS   AGE
web-0                    1/1     Running   0          52s
web-1                    1/1     Running   0          32s
web-2                    1/1     Running   0          11s

[root@k8s-master01 ~]# k get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx        ClusterIP   None         <none>        80/TCP    103s

2.4 配置清除

下面清除上面演示配置

$ cd /root/rook/deploy/examples
$ kubectl delete -f wordpress.yaml
$ kubectl delete -f mysql.yaml
$ kubectl delete -f  sts-sc.yaml
$ kubectl delete pvc www-web-0 www-web-1 www-web-2
$ kubectl delete pv pv-hostpath pv-nfs
$ kubectl delete -n rook-ceph cephblockpools.ceph.rook.io replicapool
$ kubectl delete storageclass rook-ceph-block