Kubernetes存儲-Ceph存儲


Kubernetes存儲-Ceph存儲

原文鏈接:https://www.qikqiak.com/k8strain/storage/ceph/#_11

簡介

Ceph 是一個統一的分布式存儲系統,提供較好的性能、可靠性和可擴展性。

架構

支持的接口

​ 1、Object:有原生 API,而且也兼容 Swift 和 S3 的 API

​ 2、Block:支持精簡配置、快照、克隆

​ 3、File:Posix 接口,支持快照

image

組件

Monitor:一個 Ceph 集群需要多個 Monitor 組成的小集群,它們通過 Paxos 同步數據,用來保存 OSD 的元數據。

OSD:全稱 Object Storage Device,也就是負責響應客戶端請求返回具體數據的進程,一個 Ceph 集群一般都有很多個 OSD。主要功能用於數據的存儲,當直接使用硬盤作為存儲目標時,一塊硬盤稱之為 OSD,當使用一個目錄作為存儲目標的時候,這個目錄也被稱為 OSD

MDS:全稱 Ceph Metadata Server,是 CephFS 服務依賴的元數據服務,對象存儲和塊設備存儲不需要該服務。

Object:Ceph 最底層的存儲單元是 Object 對象,一條數據、一個配置都是一個對象,每個 Object 包含 ID、元數據和原始數據。

Pool:Pool 是一個存儲對象的邏輯分區,它通常規定了數據冗余的類型與副本數,默認為3副本。對於不同類型的存儲,需要單獨的 Pool,如 RBD。

PG:全稱 Placement Grouops,是一個邏輯概念,一個 OSD 包含多個 PG。引入 PG 這一層其實是為了更好的分配數據和定位數據。每個 Pool 內包含很多個 PG,它是一個對象的集合,服務端數據均衡和恢復的最小單位就是 PG。

image

pool 是 ceph 存儲數據時的邏輯分區,它起到 namespace 的作用

每個 pool 包含一定數量(可配置)的 PG

PG 里的對象被映射到不同的 Object 上

pool 是分布到整個集群的

FileStore與BlueStore:FileStore 是老版本默認使用的后端存儲引擎,如果使用 FileStore,建議使用 xfs 文件系統。BlueStore 是一個新的后端存儲引擎,可以直接管理裸硬盤,拋棄了 ext4 與 xfs 等本地文件系統。可以直接對物理硬盤進行操作,同時效率也高出很多。

RADOS:全稱 Reliable Autonomic Distributed Object Store,是 Ceph 集群的精華,用於實現數據分配、Failover 等集群操作。

LibradosLibrados 是 Rados 提供庫,因為 RADOS 是協議很難直接訪問,因此上層的 RBD、RGW 和 CephFS 都是通過 librados 訪問的,目前提供 PHP、Ruby、Java、Python、C 和 C++ 支持。

CRUSHCRUSH 是 Ceph 使用的數據分布算法,類似一致性哈希,讓數據分配到預期的地方。

RBD:全稱 RADOS Block Device,是 Ceph 對外提供的塊設備服務,如虛擬機硬盤,支持快照功能。

RGW:全稱是 RADOS Gateway,是 Ceph 對外提供的對象存儲服務,接口與 S3 和 Swift 兼容。

CephFS:全稱 Ceph File System,是 Ceph 對外提供的文件系統服務。

存儲

塊存儲

典型設備:

​ 磁盤陣列,硬盤,主要是將裸磁盤空間映射給主機使用的。

優點:

​ 1、通過 Raid 與 LVM 等手段,對數據提供了保護。

​ 2、多塊廉價的硬盤組合起來,提高容量。

​ 3、多塊磁盤組合出來的邏輯盤,提升讀寫效率。

缺點:

​ 1、采用 SAN 架構組網時,光纖交換機,造價成本高。

​ 2、主機之間無法共享數據。

使用場景

​ 1、Docker 容器、虛擬機磁盤存儲分配。

