专栏首页哎_小羊Kubernetes 集群基于 Rook 的 Ceph 存储之块设备、文件系统、对象存储

Kubernetes 集群基于 Rook 的 Ceph 存储之块设备、文件系统、对象存储

文章目录

1、Rook & Ceph 介绍

Ceph 是一个开源的分布式存储系统,包括对象存储、块设备、文件系统。它可靠性高、管理方便、伸缩性强,能够轻松应对 PB、EB 级别数据。Rook 是专用于 Cloud-Native 环境的文件、块、对象存储服务。它实现了一个自动管理的、自动扩容的、自动修复的分布式存储服务。Rook 支持 Ceph 存储,基于 Kubernetes 使用 Rook 可以大大简化 Ceph 存储集群的搭建以及使用。

2、环境、软件准备

要使用基于 Rook 的 Ceph 存储中的块设备、文件系统以及对象存储,必须保证已通过 Rook 完成 Ceph 存储集群的搭建,并且保证 Ceph 存储集群处于 active + clean 状态。这里搭建过程可以参考上一篇 Kubernetes 集群基于 Rook 搭建 Ceph 分布式存储系统 文章,讲解的很详细。Kubernetes 集群搭建亦可参照上一篇文章,版本为 1.12.1,这里均忽略搭建过程,下边通过示例分别演示下如何使用这块设备、文件系统、对象存储方案。

3、Block 块存储

Ceph 块设备也可以简称为 RBD 或 RADOS 块设备,下边演示如何基于 Rook 创建 Ceph 块存储,并验证测试。

3.1、创建 CephBlockPool、StorageClass

基于 Rook 创建 Ceph 块设备,需要先创建 CephBlockPoolStorageClassCephBlockPool 这是 Rook 的 CRD 自定义资源,顾名思义就是创建一个 Block 池,然后在创建一个 StorageClass,这个是动态卷配置 (Dynamic provisioning) 可以根据需要动态的创建存储卷,Kubernetes 集群存储 PV 支持 Static 静态配置以及 Dynamic 动态配置。

$ vim storageclass.yaml 
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
  name: replicapool
  namespace: rook-ceph
spec:
  replicated:
    size: 1
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: rook-ceph-block
provisioner: ceph.rook.io/block
parameters:
  blockPool: replicapool
  clusterNamespace: rook-ceph
  fstype: xfs

$ kubectl create -f storageclass.yaml 
cephblockpool.ceph.rook.io/replicapool created
storageclass.storage.k8s.io/rook-ceph-block created
$ kubectl get sc
NAME              PROVISIONER          AGE
rook-ceph-block   ceph.rook.io/block   9s
$ kubectl -n rook-ceph get cephblockpool 
NAME          AGE
replicapool   1m

创建完毕后,我们去 Rook Dashboard Pools 下可以看到创建的 replicapool 池子。

3.2、验证并测试

现在就可以使用块存储了,创建一个 PVC 请求申请 1024Mi 存储空间。

$ vim busy-box-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: busybox-pvc
  namespace: default
spec:
  storageClassName: rook-ceph-block
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1024Mi

$ kubectl create -f busy-box-pvc.yaml 
persistentvolumeclaim/busybox-pvc created
$ kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
busybox-pvc   Bound    pvc-3e4adb48-12f0-11e9-9a38-0800272ff396   1Gi        RWO            rook-ceph-block   19s
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS      REASON   AGE
pvc-3e4adb48-12f0-11e9-9a38-0800272ff396   1Gi        RWO            Delete           Bound    default/busybox-pvc   rook-ceph-block            20s     

注意:这里的 PV 会自动创建,当提交了包含 StorageClass 字段的 PVC 之后,Kubernetes 就会根据这个 StorageClass 创建出对应的 PV,非常方便了。要注意 storageClassName: rook-ceph-block 要跟上边对应上。

我们可以通过 Rook Dashboard Block 下边查看到创建的 rbd image 了

此时,可以进入到 rook-toolbox 容器内通过 CLI 命令查看验证一下。

