3.k8s:服务发布:service,ingress;配置管理:configMap,secret,热更新;持久化存储:volumes,nfs,pv,pvc

目录​​​​​​​

一、服务发布

1.service

(1)service和pod之间的关系

(2) service内部服务创建访问

(3)service访问外部服务

(4)基于域名访问外部

(5)service的访问方式

2.服务发现ingress

(1)什么是ingress

(2)安装helm和ingress-nginx

*1)安装helm

*2)下载ingress-nginx安装包

*3)编辑ingress配置文件

*4)启动

 (3)使用ingress-nginx

(4)多域名配置

二、配置管理

1.ConfigMap

(1)创建ConfigMap

(2)使用ConfigMap

2.secret密文

(1)直接创建

(2)拉取镜像密文校验

3.SubPath解决configMap数据挂载覆盖的问题

4.配置的热更新

5.不可变的secret和configMap

三、持久化存储

1.volumes

(1)HostPath

(2)EmptyDir

2.NFS挂载

(1)安装NFS

(2)将NFS挂载到容器中

3.pv和pvc(重要)

(1)什么是pv和pvc

(2)生命周期

(3)创建pv,pvc,并关联pod,实现持久化数据

*1)创建pv

*2)创建pvc

*3)pvc和pod关联,实现容器数据持久化

(4) StorageClass动态申领

四、感谢支持


一、服务发布

1.service

负责 同层级/内部服务网络 的通信。

(1)service和pod之间的关系

  1. 一个子节点node = kubelet + kube-proxy + container runtime(容器运行时环境)+pod
  2. pod = pause容器(此处up是10.244.36.107) + 具体运行的项目(此处为nginx,nginx自带端口80)+ pod的基本信息(名称、标签)
    1. 这里有一个要对应的是,一个node宿主机的自己的ip和端口,和pod中的pause容器的ip和端口是对应上的
  3. master = service + EndPoint
    1. service中本身有一个pause容器并且暴露一个端口,同时因为service本身是一个服务并且部署在master宿主机上。因此我们可以通过宿主机ip + 宿主机真实端口访问service。也可以通过service的pause容器的ip + pause中的端口访问service。
    2. 一个service会生成一个endpoint,endpoint中会记录子宿主机中的pause容器的ip和端口
  4. service经过endpoint知道子宿主机的pause容器和端口后,通过iptables能够访问到子宿主机的真实机器,发送请求到子宿主机的kube-proxy上。并且转给自己的pod

(2) service内部服务创建访问

cd /opt/k8s/services/
vim nginx-svc.yaml ###############################################
apiVersion: v1
kind: Service #资源类型是service
metadata:name: nginx-svc #service名称labels: #service自己本身的标签app: nginx
spec:selector: #匹配哪些pod会被该service代理app: nginx-deploy #所有匹配到这个标签的pod都可以通过该service进行访问ports: #端口映射- port: 80 #service自己的端口,k8s内网ip访问时使用targetPort: 80 #目标pod的端口name: web #为端口起个名字type: NodePort #随机启动一个端口(30000-32767),映射到ports中的端口,该端口是直接绑定在宿主node上面,且集群中每一个宿主node都会绑定这个端口。也可以将服务暴露给外部访问,但是这种方式实际生产环境不推荐,因为效率低,而且service是四层负载
################################################ 创建 service
kubectl create -f nginx-svc.yaml# 查看
kubectl get svc 
kubectl get po -o wide#创建其他 pod 通过 service name 进行访问
kubectl run -it --image busybox:1.28.4 dns-test --restart=Never --rm /bin/sh
wget http://nginx-svc
cat index.html

 

(3)service访问外部服务

不使用selector属性,而是自己建endpoint。

先新建一个service:

/opt/k8s/services
vim nginx-svc-external.yaml #####################################################################
apiVersion: v1
kind: Service #资源类型是service
metadata:name: nginx-svc-external #service名称labels: #service自己本身的标签app: nginx
spec:ports: #端口映射- port: 80 #service自己的端口,k8s内网ip访问时使用targetPort: 80 #目标pod的端口name: web #为端口起个名字type: ClusterIP######################################################################启动,可以看到,我们这个没有启动endpoint,因为我们没有指定 selector 属性,需要自己建endpoint
kubectl create -f nginx-svc-external.yaml 
kubectl get svc
kubectl get ep

再新建一个endpoint:

vim nginx-svc-external.yaml#########################################################
apiVersion: v1
kind: Endpoints
metadata:labels:app: nginx # 与 service 一致name: nginx-svc-external # 与 service 一致namespace: default # 与 service 一致
subsets:
- addresses:- ip: 120.78.159.117 # 目标 ip 地址ports: # 与 service 一致- name: web port: 80protocol: TCP##########################################################启动
kubectl create -f nginx-svc-external.yaml 
kubectl get svc
kubectl get ep
kubectl describe ep nginx-svc-external #测试
kubectl run -it --image busybox:1.28.4 dns-test --restart=Never --rm /bin/sh
wget http://nginx-svc-external

可以看到,我们请求的是内部的service,但是实际上调用到了外部的地址:

(4)基于域名访问外部

vim nginx-svc-externalname.yaml###########################################################
apiVersion: v1
kind: Service
metadata:labels:app: wolfcode-external-domainname: wolfcode-external-domain
spec:type: ExternalNameexternalName: www.wolfcode.cn
############################################################启动
kubectl create -f nginx-svc-externalname.yaml 
kubectl get svc#测试
kubectl run -it --image busybox:1.28.4 dns-test --restart=Never --rm /bin/sh
wget wolfcode-external-domain