​ 2、日志存儲

​ 3、文件存儲

文件存儲

典型設備

​ FTP、NFS 服務器,為了克服塊存儲文件無法共享的問題,所以有了文件存儲,在服務器上架設 FTP 與 NFS 服務器,就是文件存儲。

優點:

​ 1、造價低,隨便一台機器就可以了

​ 2、方便文件可以共享

缺點:

​ 1、讀寫速率低

​ 2、傳輸速率慢

使用場景

​ 1、日志存儲

​ 2、有目錄結構的文件存儲

對象存儲

典型設備

​ 內置大容量硬盤的分布式服務器(swift, s3);多台服務器內置大容量硬盤,安裝上對象存儲管理軟件,對外提供讀寫訪問功能。

優點:

​ 1、具備塊存儲的讀寫高速。

​ 2、具備文件存儲的共享等特性

使用場景:(適合更新變動較少的數據)

​ 1、圖片存儲

​ 2、視頻存儲

部署

由於我們這里在 Kubernetes 集群中使用,也為了方便管理,我們這里使用 Rook 來部署 Ceph 集群,Rook 是一個開源的雲原生存儲編排工具,提供平台、框架和對各種存儲解決方案的支持,以和雲原生環境進行本地集成。

Rook 將存儲軟件轉變成自我管理、自我擴展和自我修復的存儲服務,通過自動化部署、啟動、配置、供應、擴展、升級、遷移、災難恢復、監控和資源管理來實現。Rook 底層使用雲原生容器管理、調度和編排平台提供的能力來提供這些功能,其實就是我們平常說的 Operator。Rook 利用擴展功能將其深度集成到雲原生環境中,並為調度、生命周期管理、資源管理、安全性、監控等提供了無縫的體驗。有關 Rook 當前支持的存儲解決方案的狀態的更多詳細信息,可以參考 Rook 倉庫 的項目介紹。

image

組件

​ 1、Rook Operator:Rook 的核心組件,Rook Operator 是一個簡單的容器,自動啟動存儲集群,並監控存儲守護進程,來確保存儲集群的健康。

​ 2、Rook Agent:在每個存儲節點上運行,並配置一個 FlexVolume 或者 CSI 插件,和 Kubernetes 的存儲卷控制框架進行集成。Agent 處理所有的存儲操作,例如掛接網絡存儲設備、在主機上加載存儲卷以及格式化文件系統等。

​ 3、Rook Discovers:檢測掛接到存儲節點上的存儲設備。

Rook 還會用 Kubernetes Pod 的形式,部署 Ceph 的 MON、OSD 以及 MGR 守護進程。Rook Operator 讓用戶可以通過 CRD 來創建和管理存儲集群。每種資源都定義了自己的 CRD:

​ 1、RookCluster:提供了對存儲機群的配置能力,用來提供塊存儲、對象存儲以及共享文件系統。每個集群都有多個 Pool。

​ 2、Pool:為塊存儲提供支持,Pool 也是給文件和對象存儲提供內部支持。

​ 3、Object Store:用 S3 兼容接口開放存儲服務。

​ 4、File System:為多個 Kubernetes Pod 提供共享存儲。

安裝

首先在節點上安裝lvm2軟件包:

# Centos
sudo yum install -y lvm2

# Ubuntu
sudo apt-get install -y lvm2

這里部署用的是 release-1.2 版本的 Rook,部署清單文件地址:https://github.com/rook/rook/tree/release-1.2/cluster/examples/kubernetes/ceph。

從上面鏈接中獲取 common.yaml 與 operator.yaml 兩個資源清單文件:

# 會安裝crd、rbac相關資源對象
$ kubectl apply -f common.yaml
# 安裝 rook operator
$ kubectl apply -f operator.yaml

在繼續操作之前,驗證 rook-ceph-operator 是否處於“Running”狀態:

