【Kubernetes 企业项目实战】05、基于云原生分布式存储 Ceph 实现 K8s 数据持久化(下)

news2024/9/27 17:32:48

目录

一、K8s 对接 ceph rbd 实现数据持久化

1.1 k8s 安装 ceph

1.2 创建 pod 挂载 ceph rbd

二、基于 ceph rbd 生成 pv

2.1 创建 ceph-secret

2.2 创建 ceph 的 secret

2.3 创建 pool 池

2.4 创建 pv

2.5 创建 pvc

2.6 测试 pod 挂载 pvc

2.7 注意事项

1)ceph rbd 块存储的特点

2)Deployment 更新特性

3)问题:

三、基于存储类 Storageclass 动态从 Ceph 划分 PV

3.1 准备工作

3.2 创建 rbd 的供应商 provisioner

3.3 创建 ceph-secret

3.4 创建 storageclass

3.5 创建 pvc

3.6 创建 pod 挂载 pvc

四、K8s 挂载 cephfs 实现数据持久化

4.1 创建 ceph 子目录

4.2 测试 pod 挂载 cephfs

1)创建 k8s 连接 ceph 使用的 secret

2)创建第一个 pod 挂载 cephfs-pvc

3)创建第二个 pod 挂载 cephfs-pvc


本篇文章所用到的资料文件下载地址:https://download.csdn.net/download/weixin_46560589/87403746

一、K8s 对接 ceph rbd 实现数据持久化

  • k8s-v1.23 环境

1.1 k8s 安装 ceph

        kubernetes 要想使用 ceph,需要在 k8s 的每个 node 节点安装 ceph-common,把 ceph 节点上的 ceph.repo 文件拷贝到 k8s 各个节点 /etc/yum.repos.d/ 目录下,然后在 k8s 的各个节点执行 yum install ceph-common -y :

[root@master1-admin ceph]# scp /etc/yum.repos.d/ceph.repo 192.168.78.143:/etc/yum.repos.d/
[root@master1-admin ceph]# scp /etc/yum.repos.d/ceph.repo 192.168.78.144:/etc/yum.repos.d/
[root@master1-admin ceph]# scp /etc/yum.repos.d/ceph.repo 192.168.78.145:/etc/yum.repos.d/

yum install ceph-common -y

# 将 ceph 配置文件拷贝到 k8s 的各节点
[root@master1-admin ceph]# scp /etc/ceph/* 192.168.78.143:/etc/ceph/
[root@master1-admin ceph]# scp /etc/ceph/* 192.168.78.144:/etc/ceph/
[root@master1-admin ceph]# scp /etc/ceph/* 192.168.78.145:/etc/ceph/

# 创建ceph rbd
[root@master1-admin ceph]# ceph osd pool create k8srbd1 6
pool 'k8srbd1' created

[root@master1-admin ceph]# rbd create rbda -s 1024 -p k8srbd1

# 禁用一些没用的特性
[root@master1-admin ceph]# rbd feature disable k8srbd1/rbda object-map fast-diff deep-flatten

1.2 创建 pod 挂载 ceph rbd

[root@k8s-master1 ~]# mkdir ceph
[root@k8s-master1 ~]# cd ceph/
[root@k8s-master1 ceph]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testrbd
spec:
  containers:
    - image: nginx
      name: nginx
      imagePullPolicy: IfNotPresent
      volumeMounts:
      - name: testrbd
        mountPath: /mnt
  volumes:
    - name: testrbd
      rbd:
        monitors:
        - '192.168.78.135:6789'    # ceph 集群节点
        - '192.168.78.136:6789'
        - '192.168.78.137:6789'
        pool: k8srbd1
        image: rbda
        fsType: xfs
        readOnly: false
        user: admin
        keyring: /etc/ceph/ceph.client.admin.keyring

[root@k8s-master1 ceph]# kubectl apply -f pod.yaml 

[root@k8s-master1 ceph]# kubectl get pods testrbd -o wide 
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE        NOMINATED NODE   READINESS GATES
testrbd   1/1     Running   0          34s   10.244.36.96   k8s-node1   <none>           <none>