(5)service的访问方式

  • ClusterIP:只能在集群内部使用,不配置类型的话默认就是 ClusterIP

  • ExternalName:返回定义的 CNAME 别名,可以配置为域名

  • NodePort:会在所有安装了 kube-proxy 的节点都绑定一个端口,此端口可以代理至对应的 Pod,集群外部可以使用任意节点 ip + NodePort 的端口号访问到集群中对应 Pod 中的服务。端口范围:30000~32767。不推荐

  • LoadBalancer:使用云服务商(阿里云、腾讯云等)提供的负载均衡器服务,不推荐

2.服务发现ingress

(1)什么是ingress

看调用流程会发现,ingress充当的是以前nginx的角色。但是他对nginx额外做了一层封装和抽象。我们可以简单的吧ingress认为是一个抽象,然后nginx是对ingress的一个实现。

(2)安装helm和ingress-nginx

helm是k8s里面的包管理工具,类似于Java中的Maven。

*1)安装helm
#下载、解压二进制文件
cd /opt/k8s/
mkdir helm
cd helm/
wget https://get.helm.sh/helm-v3.2.3-linux-amd64.tar.gz
tar -zxvf helm-v3.2.3-linux-amd64.tar.gzcd /opt/k8s/
chmod +x helm/#将配置文件拷贝到指定目录
cd linux-amd64/
cp helm /usr/local/bin/#查看helm
cd ~
helm version#添加helm仓库

*2)下载ingress-nginx安装包

如果你下面这些能正常运行最好:

# 添加仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx# 查看仓库列表
helm repo list# 搜索 ingress-nginx
helm search repo ingress-nginx# 下载安装包
helm pull ingress-nginx/ingress-nginx --version 4.2.2# 解压
cd /opt/k8s/helm
tar -zxvf ingress-nginx-4.2.2.tgz 

如果你的服务器被墙了,一直添加不了仓库,手动去直接下载ingress-nginx,下载地址如下:

Release helm-chart-4.2.2 · kubernetes/ingress-nginx · GitHub

上传到/helm目录下,然后解压即可:

*3)编辑ingress配置文件
cd ingress-nginx
vim values.yaml################################################################
#controller下的image改动
#registry: registry.cn-hangzhou.aliyuncs.com
#image: google_containers/nginx-ingress-controller
#tag: "v1.3.0"
#将digest,digestChroot 两行注释掉#66行dnsPolicy修改:
dnsPolicy: ClusterFirstWithHostNet#89行hostNetwork改成true
hostNetwork: true#194行kind修改
#kind: DaemonSet#292行nodeSelector新增ingress
ingress: "true" # 增加选择器,如果 node 上有 ingress=true 就部署#503行type修改:
type: ClusterIP#541行patch下面的image改动
#registry: registry.cn-hangzhou.aliyuncs.com
#image: google_containers/kube-webhook-certgen
#tag: "v1.3.0"
#将digest注释掉#596行修改admissionWebhooks:
enabled: false
################################################################

controller下的image改动:

541行patch下面的image改动:

194行kind修改:

292行nodeSelector新增ingress:

89行hostNetwork改成true:

66行dnsPolicy修改:

503行type修改:

596行修改admissionWebhooks:

*4)启动
#为ingress创建命名空间
kubectl create ns ingress-nginx# 为主宿主机节点上加标签,我的是kubernete140 
kubectl label node kubernete140 ingress=true# 安装 ingress-nginx
helm install ingress-nginx . -n ingress-nginx# 查看
helm -n ingress-nginx ls -a# 我们会发现主节点找不到,因为主节点有污点,不推荐放在主节点
kubectl get po -n ingress-nginx# 我们给141的子节点新增标签
kubectl label no kubernete141 ingress=true # 查看,显示成功
kubectl get po -n ingress-nginx
kubectl get po -n ingress-nginx -o wide

 (3)使用ingress-nginx

cd /opt/k8s/
mkdir ingress
cd ingress/#配置文件
vim xupeng-ingress.yaml
##########################################################
apiVersion: networking.k8s.io/v1
kind: Ingress # 资源类型为 Ingress
metadata:name: xupeng-nginx-ingressannotations:kubernetes.io/ingress.class: "nginx"nginx.ingress.kubernetes.io/rewrite-target: /
spec:rules: # ingress 规则配置,可以配置多个- host: k8s.wolfcode.cn # 域名配置,可以使用通配符 *http:paths: # 相当于 nginx 的 location 配置,可以配置多个- pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配backend:service: name: nginx-svc # 代理到哪个 serviceport: number: 80 # service 的端口path: /api # 等价于 nginx 中的 location 的路径前缀匹配###########################################################启动
kubectl create -f xupeng-ingress.yaml #查看
kubectl get ingress
kubectl get po -o wide#查看ingress-nginx日志
kubectl logs -f nginx-deploy-776dbd5599-v6kpb

在windows机器中,配置dns,路径:

C:\Windows\System32\drivers\etc\hosts

#此处的ip不是master宿主机,而是子宿主机
192.168.200.141 k8s.wolfcode.cn

测试:

(4)多域名配置