$ kubectl get pod -n rook-ceph
NAME                                  READY   STATUS    RESTARTS   AGE
rook-ceph-operator-658dfb6cc4-qx9bg   1/1     Running   0          69s
rook-discover-t8xqd                   1/1     Running   0          13s
rook-discover-xxwf6                   1/1     Running   0          13s

可以看到 Operator 運行成功后,還會有一個 DaemonSet 控制器運行得 rook-discover 應用,當 Rook Operator 處於 Running 狀態,我們就可以創建 Ceph 集群了。為了使集群在重啟后不受影響,請確保設置的 dataDirHostPath 屬性值為有效得主機路徑。更多相關設置,可以查看集群配置相關文檔

創建如下資源清單:

apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  name: rook-ceph
  namespace: rook-ceph
spec:
  cephVersion:
    # 最新得 ceph 鏡像, 可以查看 https://hub.docker.com/r/ceph/ceph/tags
    image: ceph/ceph:v14.2.5
  dataDirHostPath: /var/lib/rook  # 主機有效目錄
  mon:
    count: 2
  dashboard:
    enabled: true
  storage:
    useAllNodes: true
    useAllDevices: false
    # 重要: Directories 應該只在預生產環境中使用
    directories:
    - path: /data/rook

其中有幾個比較重要的字段:

  • dataDirHostPath:宿主機上的目錄,用於每個服務存儲配置和數據。如果目錄不存在,會自動創建該目錄。由於此目錄在主機上保留,因此在刪除 Pod 后將保留該目錄,另外不得使用以下路徑及其任何子路徑:/etc/ceph/rook/var/log/ceph
  • useAllNodes:用於表示是否使用集群中的所有節點進行存儲,如果在 nodes 字段下指定了各個節點,則必須將useAllNodes設置為 false。
  • useAllDevices:表示 OSD 是否自動使用節點上的所有設備,一般設置為 false,這樣可控性較高
  • directories:一般來說應該使用一塊裸盤來做存儲,有時為了測試方便,使用一個目錄也是可以的,當然生成環境不推薦使用目錄。

除了上面這些字段屬性之外還有很多其他可以細粒度控制得參數,可以查看集群配置相關文檔

現在直接創建上面的 CephCluster 對象即可,創建完成后,Rook Operator就會根據我們的描述信息去自動創建Ceph集群了。

驗證

要驗證集群是否處於正常狀態,我們可以使用 Rook 工具箱 來運行 ceph status 命令查看。

Rook 工具箱是一個用於調試和測試 Rook 的常用工具容器,該工具基於 CentOS 鏡像,所以可以使用 yum 來輕松安裝更多的工具包。我們這里用 Deployment 控制器來部署 Rook 工具箱,部署的資源清單文件如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rook-ceph-tools
  namespace: rook-ceph
  labels:
    app: rook-ceph-tools
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rook-ceph-tools
  template:
    metadata:
      labels:
        app: rook-ceph-tools
    spec:
      dnsPolicy: ClusterFirstWithHostNet
      containers:
      - name: rook-ceph-tools
        image: rook/ceph:v1.2.1
        command: ["/tini"]
        args: ["-g", "--", "/usr/local/bin/toolbox.sh"]
        imagePullPolicy: IfNotPresent
        env:
          - name: ROOK_ADMIN_SECRET
            valueFrom:
              secretKeyRef:
                name: rook-ceph-mon
                key: admin-secret
        securityContext:
          privileged: true
        volumeMounts:
          - mountPath: /dev
            name: dev
          - mountPath: /sys/bus
            name: sysbus
          - mountPath: /lib/modules
            name: libmodules
          - name: mon-endpoint-volume
            mountPath: /etc/rook
      # 如果設置 hostNetwork: false,  "rbd map" 命令會被 hang 住, 參考 https://github.com/rook/rook/issues/2021
      hostNetwork: true
      volumes:
        - name: dev
          hostPath:
            path: /dev
        - name: sysbus
          hostPath:
            path: /sys/bus
        - name: libmodules
          hostPath:
            path: /lib/modules
        - name: mon-endpoint-volume
          configMap:
            name: rook-ceph-mon-endpoints
            items:
            - key: data
              path: mon-endpoints