$ kubectl -n rook-ceph exec -it rook-ceph-tools-5bd5cdb949-d22ql bash
[root@node2 /]# rbd list -p replicapool
pvc-3e4adb48-12f0-11e9-9a38-0800272ff396
[root@node2 /]# rbd info -p replicapool pvc-3e4adb48-12f0-11e9-9a38-0800272ff396
rbd image 'pvc-3e4adb48-12f0-11e9-9a38-0800272ff396':
	size 1 GiB in 256 objects
	order 22 (4 MiB objects)
	id: 4ede6b8b4567
	block_name_prefix: rbd_data.4ede6b8b4567
	format: 2
	features: layering
	op_features: 
	flags: 
	create_timestamp: Tue Jan  8 02:51:08 2019
[root@node2 /]# ceph df
GLOBAL:
    SIZE       AVAIL      RAW USED     %RAW USED 
    96 GiB     75 GiB       21 GiB         21.96 
POOLS:
    NAME            ID     USED       %USED     MAX AVAIL     OBJECTS 
    test_pool       1         0 B         0        67 GiB           0 
    replicapool     2      14 MiB      0.02        67 GiB          16 

现在就可以将申请的资源挂载到容器内使用了。创建一个基于 busy-box 镜像的 Pod 资源,将申请的资源挂载到 /mnt/busy-box 目录。

$ vim busy-box-pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: busy-box-test1
  namespace: default
spec:
  restartPolicy: OnFailure
  containers:
  - name: busy-box-test1
    image: busybox
    volumeMounts:
    - name: busy-box-test-pv1
      mountPath: /mnt/busy-box
    command: ["sleep", "60000"]
  volumes:
  - name: busy-box-test-pv1
    persistentVolumeClaim:
      claimName: busybox-pvc

$ kubectl create -f busy-box-pod1.yaml 
pod/busy-box-test1 created
$ kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
busy-box-test1                      1/1     Running   0          9s

创建完毕,进入到容器内查看验证一下,是否正确挂载。

$ kubectl exec -it busy-box-test1 /bin/sh
/ # df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  32.0G      8.0G     23.9G  25% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                     1.1G         0      1.1G   0% /sys/fs/cgroup
/dev/rbd0              1014.0M     32.3M    981.7M   3% /mnt/busy-box
/dev/mapper/cl-root      32.0G      8.0G     23.9G  25% /dev/termination-log
/dev/mapper/cl-root      32.0G      8.0G     23.9G  25% /etc/resolv.conf
......

/ # echo "This message write from busy-box-test1" > /mnt/busy-box/message.txt
/ # ls /mnt/busy-box/
message.txt

可以看到申请的 1024Mi 存储挂载到了 /mnt/busy-box 目录,同时我们写入一个文件到该目录,来验证一下其他容器挂载同一 PVC 后,数据是否可以共享访问。

# 先干掉之前 Pod,保留 PVC
$ kubectl delete pod/busy-box-test1 
pod "busy-box-test1" deleted

# 创建一个新的 Pod,并挂载同一 PVC
$ vim busy-box-pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: busy-box-test2
  namespace: default
spec:
  restartPolicy: OnFailure
  containers:
  - name: busy-box-test2
    image: busybox
    volumeMounts:
    - name: busy-box-test-pv2
      mountPath: /mnt/busy-box
    command: ["sleep", "60000"]
  volumes:
  - name: busy-box-test-pv2
    persistentVolumeClaim:
      claimName: busybox-pvc
      
$ kubectl create -f busy-box-pod2.yaml 
pod/busy-box-test2 created
$ kubectl get pods | grep busy-box
busy-box-test2                      1/1     Running   0          17s

# 进入到容器内,查看验证
$ kubectl exec -it busy-box-test2 /bin/sh
/ # df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  32.0G      8.0G     23.9G  25% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                     1.1G         0      1.1G   0% /sys/fs/cgroup
/dev/rbd0              1014.0M     32.3M    981.7M   3% /mnt/busy-box
/dev/mapper/cl-root      32.0G      8.0G     23.9G  25% /dev/termination-log
/dev/mapper/cl-root      32.0G      8.0G     23.9G  25% /etc/resolv.conf
...

/ # cat /mnt/busy-box/message.txt 
This message write from busy-box-test1

可以看到数据能够被读取到。

4、File System 文件系统

Ceph 文件系统,我们一般称为 cephfs,下边演示如何基于 Rook 创建 Ceph 文件系统,并验证测试。

4.1、创建 CephFileSystem

基于 Rook 创建 Ceph 块设备,需要先创建 CephFilesystem