apiVersion: networking.k8s.io/v1
kind: Ingress # 资源类型为 Ingress
metadata:name: wolfcode-nginx-ingressannotations:kubernetes.io/ingress.class: "nginx"nginx.ingress.kubernetes.io/rewrite-target: /
spec:rules: # ingress 规则配置,可以配置多个- host: k8s.wolfcode.cn # 域名配置,可以使用通配符 *http:paths: # 相当于 nginx 的 location 配置,可以配置多个- pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配backend:service: name: nginx-svc # 代理到哪个 serviceport: number: 80 # service 的端口path: /api # 等价于 nginx 中的 location 的路径前缀匹配- pathType: Exec # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配>,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配backend:service:name: nginx-svc # 代理到哪个 serviceport:number: 80 # service 的端口path: /- host: api.wolfcode.cn # 域名配置,可以使用通配符 *http:paths: # 相当于 nginx 的 location 配置,可以配置多个- pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配>,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配backend:service:name: nginx-svc # 代理到哪个 serviceport:number: 80 # service 的端口path: /

二、配置管理

1.ConfigMap

明文键值对的配置。

(1)创建ConfigMap

#创建文件夹
cd /opt/k8s/
mkdir config
cd config/#新增两个配置文件
mkdir test
cd test/
touch db.properties
touch redis.properties##################################
文件内容随便:
username=aa
port: 111
###################################基于文件夹方式创建
cd /opt/k8s/config/
kubectl create configmap test-dir-config --from-file=test/
kubectl get cm
kubectl describe cm test-dir-config#基于单个文件创建
cd /opt/k8s/config/
vim application.yaml
###################################
spring:application: name: test-app
server:port: 8080
###################################
kubectl create cm spring-boot-test-yaml --from-file=/opt/k8s/config/application.yaml
kubectl get cm
kubectl describe cm spring-boot-test-yaml#基于单文件重命名方式创建
kubectl create cm spring-boot-test-alises-yaml --from-file=app.yml=/opt/k8s/config/application.yaml
kubectl describe cm spring-boot-test-alises-yaml#直接写入key-value方式创建
kubectl create cm test-key-value-config --from-literal=username=root --from-literal=password=admin
kubectl describe cm test-key-value-config

(2)使用ConfigMap

*1)方法一:不推荐

#先创建一个cm
kubectl create cm test-env-config --from-literal=JAVA_OPTS_TEST='-Xms512m -Xmx512m' --from-literal=APP_NAME=springboot-env-test
kubectl describe cm/test-env-config#运行一个pod
vim env-test-cm.yaml
#############################################
apiVersion: v1
kind: Pod
metadata:name: test-env-cm
spec:containers:- name: env-testimage: alpinecommand: ["/bin/sh","-c","env;sleep 3600"]imagePullPolicy: IfNotPresentenv:- name: JAVA_VM_OPTSvalueFrom:configMapKeyRef:name: test-env-config #configMap的名字key: JAVA_OPTS_TEST #从name的cm中获取名字为key的value,将其赋值给本地变量JAVA_VM_OPTSrestartPolicy: Never
##############################################启动
kubectl create -f env-test-pod.yaml #查看
kubectl logs -f test-env-cm

可以看到我们已经使用了配置文件中的value:

*2)方法二:数据卷方式挂载cm

#删除上面的pod
kubectl delete po test-env-cm#配置文件
vim file-test-pod.yaml
#################################################################
apiVersion: v1
kind: Pod
metadata:name: test-configfile-cm
spec:containers:- name: config-testimage: alpinecommand: ["/bin/sh","-c","sleep 3600"]imagePullPolicy: IfNotPresentenv:- name: JAVA_VM_OPTSvalueFrom:configMapKeyRef:name: test-env-config #configMap的名字key: JAVA_OPTS_TEST #从name的cm中获取名字为key的value,将其赋值给本地变量JAVA_VM_OPTSvolumeMounts: #加载数据卷- name: db-config #加载volumes中哪个数据卷mountPath: "/usr/local/mysql/conf" #想要将数据卷中的文件加载到哪个目录下readOnly: true #只读volumes: #数据卷挂载:configmap,secret- name: db-configconfigMap: #数据卷类型为configMapname: test-dir-config #cm的名字,必须要跟想加载的cm一致items: #对cm中的key进行映射,如果不指定,默认会将cm中所有key全部转化为一个同名的文件- key: "db.properties" #cm中的keypath: "db.properties" #将该key的值转化为文件restartPolicy: Never
##################################################################启动
kubectl create -f file-test-pod.yaml #查看
kubectl get po#进入容器查看配置文件有没有挂载
kubectl exec -it test-configfile-cm  -- sh
cd /usr/local/mysql/conf/
cat db.properties 

2.secret密文

使用场景:

(1)直接创建

密文创建,有特殊字符需要加单引号:用得不多

#直接创建密文
kubectl create secret generic ori-secret --from-literal=username=admin --from-literal=password='ss@!3~/\'#加解密方式
echo 'ss@!3~/\' | base64
echo 'c3NAITN+L1wK' | base64 --decode

(2)拉取镜像密文校验