注意:k8srbd1 下的 rbda 被 pod 挂载了,那其他 pod 就不能使用这个 k8srbd1 下的 rbda 了!

二、基于 ceph rbd 生成 pv

2.1 创建 ceph-secret

        这个 k8s secret 对象用于 k8s volume 插件访问 ceph 集群,获取 client.admin 的 keyring 值,并用 base64 编码,在 master1-admin(ceph 管理节点)操作:

# 每个人的不一样,是唯一的
[root@master1-admin ceph]# ceph auth get-key client.admin | base64
QVFES0hOWmpaWHVHQkJBQTM1NGFSTngwcGloUWxWYjhVblM2dUE9PQ==

2.2 创建 ceph 的 secret

在 k8s 的控制节点操作:

[root@k8s-master1 ceph]# vim ceph-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret
data:
  key: QVFES0hOWmpaWHVHQkJBQTM1NGFSTngwcGloUWxWYjhVblM2dUE9PQ==

[root@k8s-master1 ceph]# kubectl apply -f ceph-secret.yaml 
secret/ceph-secret created

[root@k8s-master1 ceph]# kubectl get secrets 
NAME                          TYPE                                  DATA   AGE
ceph-secret                   Opaque                                1      16s

2.3 创建 pool 池

[root@master1-admin ceph]# ceph osd pool create k8stest 6
pool 'k8stest' created

[root@master1-admin ceph]# rbd create rbda -s 1024 -p k8stest

[root@master1-admin ceph]# rbd feature disable  k8stest/rbda object-map fast-diff deep-flatten

2.4 创建 pv

[root@k8s-master1 ceph]# vim pv.yaml
apiVersion: v1
kind: PersistentVolume 
metadata: 
  name: ceph-pv 
spec:   
   capacity:     
     storage: 1Gi   
   accessModes:     
   - ReadWriteOnce   
   rbd:     
         monitors:       
         - '192.168.78.135:6789'
         - '192.168.78.136:6789'
         - '192.168.78.137:6789'    
         pool: k8stest     
         image: rbda     
         user: admin     
         secretRef:       
             name: ceph-secret     
         fsType: xfs     
         readOnly: false   
   persistentVolumeReclaimPolicy: Recycle

[root@k8s-master1 ceph]# kubectl apply -f pv.yaml 
persistentvolume/ceph-pv created

[root@k8s-master1 ceph]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                            STORAGECLASS       REASON   AGE
ceph-pv                                    1Gi        RWO            Recycle          Available                                                                3s

2.5 创建 pvc

[root@k8s-master1 ceph]# vim pvc.yaml
kind: PersistentVolumeClaim 
apiVersion: v1 
metadata:   
  name: ceph-pvc 
spec:   
  accessModes:     
  - ReadWriteOnce   
  resources:     
   requests:       
    storage: 1Gi

[root@k8s-master1 ceph]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/ceph-pvc created

[root@k8s-master1 ceph]# kubectl get pvc
NAME       STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ceph-pvc   Bound    ceph-pv   1Gi        RWO                           4s

2.6 测试 pod 挂载 pvc

[root@k8s-master1 ceph]# vim pod-pvc.yaml
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
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
          - mountPath: "/ceph-data"
            name: ceph-data
      volumes:
      - name: ceph-data
        persistentVolumeClaim:
            claimName: ceph-pvc

[root@k8s-master1 ceph]# kubectl apply -f pod-pvc.yaml 

        注意:deployment 生成的 pod 必须与前面创建的 pv 在同一节点才行,不然会出现下面这种情况:

其中一个 pod 是 ContainerCreating 状态,原因是 pv 已被占用,pv 不能跨节点!!!

解决办法:

# 在原来的基础上添加一个 nodeselector 节点选择器
# 给指定节点创建标签
[root@k8s-master1 ceph]# kubectl label nodes k8s-node1 project=ceph-pv

[root@k8s-master1 ceph]# vim pod-pvc.yaml 
······
        volumeMounts:
          - mountPath: "/ceph-data"
            name: ceph-data
      nodeSelector:
        project: ceph-pv
      volumes:
······

[root@k8s-master1 ceph]# kubectl delete -f pod-pvc.yaml 

[root@k8s-master1 ceph]# kubectl apply -f pod-pvc.yaml 

[root@k8s-master1 ceph]# kubectl get pods -o wide 
NAME                                READY   STATUS    RESTARTS      AGE   IP               NODE        NOMINATED NODE   READINESS GATES
nginx-deployment-75b94569dc-6fgxp   1/1     Running   0             70s   10.244.36.103    k8s-node1   <none>           <none>
nginx-deployment-75b94569dc-6w9m7   1/1     Running   0             70s   10.244.36.104    k8s-node1   <none>           <none>

通过上面实验可以发现 pod 是可以以 ReadWriteOnce 共享挂载相同的 pvc 的。

2.7 注意事项

1)ceph rbd 块存储的特点

  • 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 不会正常运行。

2)Deployment 更新特性

        deployment 触发更新的时候,它确保至少所需 Pods 75% 处于运行状态(最大不可用比例为 25%)。故像一个 pod 的情况,肯定是新创建一个新的 pod,新 pod 运行正常之后,再关闭老的 pod。

默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 25%。

3)问题:

结合 ceph rbd 共享挂载的特性和 deployment 更新的特性,我们发现原因如下:

        由于 deployment 触发更新,为了保证服务的可用性,deployment 要先创建一个 pod 并运行正常之后,再去删除老 pod。而如果新创建的 pod 和老 pod 不在一个 node,就会导致此故障。

解决办法:

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

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

三、基于存储类 Storageclass 动态从 Ceph 划分 PV

3.1 准备工作

在 ceph 集群和 k8s 集群中各节点都需要执行下面命令:

chmod 777 -R /etc/ceph/*

mkdir /root/.ceph/

cp -ar /etc/ceph/ /root/.ceph/

3.2 创建 rbd 的供应商 provisioner

把 rbd-provisioner.tar.gz 上传到 node1、node2 上手动解压:

[root@k8s-node1 ~]# docker load -i rbd-provisioner.tar.gz 
[root@k8s-node2 ~]# docker load -i rbd-provisioner.tar.gz 

[root@k8s-master1 ceph]# vim rbd-provisioner.yaml
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
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: rbd-provisioner

[root@k8s-master1 ceph]# kubectl apply -f rbd-provisioner.yaml 

[root@k8s-master1 ceph]# kubectl get pods 
NAME                               READY   STATUS    RESTARTS      AGE
rbd-provisioner-5d58f65ff5-9c8q2   1/1     Running   0             2s

3.3 创建 ceph-secret

# 创建 pool 池
[root@master1-admin ~]# ceph osd pool create k8stest1 6

[root@master1-admin ~]# ceph auth get-key client.admin | base64
QVFES0hOWmpaWHVHQkJBQTM1NGFSTngwcGloUWxWYjhVblM2dUE9PQ==

[root@k8s-master1 ceph]# vim ceph-secret-1.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret-1
type: "ceph.com/rbd"
data:
  key: QVFES0hOWmpaWHVHQkJBQTM1NGFSTngwcGloUWxWYjhVblM2dUE9PQ==

[root@k8s-master1 ceph]# kubectl apply -f ceph-secret-1.yaml 

[root@k8s-master1 ceph]# kubectl get secrets 
NAME                          TYPE                                  DATA   AGE
ceph-secret                   Opaque                                1      17h
ceph-secret-1                 ceph.com/rbd                          1      44s
rbd-provisioner-token-fknvw   kubernetes.io/service-account-token   3      6m35s

3.4 创建 storageclass

[root@k8s-master1 ceph]# vim storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: k8s-rbd
provisioner: ceph.com/rbd
parameters:
  monitors: 192.168.78.135:6789,192.168.78.136:6789,192.168.78.137:6789
  adminId: admin
  adminSecretName: ceph-secret-1
  pool: k8stest1
  userId: admin
  userSecretName: ceph-secret-1
  fsType: xfs
  imageFormat: "2"
  imageFeatures: "layering"

[root@k8s-master1 ceph]# kubectl apply -f storageclass.yaml 

注意:k8s-v1.20 版本通过 rbd  provisioner 动态生成 pv 会报错:

[root@k8s-master1 ceph]# kubectl logs rbd-provisioner-5d58f65ff5-kl2df
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,解决方法如下:

# 添加这一行:- --feature-gates=RemoveSelfLink=false,如果有则无需添加
[root@k8s-master1 ceph]# vim /etc/kubernetes/manifests/kube-apiserver.yaml 
······
spec:
  containers:
  - command:
    - kube-apiserver
    - --feature-gates=RemoveSelfLink=false    # 添加此内容
    - --advertise-address=192.168.78.143
    - --allow-privileged=true
······

[root@k8s-master1 ceph]# systemctl restart kubelet
[root@k8s-master1 ceph]# kubectl get pods -n kube-system 

3.5 创建 pvc

[root@k8s-master1 ceph]# vim rbd-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: rbd-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi
  storageClassName: k8s-rbd

[root@k8s-master1 ceph]# kubectl apply -f rbd-pvc.yaml 
persistentvolumeclaim/rbd-pvc created

[root@k8s-master1 ceph]# kubectl get pvc
NAME       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ceph-pvc   Bound    ceph-pv                                    1Gi        RWO                           17h
rbd-pvc    Bound    pvc-881076c6-7cac-427b-a29f-43320847cde1   1Gi        RWO            k8s-rbd        5s

3.6 创建 pod 挂载 pvc

[root@k8s-master1 ceph]# vim pod-sto.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: rbd-pod
  name: ceph-rbd-pod
spec:
  containers:
  - name: ceph-rbd-nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: ceph-rbd
      mountPath: /mnt
      readOnly: false
  volumes:
  - name: ceph-rbd
    persistentVolumeClaim:
      claimName: rbd-pvc

[root@k8s-master1 ceph]# kubectl apply -f pod-sto.yaml 

[root@k8s-master1 ceph]# kubectl get pods 
NAME                               READY   STATUS    RESTARTS      AGE
ceph-rbd-pod                       1/1     Running   0             41s
rbd-provisioner-5d58f65ff5-kl2df   1/1     Running   0             21m

四、K8s 挂载 cephfs 实现数据持久化

# 查看 ceph 文件系统
[root@master1-admin ~]# ceph fs ls
name: test, metadata pool: cephfs_metadata, data pools: [cephfs_data ]

4.1 创建 ceph 子目录

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

# 挂载 cephfs 的根目录到集群的 mon 节点下的一个目录,比如 test_data,因为挂载后,我们就可以直接在test_data 下面用 Linux 命令创建子目录了
[root@master1-admin ~]# mkdir test_data
[root@master1-admin ~]# mount -t ceph 192.168.78.135:6789:/ /root/test_data/ -o name=admin,secretfile=/etc/ceph/admin.secret
[root@master1-admin ~]# df -Th
文件系统                类型      容量  已用  可用 已用% 挂载点
······
192.168.78.135:6789:/   ceph       15G  388M   15G    3% /root/test_data

# 在 cephfs 的根目录里面创建了一个子目录 lucky,k8s 以后就可以挂载这个目录
[root@master1-admin ~]# cd test_data/
[root@master1-admin test_data]# mkdir lucky
[root@master1-admin test_data]# chmod 0777 lucky/

4.2 测试 pod 挂载 cephfs

1)创建 k8s 连接 ceph 使用的 secret

# 将 /etc/ceph/ceph.client.admin.keyring 里面的 key 的值转换为 base64,否则会有问题
[root@master1-admin test_data]# cat /etc/ceph/ceph.client.admin.keyring 
[client.admin]
	key = AQDKHNZjZXuGBBAA354aRNx0pihQlVb8UnS6uA==
	caps mds = "allow *"
	caps mon = "allow *"
	caps osd = "allow *"

[root@master1-admin test_data]# echo "AQDKHNZjZXuGBBAA354aRNx0pihQlVb8UnS6uA==" | base64
QVFES0hOWmpaWHVHQkJBQTM1NGFSTngwcGloUWxWYjhVblM2dUE9PQo=

[root@k8s-master1 ceph]# vim cephfs-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: cephfs-secret
data:
  key: QVFES0hOWmpaWHVHQkJBQTM1NGFSTngwcGloUWxWYjhVblM2dUE9PQo=

[root@k8s-master1 ceph]# kubectl apply -f cephfs-secret.yaml 
[root@k8s-master1 ceph]# kubectl get secrets 
NAME                          TYPE                                  DATA   AGE
ceph-secret                   Opaque                                1      18h
ceph-secret-1                 ceph.com/rbd                          1      68m
cephfs-secret                 Opaque                                1      61s
·····

[root@k8s-master1 ceph]# vim cephfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: cephfs-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  cephfs:
    monitors:
      - 192.168.78.135:6789
    path: /lucky
    user: admin
    readOnly: false
    secretRef:
        name: cephfs-secret
  persistentVolumeReclaimPolicy: Recycle

[root@k8s-master1 ceph]# kubectl apply -f cephfs-pv.yaml 
persistentvolume/cephfs-pv created

[root@k8s-master1 ceph]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                            STORAGECLASS       REASON   AGE
ceph-pv                                    1Gi        RWO            Recycle          Bound       default/ceph-pvc                                             18h
cephfs-pv                                  1Gi        RWX            Recycle          Available                                                                4s
······

[root@k8s-master1 ceph]# vim cephfs-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: cephfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  volumeName: cephfs-pv
  resources:
    requests:
      storage: 1Gi

[root@k8s-master1 ceph]# kubectl apply -f cephfs-pvc.yaml 
persistentvolumeclaim/cephfs-pvc created

[root@k8s-master1 ceph]# kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ceph-pvc     Bound    ceph-pv                                    1Gi        RWO                           18h
cephfs-pvc   Bound    cephfs-pv                                  1Gi        RWX                           4s
rbd-pvc      Bound    pvc-881076c6-7cac-427b-a29f-43320847cde1   1Gi        RWO            k8s-rbd        33m

2)创建第一个 pod 挂载 cephfs-pvc

[root@k8s-master1 ceph]# vim cephfs-pod-1.yaml
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

[root@k8s-master1 ceph]# kubectl apply -f cephfs-pod-1.yaml 
pod/cephfs-pod-1 created

[root@k8s-master1 ceph]# kubectl get pods 
NAME                               READY   STATUS    RESTARTS       AGE
ceph-rbd-pod                       1/1     Running   0              33m
cephfs-pod-1                       1/1     Running   0              5s
······

3)创建第二个 pod 挂载 cephfs-pvc

[root@k8s-master1 ceph]# vim cephfs-pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: cephfs-pod-2
spec:
  containers:
    - image: nginx
      name: nginx
      imagePullPolicy: IfNotPresent
      volumeMounts:
      - name: test-v1
        mountPath: /mnt
  volumes:
  - name: test-v1
    persistentVolumeClaim:
      claimName: cephfs-pvc

[root@k8s-master1 ceph]# kubectl apply -f cephfs-pod-2.yaml 
pod/cephfs-pod-2 created

[root@k8s-master1 ceph]# kubectl get pods -o wide 
NAME                               READY   STATUS    RESTARTS       AGE    IP               NODE        NOMINATED NODE   READINESS GATES
ceph-rbd-pod                       1/1     Running   0              35m    10.244.169.171   k8s-node2   <none>           <none>
cephfs-pod-1                       1/1     Running   0              2m9s   10.244.169.172   k8s-node2   <none>           <none>
cephfs-pod-2                       1/1     Running   0              5s     10.244.36.107    k8s-node1   <none>           <none>

[root@k8s-master1 ceph]# kubectl exec -it cephfs-pod-1 -- sh
# cd /mnt
# ls
# touch	1.txt
# exit

[root@k8s-master1 ceph]# kubectl exec -it cephfs-pod-2 -- sh
# cd /mnt
# ls
1.txt
# touch 2.txt
# ls
1.txt  2.txt
# exit

# 回到 master1-admin 上,可以看到在 cephfs 文件目录下已经存在内容了
[root@master1-admin test_data]# pwd
/root/test_data
[root@master1-admin test_data]# ls lucky/
1.txt  2.txt

由上面可知,cephfs 可跨 node 节点共享存储。

上一篇文章: 【Kubernetes 企业项目实战】05、基于云原生分布式存储 Ceph 实现 K8s 数据持久化(上)_Stars.Sky的博客-CSDN博客

下一篇文章:【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(上)_Stars.Sky的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/186919.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考高项—第一章信息系统项目管理基础

项目特点 1、临时性&#xff1a;有明确的开始时间和结束时间 2、独特的产品、可交付成果 3、逐步完善&#xff1a;项目团队从开始的粗略计划到详细计划&#xff0c;在到完成项目 4、资源约束&#xff1a;每个项目都需要各种资源保证&#xff0c;资源是有限的 5、目的性&#x…

C语言重点复习大纲

目录数据存储(3星)判断大小端写一个函数判断大小端截断与整形提升数组和指针(5星)几个特殊的指针数组传参字符串数组库函数的实现(4星)atoi与itoamemcpy与memmove内存重叠自定义类型(4星)内存对齐结构体&#xff0c;联合体&#xff0c;枚举位段编译链接(3星)编译和链接的过程条…

循环队列实现---kfifo

循环队列 概述 在优化系统性能时&#xff0c;我们通常需要分析一个单线程程序各模块的功能和性能&#xff0c;然后将这些模块拆分到多个线程中并行执行。而多个线程之间需要加入缓存以实现线程间的通信。如图1所示&#xff1a; 图1&#xff1a;多线程缓存为方便进程间通信&am…

Python【xpath】实战下

项目要求&#xff1a;获取某二手租房平台关于房源信息的简介和价格代码&#xff1a;python编写&#xff0c;实现需要准备的第三方库&#xff1a;requests &#xff0c;lxml&#xff0c; time代码分析&#xff1a;导入需要使用的第三方库&#xff1a;import requests import tim…

java ssm校园快递代领系统的设计与实现idea maven

近几年随着国民经济的不断发展&#xff0c;电子商务行业的不断创新。作为物流业一个重要分支的校园快递代领逐渐兴起&#xff0c;各种快递公司层出不穷。校园快递代领在不断向前发展的同时也存在一些无法避免的小问题&#xff0c;例如许多小型的快递公司在信息处理和管理上存在…

基于微信小程序的民宿短租系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

Spring Boot Actuator详解

Actuator简介 什么是Spring Boot Actuator&#xff1f; Spring Boot Actuator 模块提供了生产级别的功能&#xff0c;比如健康检查&#xff0c;审计&#xff0c;指标收集&#xff0c;HTTP跟踪等&#xff0c;帮助我们监控和管理Spring Boot应用。这个模块是一个采集应用内部信…

react知识点整理

1、react hooks是用来做什么的? 加入hooks,让react函数组件更加的灵活 hooks之前,React存在很多问题: 1、组件间服用状态逻辑难2、复杂组件变的难以理解,高阶组件和函数组件的嵌套过深3、class组件的this问题4、难以记忆的生命周期hooks有: useState()useEffects()useR…

从头开始创建一个OData SAP Gateway Service

可能用到的事务代码&#xff1a;/IWFND/IWF_ACTIVATE – Activate / Deactivate SAP GatewaySEGW – SAP Gateway Service Builder/IWFND/MAINT_SERVICE – Activate and Maintain Services/IWFND/EXPLORER – Service Explorer/IWFND/GW_CLIENT – SAP Gateway Client/IWFND/S…

Android | 输入系统(IMS)

前言 一般情况下很多同学对于点击事件的认识都只存在于从 Activity 开始的&#xff0c;然后从 Window 中进行分发&#xff0c;甚至有些人可能也只知道 onTouchEvent 和 dispatchTouchEvetn 这几个方法&#xff0c;对于 View 层的了解都不属性。 自从对于应用层面的分发过程了…

logging日志模块详解

说到日志&#xff0c;无论是写框架代码还是业务代码都离不开日志的记录&#xff0c;其能给我们定位问题带来极大的帮助。 记录日志最简单的方式是在你想要记录的地方加上一句print。我相信无论是新手还是老鸟都经常这么干&#xff0c;在简单的代码或者小型项目中这么干一点问题…

这样吃才能有效补脑

核桃长得像大脑&#xff0c;还含有Ω-3&#xff0c;一直被认为补脑效果很好。但是现代科学研究发现&#xff0c;Ω-3并不是核桃专有的&#xff0c;很多坚果都有&#xff0c;所以核桃在补脑这方面并没有什么特殊功效。补脑其实就是维持大脑的正常工作&#xff0c;还要延缓大脑认…

SAP ADM100-Unit4 数据库工作原理:监控数据库

概览 除了执行数据备份之外,还需要对数据库进行大量的周期性检查。 课程目标 对数据库计划额外的周期性检查。 1、数据库定期监控 除了日常监控数据库备份外,还有大量的其他检查不得不定期执行。有的检查可以通过DBA Cockpit Planning Calendar来计划。 例如: 当存取数…

Mac电脑使用:查看本机已连接Wi-Fi密码的方法

前言 在使用Mac电脑的时候&#xff0c;电脑自身所连接成功的Wi-Fi一般都不显示密码&#xff0c;这是苹果出于安全考量的保护措施&#xff0c;但是有时候遇到新的设备想要连接已经连过的Wi-Fi&#xff0c;由于时间太久忘记Wi-Fi密码&#xff0c;这就需要查看一下电脑连接的Wi-Fi…

点击化学标记1817735-33-3,Pyrene-PEG5-propargyl,芘甲酰胺五聚乙二醇丙炔

Pyrene-PEG5-propargyl&#xff0c;芘甲酰胺-五聚乙二醇-丙炔Product structure&#xff1a;Pyrene-PEG5-propargyl结构式Product specifications&#xff1a;1.CAS No&#xff1a;1817735-33-32.Molecular formula&#xff1a;C30H33NO63.Molecular weight&#xff1a;503.64.…

终于有多位大神联手把计算机基础知识与操作系统讲清楚了

操作系统的定义 指的是控制和管理整个计算机系统的硬件和软件资源&#xff0c;并合理地组织调度计算机的工作和资源的分配&#xff0c;以提供给用户和其他软件方便的接口和环境&#xff0c;它是计算机系统中最基本的系统软件。 计算机系统的层级结构 1、用户 应用程序 2、操…

vue前端框架课程笔记(三)

目录条件渲染v-ifv-show列表渲染关于:key列表过滤watch属性实现computed属性列表排序表单数据收集input是否配置value属性过滤器本博客参考尚硅谷官方课程&#xff0c;详细请参考 【尚硅谷bilibili官方】 本博客以vue2作为学习目标&#xff08;请勿混淆v2与v3的代码规范&…

Azure 语音用人工智能改变游戏开发的三种方式

通过 Azure 认知服务的智能语音功能[1]&#xff0c;用户可以使用语音 SDK 开发工具包快速构建支持语音交互的各种应用。将语音转录为准确的文本 &#xff08;STT&#xff0c;或语音识别&#xff09;或者将文本转换成生动的语音 &#xff08;TTS&#xff0c;或语言合成&#xff…

大数据NiFi(十五):NiFi入门案例二

文章目录 NiFi入门案例二 一、配置“GenerateFlowFile”处理器 1、拖拽“Processor”在弹框中输入“GenerateFlowFile” <

如何解决缓存雪崩、击穿、穿透难题?

缓存雪崩、缓存击穿和缓存穿透这三个问题是我们在使用redis做缓存的时候要面临的&#xff0c;一旦发生这三个问题&#xff0c;就会导致大量的请求都积压到了数据库层&#xff0c;有可能导致数据库宕机&#xff0c;进入导致整个系统不可用。 下边&#xff0c;具体看一下这三个问…