一旦 toolbox 的 Pod 運行成功后,我們就可以使用下面的命令進入到工具箱內部進行操作:

$ kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') bash

工具箱中的所有可用工具命令均已准備就緒,可滿足您的故障排除需求。例如:

ceph status
ceph osd status
ceph df
rados df

比如現在我們要查看集群的狀態,需要滿足下面的條件才認為是健康的:

​ 1、所有 mons 應該達到法定數量

​ 2、mgr 應該是激活狀態

​ 3、至少有一個 OSD 處於激活狀態

​ 4、如果不是 HEALTH_OK 狀態,則應該查看告警或者錯誤信息

# ceph status
  cluster:
    id:     01afabec-6f13-4336-a2cb-c91bbbca7798
    health: HEALTH_WARN
            OSD count 2 < osd_pool_default_size 3
 
  services:
    mon: 2 daemons, quorum a,b (age 3m)
    mgr: a(active, since 2m)
    osd: 2 osds: 2 up (since 2m), 2 in (since 2m)
 
  data:
    pools:   0 pools, 0 pgs
    objects: 0 objects, 0 B
    usage:   45 GiB used, 25 GiB / 70 GiB avail
    pgs:     

如果群集運行不正常,可以查看 Ceph 常見問題以了解更多詳細信息和可能的解決方案。

Dashboard

Ceph 有一個 Dashboard 工具,我們可以在上面查看集群的狀態,包括總體運行狀態,mgr、osd 和其他 Ceph 進程的狀態,查看池和 PG 狀態,以及顯示守護進程的日志等等。

我們可以在上面的 cluster CRD 對象中開啟 dashboard,設置dashboard.enable=true即可,這樣 Rook Operator 就會啟用 ceph-mgr dashboard 模塊,並將創建一個 Kubernetes Service 來暴露該服務,將啟用端口 7000 進行 https 訪問,如果 Ceph 集群部署成功了,我們可以使用下面的命令來查看 Dashboard 的 Service:

$ kubectl get svc -n rook-ceph
NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
csi-cephfsplugin-metrics   ClusterIP   10.99.162.98     <none>        8080/TCP,8081/TCP   5m47s
csi-rbdplugin-metrics      ClusterIP   10.103.124.243   <none>        8080/TCP,8081/TCP   5m47s
rook-ceph-mgr              ClusterIP   10.102.96.161    <none>        9283/TCP            4m33s
rook-ceph-mgr-dashboard    ClusterIP   10.98.21.237     <none>        7000/TCP            4m58s
rook-ceph-mon-a            ClusterIP   10.99.73.73      <none>        6789/TCP,3300/TCP   5m20s
rook-ceph-mon-b            ClusterIP   10.108.132.47    <none>        6789/TCP,3300/TCP   5m15s

這里的 rook-ceph-mgr 服務用於報告 Prometheus metrics 指標數據的,而后面的的 rook-ceph-mgr-dashboard 服務就是我們的 Dashboard 服務,如果在集群內部我們可以通過 DNS 名稱 http://rook-ceph-mgr-dashboard.rook-ceph:7000或者 CluterIP http://10.111.195.180:7000 來進行訪問,但是如果要在集群外部進行訪問的話,我們就需要通過 Ingress 或者 NodePort 類型的 Service 來暴露了,為了方便測試我們這里創建一個新的 NodePort 類型的服務來訪問 Dashboard,資源清單如下所示:

apiVersion: v1
kind: Service
metadata:
  name: rook-ceph-mgr-dashboard-external
  namespace: rook-ceph
  labels:
    app: rook-ceph-mgr
    rook_cluster: rook-ceph
