1. 概述
1.1 基本介绍
集群统一入口,以restful方式,交个etcd存储
- scheduler
节点调度,选择node节点应用部署
- controller-manager
处理集群中常规后台任务,一个资源对应一个控制器
- etcd
存储系统,用于保存集群相关的数据
node 组件
- kube let
master排到node节点代表,管理本机容器
- kube-proxy
1.3 k8s核心概念
Pod
- 最小部署单元
- 一组容器(如Docker容器)的集合
- 共享网络,一个pod中的网络共享
- 声明周期是短暂的
- 一个Pod有一个特殊的被称为“根容器”的Pause容器
Controller
- 定期检查系统中存活的Pod,确保预期的pod数量和Replication Controller(RC)提交的一致
- 支持无状态应用部署
- 支持有状态应用部署
- 确保所有的node运行同一个pod
- 定义一次性任务和定时任务
Service
kubectl [common] [TYPE] [NAME] [flags]
[root@master1 ~]# kubectl get nodes node2
帮助命令
kubectl --help具体查看某个操作kubectl get --help
目前使用到的命令
#部署一个服务kubectl create deployment nginx --image=nginx
#开放服务端口kubectl expose deployment nginx --port=80 --type=NodePort
#查看已经部署服务kubectl get pod,svc
#通过yaml文件部署服务kubectl apply -f
#查看controller服务kubectl get cs
#查看node节点kubectl get nodes
3.2 如何快速编写yaml文件
# 第一种:使用kubectl create 命令生成yaml文件,新建一条yaml文件kubectl create deployment web1 --image=nginx --dry-run -o yaml > deployment.yaml
第二种:使用kubectl get 命令导出yaml文件,用已经创建好的pod来生成yaml文件kubectl get deploykubectl get deploy nginx -o=yaml --export > de.yaml
4. POD 最小单元
4.1 Pod节本概念
- 最小部署的单元
- 包含多个容器(一组容器(如Docker容器)的集合)
- 一个pod中容器共享网络命名空间
-
4.2 Pod存在的意义
创建容器使用docker,一个docker对应一个容器,一个容器有进程,一个容器运行一个应用程序
- Pod是多进程设计,运行多个应用程序(一个Pod 有多个容器,一个容器里面运行一个应用程序)
- Pod存在为了亲密性应用
- 两个应用之间进行交互
- 网络之间调用
- 两个应用需要频繁调用
4.3 共享网络
共享网络
通过Pause容器(每个pod默认都包含有一个Pause容器),把其他容器加入到Pause容器里面,让所有业务容器在同一个名称空间中,可以实现网络共享
共享存储
引入数据卷概念Volumn,使用数据卷进行持久化存储4.4 Pod镜像拉取策略
pod提供三种镜像拉取策略
IfNotPresent: 默认值,镜像在宿主机上不存在时才拉取
Always:每次创建Pod 都会重新拉取一次镜像
Never: Pod 永远不会主动拉取这个镜像4.5 Pod资源限制
pod提供对节点主机资源的上限和下限限制resources:requests:memory: "64Mi" #对内存最小调度限制cpu: "250m" #对cpu最小调度限制limits:memory: "128Mi" #对内存最大调度限制cpu: "500m" #对cpu最大调度限制
4.6 Pod重启策略
yaml文件中用restartPolicy:Never 表示重启机制,提供三种重启机制
Always:当容器终止退出后,总是重启容器,默认策略
OnFailure:当容器异常退出(退出状态码非0)时,才重启容器
Never:当容器终止退出,从不重启容器4.7 Pod健康检查
```yamllivenessProbe (存活检查)
如果检查失败,将杀死容器,根据Pod的restartPolicy来操作
readinessProbe (就绪检查)
如果检查失败,Kubernetes会把Pod从service endpoints中剔除
```yaml# Probe 支持以下三种检查方式## httpGet### 发送HTTP请求,返回200-400范围状态码为成功## exec### 执行Shell命令返回状态码是0为成功## tcpSocket### 发起TCP Socket建立成功
4.8 Pod创建流程
说明:
master节点
- createpod — apiserver — etcd
- scheduler — apiserver — etcd — 调度算法,把pod调度某个node节点上
node节点
- kubelet — apiserver — 读取etcd拿到分配给当前节点pod — docker 创建容器
4.9 Pod调度节点亲和性
硬亲和性: 约束条件必须满足spec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:- nodeSelectorTerms:- key: env roleoperator: Invalues:- dev- test
软亲和性: 尝试满足,不保证一定满足
spec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:- weight: 1preference:matchExpressions:-key: groupoperator: Invalues:- otherprod
4.10 Pod调度节点选择器
Pod资源限制对Pod调用产生影响
resources:requests:memory: "64Mi"cpu: "250m"
节点选择器标签影响Pod调度
spec:nodeSelector:env_role: dev
4.11 Pod调度污点和污点容忍
- 基本介绍
nodeSelector和nodeAffinity:Pod调度到某些节点上,Pod属性调度时候实现
Taint污点:节点不做普通分配调度,是节点属性
- 使用场景
- 专用节点
- 配置特点硬件节点
- 基于Taint驱逐
- 查看节点污点情况
#kubectl describe node [节点名称] | grep Taintkubectl describe node k8smaster | grep Taint
污点有三个值
NoSchedule:一定不被调用
PreferNoSchdule: 尽量不被调度
NoExecute:不会调度,并且还会驱逐Node已有Pod
为节点添加污点
#kubectl taint node [节点名称] key=value:[污点的三个值]kubectl taint node master1 key=value:NoSchedule
删除污点
kubectl taint node master1 env_role:NoSchedule-node/master1 untainted
污点容忍
spec:tolerations:- key: "key"operator: "Equal"value: "value"effect: "NoSchedule"
4.12 常用命令
查看已经部署的pod
kubectl get deployment
删除pod
kubectl delete deployment nginx-dep
查看pvc
kubectl get pvc -A
删除pvc
#删除pvckubectl delete pvc XXX#强制删除kubectl delete pvc XXX --force --grace-period=0
5. Controller控制器
5.1 什么是Controller
Controller是一个在集群上管理和运行容器的对象,通俗的说就是用来管理Pod的
5.2 Pod和Controller的关系
- Pod是通过Controller 实现应用的运维,比如伸缩,滚动升级等等
- Pod和Controller 之间通过label标签建立关系
spec:selector:matchLabels:app: filebeat #和labels app保持一致template:metadata:labels:app: filebeat #和selector app保持一致
5.3 deployment 应用场景
- 部署无状态应用
- 管理Pod和ReplicaSet
- 部署,滚动升级等功能
- 应用场景:web服务,微服务
5.4 使用deployment部署应用
- 导出yaml文件
通过镜像拉去创建yaml文件
kubectl create deployment web --image=nginx --dry-run -o yaml > web.yaml
通过已经创建的pod生成yaml文件
[root@master1 kubernetes]# kubectl get deployNAME READY UP-TO-DATE AVAILABLE AGEnginx 1/1 1 1 5h4m[root@master1 kubernetes]# kubectl get deploy nginx -o=yaml --export > web1.yaml
使用yaml部署应用
kubectl apply -f web.yaml
对外暴露发布端口
生成yaml文件kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web -o yaml > web.yaml部署应用kubectl apply -f web.yaml查看访问端口kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.1.0.1 <none> 443/TCP 5h31mnginx NodePort 10.1.8.108 <none> 80:30499/TCP 5h9mweb NodePort 10.1.181.210 <none> 80:30942/TCP 103s
5.5 应用升级回滚和弹性伸缩
- 应用升级
kubectl set image deployment web nginx=nginx:1.15
kubectl rollout status deployment web
查看升级版本
[root@master1 kubernetes]# kubectl rollout history deployment webdeployment.apps/webREVISION CHANGE-CAUSE1 <none>2 <none>3 <none>
回滚到上一个版本
kubectl rollout undo deployment web
回滚到指定的版本
kubectl rollout undo deployment web --to-revision=3
查看升级状态
kubectl rollout status deployment webWaiting for deployment "web" rollout to finish: 1 old replicas are pending termination...Waiting for deployment "web" rollout to finish: 1 old replicas are pending termination...deployment "web" successfully rolled out
弹性伸缩
kubectl scale deployment web --replicas=10
6. Service
6.1 Service 存在的意义
- 防止Pod 失联(起到服务发现的作用)
-
6.2 Pod和Service关系
通过selector.app.nginx 和 labels.app.nginx关联
6.3 常用Service 类型
ClusterIP: 集群内部使用
- NodePort:对外访问应用使用
- LoadBalancer:对外访问应用使用,公有云
说明:node 内网部署应用时,外网是不可以访问的。可以通过一台可以访问外网的服务器,部署nginx做反向代理。手动把可以访问的节点添加到nginx里面
7. 配置管理
8. 集群安全机制
8.1 概述
- 访问k8s集群的时候,需要经过三个步骤完成具体操作
- 第一步 认证
- 第二步 鉴权(授权)
- 第三部 准入控制
- 进行访问的时候,过程中都需要经过apiserver,apiserver 做统一协调,比如门卫。
- 传输安全
对外不暴露8080端口,只能内部访问,对外使用端口6443
- 认证
客户端身份证方式:
role:特定命名空间访问权限
ClusterRole:所有命名空间访问权限
- 角色绑定
roleBinding:角色绑定到主体
ClusterRoleBinding:集群角色绑定到主体
- 主体
user:用户
group:用户组
serviceAccount:服务账号
8.6 rbac实现鉴权
创建命名空间
kubectl create ns roledemo
在新建的命名空间创建pod
kubectl run nginx --image=nginx -n roledemo
创建角色
新建rbac-role.yaml文件,文件名可以随意
kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:namespace: ctnrsname: pod-readerrules:- apiGroups: [""] # "" indicates the core API groupresources: ["pods"]verbs: ["get", "watch", "list"]
执行yaml文件
kubectl apply -f rbac-role.yaml
查看角色
kubectl get role -n roledemo
- 创建角色绑定
新建rbac-rolebinding.yaml文件
kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:name: read-podsnamespace: roletestsubjects:- kind: Username: lucy # Name is case sensitiveapiGroup: rbac.authorization.k8s.ioroleRef:kind: Role #this must be Role or ClusterRolename: pod-reader # this must match the name of the Role or ClusterRole you wish to bind toapiGroup: rbac.authorization.k8s.io
执行yaml文件
kubectl apply -f rbac-rolebinding.yaml
查看角色和角色绑定
kubectl get role,rolebinding -n roledemo
9. Ingress
9.1 为什么引入Ingress
- 把端口号对外暴露,通过ip+端口号进行访问
使用Service里面的NodePort实现
- NodePort缺陷
- 在每个节点上都会起到端口,在访问时候通过任何节点,通过节点ip+暴露端口实现访问
- 这意味着每个端口只能使用一次,一个端口号对应着一个应用
- 实际访问中都是用域名,根据不同域名跳转到不同端口对应的服务中
9.2 Ingress和Pod关系
- pod和ingress通过service关联的
-
9.3 使用Ingress对外暴露应用
部署ingress Controller
这里选择官方维护的nginx控制器实现部署 创建nginx应用
kubectl create deployment web2 --image=nginx
对外暴露端口使用NodePort
kubectl expose deployment web2 --port=80 --target-port=80 --type=NodePort
部署Ingress controller
新建ingress-con.yaml文件,文件名可以随意
apiVersion: v1kind: Namespacemetadata:name: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:name: nginx-configurationnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:name: tcp-servicesnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata:name: udp-servicesnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---apiVersion: v1kind: ServiceAccountmetadata:name: nginx-ingress-serviceaccountnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginx---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRolemetadata:name: nginx-ingress-clusterrolelabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxrules:- apiGroups:- ""resources:- configmaps- endpoints- nodes- pods- secretsverbs:- list- watch- apiGroups:- ""resources:- nodesverbs:- get- apiGroups:- ""resources:- servicesverbs:- get- list- watch- apiGroups:- ""resources:- eventsverbs:- create- patch- apiGroups:- "extensions"- "networking.k8s.io"resources:- ingressesverbs:- get- list- watch- apiGroups:- "extensions"- "networking.k8s.io"resources:- ingresses/statusverbs:- update---apiVersion: rbac.authorization.k8s.io/v1beta1kind: Rolemetadata:name: nginx-ingress-rolenamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxrules:- apiGroups:- ""resources:- configmaps- pods- secrets- namespacesverbs:- get- apiGroups:- ""resources:- configmapsresourceNames:# Defaults to "<election-id>-<ingress-class>"# Here: "<ingress-controller-leader>-<nginx>"# This has to be adapted if you change either parameter# when launching the nginx-ingress-controller.- "ingress-controller-leader-nginx"verbs:- get- update- apiGroups:- ""resources:- configmapsverbs:- create- apiGroups:- ""resources:- endpointsverbs:- get---apiVersion: rbac.authorization.k8s.io/v1beta1kind: RoleBindingmetadata:name: nginx-ingress-role-nisa-bindingnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxroleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: nginx-ingress-rolesubjects:- kind: ServiceAccountname: nginx-ingress-serviceaccountnamespace: ingress-nginx---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata:name: nginx-ingress-clusterrole-nisa-bindinglabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: nginx-ingress-clusterrolesubjects:- kind: ServiceAccountname: nginx-ingress-serviceaccountnamespace: ingress-nginx---apiVersion: apps/v1kind: Deploymentmetadata:name: nginx-ingress-controllernamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxspec:replicas: 1selector:matchLabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxtemplate:metadata:labels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxannotations:prometheus.io/port: "10254"prometheus.io/scrape: "true"spec:hostNetwork: true# wait up to five minutes for the drain of connectionsterminationGracePeriodSeconds: 300serviceAccountName: nginx-ingress-serviceaccountnodeSelector:kubernetes.io/os: linuxcontainers:- name: nginx-ingress-controllerimage: lizhenliang/nginx-ingress-controller:0.30.0args:- /nginx-ingress-controller- --configmap=$(POD_NAMESPACE)/nginx-configuration- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services- --udp-services-configmap=$(POD_NAMESPACE)/udp-services- --publish-service=$(POD_NAMESPACE)/ingress-nginx- --annotations-prefix=nginx.ingress.kubernetes.iosecurityContext:allowPrivilegeEscalation: truecapabilities:drop:- ALLadd:- NET_BIND_SERVICE# www-data -> 101runAsUser: 101env:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespaceports:- name: httpcontainerPort: 80protocol: TCP- name: httpscontainerPort: 443protocol: TCPlivenessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPinitialDelaySeconds: 10periodSeconds: 10successThreshold: 1timeoutSeconds: 10readinessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPperiodSeconds: 10successThreshold: 1timeoutSeconds: 10lifecycle:preStop:exec:command:- /wait-shutdown---apiVersion: v1kind: LimitRangemetadata:name: ingress-nginxnamespace: ingress-nginxlabels:app.kubernetes.io/name: ingress-nginxapp.kubernetes.io/part-of: ingress-nginxspec:limits:- min:memory: 90Micpu: 100mtype: Container
执行yaml文件
kubectl apply -f ingress-con.yaml
查看ingress controller状态
kubectl get pods -n ingress-nginx
- 创建ingress规则
新建ingressy.yaml规则文件
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata:name: example-ingressspec:rules:- host: example.ingredemo.comhttp:paths:- path: /backend:serviceName: webservicePort: 80
执行yaml文件
kubectl apply -f ingress.yaml
查看部署应用在哪个节点上
kubectl get pods -n ingress-nginx -o wide
查看域名映射端口
kubectl get ing
10. Helm
10.1 Helm介绍
Helm是一个Kubernetes的包管理工具,就像Linux 下的包管理器,如yum/apt等,可以很方便的将之前打包好的yaml文件部署到kubernetes上
10.2 使用helm 可以解决哪些问题?
- 使用helm可以把这些yaml作为一个整体管理
- 实现yaml高效复用
-
10.3 Helm三个重要概念
helm 是一个命令行客户端工具
- Chart 把yaml打包,是yaml集合
- Release 基于chart部署实体,应用级别的版本管理
10.4 Helm常用命令
创建一个chart并制定名字
helm create mchart
管理chart依赖
helm dependency
下载一个 release。 可用子命令: all、 hooks、 manifest、 notes、 values
获取 release 历史
安装一个 chart
#helm install 安装之后名称 应用名称或创建的chart名称helm install ui stable/weave-scope
列出 release
helm list
将 chart 目录打包到 chart 存档文件中
从远程仓库中下载 chart 并解压到本地
helm pull stable/mysql -- untar
添加, 列出, 移除, 更新和索引 chart 仓库。 可用子命令: add、 index、 list、 remove、 update
#添加仓库 helm repo add [仓库名称] [仓库地址]helm repo add stable http://mirror.azure.cn/kubernetes/charts#仓库列表helm repo list#更新仓库helm repo update#索引helm repo index#移除 helm repo remove [仓库名称]helm repo remove aliyun
从之前版本回滚
helm rollback
根据关键字搜索 chart。 可用子命令: hub、 repo ```shell helm search repo mysql
helm search hub mysql
11. 查看 chart 详细信息。 可用子命令: all、 chart、 readme、 values```shellshow
显示已命名版本的状态
#helm status [应用名称]helm status web3
本地呈现模板
template
卸载一个release
helm release web3
更新一个release
helm upgrade web3
查看helm客户端版本
helm version
10.5 Helm安装(v3版本)
- 下载离线压缩文件
解压helm压缩文件
tar -zxvf helm-v3.0.0-linux-amd64.tar.gz
把解压缩之后的helm目录复制(移动)到Linux服务器的/usr/bin目录下
mv help /usr/bin
10.6 helm仓库管理
添加仓库
#helm repo add 仓库名称 仓库地址helm repo add stable http://mirror.azure.cn/kubernetes/charts
查看仓库地址
helm repo list
更新仓库地址
helm repo update
删除仓库地址
helm repo remove aliyun
10.7 使用helm快速部署应用
根据helm命令搜索应用
#helm search repo [应用名称][root@master1 bin]# helm search repo weaveNAME CHART VERSION APP VERSION DESCRIPTIONstable/weave-cloud 0.3.9 1.4.0 DEPRECATED - Weave Cloud is a add-on to Kuberne...stable/weave-scope 1.1.12 1.12.0 DEPRECATED - A Helm chart for the Weave Scope c...
根据helm搜索内容选择安装
#helm install 安装之后名称 搜索之后应用名称helm install ui stable/weave-scope
查看通过helm安装的应用列表
helm list
查看通过helm安装的应用状态
#helm status [应用名称]helm status ui
10.8 如何使用Chart
- 使用命令创建chart
# 创建mcharthelm create mchart# 进入mchart文件夹[root@master1 mchart]# lscharts Chart.yaml templates values.yaml
文件说明
Chart yaml:当前Chart属性配置信息
templates:编写yaml文件放到这个目录中
values.yaml:yaml文件可以使用全局变量
在templates文件夹下创建两个yaml文件
可以通过 导出yaml的方式导出文件生成deployment.yaml文件kubectl create deployment web3 --image=nginx --dry-run -o yaml > deployment.yaml生成service.yaml文件kubectl expose deployment web3 --port=80 --target-port=80 --type=NodePort --dry-run -o yaml > service.yaml
安装chart(要回到mchart的上级目录下)
helm install web3 mchart/
10.9 复用yaml文件
待完善
11. 持久存储
数据卷emptydir 是本地存储,当pod重启后数据就不存在了,需要对数据持久化存储
NFS是一个网络存储,当pod重启后,数据还是存在的
11.1 NFS安装
安装NFS
找一台nfs存储服务器yum install -y nfs-utils
设置挂载路径
vi /etc/exports
/data/nfs *(rw,no_root_squash)
注意:挂载路径需要手动创建出来
11.2 在k8s集群node节点中安装nfs
yum install -y nfs-utils
11.3 在nfs服务器中启动nfs服务
#启动nfs服务systemctl start nfs#查看nfs服务是否启动ps -ef | grep nfs
11.4 在k8s集群部署应用使用nfs持久网络存储
apiVersion: apps/v1kind: Deploymentmetadata:name: nginx-dep1spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxvolumeMounts:- name: wwwrootmountPath: /usr/share/nginx/html # k8s集群中目录,nfs目录中的文件会同步到这个文件夹ports:- containerPort: 80volumes:- name: wwwrootnfs:server: 192.168.44.134 # nfs服务器ippath: /data/nfs # nfs 挂载目录
这样nfs服务器中/data/nfs目录中的文件就可以同步到/usr/share/nginx/html文件夹中了
11.5 PV和PVC
nfs存储,需要制定nfs服务器的ip,这在实际生产项目中有诸多的不变为了解决这个问题引入pv和pvc,在yaml文件中指定nfs的别名,根据容量来匹配nfs服务器
- PV:持久化存储,对存储资源进行抽象,对外提供可以调用的地方(生产者)
- PVC:用于调用,不需要关心内部实现细节(消费者)
11.6 PV和PVC的使用
- 在master节点中安装服务
新建pvc.yaml文件,在文件中指定nfs别名
apiVersion: apps/v1kind: Deploymentmetadata:name: nginx-dep1spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxvolumeMounts:- name: wwwrootmountPath: /usr/share/nginx/htmlports:- containerPort: 80volumes:- name: wwwrootpersistentVolumeClaim:claimName: my-pvc #通过别名的方式指定nfs服务器---# 声明nfs服务器别名apiVersion: v1kind: PersistentVolumeClaimmetadata:name: my-pvcspec:accessModes:- ReadWriteMany #匹配模式,pv和pvc是根据容量来匹配的resources:requests:storage: 5Gi
安装pvc服务
kubectl apply -f pvc.yaml
查看pvc服务
kubectl get pvc
- 安装pv服务
新建pv.yaml文件
apiVersion: v1kind: PersistentVolumemetadata:name: my-pvspec:capacity:storage: 5GiaccessModes:- ReadWriteManynfs:path: /k8s/nfsserver: 192.168.242.150 # 这个是nfs服务的ip
安装pv服务
kubectl get pv