# 生成密文
kubectl create secret docker-registry harbor-secret --docker-username=admin --docker-password=wolfcode --docker-email=aa@163.com --docker-server=192.168.113.122:8858
kubectl edit secret/harbor-secret
docker image# 打包nginx上传镜像仓库
docker tag nginx:1.9.1 192.168.113.122:8858/opensource/nginx:1.9.1
docker login -uadmin 192.168.113.122:8858
docker push 192.168.113.122:8858/opensource/nginx:1.9.1# 编写配置文件,拉取镜像需要校验密文
vim private-image-pull.yaml#########################################################################
apiVersion: v1
kind: Pod
metadata:name: private-image-pull
spec:imagePullSecrets: #配置登录docker仓库的secret- name: harbor-secretcontainers:- name: nginximage: 192.168.113.122:8858/opensource/nginx:1.9.1command: ["/bin/sh","-c","sleep 3600"]imagePullPolicy: IfNotPresentenv:- name: JAVA_VM_OPTSvalueFrom:configMapKeyRef:name: test-env-config #configMap的名字key: JAVA_OPTS_TEST #从name的cm中获取名字为key的value,将其赋值给本地变量JAVA_VM_OPTSvolumeMounts: #加载数据卷- name: db-config #加载volumes中哪个数据卷mountPath: "/usr/local/mysql/conf" #想要将数据卷中的文件加载到哪个目录下readOnly: true #只读volumes: #数据卷挂载:configmap,secret- name: db-configconfigMap: #数据卷类型为configMapname: test-dir-config #cm的名字,必须要跟想加载的cm一致items: #对cm中的key进行映射,如果不指定,默认会将cm中所有key全部转化为一个同名的文件- key: "db.properties" #cm中的keypath: "db.properties" #将该key的值转化为文件restartPolicy: Never
##########################################################################启动
kubectl create -f private-image-pull.yaml
kubectl get po -o wide 

3.SubPath解决configMap数据挂载覆盖的问题

目的:

我们在一个po里面复制出来他的配置文件,然后吧配置文件用configMap保存,然后用数据卷映射到容器里的配置文件,目的是想直接改映射文件中的内容,同步修改容器中的配置。

问题:

configMap的映射文件一旦挂载数据卷,原本容器里有很多文件的,挂载后就只剩下我们挂载的文件了。其他的文件都没了,被覆盖了

复现如下:

#先找一个运行的po,找到里面的配置文件,我们这边复制nginx配置
kubectl get po
kubectl exec -it nginx-deploy-776dbd5599-v6kpb -- sh
cd /etc/nginx
cat nginx.conf#将配置文件复制出来,作为一个configMap保存
cd /opt/k8s/config/
vim config-nginx###########################################
user  nginx;
worker_processes  1;error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;events {worker_connections  1024;
}http {include       /etc/nginx/mime.types;default_type  application/octet-stream;log_format  main  '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log  /var/log/nginx/access.log  main;sendfile        on;#tcp_nopush     on;keepalive_timeout  65;#gzip  on;include /etc/nginx/conf.d/*.conf;
}############################################设置成cm
kubectl create cm nginx-conf-cm --from-file=./config-nginx
kubectl describe cm nginx-conf-cm#编辑deploy
kubectl edit deploy nginx-deploy###########################################
#新增数据卷挂载相关内容spec:containers:- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: nginxresources:limits:cpu: 100mmemory: 128Mirequests:cpu: 100mmemory: 128MiterminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /etc/nginxname: nginx-confdnsPolicy: ClusterFirstrestartPolicy: AlwaysschedulerName: default-schedulersecurityContext: {}terminationGracePeriodSeconds: 30volumes:- configMap:items:- key: config-nginxpath: config-nginxname: nginx-conf-cmname: nginx-conf
############################################等到po重启好了,进入容器
kubectl get po
kubectl exec -it nginx-deploy-564b4bc87b-4k4jc -- sh
cd /etc/nginx
ls

解决方案:

修改路径path,并且添加subPath。注意,路径path的etc前面不要/

    spec:containers:- command:- /bin/sh- -c- 'nginx daemon off;sleep 3600 'image: nginx:1.7.9imagePullPolicy: IfNotPresentname: nginxresources:limits:cpu: 100mmemory: 128Mirequests:cpu: 100mmemory: 128MiterminationMessagePath: /dev/termination-logterminationMessagePolicy: FilevolumeMounts:- mountPath: /etc/nginx/nginx.confname: nginx-confsubPath: etc/nginx/nginx.configdnsPolicy: ClusterFirstrestartPolicy: AlwaysschedulerName: default-schedulersecurityContext: {}terminationGracePeriodSeconds: 30volumes:- configMap:defaultMode: 420items:- key: config-nginxpath: etc/nginx/nginx.configname: nginx-conf-cmname: nginx-conf

可以看到,那些被覆盖的文件又出现了:

注意事项:

使用SubPath不支持热更新!!

4.配置的热更新

我们通常会将项目的配置文件作为 configmap 然后挂载到 pod,那么如果更新 configmap 中的配置,会不会更新到 pod 中呢?

这得分成几种情况:

  • 默认方式:会更新,更新周期是更新时间 + 缓存时间。但是默认情况挂载后会覆盖原来的文件
  • subPath:不会覆盖原来文件,但是他不支持热更新
  • 变量形式:如果 pod 中的一个变量是从 configmap 或 secret 中得到,同样也是不会更新的

最终实现热更新的思路:

使用默认方式,将配置文件挂载到一个不存在的目录,避免目录的覆盖,然后再利用软连接的形式,将该文件链接到目标位置

对于默认方式的更新方式有两种:

直接edit更新:

kubectl edit cm test.config

使用replace替换:

以往我们使用replace都是变更yaml配置文件,然后配置文件替换就行。但是cm中没有配置文件的概念,实现方式是: --dry-run

该参数的意思打印 yaml 文件,但不会将该文件发送给 apiserver,再结合 -o yaml 输出 yaml 文件就可以得到一个配置好但是没有发给 apiserver 的文件,然后再结合 replace 监听控制台输出得到 yaml 数据即可实现替换

#最后的-f-:管道前面会输出一个内容,这个输出的内容会作为输入,发送给k8s执行
kubectl create cm test-dir-config --from-file=./test/ --dry-run -o yaml | kubectl replace -f-

5.不可变的secret和configMap

对于一些敏感服务的配置文件,在线上有时是不允许修改的,此时在配置 configmap 时可以设置 immutable: true 来禁止修改

kubectl edit cm test-dir#前面不需要空格,就是第一层级添加即可
immutable: true

三、持久化存储

1.volumes

(1)HostPath

将节点上的文件或目录挂载到 Pod 上,此时该目录会变成持久化存储目录,即使 Pod 被删除后重启,也可以重新加载到该目录,该目录下的文件不会丢失

cd /opt/k8s/
mkdir volumes
cd volumes/
vim volume-test-pd.yaml##################################################
apiVersion: v1
kind: Pod
metadata:name: test-pd
spec:containers:- image: nginxname: nginx-volumevolumeMounts:- mountPath: /test-pd # 挂载到容器的哪个目录name: test-volume # 挂载哪个 volumevolumes:- name: test-volumehostPath: #与主机共享目录,加载主机中的指定目录到容器中path: /data # 节点中的目录type: DirectoryOrCreate # 检查类型,在挂载前对挂载目录做什么检查操作,有多种选项,默认为空字符串,不做任何检查
###################################################启动,并查看在哪台机器运行
kubectl create -f volume-test-pd.yaml 
kubectl get po -o wide#来到对应的机器
cd /data/
touch index.html#回到主机器,进入容器内部
kubectl exec -it test-pd -- sh
cd /test-pd
echo 'a' > index.html
类型:
空字符串:默认类型,不做任何检查
DirectoryOrCreate:如果给定的 path 不存在,就创建一个 755 的空目录
Directory:这个目录必须存在
FileOrCreate:如果给定的文件不存在,则创建一个空文件,权限为 644
File:这个文件必须存在
Socket:UNIX 套接字,必须存在
CharDevice:字符设备,必须存在
BlockDevice:块设备,必须存在

运行效果:

(2)EmptyDir

EmptyDir 主要用于一个 Pod 中不同的 Container 共享数据使用的,由于只是在 Pod 内部使用,因此与其他 volume 比较大的区别是,当 Pod 如果被删除了,那么 emptyDir 也会被删除。不能持久化。

cd /opt/k8s/volumes/
vim empty-dir-pd.yaml#############################################
apiVersion: v1
kind: Pod
metadata:name: empty-dir-pd
spec:containers:- image: alpinename: nginx-emptydir1command: ["/bin/sh","-c","sleep 3600;"]volumeMounts:- mountPath: /cachename: cache-volume- image: alpinename: nginx-emptydir2command: ["/bin/sh","-c","sleep 3600;"]volumeMounts:- mountPath: /optname: cache-volumevolumes:- name: cache-volumeemptyDir: {}##############################################启动
kubectl create -f empty-dir-pd.yaml 
kubectl get po#看一下两个容器能不能互通
kubectl exec -it empty-dir-pd -c nginx-emptydir1 -- sh
cd /cachekubectl exec -it empty-dir-pd -c nginx-emptydir2 -- sh
cd /opttouch a.txt

2.NFS挂载

nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

因为有磁盘io和网络io,所以稳定性会略差一点。

(1)安装NFS

在三个机器都要运行:

# 安装 nfs
yum install nfs-utils -y# 启动 nfs
systemctl start nfs-server# 查看 nfs 版本
cat /proc/fs/nfsd/versions

在141上执行:

#创建读写、只读目录
cd /home
mkdir nfs
cd nfs/
mkdir rw
mkdir ro#设置共享目录 export
vim /etc/exports#########################################################################
/home/nfs/rw 192.168.200.0/24(rw,sync,no_subtree_check,no_root_squash)
/home/nfs/ro 192.168.200.0/24(ro,sync,no_subtree_check,no_root_squash)
########################################################################## 重新加载
exportfs -f
systemctl reload nfs-server#创建一个只读文件
cd ro
touch README.md
echo 'hello NFS' > README.md 

在主机器上执行:

#创建目录
mkdir -p /mnt/nfs/rw
mkdir -p /mnt/nfs/ro#映射目录
mount -t nfs 192.168.200.141:/home/nfs/rw /mnt/nfs/rw
mount -t nfs 192.168.200.141:/home/nfs/ro /mnt/nfs/ro#能够看到141中创建的内容,并且只读,不能编辑。同样读写里面我们自己创建文件,141中也能看到
cd /mnt/nfs/ro
ls

141中:

主机器:

(2)将NFS挂载到容器中

先在141中创建好目录:

cd /home/nfs/rw
mkdir -p www/xupeng
echo 'xupeng' > /home/nfs/rw/www/xupeng/index.html

在主机器中执行:

cd /opt/k8s/volumes/
vim nfs-test-pd.yaml####################################################
apiVersion: v1
kind: Pod
metadata:name: nfs-test-pd1
spec:containers:- image: nginxname: test-containervolumeMounts:- mountPath: /usr/share/nginx/htmlname: test-volumevolumes:- name: test-volumenfs:server: 192.168.200.141 # 网络存储服务地址path: /home/nfs/rw/www/xupeng # 网络存储路径readOnly: false # 是否只读
#####################################################启动
kubectl create -f nfs-test-pd.yaml 
kubectl get po -o wide#访问pod对应的内网ip
curl 10.244.91.144#然后我们更改141里面的内容,再次访问会发现内容变了

我们可以把配置文件的名称改成nfs-test-pd2,在生成一个,还是可以访问到共享内容。并且两个contianer都删了,共享文件还能保留

3.pv和pvc(重要)

(1)什么是pv和pvc

假设公司有一台数据服务器,其他多个项目的共享目录都在这个服务器里面,当每个项目和数据服务器都是用不同的持久化方式,比如A用nfs挂载,B用其他的方式挂载,就会导致要安装各种配置、环境。没有统一的存储规范。

pv(持久卷),他是对各种具体挂载的抽象,可以理解为是一个接口,他是一个规范,具体方案是对接口的实现。

pvc(持久卷申领),不同的微服务会需要不同的资源,微服务会告诉pvc,然后pvc拿着微服务的需求来向pv要资源,pv把资源分配给微服务。

  • 微服务:消费者
  • pvc:代购
  • pv:商家的门店,用来卖东西
  • 具体对pv的实现:工厂,真正生产东西

(2)生命周期

  1. pv构建
    1. 静态构建:集群管理员创建若干 PV 卷

    2. 动态构建:如果集群中已经有的 PV 无法满足 PVC 的需求,那么集群会根据 PVC 自动构建一个 PV,该操作是通过 StorageClass 实现的

  2. 绑定:当用户创建一个 PVC 对象后,主节点会监测新的 PVC 对象,并且寻找与之匹配的 PV 卷,找到 PV 卷后将二者绑定在一起。如果找不到对应的 PV,则需要看 PVC 是否设置 StorageClass 来决定是否动态创建 PV,若没有配置,PVC 就会一致处于未绑定状态,直到有与之匹配的 PV 后才会申领绑定关系。

  3. 使用:Pod 一旦使用 PVC 绑定 PV 后,为了保护数据,避免数据丢失问题,PV 对象会受到保护,在系统中无法被删除。

  4. 回收策略

    1. 保留(Retain):pv删除,数据保留

    2. 删除(Delete):pv、数据都删除

    3. 回收(Recycle):回收策略 Recycle 已被废弃

(3)创建pv,pvc,并关联pod,实现持久化数据

*1)创建pv

先在141创建一个nfs的路径:

cd /home/nfs/rw
mkdir test-pv

主机器创建pv:

cd /opt/k8s/volumes/
vim pv-nfs.yaml################################################
apiVersion: v1
kind: PersistentVolume #描述资源对象为pc类型
metadata:name: pv0001 #pv名字
spec:capacity: #容量配置storage: 5Gi # pv 的容量volumeMode: Filesystem # 存储类型为文件系统accessModes: # 访问模式:ReadWriteOnce、ReadWriteMany、ReadOnlyMany- ReadWriteMany # 可以被多节点独写persistentVolumeReclaimPolicy: Retain # 回收策略storageClassName: slow # 创建 PV 的存储类名,需要与 pvc 的相同mountOptions: # 加载配置- hard- nfsvers=4.1nfs: # 连接到 nfspath: /home/nfs/rw/test-pv # 存储路径server: 192.168.200.141 # nfs 服务地址#################################################启动
kubectl create -f pv-nfs.yaml 
kubectl get pv

pv的状态:

  • Available:空闲,未被绑定
  • Bound:已经被 PVC 绑定
  • Released:PVC 被删除,资源已回收,但是 PV 未被重新使用
  • Failed:自动回收失败

*2)创建pvc
vim pvc-test.yaml###################################################################
apiVersion: v1
kind: PersistentVolumeClaim #资源类型pvc
metadata:name: nfs-pvc
spec:accessModes:- ReadWriteMany # 权限需要与对应的 pv 相同volumeMode: Filesystemresources:requests:storage: 5Gi # 资源可以小于 pv 的,但是不能大于,如果大于就会匹配不到 pvstorageClassName: slow # 名字需要与对应的 pv 相同
#  selector: # 使用选择器选择对应的 pv
#  #    matchLabels:
#  #      release: "stable"
#  #    matchExpressions:
#  #      - {key: environment, operator: In, values: [dev]}
#
#
#
####################################################################启动
kubectl create -f pvc-test.yaml 
kubectl get pvc

*3)pvc和pod关联,实现容器数据持久化

实现通过pv、pvc来将pod中存储内容和nfs中内容进行挂载:

/opt/k8s/volumes
vim pvc-test-pd.yaml #################################################
apiVersion: v1
kind: Pod
metadata:name: test-pvc-pd
spec:containers:- image: nginxname: nginx-volumevolumeMounts:- mountPath: /usr/share/nginx/html # 挂载到容器的哪个目录name: test-volume # 挂载哪个 volumevolumes:- name: test-volumepersistentVolumeClaim:  #关联pvcclaimName: nfs-pvc #要关联到哪个pvc
##################################################启动,找到pod对应的ip
kubectl create -f pvc-test-pd.yaml 
kubectl get po -o wide#我们先去curl那个ip是没有的,然后我们去141的/home/nfs/rw/test-pv/路径下新增一个
echo 'hello' > index.html#再去curl就可以看到了

(4) StorageClass动态申领

我们每构建一个pod,就要绑定一个pvc,然后去关联pv。当我们的pod非常多的时候是不是需要创建非常多的pvc和pv?这很不方便。我们需要动态申领sc( StorageClass)

k8s 中提供了一套自动创建 PV 的机制,就是基于 StorageClass 进行的,通过 StorageClass 可以实现仅仅配置 PVC,然后交由 StorageClass 根据 PVC 的需求动态创建 PV。

sc通过制备器(Provisioner)选择需要的资源真正去创建pv。

vim 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-runnernamespace: kube-system
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"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: run-nfs-client-provisionernamespace: kube-system
subjects:- kind: ServiceAccountname: nfs-client-provisionernamespace: default
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-provisionernamespace: kube-system
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-provisionernamespace: kube-system
subjects:- kind: ServiceAccountname: nfs-client-provisioner
roleRef:kind: Rolename: leader-locking-nfs-client-provisionerapiGroup: rbac.authorization.k8s.io

vim nfs-storage-class.yaml:

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

vim nfs-provisioner-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:name: nfs-client-provisionernamespace: kube-systemlabels:app: nfs-client-provisioner
spec:replicas: 1strategy:type: Recreateselector:matchLabels:app: nfs-client-provisionertemplate:metadata:labels:app: nfs-client-provisionerspec:serviceAccountName: nfs-client-provisionercontainers:- name: nfs-client-provisionerimage: registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.2volumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAMEvalue: fuseim.pri/ifs- name: NFS_SERVERvalue: 192.168.200.141- name: NFS_PATHvalue: /home/nfs/rwvolumes:- name: nfs-client-rootnfs:server: 192.168.200.141path: /home/nfs/rw


vim ndf-sc-demo-statefulset.yaml:

---
apiVersion: v1
kind: Service
metadata:name: nginx-sclabels:app: nginx-sc
spec:type: NodePortports:- port: 80name: webprotocol: TCPselector:app: nginx-sc
---
apiVersion: apps/v1
kind: StatefulSet #资源类型
metadata:name: nginx-sc
spec:serviceName: "nginx-sc" #使用哪个service管理管理dnsreplicas: 1selector:matchLabels:app: nginx-sctemplate:metadata:labels:app: nginx-scspec:containers:- name: nginx-scimage: nginximagePullPolicy: IfNotPresentvolumeMounts:- mountPath: /usr/share/nginx/html #挂载到容器内哪个目录name: nginx-sc-test-pvcvolumeClaimTemplates: #数据卷模板- metadata: #数据卷描述name: nginx-sc-test-pvc #数据卷名称spec: #数据卷规约配置storageClassName: managed-nfs-storageaccessModes: - ReadWriteMany #访问模式resources: requests:storage: 1Gi #需要一个G存储资源

vim nfs-pvc-test.yaml:

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

执行:

#删除pv、pvc
kubectl get pvc
kubectl get pv
kubectl delete pv XXX
kubectl delete pvc XXX#创建角色
kubectl apply -f nfs-provisioner-rbac.yaml #创建deployment
kubectl apply -f nfs-provisioner-deployment.yaml #创建sc
kubectl apply -f nfs-storage-class.yaml #查看
kubectl get sc
kubectl get po -n kube-system|grep nfs#创建sts
kubectl apply -f ndf-sc-demo-statefulset.yaml #查看
kubectl get po -n kube-system | grep nfs
kubectl get po
kubectl get pvc
kubectl get pv

四、感谢支持

感谢各位大佬支持,如果觉得满意可以请喝一杯咖啡吗:

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

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

相关文章

Java中的优先级队列(PriorityQueue)(如果想知道Java中有关优先级队列的知识点,那么只看这一篇就足够了!)

前言:优先级队列(Priority Queue)是一种抽象数据类型,其中每个元素都关联有一个优先级,元素按照优先级顺序进行处理。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 …

足浴行业押金原路退回怎么开通?

一手机版和电脑版差别 手机版押金管理的优点: 1. 便携性:管理人员可以随时随地通过手机查看和处理押金相关事务,不受地点限制。例如,当不在店内时,仍能及时了解押金的收支情况,对突发问题进行处理。 2. 实…

基于微信小程序的校园二手交易平台/Java的二手交易网站/基于Javaweb校园二手商品交易系统(附源码)

摘 要 使用校园二手交易平台管理校园二手物品交易,不仅实现了智能化管理,还提高了管理员的管理效率,用户查询的功能也需要校园二手交易平台来提供。 设计校园二手交易平台是毕设的目标,校园二手交易平台是一个不断创新的系统&…

【通信模块】简单玩转WiFi模块(ESP32、ESP8266)

笔者学习太极创客的学习笔记,链接如下:www.taichimaker.com 前期准备 电脑端口 固件烧录 WIFI到网页 对应七层网络协议 WIFI工作模式(链路层) 接入点模式、无线中断模式、混合模式 IP协议(网络层) 子网…

Kafka知识总结(选举机制+控制器+幂等性)

文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 文章收录在网站:http://hardyfish.top/ 选举机制 控制器(Broker)选举 控制器就是…

springboot使用Gateway做网关并且配置全局拦截器

一、为什么要用网关 统一入口: 作用:作为所有客户端请求的统一入口。说明:所有客户端请求都通过网关进行路由,网关负责将请求转发到后端的微服务 路由转发: 作用:根据请求的URL、方法等信息将请求路由到…

【初阶数据结构篇】时间(空间)复杂度

文章目录 算法复杂度时间复杂度1. 定义2. 表示方法3. 常见时间复杂度4.案例计算分析冒泡排序二分查找斐波那契数列(递归法)斐波那契数列(迭代法) 空间复杂度案例分析冒泡排序斐波那契数列(递归法)斐波那契数…

【漏洞复现】ServiceNow UI Jelly模板注入(CVE-2024-4879)

声明:本文档或演示材料仅用于教育和教学目的。如果任何个人或组织利用本文档中的信息进行非法活动,将与本文档的作者或发布者无关。 一、漏洞描述 ServiceNow是一家专注于提供企业级云计算服务的企业,其旗舰产品是基于云的服务管理解决方案&…

视觉巡线小车(STM32+OpenMV)——总结

文章目录 目录 文章目录 前言 一、效果展示 二、完整流程 1、STM32CubeMX配置 2、Keil编辑 3、硬件接线 4、参数调试 5、图像处理调试 三、总结 前言 基于前面的系列文章,已基本介绍完了基于STM32OpenMV的视觉巡线小车,本文将以小编自己的小车…

SeaCMS海洋影视管理系统远程代码执行漏洞复现

SeaCMS海洋影视管理系统远程代码执行漏洞复现 Ⅰ、环境搭建Ⅱ、漏洞复现Ⅲ、漏洞分析 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责&…

全栈嵌入式C++、STM32、Modbus、FreeRTOS和MQTT协议:工业物联网(IIoT)可视化系统设计思路(附部分代码解析)

项目概述 随着工业4.0时代的到来,工业物联网(IIoT)在提高生产效率、降低运营成本和实现智能制造方面得到了广泛应用。本项目旨在开发一个全面的工业物联网监控系统,能够实时监测设备的温度、压力、振动和电流等参数,并…

【Python实战因果推断】60_随机实验与统计知识2

目录 An A/B Testing Example An A/B Testing Example 在许多公司中,一种常见的策略是提供廉价甚至免费的产品,这种产品本身可能并不盈利,但其目的是吸引新客户。一旦公司获得了这些客户,就可以向他们推销其他更盈利的产品&#x…

ThinkPHP一对一关联模型的运用(ORM)

一、序言 最近在写ThinkPHP关联模型的时候一些用法总忘,我就想通过写博客的方式复习和整理下一些用法。 具体版本: topthink/framework:6.1.4topthink/think-orm:2.0.61 二、实例应用 1、一对一关联 1.1、我先设计了两张表&#x…

[SWPU2019]Web1

上来看到两个功能,登录和注册,看到登录框直接sqlmap嗦一下 失败 注册admin显示被注册,那就注册一个账密都为aaa 登录进来发现两个功能点 发了一个广告却显示代管理确认,这里肯定没有管理员,所以我们得想办法自己上去a…

铲屎官的必备好物——希喂、352、米家养宠空气净化器分享

对于每一位深爱着家中萌宠的铲屎官而言,无尽的温情往往也伴随着日常生活中的小烦恼。那些不经意间飘散在空气中的毛发,偶尔缠绕在鼻腔或口腔中的细微触感,以及偶尔袭来的不明异味,都是与宠物共度的日子里不可或缺的一部分。幸好随…

聊聊RNNLSTM

RNN 用于解决输入数据为,序列到序列(时间序列)数据,不能在传统的前馈神经网络(FNN)很好应用的问题。时间序列数据是指在不同时间点上收集到的数据,这类数据反映了某一事物、现象等随时间的变化状态或程度,即输入内容的上下文关联…

基于Orangepi全志H616开发嵌入式数据库——SQLite

目录 一、SQLite数据库 1.1 SQLite 的特点: 1.2 SQLite 的使用场景: 1.3 SQLite数据库与传统MySQL数据库的区别: 二、SQLite数据库安装 2.1 SQLite数据库安装方式一: 2.2 SQlite数据库安装方式二: 三、SQLite数…

Nacos适配达梦数据库并制作镜像

背景:因项目需要信创,需将原本的mysql数据库,改成达梦数据库 一、部署达梦数据库 1.1 部署达梦数据库服务 可参考:Docker安装达梦数据库_达梦数据库docker镜像-CSDN博客 1.2 创建nacos数据库 create user SAFE_NACOS identifi…

放大电路总结

补充: 只有直流移动时才有Rbe动态等效电阻 从RsUs看进去,实际上不管接了什么东西都能够看成是一个Ri(输入电阻) Ri Ui/Ii Rb//Rbe Ui/Us Ri/(RiRs) Aus (Uo/Ui)*(Ui/Us) Au *Ri/(RiRs) 当前面是一个电压源的信号 我们就需要输入电阻更大 Ro--->输出电阻--->将…

VSCode+git的gitee仓库搭建

​ 在此之前你已经在gitee创建好了账号,并新建了一个仓库。 1. 安装 Visual Studio Code Visual Studio Code 是编辑 Markdown 和站点配置文件的基础,以下将其简称为 VSCode,你可以在它的 官方网站 下载到它。 如若不理解各个版本之间的区别…