spec:
  ports:
  - name: dashboard
    port: 7000
    protocol: TCP
    targetPort: 7000
  selector:
    app: rook-ceph-mgr
    rook_cluster: rook-ceph
  type: NodePort

創建完成后我們可以查看到新創建的 rook-ceph-mgr-dashboard-external 這個 Service 服務:

$ kubectl get svc -n rook-ceph
NAME                               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
csi-cephfsplugin-metrics           ClusterIP   10.99.162.98     <none>        8080/TCP,8081/TCP   9m17s
csi-rbdplugin-metrics              ClusterIP   10.103.124.243   <none>        8080/TCP,8081/TCP   9m17s
rook-ceph-mgr                      ClusterIP   10.102.96.161    <none>        9283/TCP            8m3s
rook-ceph-mgr-dashboard            ClusterIP   10.98.21.237     <none>        7000/TCP            8m28s
rook-ceph-mgr-dashboard-external   NodePort    10.110.93.143    <none>        7000:32745/TCP      7s
rook-ceph-mon-a                    ClusterIP   10.99.73.73      <none>        6789/TCP,3300/TCP   8m50s
rook-ceph-mon-b                    ClusterIP   10.108.132.47    <none>        6789/TCP,3300/TCP   8m45s

現在我們需要通過 http://<NodeIp>:32745 就可以訪問到 Dashboard 了。

image

但是在訪問的時候需要我們登錄才能夠訪問,Rook 創建了一個默認的用戶 admin,並在運行 Rook 的命名空間中生成了一個名為 rook-ceph-dashboard-admin-password 的 Secret,要獲取密碼,可以運行以下命令:

$ kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo
xxxx(登錄密碼)

image

使用

現在我們的 Ceph 集群搭建成功了,我們就可以來使用存儲了。首先我們需要創建存儲池,可以用 CRD 來定義 Pool。Rook 提供了兩種機制來維持 OSD:

​ 1、副本:缺省選項,每個對象都會根據 spec.replicated.size 在多個磁盤上進行復制。建議非生產環境至少 2 個副本,生產環境至少 3 個。

​ 2、Erasure Code:是一種較為節約的方式。EC 把數據拆分 n 段(spec.erasureCoded.dataChunks),再加入 k 個代碼段(spec.erasureCoded.codingChunks),用分布的方式把 n+k 段數據保存在磁盤上。這種情況下 Ceph 能夠隔離 k 個 OSD 的損失。

我們這里使用副本的方式,創建如下所示的 RBD 類型的存儲池:

apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
  name: k8s-test-pool   # operator會監聽並創建一個pool,執行完后界面上也能看到對應的pool
  namespace: rook-ceph
spec:
  failureDomain: host  # 數據塊的故障域: 值為host時,每個數據塊將放置在不同的主機上;值為osd時,每個數據塊將放置在不同的osd上
  replicated:
    size: 3   # 池中數據的副本數,1就是不保存任何副本

存儲池創建完成后我們在 Dashboard 上面的確可以看到新增了一個 pool,而且集群健康狀態下多了一條日志:

Health check update: too few PGs per OSD (6 < min 30) (TOO_FEW_PGS)

這是因為每個 osd 上的 pg 數量小於最小的數目30個。pgs 為8,因為是3副本的配置,所以當有4個 osd 的時候,每個 osd 上均分了8/4 *3=6個pgs,也就是出現了如上的錯誤小於最小配置30個,集群這種狀態如果進行數據的存儲和操作,集群會卡死,無法響應io,同時會導致大面積的 osd down。

我們可以進入 toolbox 的容器中查看上面存儲的 pg 數量,並可以通過增加pg_num來解決這個問題:

$ ceph osd pool get k8s-test-pool pg_num
pg_num: 8

$ ceph osd pool set k8s-test-pool pg_num 64
set pool 1 pg_num to 64

