云原生
Kubernetes基础
容器技术介绍
Docker快速入门
Containerd快速入门
K8S主要资源罗列
认识YAML
API资源对象
Kubernetes安全掌控
Kubernetes网络
Kubernetes高级调度
Kubernetes 存储
Kubernetes集群维护
Skywalking全链路监控
ConfigMap&Secret场景应用
Kubernetes基础概念及核心组件
水平自动扩容和缩容HPA
Jenkins
k8s中部署jenkins并利用master-slave模式实现CICD
Jenkins构建过程中常见问题排查与解决
Jenkins部署在k8s集群之外使用动态slave模式
Jenkins基于Helm的应用发布
Jenkins Pipeline语法
EFKStack
EFK日志平台部署管理
海量数据下的EFK架构优化升级
基于Loki的日志收集系统
Ingress
基于Kubernetes的Ingress-Nginx解决方案
Ingress-Nginx高级配置
使用 Ingress-Nginx 进行灰度(金丝雀)发布
Ingress-nginx优化配置
APM
Skywalking全链路监控
基于Helm部署Skywalking
应用接入Skywalking
服务网格
Istio
基于Istio的微服务可观察性
基于Istio的微服务Gateway实战
Kubernetes高可用集群部署
Kuberntes部署MetalLB负载均衡器
Ceph
使用cephadm部署ceph集群
使用Rook部署Ceph存储集群
openstack
glance上传镜像失败
mariadb运行不起来
创建域和项目错误_1
创建域和项目错误_2
安装计算节点
时钟源
网络创建失败
本文档使用 MrDoc 发布
-
+
首页
Kubernetes 存储
存储持久化相关三个概念: - 1)PersistentVolume(PV) 是对具体存储资源的描述,比如NFS、Ceph、GlusterFS等,通过PV可以访问到具体的存储资源; - 2)PersistentVolumeClaim(PVC) Pod想要使用具体的存储资源需要对接到PVC,PVC里会定义好Pod希望使用存储的属性,通过PVC再去申请合适的存储资源(PV),匹配到合适的资源后PVC和PV会进行绑定,它们两者是一一对应的; - 3)StorageClass(SC) PV可以手动创建,也可以自动创建,当PV需求量非常大时,如果靠手动创建PV就非常麻烦了,SC可以实现自动创建PV,并且会将PVC和PV绑定。 SC会定义两部分内容: - ① pv的属性,比如存储类型、大小; - ② 创建该PV需要用到的存储插件(provisioner),这个provisioner是实现自动创建PV的关键。 # 1、API资源对象PV和PVC ##1.1 PV PV YAML示例: vi testpv.yaml ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: testpv spec: storageClassName: test-storage accessModes: - ReadWriteOnce capacity: storage: 500Mi ##提供500Mi空间 hostPath: path: /tmp/testpv/ ``` 说明: storageClassName: 定义存储类名称,PV和PVC中都会有该字段,目的是为了方便两者匹配绑定在一起 accessModes定义该pv的访问权限模式,有三种: - ReadWriteOnce:存储卷可读可写,但只能被一个节点上的 Pod 挂载; - ReadOnlyMany:存储卷只读不可写,可以被任意节点上的 Pod 多次挂载; - ReadWriteMany:存储卷可读可写,也可以被任意节点上的 Pod 多次挂载; capacity 定义该存储大小 hostPath 定义该存储访问路径,这里指的是本地的磁盘。 ## 1.2 PVC PVC YAML示例 vi testpvc.yaml ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: testpvc spec: storageClassName: test-storage accessModes: - ReadWriteOnce resources: requests: storage: 100Mi ##期望申请100Mi空间 ``` 应用pv和pvc的YAML ```Bash $ kubectl apply -f testpv.yaml -f testpvc.yaml ``` 查看状态 ```Bash $ kubectl get pv,pvc ``` 实验: 将testpvc的期望100Mi改为1000Mi,查看PV的STATUS ```Bash $ kubectl get pv,pvc NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE persistentvolume/testpv 500Mi RWO Retain Available test-storage 22s NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE persistentvolumeclaim/testpvc Pending test-storage 10s ``` ## 1.3 PV和PVC匹配规则 PV创建好后,会等待PVC与其进行绑定,PVC一旦找到合适的PV就会绑定。如果有多个PV时,PVC又是如何匹配PV的呢?它有如下一些规则: - ① 访问模式和存储类匹配:Kubernetes会筛选出访问模式(accessModes)和存储类(storageClassName)与PVC相匹配的PV。如果没有匹配的PV,PVC将保持未绑定状态。 - ② 资源大小:在满足访问模式和存储类匹配的PV中,Kubernetes会选择资源大小大于或等于PVC请求大小的PV。 - ③ 最佳匹配:在满足访问模式、存储类和资源大小的PV中,Kubernetes会选择资源大小最接近PVC请求大小的PV。如果有多个PV具有相同的资源大小,Kubernetes会选择其中一个进行绑定。 - ④ 避免重复绑定:一个PV在任何时候只能被一个PVC绑定。一旦PV被绑定到一个PVC,它将不再可用于其他PVC。 # 2、本地存储 ## 2.1 本地存储介绍 在10.1章节中的PV YAML示例,就是本地存储。本地存储类型的PV是Kubernetes中一种比较特殊的持久化存储,它允许将节点上的本地磁盘或目录用作PV。与其他PV类型(例如NFS、Ceph或云存储)不同,本地存储类型的PV直接使用节点上的存储资源,因此具有更低的延迟和更高的性能。 使用本地存储类型的PV时,需注意以下几个关键点: - 节点特性:本地存储类型的PV与特定的节点绑定,因为它直接使用节点上的存储资源。这意味着当创建PV时,需要指定与之关联的节点。可以在PV的spec部分设置nodeAffinity来实现的。 ```yaml nodeAffinity: ##定义节点亲和性 required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - node-name ``` - 数据持久性:由于本地存储类型的PV与特定节点关联,当该节点发生故障时,存储在PV中的数据可能无法访问。因此,在使用本地存储类型的PV时,请确保采取适当的数据备份策略,以防止节点故障导致的数据丢失。 - 调度限制:Pod使用本地存储类型的Persistent Volume Claim(PVC)时,Kubernetes会尝试将Pod调度到关联PV的节点上。如果节点上的资源不足以运行Pod,Pod将无法启动。因此,在使用本地存储类型的PV时,请确保关联的节点有足够的资源来运行Pod。 - 回收策略:当PVC被删除时,PV的回收策略将决定如何处理关联的本地存储。对于本地存储类型的PV,建议使用Retain或Delete回收策略。Retain策略表示保留存储和数据,以便手动清理和管理;Delete策略表示删除存储和数据。需要注意的是,Recycle策略并不适用于本地存储类型的PV。 ```yaml persistentVolumeReclaimPolicy: Retain ``` ## 2.2 本地存储示例 首先,确保在每个要使用本地存储的节点上创建一个本地目录。例如,在节点上创建/mnt/local-storage目录: ```Bash $ mkdir -p /mnt/local-storage ``` 然后,创建一个PV资源配置文件,例如local-pv.yaml: ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: local-pv labels: type: local spec: storageClassName: local-storage capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain local: path: /mnt/local-storage nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname #这是内置的节点标签,表示节点的主机名 operator: In values: - aminglinux02 #只有aminglinux02这个主机节点才满足要求 ``` 应用PV资源配置文件: ```Bash $ kubectl apply -f local-pv.yaml ``` 再创建一个PVC资源配置文件,例如local-pvc.yaml: ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: local-pvc spec: storageClassName: local-storage accessModes: - ReadWriteOnce resources: requests: storage: 5Gi ``` 应用PVC资源配置文件: ```Bash $ kubectl apply -f local-pvc.yaml ``` 使用本地存储时,storageClass可以不存在 Kubernetes会自动将PVC与PV绑定。创建好的PVC可以在Pod中使用,将本地存储挂载到容器中。 最后,创建一个Pod资源配置文件,例如local-pod.yaml: ```yaml apiVersion: v1 kind: Pod metadata: name: local-pod spec: containers: - name: local-container image: nginx:1.21.0 volumeMounts: - name: local-storage mountPath: /data volumes: - name: local-storage persistentVolumeClaim: claimName: local-pvc ``` 应用Pod资源配置文件: ```Bash $ kubectl apply -f local-pod.yaml ``` 现在,local-pod中的local-container已经挂载了本地存储。所有写入/data目录的数据都将持久化在本地存储中。 # 3、NFS存储 注意:在做本章节示例时,需要拿单独一台机器来部署NFS,具体步骤略。 NFS作为常用的网络文件系统,在多机之间共享文件的场景下用途广泛,毕竟NFS配置方便,而且稳定可靠。 NFS同样也有一些缺点: - ① 存在单点故障的风险; - ② 不方便扩容; - ③ 性能一般。 NFS比较适合一些简单的、对存储要求不高的场景,比如测试环境、开发环境。 完整示例: 首先部署好NFS服务,并且保证所有Kubernetes节点可以顺利挂载(showmount -e 192.168.222.128 ) 安装NFS客户端 ```Bash $ yum install -y nfs-utils ``` 定义基于NFS的PV ```Bash $ vi nfs-pv.yaml ``` ```yaml apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv spec: capacity: storage: 5Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: nfs-storage nfs: path: /data/nfs2 server: 192.168.222.128 ``` 应用 ```Bash $ kubectl apply -f nfs-pv.yaml ``` 定义PVC ```Bash $ vi nfs-pvc.yaml ``` ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-pvc spec: storageClassName: nfs-storage accessModes: - ReadWriteMany resources: requests: storage: 5Gi ``` 应用 ```Bash $ kubectl apply -f nfs-pvc.yaml ``` 定义Pod ```Bash $ vi nfs-pod.yaml ``` ```yaml apiVersion: v1 kind: Pod metadata: name: nfs-pod spec: containers: - name: nfs-container image: nginx:1.21.0 volumeMounts: - name: nfs-storage mountPath: /data volumes: - name: nfs-storage persistentVolumeClaim: claimName: nfs-pvc ``` 应用 ```Bash $ kubectl apply -f nfs-pod.yaml ``` # 4、API资源对象StorageClass SC的主要作用在于,自动创建PV,从而实现PVC按需自动绑定PV。 下面我们通过创建一个基于NFS的SC来演示SC的作用。 要想使用NFS的SC,还需要安装一个NFS provisioner,provisioner里会定义NFS相关的信息(服务器IP、共享目录等) github地址: https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner 将源码下载下来: ```Bash git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner ``` ```Bash $ cd nfs-subdir-external-provisioner/deploy $ sed -i 's/namespace: default/namespace: kube-system/' rbac.yaml ##修改命名空间为kube-system $ kubectl apply -f rbac.yaml ##创建rbac授权 ``` 修改deployment.yaml ```Bash sed -i 's/namespace: default/namespace: kube-system/' deployment.yaml ##修改命名空间为kube-system ``` ```yaml ##你需要修改注释的部分 spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: registry.cn-hangzhou.aliyuncs.com/kavin1028/nfs-subdir-external-provisioner:v4.0.2 ##改为dockerhub地址 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: k8s-sigs.io/nfs-subdir-external-provisioner - name: NFS_SERVER value: 192.168.222.99 ##nfs服务器地址 - name: NFS_PATH value: /data/nfs ##nfs共享目录 volumes: - name: nfs-client-root nfs: server: 192.168.222.99 ##nfs服务器地址 path: /data/nfs ##nfs共享目录 ``` 应用yaml ```Bash $ kubectl apply -f deployment.yaml $ kubectl apply -f class.yaml ##创建storageclass ``` SC YAML示例 ```Bash $ cat class.yaml ``` ```yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-client provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME' parameters: archiveOnDelete: "false" ##自动回收存储空间 ``` 有了SC,还需要一个PVC ```Bash $ vi nfsPvc.yaml ``` ```yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfspvc spec: storageClassName: nfs-client accessModes: - ReadWriteMany resources: requests: storage: 500Mi ``` 下面创建一个Pod,来使用PVC ```Bash $ vi nfsPod.yaml ``` ```yaml apiVersion: v1 kind: Pod metadata: name: nfspod spec: containers: - name: nfspod image: nginx:1.23.2 volumeMounts: - name: nfspv mountPath: "/usr/share/nginx/html" volumes: - name: nfspv persistentVolumeClaim: claimName: nfspvc ``` 总结一下: ```Bash pod想使用共享存储 --> PVC (定义具体需求属性) -->SC (定义Provisioner) --> Provisioner(定义具体的访问存储方法) --> NFS-server | | |___________________________________|-->自动创建PV ``` # 5、Ceph存储 说明:Kubernetes使用Ceph作为存储,有两种方式,一种是将Ceph部署在Kubernetes里,需要借助一个工具rook;另外一种就是使用外部的Ceph集群,也就是说需要单独部署Ceph集群。本文主要介绍第二种。 ## 5.1 对比两种方式 Rook Ceph 集成: - 使用 Rook 可以在 Kubernetes 集群内部部署和管理 Ceph 存储集群。Rook 是一个开源的项目,它允许你通过 Kubernetes Operator 部署和管理 Ceph。这种方式将 Ceph 部署为 Kubernetes 集群的一部分,使得存储资源更加集成和易于管理。这适用于需要在 Kubernetes 内部快速部署和管理 Ceph 的场景。 外部独立 Ceph 集群 - 在这种方式下,你需要单独部署和维护一个独立的 Ceph 存储集群,而不将其嵌入到 Kubernetes 集群中。Kubernetes 集群将通过 Ceph 的网络接口与外部 Ceph 集群进行通信。这适用于已经存在或希望独立维护的 Ceph 集群,并且 Kubernetes 集群只需要连接到这个外部 Ceph 集群来使用存储资源。 选择哪种方式取决于你的需求和环境。如果你需要更好的集成和自动化管理,并且不希望单独管理 Ceph 集群,那么使用 Rook Ceph 集成可能更合适。如果你已经有一个独立的 Ceph 集群或者希望将存储资源与 Kubernetes 集群分离开,那么使用外部独立 Ceph 集群可能更合适。 ## 5.2 搭建Ceph集群 见文档:http://10.0.1.2:10086/modify_doc/26/ ## 5.3 k8s使用ceph 1、获取ceph集群信息和admin用户的key(ceph那边) ```Bash #获取集群信息 $ ceph mon dump epoch 3 fsid 69e2f148-7005-11ee-8438-00505684afef last_changed 2023-10-21T11:50:13.661918+0000 created 2023-10-21T11:33:10.492205+0000 min_mon_release 16 (pacific) election_strategy: 1 0: [v2:10.0.1.211:3300/0,v1:10.0.1.211:6789/0] mon.ceph01 1: [v2:10.0.1.212:3300/0,v1:10.0.1.212:6789/0] mon.ceph02 2: [v2:10.0.1.213:3300/0,v1:10.0.1.213:6789/0] mon.ceph03 dumped monmap epoch 3 #获取admin用户key $ ceph auth get-key client.admin ; echo AQD2tjNlGwqpABAArWONbjkHLYkvu9KnpvHbig== ``` 2、下载并导入镜像(K8S集群操作) 将用到的镜像先下载下来,避免启动容器时,镜像下载太慢或者无法下载 可以下载到其中某一个节点上,然后将镜像拷贝到其它节点 ```Bash #下载镜像(其中一个节点) $ wget -P /tmp/ https://d.frps.cn/file/tools/ceph-csi/k8s_1.24_ceph-csi.tar #拷贝(所有k8s节点) $ scp /tmp/k8s_1.24_ceph-csi.tar aminglinux02:/tmp/ $ scp /tmp/k8s_1.24_ceph-csi.tar aminglinux03:/tmp/ #导入镜像(所有k8s节点) ctr -n k8s.io i import k8s_1.24_ceph-csi.tar ``` 3、创建ceph的 provisioner 创建ceph目录,后续将所有yaml文件放到该目录下 ```Bash $ mkdir ceph $ cd ceph ``` 创建secret.yaml ```Bash cat > secret.yaml <<EOF apiVersion: v1 kind: Secret metadata: name: csi-rbd-secret namespace: default stringData: userID: admin userKey: AQD2tjNlGwqpABAArWONbjkHLYkvu9KnpvHbig== #这串上面已经获取 EOF ``` 创建config-map.yaml ```Bash cat > csi-config-map.yaml <<EOF apiVersion: v1 kind: ConfigMap metadata: name: "ceph-csi-config" data: config.json: |- [ { "clusterID": "69e2f148-7005-11ee-8438-00505684afef", # ceph mon dump命令回显中的fsid "monitors": [ "10.0.1.211:6789", "10.0.1.212:6789", "10.0.1.213:6789" ] } ] EOF ``` - clusterID后的注释一定要删除 创建ceph-conf.yaml ```Bash cat > ceph-conf.yaml <<EOF apiVersion: v1 kind: ConfigMap data: ceph.conf: | [global] auth_cluster_required = cephx auth_service_required = cephx auth_client_required = cephx # keyring is a required key and its value should be empty keyring: | metadata: name: ceph-config EOF ``` 创建csi-kms-config-map.yaml(该config内容为空) ```Bash cat > csi-kms-config-map.yaml <<EOF --- apiVersion: v1 kind: ConfigMap data: config.json: |- {} metadata: name: ceph-csi-encryption-kms-config EOF ``` 下载其余rbac以及provisioner相关yaml ```Bash $ wget https://d.frps.cn/file/tools/ceph-csi/csi-provisioner-rbac.yaml $ wget https://d.frps.cn/file/tools/ceph-csi/csi-nodeplugin-rbac.yaml $ wget https://d.frps.cn/file/tools/ceph-csi/csi-rbdplugin.yaml $ wget https://d.frps.cn/file/tools/ceph-csi/csi-rbdplugin-provisioner.yaml ``` 应用所有yaml(注意,当前目录是在ceph目录下) ```Bash $ for f in `ls *.yaml`; do echo $f; kubectl apply -f $f; done ``` 检查provisioner的pod,状态为running才对 ```Bash $ kubectl get po NAME READY STATUS RESTARTS AGE csi-rbdplugin-29q68 3/3 Running 0 14s csi-rbdplugin-h44dh 3/3 Running 0 14s csi-rbdplugin-ktchl 3/3 Running 0 14s csi-rbdplugin-lpbmj 3/3 Running 0 14s csi-rbdplugin-provisioner-5c7d54dd8d-2msht 7/7 Running 0 14s csi-rbdplugin-provisioner-5c7d54dd8d-btvr6 7/7 Running 0 14s csi-rbdplugin-provisioner-5c7d54dd8d-sxdtj 7/7 Running 0 14s csi-rbdplugin-sn66h 3/3 Running 0 14s csi-rbdplugin-wmgpn 3/3 Running 0 14s ``` 4、创建storageclass 在k8s上创建ceph-sc.yaml ```Bash cat > ceph-sc.yaml <<EOF apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: csi-rbd-sc #storageclass名称 provisioner: rbd.csi.ceph.com #驱动器 parameters: clusterID: 69e2f148-7005-11ee-8438-00505684afef #ceph集群id pool: pool01 #pool空间 imageFeatures: layering #rbd特性 csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret csi.storage.k8s.io/provisioner-secret-namespace: default csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret csi.storage.k8s.io/controller-expand-secret-namespace: default csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret csi.storage.k8s.io/node-stage-secret-namespace: default reclaimPolicy: Delete #pvc回收机制 allowVolumeExpansion: true #对扩展卷进行扩展 mountOptions: #StorageClass 动态创建的 PersistentVolume 将使用类中 mountOptions 字段指定的挂载选项 - discard EOF ##应用yaml kubectl apply -f ceph-sc.yaml ``` 5、创建pvc 在k8s上创建ceph-pvc.yaml ```Bash cat > ceph-pvc.yaml <<EOF apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ceph-pvc #pvc名称 spec: accessModes: - ReadWriteOnce #访问模式 resources: requests: storage: 1Gi #存储空间 storageClassName: csi-rbd-sc EOF #应用yaml kubectl apply -f ceph-pvc.yaml ``` 查看pvc状态,STATUS必须为Bound ```Bash $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE ceph-pvc Bound pvc-b7e8db6e-043c-4ee9-9fde-6158906d93a7 1Gi RWO csi-rbd-sc 72s ``` 6、创建pod使用ceph存储 ```Bash cat > ceph-pod.yaml <<EOF apiVersion: v1 kind: Pod metadata: name: ceph-pod spec: containers: - name: ceph-ng image: nginx:1.23.2 volumeMounts: - name: ceph-mnt mountPath: /mnt readOnly: false volumes: - name: ceph-mnt persistentVolumeClaim: claimName: ceph-pvc EOF $ kubectl apply -f ceph-pod.yaml ``` 查看pv ```Bash $ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-b7e8db6e-043c-4ee9-9fde-6158906d93a7 1Gi RWO Delete Bound default/ceph-pvc csi-rbd-sc 2m57s ``` 查看pod ```Bash $ kubectl get po NAME READY STATUS RESTARTS AGE ceph-pod 1/1 Running 0 51s ``` 在ceph这边查看rbd ```Bash [ceph: root@ceph1 /]# rbd ls pool01 csi-vol-16a0841b-7010-11ee-81a4-b6725ee39efe ``` 在pod里查看挂载情况 ```Bash $ kubectl exec -it ceph-pod -- df Filesystem 1K-blocks Used Available Use% Mounted on overlay 64161168 14775416 49385752 24% / tmpfs 65536 0 65536 0% /dev tmpfs 8200248 0 8200248 0% /sys/fs/cgroup /dev/rbd0 996780 24 980372 1% /mnt /dev/mapper/rl-root 64161168 14775416 49385752 24% /etc/hosts shm 65536 0 65536 0% /dev/shm tmpfs 16298100 12 16298088 1% /run/secrets/kubernetes.io/serviceaccount tmpfs 8200248 0 8200248 0% /proc/acpi tmpfs 8200248 0 8200248 0% /proc/scsi tmpfs 8200248 0 8200248 0% /sys/firmware ``` ## 10.6 GlusterFS存储
阿星
2024年1月6日 15:48
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码