持续集成部署-k8s-配置与存储-存储类:动态创建NFS-PV案例

动态创建NFS-PV案例

  • 1. 前置条件
  • 2. StorageClass 存储类的概念和使用
  • 3. RBAC 配置
  • 4. storageClass 配置
  • 5. 创建应用,测试 PVC 的自动配置
  • 6. 解决 PVC 为 Pending 状态问题
  • 7. 单独测试自动创建 PVC

1. 前置条件

这里使用 NFS 存储的方式,来演示动态创建 PV 的案例。

前置条件是需要在 K8s 集群中安装 NFS 的环境,安装可参考:持续集成部署-k8s-数据持久化-NFS安装与使用

确保 NFS 服务器正常可用之后,接着后续的步骤操作。

验证配置是否生效:

  • 在当前nfs-server 上查看:
[root@docker-54 nfs]# showmount --export
Export list for docker-54:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-54 nfs]#
  • 在 nfs-client 上查看:
[root@docker-55 ~]# showmount -e master
Export list for master:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-55 ~]# [root@docker-56 ~]# showmount -e master
Export list for master:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-56 ~]# 

可以看到,两台 Node 节点上均已显示 NFS Server 的信息了。

在动态创建 PV 之前,我们需要先了解下用到的组件的基础概念。

2. StorageClass 存储类的概念和使用

Kubernetes 中,StorageClass 是用于定义动态存储卷的对象。它允许管理员定义不同类型的存储,并使开发人员能够按需创建 PVC(Persistent Volume Claim 持久卷声明)。

StorageClass 可以看作是一种存储资源的抽象,它定义了存储的类型、属性和参数等信息。Kubernetes 可以根据这些信息动态地创建 PV(Persistent Volume 持久卷),并将其绑定到 PVC 上。
在这里插入图片描述
在数据存储,动态构建 PV 的过程,如上面的流程图所示。

但是在我们创建的过程中,则需要先创建 StorageClass,才能保证在 PVC 使用时,对应上,另外 在 Pod 创建时指定的 PVC 也是需要提前创建才行。

3. RBAC 配置

新建配置文件:nfs-provisioner-rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisionernamespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]resources: ["persistentvolumes"]verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]resources: ["persistentvolumeclaims"]verbs: ["get", "list", "watch", "update"]
- apiGroups: [""]resources: ["endpoints"]verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: ["storage.k8s.io"]resources: ["storageclasses"]verbs: ["get", "list", "watch"]
- apiGroups: [""]resources: ["events"]verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccountname: nfs-client-provisionernamespace: kube-system
roleRef:kind: ClusterRolename: nfs-client-provisioner-runnerapiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisioner
rules:
- apiGroups: [""]resources: ["endpoints"]verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisioner
subjects:
- kind: ServiceAccountname: nfs-client-provisioner# replace with namespace where provisioner is deployednamespace: kube-system
roleRef:kind: Rolename: leader-locking-nfs-client-provisionerapiGroup: rbac.authorization.k8s.io

这个对应了 k8s 中角色权限的部分内容,在 k8s 的服务管理方面,其实就是一套类似 HTTP 的 RESTful 风格的 API,这些 API 默认是具备一个 RBAC 权限的。

上面的配置文件创建了角色、账号,以及如何把角色和账号关联起来。

4. storageClass 配置

新建的配置文件:nfs-storage-class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: managed-nfs-storage
provisioner: fuseim.pri/ifs
parameters:archiveOnDelete: "false" # 是否存档 false 表示不存档,会删除 oldPath 下的数据,true表示会存档,会重命名路径
reclaimPolicy: Retain # 回收策略, 默认为 Delete  可以配置为 Retain 
volumeBindingMode: Immediate # 默认为 Immediate,表示创建 PVC 立即绑定,只有azuredisk 和 AWSelasticblockstore 支持其他值

新建制备器配置文件:nfs-provisioner-deployment.yaml

apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisionernamespace: kube-system
---
kind: Deployment
apiVersion: apps/v1
metadata:namespace: kube-systemname: nfs-client-provisionerlabels:app: nfs-client-provisioner
spec:replicas: 1strategy:type: Recreateselector:matchLabels:app: nfs-client-provisionertemplate:metadata:labels:app: nfs-client-provisionerspec:serviceAccount: nfs-client-provisionercontainers:- name: nfs-client-provisioner
#          image: quay.io/external_storage/nfs-client-provisioner:latestimage: registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0volumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAMEvalue: fuseim.pri/ifs # 对应 sc 里面的provisioner 的名称- name: NFS_SERVERvalue: 192.168.104.54 # nfs 服务的IP 和 路径 都需要关联上才行- name: NFS_PATHvalue: /home/nfs/rwvolumes:- name: nfs-client-rootnfs:server: 192.168.104.54path: /home/nfs/rw

上面这些东西,可能刚开始的时候看有点熟悉,又有点懵,上面的内容,不需要特殊记忆,理解就行,需要改动的地方,也就是最下面 volumes 相关的 server 和 path ,其他内容均为官方配置的内容。基本上也不会有很大的改动。

接着最后是应用的配置文件:nfs-sc-demo-statefulset.yaml

---
apiVersion: v1
kind: Service
metadata:name: nginx-sclabels:app: nginx-sc
spec:type: NodePortports:- name: webport: 80protocol: TCPselector:app: nginx-sc
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: nginx-sc
spec:replicas: 1serviceName: "nginx-sc" # 对应上面的 Service selector:matchLabels:app: nginx-sc # 匹配到下面的 Pod 的标签配置template:metadata:labels:app: nginx-sc # Pod 模板标签spec:containers:- image: nginxname: nginx-scimagePullPolicy: IfNotPresentvolumeMounts:- mountPath: /usr/share/nginx/html # 挂载到容器的哪个目录name: nginx-sc-test-pvc # 挂载哪个 volumevolumeClaimTemplates:- metadata:name: nginx-sc-test-pvcspec:storageClassName: managed-nfs-storageaccessModes:- ReadWriteManyresources:requests:storage: 1Gi

这里创建了 Service 和 StatefulSet ,来管理 Nginx 的 Pod。

volumeClaimTemplates 的配置为 希望可以帮我自动创建一个 PVC,这个 PVC 声明了使用的存储类 storageClass,配置了 storageClass 的名称storageClassName和访问模式accessModes,这声明为可以多个节点同时读写的一个模式。最后声明,期望所需的资源最小是 1Gi

5. 创建应用,测试 PVC 的自动配置

我们希望的效果是,一旦上面的应用创建起来之后,它自动帮我们把 PVC 创建出来,并且把 PV 也创建出来。

接下来完成上面这些内容的构建,分别把他们构建出来,然后再去把应用跑起来。

先看下当前环境中 pv 和 pvc 的情况:

[root@docker-54 ~]# kubectl get pv | grep nginx
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl get pvc 
No resources found in default namespace.
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl get storageclass
NAME                    PROVISIONER   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-storage (default)   nfs-client    Delete          Immediate           false                  132d
[root@docker-54 ~]#

可以看到,当前是没有对应的 PV 和 PVC 的。

接着需要先把 RBAC启动起来:

[root@docker-54 ~]# cd /opt/k8s/config/
[root@docker-54 config]# ls
application.yaml   file-test-pod.yaml               nfs-provisioner-rbac.yaml  nginx.conf                   test
env-test-pod.yaml  nfs-provisioner-deployment.yaml  nfs-storage-class.yaml     private-image-pull-pod.yaml
[root@docker-54 config]# 
[root@docker-54 config]# kubectl apply -f nfs-provisioner-rbac.yaml 
serviceaccount/nfs-client-provisioner unchanged
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner configured
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner unchanged
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner unchanged
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner unchanged
[root@docker-54 config]# 

这里由于我之前创建过一些 RBAC 权限,这里有的显示 unchanged,首次执行这个应该是 created或者configured
可以看到,上面RBAC 里面配置了一个 serviceaccount以及它对应的集群角色,然后是角色的绑定。接着是一个普通的角色以及普通角色的绑定。

创建完权限,接着来创建 deployment:

[root@docker-54 config]# kubectl apply -f nfs-provisioner-deployment.yaml 
serviceaccount/nfs-client-provisioner unchanged
deployment.apps/nfs-client-provisioner configured
[root@docker-54 config]# 

接着创建 StorageClass:kubectl apply -f nfs-storage-class.yaml

[root@docker-54 config]# kubectl apply -f nfs-storage-class.yaml
storageclass.storage.k8s.io/managed-nfs-storage created
[root@docker-54 config]#

这里 StorageClass 也创建完成后,可以查看下:

[root@docker-54 config]# kubectl get sc
NAME                    PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage     fuseim.pri/ifs   Retain          Immediate           false                  60s
nfs-storage (default)   nfs-client       Delete          Immediate           false                  132d
[root@docker-54 config]# 

可以看到,这里确实多了一条记录managed-nfs-storage,并且 PROVISIONER 的值,也正是我们配置的 fuseim.pri/ifs,这个是我们后续使用时关联的一个标识。

接着我们来看下上面创建的 Deployment :

[root@docker-54 config]# kubectl get po -n kube-system | grep nfs
nfs-client-provisioner-77bdfd69d9-9hzhx   1/1     Running   0              134m
[root@docker-54 config]# 

可以看到已经是正常运行的状态了。

接下来我们创建statefulsetkubectl apply -f nfs-sc-demo-statefulset.yaml

[root@docker-54 config]# kubectl apply -f nfs-sc-demo-statefulset.yaml 
service/nginx-sc created
statefulset.apps/nginx-sc created
[root@docker-54 config]# 

接着看下应用的状态:

[root@docker-54 config]# kubectl get sts
NAME       READY   AGE
nginx-sc   1/1     54s
[root@docker-54 config]# 
[root@docker-54 config]# kubectl get po | grep nginx
nginx-sc-0                     1/1     Running     0                115s
[root@docker-54 config]#

可以看到正常创建、并启动了。

6. 解决 PVC 为 Pending 状态问题

如果这里 Nginx 的 Pod 为 Pending 状态,则要检查下:kubectl describe po nginx-sc-0

Events:Type     Reason            Age    From               Message----     ------            ----   ----               -------Warning  FailedScheduling  3m20s  default-scheduler  0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims.Normal   Scheduled         3m18s  default-scheduler  Successfully assigned default/nginx-sc-0 to docker-55Normal   Pulled            3m18s  kubelet            Container image "nginx" already present on machineNormal   Created           3m18s  kubelet            Created container nginx-scNormal   Started           3m18s  kubelet            Started container nginx-sc
[root@docker-54 config]# 

如果状态异常,上面命令可以看到具体的原因。这里有个FailedScheduling的警告,提示我们三个节点都是可用的,但是 3 个 pod 还是 unbound ,意思是还未绑定到 PVC。

这时候可以排查下 PVC 的状态及原因:

[root@docker-54 config]# kubectl get pvc
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
nginx-sc-test-pvc-nginx-sc-0   Bound    pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            managed-nfs-storage   6m18s
[root@docker-54 config]# 

如果这里也为 Pending,状态,此时可能 PV 也是非正常的,可以使用 describe 看下具体原因或者看下 PV 的状态。

[root@docker-54 config]# kubectl get pv | grep nginx
pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            Retain           Bound       default/nginx-sc-test-pvc-nginx-sc-0   managed-nfs-storage            8m3s
[root@docker-54 config]#

我这里 PV 是正常的,是因为我修改了,k8s制备器的镜像,k8s 默认是quay.io/external_storage/nfs-client-provisioner:latest 镜像,这个镜像需要用到 K8s 中的 一个 selfLink 的功能,但是从 1.20 版本之后,k8s 把这个功能给关掉了,可能是处于性能以及 API 调用请求的一个方向考虑的,把这个功能给禁用掉了,所以就意味着我们新版本不能再直接使用这个镜像了。

我这里使用的版本是v1.22.6

[root@docker-54 config]#   kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.6", GitCommit:"f59f5c2fda36e4036b49ec027e556a15456108f0", GitTreeState:"clean", BuildDate:"2022-01-19T17:33:06Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.6", GitCommit:"f59f5c2fda36e4036b49ec027e556a15456108f0", GitTreeState:"clean", BuildDate:"2022-01-19T17:26:47Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}
[root@docker-54 config]# 

这里PVC 处于 Pending 状态有两种解决方案:

  • 第一种是配置 SelfLink:修改 apiserver 配置文件
vim /etc/kubernetes/manifests/kube-apiserver.yamlspec:containers:- command:- kube-apiserver- --feature-gates=RemoveSelfLink=false # 新增该行......

修改后重新应用该配置,

kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml

这样可以解决因为版本导致 PVC pending 状态的问题。不过既然官方已经不支持了,我们也没必要强制修改让它支持,看下第二种方案。

  • 第二种是使用不需要 SelfLinkprovisioner:将 provisioner 修改为如下镜像之一即可,下面的为阿里云的镜像,性价比更高。
gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.0registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0

修改完镜像后,然后执行:nfs-provisioner-deployment.yaml 更新deployment

当看到 Pod 的状态正常,PVC 和 PV 的状态正常后,就完事了。

7. 单独测试自动创建 PVC

如果我们想单独测试下这个自动创建 PVC ,那么可以这么操作:

新建配置文件:auto-pv-test-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: auto-pv-test-pvc
spec:accessModes:- ReadWriteOnceresources:requests:storage: 300MistorageClassName: managed-nfs-storage

这里直接创建 PVC,并没有声明关于 PV 的内容,仅仅声明了 PVC 的名称、需要的资源、使用的 storageClassName

[root@docker-54 config]# kubectl apply -f auto-pv-test-pvc.yaml 
persistentvolumeclaim/auto-pv-test-pvc created
[root@docker-54 config]# 
[root@docker-54 config]# kubectl get pvc
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
auto-pv-test-pvc               Bound    pvc-1a180c44-a4d3-44e3-83d0-b69bbf73f2df   300Mi      RWO            managed-nfs-storage   26s
nginx-sc-test-pvc-nginx-sc-0   Bound    pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            managed-nfs-storage   47m
[root@docker-54 config]# 

可以看到,新建的 PVC auto-pv-test-pvc 已经正常绑定到名为pvc-1a180c44-a4d3-44e3-83d0-b69bbf73f2df的 PV 上了。这样也是可以达到自动创建 PVC 的目的。

在后续的使用中,我们使用自动创建 PVC 就不用关心 PV ,我们只需要写我们的需求就好了,系统可以根据我们的需求自动创建PV 来自动绑定。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java王者荣耀小游戏

Background类 package LX;import java.awt.*; //背景类 public class Background extends GameObject{public Background(GameFrame gameFrame) {super(gameFrame);}Image bg Toolkit.getDefaultToolkit().getImage("C:\\Users\\ASUS\\Desktop\\王者荣耀图片\\Map.jpg&…

【JavaEE初阶】Thread 类及常见方法、线程的状态

目录 1、Thread 类及常见方法 1.1 Thread 的常见构造方法 1.2 Thread 的几个常见属性 1.3 启动⼀个线程 - start() 1.4 中断⼀个线程 1.5 等待⼀个线程 - join() 1.6 获取当前线程引用 1.7 休眠当前线程 2、线程的状态 2.1 观察线程的所有状态 2.2 线程状态和状…

P17C++析构函数

目录 前言 01 什么是析构函数 1.1 举个栗子 02 为什么要写析构函数 前言 今天我们要讨论一下它的“孪生兄弟”,析构函数,它们在某些方面非常相似。 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时&…

Redis:持久化RDB和AOF

目录 概述RDB持久化流程指定备份文件的名称指定备份文件存放的目录触发RDB备份redis.conf 其他一些配置rdb的备份和恢复优缺点停止RDB AOF持久化流程AOF启动/修复/恢复AOF同步频率设置rewrite压缩原理触发机制重写流程no-appendfsync-on-rewrite 优缺点 如何选择 概述 Redis是…

An example of a function uniformly continuous on R but not Lipschitz continuous

See https://math.stackexchange.com/questions/69457/an-example-of-a-function-uniformly-continuous-on-mathbbr-but-not-lipschitz?noredirect1

jetpack的简单使用

Jetpack ViewModel: 什么是ViewModel? ViewModel 是 Android 架构组件的一部分,用于帮助开发者管理 UI 数据的持久性和生命周期感知。ViewModel 的主要目的是将 UI 数据与界面控制逻辑分离,以便更好地管理数据的生命周期&#…

单片机学习7——定时器/计数器编程

#include<reg52.h>unsigned char a, num; sbit LED1 P1^0;void main() {num0;EA1;ET01;//IT00;//设置TMOD的工作模式TMOD0x01;//给定时器装初值&#xff0c;50000,50ms中断20次&#xff0c;就得到1sTH0(65536-50000)/256;TL0(65536-50000)%256;TR01; // 定时器/计数器启…

高阶JAVA篇-深入了解字符集

&#x1f525;博客主页&#xff1a; 小扳_-CSDN博客 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 字符集的说明 1.1 ASCII 字符集 1.2 GBK 字符集 1.3 UTF-8字符集 2.0 字符集的编码与解码 2.1 编码提供了常见的方法 2.2 解码提供了常见的方法 1.0 字符集的说明 字…

推荐6款本周 yyds 的开源项目

&#x1f525;&#x1f525;&#x1f525;本周GitHub项目圈选: 主要包含 链接管理、视频总结、有道音色情感合成、中文文本格式校正、GPT爬虫、深度学习推理 等热点项目。 1、Dub 一个开源的链接管理工具&#xff0c;可自定义域名将繁杂的长链接生成短链接&#xff0c;便于保…

18. Python 数据处理之 Numpy

目录 1. 简介2. 安装和导入Numpy3. ndarray 对象4. 基本运算5. 索引、切片和迭代6. 条件和布尔数组7. 变换形状8. 操作数组 1. 简介 数据分析的流程概括起来主要是&#xff1a;读写、处理计算、分析建模和可视化4个部分。 Numpy 是Python 进行科学计算&#xff0c;数据分析时…

Dockerfile-CentOS7.9+Python3.11.2

本文为CentOS7.9下安装Python3.11.2环境的Dockerfile # CentOS with Python3.11.2 # Author xxmail.com# build a new image with basic centos FROM centos:centos7.9.2009 # who is the author MAINTAINER xxmail.comRUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/…

【Linux】记录错误信息日志的实现

文章目录 前言一、 目录实现&#xff08;log.hpp&#xff09;二、目录的具体使用1.comm.hpp&#xff08;管道初始化&#xff09;2.sever.cpp&#xff08;为读端且令其创建命名管道&#xff09;3.client.cpp(为写端) 前言 我们这个设计的日志可以自定以输出的方向&#xff0c;可…