$ ceph -s
  cluster:
    id:     01afabec-6f13-4336-a2cb-c91bbbca7798
    health: HEALTH_WARN
            OSD count 2 < osd_pool_default_size 3
 
  services:
    mon: 2 daemons, quorum a,b (age 18m)
    mgr: a(active, since 17m)
    osd: 2 osds: 2 up (since 16m), 2 in (since 16m)
 
  data:
    pools:   1 pools, 64 pgs
    objects: 0 objects, 0 B
    usage:   45 GiB used, 25 GiB / 70 GiB avail
    pgs:     64 active+undersized

不過需要注意的是我們這里的 pool 上沒有數據,所以修改 pg 影響並不大,但是如果是生產環境重新修改 pg 數,會對生產環境產生較大影響。因為 pg 數變了,就會導致整個集群的數據重新均衡和遷移,數據越大響應 io 的時間會越長。所以,最好在一開始就設置好 pg 數。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
  # clusterID 是 rook 集群運行的命名空間
  clusterID: rook-ceph

  # 指定存儲池
  pool: k8s-test-pool

  # RBD image (實際的存儲介質) 格式. 默認為 "2".
  imageFormat: "2"

  # RBD image 特性. CSI RBD 現在只支持 `layering` .
  imageFeatures: layering

  # Ceph 管理員認證信息,這些都是在 clusterID 命名空間下面自動生成的
  csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
  csi.storage.k8s.io/provisioner-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
  # 指定 volume 的文件系統格式,如果不指定, csi-provisioner 會默認設置為 `ext4`
  csi.storage.k8s.io/fstype: ext4
# uncomment the following to use rbd-nbd as mounter on supported nodes
# **IMPORTANT**: If you are using rbd-nbd as the mounter, during upgrade you will be hit a ceph-csi
# issue that causes the mount to be disconnected. You will need to follow special upgrade steps
# to restart your application pods. Therefore, this option is not recommended.
#mounter: rbd-nbd
reclaimPolicy: Delete

直接創建上面的StorageClass資源對象,接着創建一個PVC來使用這個StorageClass對象:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
  labels:
    app: wordpress
spec:
  storageClassName: rook-ceph-block
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

創建完成后我們可以看到我們的 PVC 對象已經是 Bound 狀態了,自動創建了對應的 PV,然后我們就可以直接使用這個 PVC 對象來做數據持久化操作了。

$ kubectl get pvc -l app=wordpress
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
mysql-pv-claim   Bound    pvc-865bff43-d921-491b-9452-aeae64e80109   20Gi       RWO            rook-ceph-block   16s

在官方倉庫 cluster/examples/kubernetes 目錄下,官方給了個 wordpress 的例子,可以直接運行測試即可:

$ kubectl apply -f mysql.yaml
$ kubectl apply -f wordpress.yaml 

官方的這個示例里面的 wordpress 用的 Loadbalancer 類型,我們可以改成 NodePort:

$ kubectl get svc
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes        ClusterIP   10.96.0.1       <none>        443/TCP        54m
wordpress         NodePort    10.104.129.67   <none>        80:32383/TCP   51s
wordpress-mysql   ClusterIP   None            <none>        3306/TCP       63s

當應用都處於 Running 狀態后,我們可以通過 `http://<任意節點IP>:32383 去訪問 wordpress 應用:

image

現在我在WordPress里創建了一個Ceph測試文章。

現在將應用的Pod全部刪掉重建:

$ kubectl delete pod -l app=wordpress
pod "wordpress-7bfc545758-pgzth" deleted
pod "wordpress-mysql-764fc64f97-vm6ml" deleted

$ kubectl get pod -l app=wordpress
NAME                               READY   STATUS    RESTARTS   AGE
wordpress-7bfc545758-chffm         1/1     Running   0          41s
wordpress-mysql-764fc64f97-k5phc   1/1     Running   0          41s

當 Pod 重建完成后再次訪問 wordpress 應用的主頁我們可以發現之前我們添加的數據仍然存在,這就證明我們的數據持久化是正確的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM