K8S使用Ceph RBD作为后端存储

本文介绍在K8S上试用Ceph RBD存储的方法。先进行准备工作,包括在Ceph上准备存储池、K8S客户端账号,为controller - manager和kubelet提供rbd命令。然后在K8S上创建存储类、提供secret、创建PVC和测试应用,还测试了pod切换节点后数据的使用情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、准备工作

Ceph版本:v13.2.5 mimic稳定版

1、Ceph上准备存储池

[root@ceph-node1 ceph]# ceph osd pool create k8s 128 128
pool 'k8s' created
[root@ceph-node1 ceph]# ceph osd pool ls
k8s

2、Ceph上准备K8S客户端账号

本环境中直接使用了Ceph的admin账号,当然生产环境中还是要根据不同功能客户端分配不同的账号:
ceph auth get-or-create client.k8s mon 'allow r' osd 'allow rwx pool=k8s' -o ceph.client.k8s.keyring
获取账号的密钥:

[root@ceph-node1 ceph]# ceph auth get-key client.admin | base64
QVFDMmIrWmNEL3JTS2hBQWwwdmR3eGJGMmVYNUM3SjdDUGZZbkE9PQ==

3、为controller-manager提供rbd命令

使用StorageClass动态创建PV时,controller-manager会自动在Ceph上创建image,所以我们要为其准备好rbd命令。
(1) 如果集群是用kubeadm部署的,由于controller-manager官方镜像中没有rbd命令,所以我们要导入外部配置:

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: extensions/v1beta1 
kind: Deployment 
metadata: 
  name: rbd-provisioner 
spec: 
  replicas: 1 
  strategy: 
    type: Recreate 
  template: 
    metadata: 
      labels: 
        app: rbd-provisioner 
    spec: 
      containers: 
      - name: rbd-provisioner 
        image: quay.io/external_storage/rbd-provisioner:latest 
        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
注意:rbd-provisioner的镜像要和ceph的版本适配,这里镜像使用最新的,根据官方提示已支持ceph mimic版。
K8S使用Ceph RBD作为后端存储
(2) 如果集群是用二进制方式部署的,直接在master节点安装ceph-common即可。
YUM源:

[Ceph]
name=Ceph packages for $basearch
baseurl=http://download.ceph.com/rpm-mimic/el7/$basearch
enabled=1
gpgcheck=1
type=rpm-md
gpgkey=https://download.ceph.com/keys/release.asc
priority=1
[Ceph-noarch]
name=Ceph noarch packages
baseurl=http://download.ceph.com/rpm-mimic/el7/noarch
enabled=1
gpgcheck=1
type=rpm-md
gpgkey=https://download.ceph.com/keys/release.asc
priority=1
[ceph-source]
name=Ceph source packages
baseurl=http://download.ceph.com/rpm-mimic/el7/SRPMS
enabled=1
gpgcheck=1
type=rpm-md
gpgkey=https://download.ceph.com/keys/release.asc
priority=1

#安装客户端
yum -y install ceph-common-13.2.5
#拷贝keyring文件
将ceph的ceph.client.admin.keyring文件拷贝到master的/etc/ceph目录下。

4、为kubelet提供rbd命令

创建pod时,kubelet需要使用rbd命令去检测和挂载pv对应的ceph image,所以要在所有的worker节点安装ceph客户端ceph-common-13.2.5。

二、K8S上试用Ceph RBD存储

1、创建存储类

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: ceph-sc
  namespace: default
  annotations: 
    storageclass.kubernetes.io/is-default-class: "false"
provisioner: ceph.com/rbd
reclaimPolicy: Retain
parameters:
  monitors: 172.16.1.31:6789,172.16.1.32:6789,172.16.1.33:6789
  adminId: admin
  adminSecretName: storage-secret
  adminSecretNamespace: default
  pool: k8s
  fsType: xfs
  userId: admin
  userSecretName: storage-secret
  imageFormat: "2"
  imageFeatures: "layering"

kubectl apply -f storage_class.yaml

2、为存储类提供secret

apiVersion: v1
kind: Secret
metadata:
  name: storage-secret
  namespace: default
data:
  key: QVFDMmIrWmNEL3JTS2hBQWwwdmR3eGJGMmVYNUM3SjdDUGZZbkE9PQ==
type:
  kubernetes.io/rbd

kubectl apply -f storage_secret.yaml
注意:provisioner的值要和rbd-provisioner设置的值一样

3、创建PVC

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

kubectl apply -f storage_pvc.yaml
#创建完PVC后,PV会自动创建:

[root@k8s-master03 ceph]# kubectl get pv       
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS   REASON   AGE
pvc-315991e9-7d4b-11e9-b6cc-0050569ba238   1Gi        RWO            Retain           Bound    default/ceph-sc-test   prom-sc                 13h

#正常情况PVC也处于Bound状态

[root@k8s-master03 ceph]# kubectl get pvc
NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ceph-sc-test   Bound    pvc-315991e9-7d4b-11e9-b6cc-0050569ba238   1Gi        RWO            prom-sc        17s

4、创建测试应用

apiVersion: v1
kind: Pod
metadata:
  name: ceph-pod1
spec:
  nodeName: k8s-node02
  containers:
  - name: nginx
    image: nginx:1.14
    volumeMounts:
    - name: ceph-rdb-vol1
      mountPath: /usr/share/nginx/html
      readOnly: false
  volumes:
  - name: ceph-rdb-vol1
    persistentVolumeClaim:
      claimName: ceph-pvc

kubectl apply -f storage_pod.yaml
#查看pod状态

[root@k8s-master03 ceph]# kubectl get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE     IP            NODE         NOMINATED NODE   READINESS GATES
ceph-pod1                        1/1     Running   0          3d23h   10.244.4.75   k8s-node02   <none>           <none>

#进入容器查看挂载情况,可以看到rbd已挂载到/usr/share/nginx/html目录。

[root@k8s-master03 ceph]# kubectl exec -it ceph-pod1 -- /bin/bash
root@ceph-pod1:/# df –hT
/dev/rbd0            xfs     1014M   33M  982M   4% /usr/share/nginx/html
#在挂载目录下添加一个测试文件
root@ceph-pod1:/# cat /usr/share/nginx/html/index.html
hello ceph!

#在Ceph上检查对应image挂载的节点,目前在172.16.1.22即k8s-node02。

[root@ceph-node1 ~]# rbd status k8s/kubernetes-dynamic-pvc-2410765c-7dec-11e9-aa80-26a98c3bc9e4
Watchers:
        watcher=172.16.1.22:0/264870305 client.24553 cookie=18446462598732840961

#而后我们删掉这个的pod

[root@k8s-master03 ceph]# kubectl delete -f  storage_pod.yaml   
pod "ceph-pod1" deleted

#修改清单文件storage_pod.yaml,将pod调度到k8s-node01上,并应用。
#稍后,查看pod的状态,改pod已部署在k8s-node01上了。

[root@k8s-master01 ~]# kubectl get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE    IP            NODE         NOMINATED NODE   READINESS GATES
ceph-pod1                        1/1     Running   0          34s    10.244.3.28   k8s-node01   <none>           <none>

#在Ceph上再次检查image挂载节点,目前在172.16.1.21即k8s-node01

[root@ceph-node1 ~]# rbd status k8s/kubernetes-dynamic-pvc-2410765c-7dec-11e9-aa80-26a98c3bc9e4
Watchers:
        watcher=172.16.1.21:0/1812501701 client.114340 cookie=18446462598732840963

#进入容器,检查文件存在并没有丢失,说明pod切换节点后使用了原来的image。

[root@k8s-master03 ceph]# kubectl exec -it ceph-pod1 -- /bin/bash
root@ceph-pod1:/# cat /usr/share/nginx/html/index.html
hello ceph!

转载于:https://blog.51cto.com/fengjicheng/2401702

<think>好的,用户现在问的是,如果他们的Kubernetes集群没有后端存储来持久化Elasticsearch集群数据,应该怎么办。之前已经讨论过在K8s中部署ES多副本StatefulSet和配置Kibana的问题,现在用户可能遇到了存储方面的问题,或者正在规划他们的集群架构,想知道没有持久化存储的影响和应对方法。 首先,我需要明确用户的问题核心。用户可能是在测试环境中,或者资源有限,无法配置持久化存储(如Persistent Volumes)。他们想知道在这种情况下运行ES集群会有什么后果,以及如何应对。 接下来,要考虑没有持久化存储的影响。ES是一个有状态应用,数据存储非常重要。如果没有持久化,Pod重启或调度到其他节点时,数据会丢失,可能导致集群健康状态恶化,甚至数据不可用。这对于生产环境是灾难性的,但在开发或测试环境中,可能可以接受临时数据丢失。 然后,需要分析可能的解决方案。用户可能希望即使没有持久化存储,也能临时运行ES,或者寻找替代存储方案。例如,使用emptyDir或者hostPath作为临时存储,但这两种方式都有各自的局限性和风险。需要向用户解释这些选项的优缺点,以及适用场景。 另外,用户可能没有意识到没有持久化存储的长期影响,需要强调持久化的重要性,尤其是在生产环境中。同时,如果用户确实无法提供后端存储,可能需要建议他们考虑其他部署方式,或者使用云服务提供的托管ES服务,避免自行管理存储。 在回答结构上,应该先说明后果,再给出临时方案,最后强调持久化的必要性。同时,结合之前的讨论,可能用户已经部署了ES,但未配置存储,需要检查他们的YAML配置,指出需要修改的部分,比如volumeClaimTemplates部分是否需要注释掉,或者改用其他卷类型。 还需要注意用户是否了解K8s存储机制,可能需要简要解释Persistent Volume(PV)和Persistent Volume Claim(PVC)的概念,以及为什么它们对于有状态应用如ES是必要的。如果用户的环境不支持动态PV配置,可能需要指导他们如何手动配置,或者使用本地存储方案。 最后,要确保回答清晰,分点列出后果、临时方案和长期建议,帮助用户逐步理解问题,并根据他们的实际情况做出决策。同时,提醒用户即使使用临时方案,也要注意数据备份和恢复策略,避免数据丢失带来的风险。</think>--- ### 一、核心结论 **若Kubernetes集群无后端存储(如PersistentVolume)持久化ES数据:** - ⚠️ **ES节点数据将随Pod删除或重启而丢失,导致集群状态不稳定**。 - ✅ **临时测试场景可通过`emptyDir`或`hostPath`暂存数据,但生产环境强烈不建议**。 --- ### 二、无持久化存储的后果与风险 #### **1. 数据丢失场景** | **场景** | **后果** | |--------------------------|-------------------------------------| | Pod重启(如节点故障) | Pod数据卷(`emptyDir`)被清空,ES节点数据丢失 | | StatefulSet缩容 | 被删除的Pod关联数据无法恢复 | | 集群整体重建 | 所有ES索引数据彻底丢失 | #### **2. ES集群状态异常表现** - 集群健康状态为`red`(分片不可用)。 - Kibana查询时报错:`No shard available for [index_name]`。 - 节点重启后可能无法重新加入集群(因元数据丢失)。 --- ### 三、临时解决方案(仅限测试环境) #### **1. 使用`emptyDir`临时存储** 修改ES StatefulSet的存储配置,移除`volumeClaimTemplates`,改用`emptyDir`: ```yaml # ES StatefulSet示例(临时存储) spec: template: spec: containers: - name: es volumeMounts: - name: es-data mountPath: /usr/share/elasticsearch/data volumes: - name: es-data emptyDir: {} # 数据存储在Pod所在节点的临时目录 ``` **特点**: - 数据在Pod生命周期内保留,但Pod删除后数据丢失。 - 节点间数据隔离,无法跨Pod共享。 #### **2. 使用`hostPath`本地目录(需谨慎)** 将节点本地目录挂载到Pod中: ```yaml volumes: - name: es-data hostPath: path: /mnt/elasticsearch-data # 需手动在节点上创建目录 type: DirectoryOrCreate ``` **风险**: - 节点故障时数据可能丢失(依赖本地磁盘可靠性)。 - Pod调度到其他节点时,数据无法自动迁移。 --- ### 四、生产环境必须持久化的原因 #### **1. 数据可靠性要求** - **ES分片机制依赖持久化数据**:主分片与副本分片需持久化存储保障一致性。 - **索引元数据(如`_cluster`状态)需持久保存**,否则集群无法恢复。 #### **2. 推荐持久化方案** | **存储类型** | **适用场景** | **示例配置** | |---------------------|---------------------------------|----------------------------------| | **云厂商块存储** | AWS EBS、GCP PD、Azure Disk | `storageClassName: gp2`(AWS) | | **分布式存储** | Ceph RBD、Longhorn、Rook | `storageClassName: rook-cephfs` | | **本地SSD(需RAID)** | 物理服务器环境 | `storageClassName: local-ssd` | **StatefulSet持久化配置示例**: ```yaml volumeClaimTemplates: - metadata: name: es-data spec: accessModes: [ "ReadWriteOnce" ] storageClassName: "rook-ceph-block" # 根据实际存储类修改 resources: requests: storage: 50Gi ``` --- ### 五、无持久化时的应急恢复策略 #### **1. 定期备份索引快照** 即使无持久化,可通过快照临时保存数据到外部存储(如S3): ```bash # 创建快照仓库 PUT _snapshot/my_backup { "type": "s3", "settings": { "bucket": "my-es-backup-bucket", "region": "us-west-2" } } # 手动触发快照 PUT _snapshot/my_backup/snapshot_1 ``` #### **2. 重建集群时恢复快照** ```bash # 恢复快照(需先创建同名索引) POST _snapshot/my_backup/snapshot_1/_restore ``` --- ### 六、总结建议 | **场景** | **存储方案** | **数据可靠性** | **适用性** | |------------------|---------------------------|--------------|------------------| | **开发/测试** | `emptyDir`或`hostPath` | 低 | 短期临时使用 | | **生产环境** | 云存储/分布式存储 + PVC | 高 | 必须配置 | **关键决策点**: - 若集群仅为短期测试(如CI/CD流水线),可接受数据丢失,使用`emptyDir`。 - 若需保留索引数据,必须配置持久化存储,并定期备份快照。 - 资源受限时,可考虑托管ES服务(如Elastic Cloud、AWS OpenSearch)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值