$ vim busy-box-fs.yaml
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
  name: busy-box-fs
  namespace: rook-ceph
spec:
  metadataPool:
    replicated:
      size: 3
  dataPools:
    - failureDomain: osd
      replicated:
        size: 3
  metadataServer:
    activeCount: 1
    activeStandby: true
    placement:
    resources:

# 干掉之前 busy-box Pod 容器,方便演示
$ kubectl delete pod/busy-box-test2
pod "busy-box-test2" deleted

$ kubectl create -f busy-box-fs.yaml 
cephfilesystem.ceph.rook.io/busy-box-fs created
$ kubectl -n rook-ceph get cephfilesystem 
NAME          MDSCOUNT   AGE
busy-box-fs   1          30s
$ kubectl -n rook-ceph get pod -l app=rook-ceph-mds
NAME                                          READY   STATUS    RESTARTS   AGE
rook-ceph-mds-busy-box-fs-a-d8955cd94-wthsc   1/1     Running   0          98s
rook-ceph-mds-busy-box-fs-b-8f5b6cf8-b27q9    1/1     Running   0          97s

注意:这里 spec.metadataPool.replicated.size 字段和 spec.dataPools.replicated.size 配置为集群 OSD 个数。可以看到,默认会创建两个相关 MDS:rook-ceph-mds-busy-box-fs,同时他还会在底层创建两个 Pool:busy-box-fs-metadata 元数据和 busy-box-fs-data0 数据,这点跟之前 初试 Ceph 存储之块设备、文件系统、对象存储 #3、Ceph 文件系统 文章中通过 CLI 命令操作是一致的,这里自动帮我们创建了。

此时去 Rook Dashboard Filesystems 下边可以看到创建的 MDS。

去 Pools 下边可以看到新创建的元数据池和数据池。

4.2、验证并测试

我们可以进入到 rook-toolbox 容器内通过 CLI 命令查看验证一下。

$ kubectl -n rook-ceph exec -it rook-ceph-tools-5bd5cdb949-d22ql bash
[root@node2 /]# ceph status
  cluster:
    id:     6c117372-a462-447c-bfd4-a0378393f69e
    health: HEALTH_WARN
            clock skew detected on mon.a, mon.c
 
  services:
    mon: 3 daemons, quorum b,a,c
    mgr: a(active)
    mds: busy-box-fs-1/1/1 up  {0=busy-box-fs-b=up:active}, 1 up:standby-replay
    osd: 3 osds: 3 up, 3 in
 
  data:
    pools:   4 pools, 364 pgs
    objects: 38  objects, 14 MiB
    usage:   21 GiB used, 75 GiB / 96 GiB avail
    pgs:     364 active+clean
 
  io:
    client:   1.2 KiB/s rd, 2 op/s rd, 0 op/s wr
 
[root@node2 /]# ceph fs ls
name: busy-box-fs, metadata pool: busy-box-fs-metadata, data pools: [busy-box-fs-data0 ]
[root@node2 /]# ceph mds stat
busy-box-fs-1/1/1 up  {0=busy-box-fs-b=up:active}, 1 up:standby-replay

确认自动创建了,接下来我们创建一个实例来挂载 fs 到指定目录 /mnt/busy-box/fs

$ vim busy-box-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: busy-box-test3
  namespace: default
  labels:
    k8s-app: busy-box-test3
spec:
  replicas: 3
  selector:
    k8s-app: busy-box-test3
  template:
    metadata:
      labels:
        k8s-app: busy-box-test3
        kubernetes.io/cluster-service: "true"
    spec:
      restartPolicy: Always
      containers:
      - name: busy-box-test3
        image: busybox
        volumeMounts:
        - name: busy-box-test-fs
          mountPath: /mnt/busy-box/fs
        command: ["sleep", "60000"]
      volumes:
      - name: busy-box-test-fs
        flexVolume:
          driver: ceph.rook.io/rook
          fsType: ceph
          options:
              fsName: busy-box-fs
              clusterNamespace: rook-ceph 

$ vim busy-box-rc.yaml
$ kubectl create -f busy-box-rc.yaml 
replicationcontroller/busy-box-test3 created
$ kubectl get pod -o wide
NAME                                READY   STATUS    RESTARTS   AGE     IP            NODE           NOMINATED NODE
busy-box-test3-4lm9n                1/1     Running   0          31s     172.20.1.9    10.222.78.64   <none>
busy-box-test3-5gc4x                1/1     Running   0          31s     172.20.2.14   10.222.78.86   <none>
busy-box-test3-kbm8c                1/1     Running   0          31s     172.20.0.17   10.222.78.63   <none>              

注意:这里 fsName:busy-box-fs 要跟上边的 CephFilesystem Name 一致。replicas: 3 这个我设置成跟集群节点个数一致,这样可以分配到每个节点上,方便下边验证。

分别进入到各个容器内,查看验证一下。

# 进入 busy-box-test3-4lm9n 容器内查看
$ kubectl exec -it busy-box-test3-4lm9n /bin/sh
/ # cat /etc/hostname 
busy-box-test3-4lm9n
/ # df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  32.0G      7.9G     24.0G  25% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                     1.1G         0      1.1G   0% /sys/fs/cgroup
10.68.144.184:6790,10.68.107.193:6790,10.68.253.125:6790:/
                         22.3G         0     22.3G   0% /mnt/busy-box/fs
/dev/mapper/cl-root      32.0G      7.9G     24.0G  25% /dev/termination-log
/dev/mapper/cl-root      32.0G      7.9G     24.0G  25% /etc/resolv.conf
/dev/mapper/cl-root      32.0G      7.9G     24.0G  25% /etc/hostname
......

# 写入测试文件
/ # echo "This message write from busy-box-test3-4lm9n." > /mnt/busy-box/fs/message.txt

然后,我们进入到 busy-box-test3-5gc4x 容器内查看下。

# 进入到 busy-box-test3-5gc4x 查看下
$ kubectl exec -it busy-box-test3-5gc4x /bin/sh
/ # cat /etc/hostname 
busy-box-test3-5gc4x
/ # df -h
Filesystem                Size      Used Available Use% Mounted on
overlay                  32.0G      5.1G     26.9G  16% /
tmpfs                    64.0M         0     64.0M   0% /dev
tmpfs                     1.1G         0      1.1G   0% /sys/fs/cgroup
10.68.144.184:6790,10.68.107.193:6790,10.68.253.125:6790:/
                         22.3G         0     22.3G   0% /mnt/busy-box/fs
/dev/mapper/cl-root      32.0G      5.1G     26.9G  16% /dev/termination-log
/dev/mapper/cl-root      32.0G      5.1G     26.9G  16% /etc/resolv.conf
/dev/mapper/cl-root      32.0G      5.1G     26.9G  16% /etc/hostname
......

/ # cat /mnt/busy-box/fs/message.txt 
This message write from busy-box-test3-4lm9n.
/ # echo "This message write from busy-box-test3-5gc4x." >> /mnt/busy-box/fs/message.txt 
/ # cat /mnt/busy-box/fs/message.txt 
This message write from busy-box-test3-4lm9n.
This message write from busy-box-test3-5gc4x.

最后,进入到 busy-box-test3-kbm8c 容器内查看,妥妥没问题的,这里就不在演示了。

此时,我们去 Rook Dashboard Filesystem 下查看,会发现下方图形化,有两个突出值,就是上边演示时写入了值的体现。

5、Object 对象存储

Ceph 对象存储可以简称为 RGW,Ceph RGW 是基于 librados,为应用提供 RESTful 类型的对象存储接口,其接口方式支持 S3(兼容 Amazon S3 RESTful API) 和 Swift(兼容 OpenStack Swift API) 两种类型。下边演示如何基于 Rook 创建 Ceph 对象存储,并验证测试。

5.1、创建 Object Store

创建一个 CephObjectStore,名称为:busy-box-obj

$ vim busy-box-obj.yaml
apiVersion: ceph.rook.io/v1
kind: CephObjectStore
metadata:
  name: busy-box-obj
  namespace: rook-ceph
spec:
  metadataPool:
    failureDomain: host
    replicated:
      size: 3
  dataPool:
    failureDomain: osd
    erasureCoded:
      dataChunks: 2
      codingChunks: 1
  gateway:
    type: s3
    sslCertificateRef:
    port: 80
    securePort:
    instances: 1
    allNodes: false
    placement:
    resources:

$ kubectl create -f busy-box-obj.yaml 
cephobjectstore.ceph.rook.io/busy-box-obj created
$ kubectl -n rook-ceph get cephobjectstore
NAME           AGE
busy-box-obj   25s
$ kubectl -n rook-ceph get pod -l app=rook-ceph-rgw
NAME                                          READY   STATUS    RESTARTS   AGE
rook-ceph-rgw-busy-box-obj-545b8b8b6b-j84wq   1/1     Running   0          21s
$ kubectl -n rook-ceph get svc -l app=rook-ceph-rgw
NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
rook-ceph-rgw-busy-box-obj   ClusterIP   10.68.117.190   <none>        80/TCP    2m7s

注意:它会自动创建一个 rook-ceph-rgw,并且创建一个 Service。默认使用 s3 存储类型,端口 80。这里 metadataPool.replicated.size 字段配置为集群 OSD 个数。如果 Ceph 集群 OSD 数量 >=3dataPool 字段配置如上,否则配置如下:

dataPool:
    failureDomain: osd
    replicated:
      size: 1

5.2、创建 User 用户

然后创建一个 CephObjectStoreUser User 账户,来生成 AccessKeySecretKey,为了后边该用户访问 S3 存储使用。

$ vim busy-box-obj-user.yaml
apiVersion: ceph.rook.io/v1
kind: CephObjectStoreUser
metadata:
  name: busy-box-obj-user
  namespace: rook-ceph
spec:
  store: busy-box-obj
  displayName: "busy-box display name"

$ kubectl create -f busy-box-obj-user.yaml 
cephobjectstoreuser.ceph.rook.io/busy-box-obj-user created
$ kubectl -n rook-ceph get cephobjectstoreuser
NAME                AGE
busy-box-obj-user   31s

默认 Rook 将生成的包含认证 Key 的用户信息存在 secret 中,那么,查看下该 secret 生成的 Key 是什么。

$ kubectl -n rook-ceph get secret | grep rook-ceph-object-user
rook-ceph-object-user-busy-box-obj-busy-box-obj-user   kubernetes.io/rook         2      2m34s
$ kubectl -n rook-ceph describe secret/rook-ceph-object-user-busy-box-obj-busy-box-obj-user
Name:         rook-ceph-object-user-busy-box-obj-busy-box-obj-user
Namespace:    rook-ceph
Labels:       app=rook-ceph-rgw
              rook_cluster=rook-ceph
              rook_object_store=busy-box-obj
              user=busy-box-obj-user
Annotations:  <none>

Type:  kubernetes.io/rook

Data
====
AccessKey:  20 bytes
SecretKey:  40 bytes

貌似 AccessKeySecretKey 都隐藏了,我们可以通过另一种方式来获取。

$ kubectl -n rook-ceph get secret/rook-ceph-object-user-busy-box-obj-busy-box-obj-user -o jsonpath='{.data.AccessKey}' | base64 --decode
RZTGKUPYG4OJ2EASVPCY
$ kubectl -n rook-ceph get secret/rook-ceph-object-user-busy-box-obj-busy-box-obj-user -o jsonpath='{.data.SecretKey}' | base64 --decode
EWRo6aKjO7OcBWaT974UASUX0SWn4PyzvJGzJSKT

要牢记这两个 Key 值,因为以后访问 S3 的时候必须带上,否则认证不通过。

此时,我们查看 Rook Dashboard Pools 一下,会发现新增了 6 个跟 rgw 相关的底层 pools。

5.3、集群内访问

我们可以进入到 rook-toolbox 容器内访问该文件存储。首先需要安装一下 s3cmd 客户端工具,该工具提供 CLI 专门用来操作 s3 存储。

$ kubectl -n rook-ceph exec -it rook-ceph-tools-5bd5cdb949-d22ql bash
[root@node2 /]# yum install s3cmd

然后,我们可以将连接 s3 存储的一些配置信息设置为 ENV 环境变量的形式,会大大方便后边访问。

export AWS_HOST=rook-ceph-rgw-busy-box-obj.rook-ceph
export AWS_ENDPOINT=10.68.117.190:80
export AWS_ACCESS_KEY_ID=RZTGKUPYG4OJ2EASVPCY
export AWS_SECRET_ACCESS_KEY=EWRo6aKjO7OcBWaT974UASUX0SWn4PyzvJGzJSKT

简单说明一下:

  • HOST:rgw 服务在集群内 DNS 地址,按照 K8s DNS 服务命名规则,简单一些可以配置为:rook-ceph-rgw-busy-box-obj.rook-ceph
  • ENDPOINT:rgw 服务监听地址,因为是在进群内部访问,所以可以通过获取 rook-ceph-rgw-busy-box-obj Service 的 Cluster_IPPort,上边 5.1、创建 Object Store 已经获取到了,那么地址为: 10.68.117.190:80
  • ACCESS_KEY:上边获取的
  • SECRET_KEY:上边获取的

一切准备就绪,就可以通过 s3cmd 工具来操作了。注意:以下操作均在 rook-ceph-tools-5bd5cdb949-d22ql 容器内操作。

5.3.1、创建 Bucket

# 创建一个 rookbucket 
[root@node2 /]# s3cmd mb --no-ssl --host=${AWS_HOST} --host-bucket=  s3://rookbucket
Bucket 's3://rookbucket/' created

5.3.2、获取 Bucket 列表

# 获取所有 bucket 列表
[root@node2 /]# s3cmd ls --no-ssl --host=${AWS_HOST}
2019-01-08 06:46  s3://rookbucket

5.3.3、Put Object

# 创建一个数据文件,并上传到 s3 rookbucket
[root@node2 /]# echo "This is test data from rook-toolbox." > /rookdata   
[root@node2 /]# s3cmd put /rookdata --no-ssl --host=${AWS_HOST} --host-bucket=  s3://rookbucket
upload: '/rookdata' -> 's3://rookbucket/rookdata'  [1 of 1]
 37 of 37   100% in    0s   582.89 B/s  done

5.3.4、Get Object

# 从 s3 rookbucket 获取 rootdata 数据到本地
[root@node2 /]# s3cmd get s3://rookbucket/rookdata /rookdata-s3 --no-ssl --host=${AWS_HOST} --host-bucket=
download: 's3://rookbucket/rookdata' -> '/rookdata-s3'  [1 of 1]
 37 of 37   100% in    0s   763.14 B/s  done
[root@node2 /]# cat /rookdata-s3 
This is test data from rook-toolbox.

数据读取出来了,跟上传的一模一样。s3cmd 其他命令,例如:Remove (rb)Delete (del)Copy (cp)Modify (modify) 等命令,可以通过 s3cmd -h 命令查看,大家可以尝试一下,这里就不在演示了。

5.4、集群外访问

以上都是在集群内部容器访问的,如果我们需要外部访问的话,就不行了。这里可以通过部署一个新的 Service 使用 NodePort 暴漏方式。

$ vim busy-box-obj-rgw-external.yaml
apiVersion: v1
kind: Service
metadata:
  name: rook-ceph-rgw-busy-box-obj-external
  namespace: rook-ceph
  labels:
    app: rook-ceph-rgw
    rook_cluster: rook-ceph
    rook_object_store: busy-box-obj
spec:
  ports:
  - name: rgw
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: rook-ceph-rgw
    rook_cluster: rook-ceph
    rook_object_store: busy-box-obj
  sessionAffinity: None
  type: NodePort
  
$ kubectl create -f busy-box-obj-rgw-external.yaml 
service/rook-ceph-rgw-busy-box-obj-external created
$ kubectl -n rook-ceph get svc | grep rook-ceph-rgw
rook-ceph-rgw-busy-box-obj               ClusterIP   10.68.117.190   <none>        80/TCP           90m
rook-ceph-rgw-busy-box-obj-external      NodePort    10.68.127.192   <none>        80:24313/TCP     66s

这样,外部就可以通过 http://10.222.78.63:24313 来访问了。我们在集群外部机器,写一个 Python 测试脚本,该脚本将会连接 rgw,然后新建一个新的 bucket,再列出所有的 buckets。脚本变量 access_keysecret_key 值就是上边的 access_keysecret_key

# 安装一下 python-boto 工具
$ yum install python-boto

$ vim s3.py
import boto
import boto.s3.connection
access_key = 'RZTGKUPYG4OJ2EASVPCY'
secret_key = 'EWRo6aKjO7OcBWaT974UASUX0SWn4PyzvJGzJSKT'
conn = boto.connect_s3(
    aws_access_key_id = access_key,
    aws_secret_access_key = secret_key,
    host = '10.222.78.63', port=24313,
    is_secure=False,
    calling_format = boto.s3.connection.OrdinaryCallingFormat(),
)
bucket = conn.create_bucket('my-s3-bucket')
for bucket in conn.get_all_buckets():
        print "{name}\t{created}".format(
                name = bucket.name,
                created = bucket.creation_date,
)

$ python s3.py 
Traceback (most recent call last):
  File "s3.py", line 13, in <module>
    for bucket in conn.get_all_buckets():
  File "/usr/lib/python2.7/site-packages/boto/s3/connection.py", line 444, in get_all_buckets
    response.status, response.reason, body)
boto.exception.S3ResponseError: S3ResponseError: 403 Forbidden
<?xml version="1.0" encoding="UTF-8"?><Error><Code>RequestTimeTooSkewed</Code><RequestId>tx00000000000000000003b-005c3465ac-363d-busy-box-obj</RequestId><HostId>363d-busy-box-obj-busy-box-obj</HostId></Error>

配置好 hostportaccess_keysecret_key,测试一下,不过很遗憾报错了。。。提示 403 Forbidden,但是我们明明在脚本里面设置了正确的 access_keysecret_key 为啥报这个错误? 不过后边 <Code>RequestTimeTooSkewed</Code> 这个错误日志指出,是因为请求时间不合理。

经过一番排查后,的确是这个问题,因为集群外部机器时间跟集群内 Pod 时间是不一致的,相差了 10 个小时左右,初步判断应该是时区设置不正确。当初启动 Pod 的时候没有将系统当前时间挂载到容器内,导致时间不一致。那么怎么办呢?我们可以去集群内任意一个容器内执行该脚本,因为他们的时间是一致的。虽然还是容器内执行,但是我们连接 s3 服务地址和方式都一样了呦!那么继续去 rook-toolbox 容器内执行吧!

$ kubectl -n rook-ceph exec -it rook-ceph-tools-5bd5cdb949-d22ql bash
[root@node2 /] yum install python-boto
[root@node2 /] vim s3.py
[root@node2 /] python s3.py 
my-s3-bucket	2019-01-08T07:49:31.517Z
rookbucket	2019-01-08T06:46:23.843Z

测试通过,只要时间一致,妥妥没问题的。

6、配置 Ceph Object Gateway Management Frontend

最后我们访问一下 Rook Dashboard Object Gateway,发现还是什么都没有。但是页面提示我们去参考 Ceph Documents 文档,开启 Object Gateway Management Frontend 功能,这样在 Rook Dashboard 就可以看到了。那么赶紧去实验一下吧!

还是进入 rook-toolbox 容器内操作。

$ kubectl -n rook-ceph exec -it rook-ceph-tools-5bd5cdb949-d22ql bash

# 获取 user 列表
[root@node2 /]# radosgw-admin user list
[
    "busy-box-obj-user"
]

# 查看 user 信息
[root@node2 /]# radosgw-admin user info --uid=busy-box-obj-user
{
    "user_id": "busy-box-obj-user",
    "display_name": "busy-box display name",
    "email": "",
    "suspended": 0,
    "max_buckets": 1000,
    "auid": 0,
    "subusers": [],
    "keys": [
        {
            "user": "busy-box-obj-user",
            "access_key": "RZTGKUPYG4OJ2EASVPCY",
            "secret_key": "EWRo6aKjO7OcBWaT974UASUX0SWn4PyzvJGzJSKT"
        }
    ],
    "swift_keys": [],
    "caps": [],
    "op_mask": "read, write, delete",
    "default_placement": "",
    "placement_tags": [],
    "bucket_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "user_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "temp_url_keys": [],
    "type": "rgw",
    "mfa_ids": []
}

# ceph dashboard 设置 host、port、access-key、secret-key 等连接 s3 的配置信息
[root@node2 /]# ceph dashboard set-rgw-api-access-key RZTGKUPYG4OJ2EASVPCY
Option RGW_API_ACCESS_KEY updated
[root@node2 /]# ceph dashboard set-rgw-api-secret-key EWRo6aKjO7OcBWaT974UASUX0SWn4PyzvJGzJSKT
Option RGW_API_SECRET_KEY updated
[root@node2 /]# ceph dashboard set-rgw-api-host 10.222.78.63
Option RGW_API_HOST updated
[root@node2 /]# ceph dashboard set-rgw-api-port 24313
Option RGW_API_PORT updated
[root@node2 /]# ceph dashboard set-rgw-api-user-id busy-box-obj-user
Option RGW_API_USER_ID updated
[root@node2 /]# ceph dashboard set-rgw-api-scheme http
Option RGW_API_SCHEME updated

此时,在去 Rook Dashboard Object Gateway 查看下 Daemon 就有值了。

满心欢喜的打开 Users 和 Buckets 页面,但是依旧没值,而且还提示 500 错误!!!

报错信息如下:

{"detail": "RGW REST API failed request with status code 403\n'{\"Code\":\"AccessDenied\",\"RequestId\":\"tx000000000000000000044-005c346b6b-363d-busy-box-obj\",\"HostId\":\"363d-busy-box-obj-busy-box-obj\"}'"}

是不是似曾相识,跟上边的问题一毛一样。按照我们上边的操作,正常的话是可以取到这些信息的,这里还是时间的问题。。。解决办法就是将集群内跟集群外时间保持一致。

好了,这次分享就到这里!总结一下,使用 Kubernetes 集群基于 Rook 搭建 Ceph 分布式存储系统,方便简洁,并且提供 Dashboard 直观查看存储集群变化。基于此,创建和使用 Ceph 块设备、文件系统、对象存储,就非常简单了,对于想在 Kubernetes 集群上搭建并使用 Ceph 存储系统的用户来说,是个很不错的选择。

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

推荐阅读

  • 如何将设计思维应用到精益初创公司的软件开发

    我们所说的设计思维,是指由 IDEO 公司的 Tim Brown 提出,并且正在改变全世界组织的设计思维,简称 DT。(译者注:IDDO,当代最具影响力的设计公司之一)

    Aceyclee
    Serverless无服务器云函数
  • InnoDB 事务加锁分析

    一般大家对数据库事务的了解可能停留在事务的ACID特性以及事务4种不同的隔离级别层面上,而对于事务 4 种不同隔离级别如何实现了解相对较少。

    2020labs小助手
    MySQLSQL数据库MVCMVCC
  • FutureTask 核心源码解析

    研究源码,一般我们都从整体以及实例先入手,再研究细节,不至于一开始就“深陷其中而"当局者迷".

    JavaEdge
    HTTPJava
  • 200行代码落地人脸识别开锁应用

    2019年国庆,帮朋友实现了一个人脸识别进行开锁的功能,用在他的真人实景游戏业务中。几个月来运行稳定,体验良好,借着这个春节宅家的时间,整理一下这个应用的实现过程。

    高树磊
    人脸识别图像处理
  • 滑动验证码攻防对抗

        在业务安全领域,滑动验证码已经是国内继,传统字符型验证码之后的标配。众所周知,打码平台和机器学习这两种绕过验证码的方式,已经是攻击者很主流的思路,不再阐述。冷渗透介绍的是一个冷门的绕过思路和防御方案。这些积累,均来自于实战之中,希望有用。

    周俊辉
    HTTP网络安全安全网站
  • 程序员进阶必读,万字总结Mysql优化精华篇

    price decimal(8,2)有2位小数的定点数,定点数支持很大的数(甚至是超过int,bigint存储范围的数)

    程序员内点事
    全文检索缓存SQL数据库Python
  • 运维转型 | 运维人不再只是“救火英雄”

    各行各业都开启了数字化转型的进程,运维团队在这种时代的浪潮中又该何去何从?我在帮助一些企业落地了运维技术平台之后,开始反思这个问题,并将所思所想整理成本篇文章。

    嘉为科技
    企业运维自动化云计算
  • WEB开发常见的安全漏洞和解决思路

    SQL注入时web开发中最常见也是危害性最大的安全漏洞,SQL注入攻击可能会导致 服务器故障,数据泄漏,数据被恶意删除等等严重后果。

    windwei
    SQLHTTPhttps安全漏洞PHP
  • 详解Winograd变换矩阵生成原理

    文本首发知乎:https://zhuanlan.zhihu.com/p/87516875

    Ldpe2G
    编程算法
  • Linux网络性能优化相关策略

    1. rx-checksumming:校验接收报文的checksum。

    glinuxer
    Linux

扫码关注云+社区

领取腾讯云代金券