文章目录
- Pod Hook回调钩子+数据持久化存储
- 一、简单介绍
- 二、PorStart(启动钩子)
- 数据持久化(存储卷)
- 一、介绍
- 二、四种类型案例
- 1.emptyDir
- 2.hostPath
- 举例测试:DirectoryOrCreate
- 3.PV、PVC
- 1)简介
- 2)实现原理
- 3)使用示例
- 1> 安装NFS(所有节点)
- 2> 配置NFS
- 3> 编写nfs测试清单
- 4> 创建Pod并测试
- 4)访问模式与回收策略
- 1> 访问模式
- 2> 回收策略
- 3> PV的状态
- 4)创建并绑定PV
- 1> 编写配置清单
- 2> 运行测试
- 3> 绑定PV
- 4> 运行测试
- 5)使用PV/PVC来管理NFS
- 4.StorageClass
- 1)准备下载Discuz包
- 2)部署Discuz
- 3)使用StorageClass部署Discuz论坛
Pod Hook回调钩子+数据持久化存储
- PostStart: 启动回调钩子,是在容器启动之后立即执行
- PreStop : 结束回调钩子,是在容器结束之前立即执行
- 若两者有一个失败,即会杀死容器,所以我们应该让钩子函数尽可能的轻量一些;当然有些情况下,长时间运行命令也是合理的,比如在停止容器之前预先保存状态。
一、简单介绍
Hook(钩子)是一种编程范例,对消息进行拦截,所以经常用来做木马~
- Hooks就像一些外来的钩子,在源代码之间钩取(窃听)一些信息,当它捕捉到自己感兴趣的事发生,就拦截下来,让自己的代码执行一下,处理一下这个信息,然后再放出去继续之前的进程,这样就可以再不用改变源代码的情况下,做一些别的事,比如监控、分析一些恶意的事。
- 在已经可以正常运作的程序中额外的添加流程控制可以实现,也就是说,达到目的的情况下,在事件的过程中可以做一些别的事。
二、PorStart(启动钩子)
1、回调钩子
kind: Deployment
apiVersion: apps/v1
metadata:
name: lifecycle
spec:
selector:
matchLabels:
app: cycle
template:
metadata:
labels:
app: cycle
spec:
nodeName: k8s-m-01
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html/
name: lifecycle-data
lifecycle:
postStart:
exec:
command:
- "/bin/bash"
- "-c"
- "echo 'This is Lifecycle' > /usr/share/nginx/html/index.html"
preStop:
exec:
command:
- "/bin/bash"
- "-c"
- "echo 'This is Lifecycle preStop' >> /usr/share/nginx/html/index.html"
volumes:
- name: lifecycle-data
hostPath:
path: /opt/discuz/data
数据持久化(存储卷)
- 持久化:即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)
- 持久化:主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。
一、介绍
Pod是由容器组成的,容器若宕机或停止,数据也会随之丢了;这样一说,k8s做集群就不得不考虑存储的问题,存储卷就是为了Pod保存出具而生的。
常用的四种类型:
- emptyDir:临时存储卷
- hostPath:节点存储卷
- PV、PVC(持久卷)
- StorageClass(存储类)
二、四种类型案例
1.emptyDir
官方文档参考:https://kubernetes.io/zh/docs/concepts/storage/volumes/#emptydir
- 是Pod调度到节点上时创建的一个空目录,当Pod删除时,emtyDir中的数据也随之删除
- 常用于容器间分享文件、应用程序,是一个无需永久保存的临时目录(如:nginx产生的临时文件可保存于此)
- 注:emptyDir不能够用来做数据持久化
kind: Deployment
apiVersion: apps/v1
metadata:
name: emptydir
spec:
selector:
matchLabels:
app: emptydir
template:
metadata:
labels:
app: emptydir
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/nginx
name: test-emptydir
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumeMounts:
- mountPath: /usr/share/nginx
name: test-emptydir # 此名称填写下面的存储卷名
volumes:
- name: test-emptydir
emptyDir: {}
2.hostPath
官方文档参考:https://kubernetes.io/zh/docs/concepts/storage/volumes/#hostpath
- 挂载宿主机的文件或目录到Pod中
- 可以理解为挂载,类似又强于docker 的-v参数(Pod调度到哪个节点,则可直接挂载到当前节点上)
- 支持的类型:
取值 | 行为 |
空字符串(默认)用于向后兼容,这意味着在安装 hostPath 卷之前不会执行任何检查。 | |
| 如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。 |
| 在给定路径上必须存在的目录。 |
| 如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。 |
| 在给定路径上必须存在的文件。 |
| 在给定路径上必须存在的 UNIX 套接字。 |
| 在给定路径上必须存在的字符设备。 |
| 在给定路径上必须存在的块设备。 |
当使用这种类型的卷时要小心,因为:
- 具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同 而在不同节点上有不同的行为。
- 下层主机上创建的文件或目录只能由 root 用户写入。你需要在 特权容器 中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入
hostPath
卷。
举例测试:DirectoryOrCreate
- 挂载宿主机的 /opt/hostpath 到Pod容器中的 /usr/share/nginx
kind: Deployment
apiVersion: apps/v1
metadata:
name: hostpath
spec:
selector:
matchLabels:
app: hostpath
template:
metadata:
labels:
app: hostpath
spec:
nodeName: k8s-master1
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/nginx
name: test-hostpath
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumeMounts:
- mountPath: /usr/share/nginx # Pod容器
name: test-hostpath
volumes:
- name: test-hostpath
hostPath:
path: /opt/hostpath # 宿主机挂载点
type: DirectoryOrCreate # 若存在则不创建(在master1上)
3.PV、PVC
官方文档参考:https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/#introduction
1)简介
- PV(persistentVolume)持久化存储
- 集群级资源,无需使用Namespace
- 是外部存储系统中的一块存储空间,由管理员创建和维护,与Volume一样,PV具有持久性,生命周期独立于Pod。
- PVC(persistentVolumeClaim)持久化存储的分配
- 名称空间及资源,使用Namespave,无需单独指定,谁用写在谁的配置清单即可
- 对pv的申请,通常由普通用户创建和维护,需要为Pod分配
- 注:以多路可读可写的方式挂载一个pvc,至少需要6个G大小
- 一个pv只能绑定一个pvc,再绑定第二个即为Pending(等待)状态
- 是一一对应的,所以创建PV时要预估用多少容量再来创建,否则浪费空间~
2)实现原理
PVC:描述 Pod想要使用的持久化属性,比如存储大小、读写权限等
PV:描述一个具体的Volume(卷)属性,比如Volume的类型、挂载目录、远程存储服务器地址等
StorageClass:充当PV的模板,自动为PVC创建PV
3)使用示例
例如:master1磁盘上有100G空间,被创建并分成了三份不同大小的pv空间:
disk —> 100G k8s-master1
pv1 —> 50G
pv2 —> 30G
pv3 —> 20G
pod —> 10G k8s-m-02
master2上的Pod要用master1上的pv3空间,该如何用呢?>>>用挂载的方式,例如配置清单挂载指定要使用的空间大小为10G的话,就这样写:PVC1(10G);如果PV还有空间,可以继续指定,如PV2
也就用到了NFS,接下来我们就先安装NFS,并给与配置。
NFS可以挂载可用空间到Pod中,并允许我么你让那个提前对数据处理,且数据可以在Pod之间相互传递,NFS可以同时被多个Pod挂载并进行读写,当Pod被删除时,NFS不会被删除,仅仅是解除挂载的状态而已。
1> 安装NFS(所有节点)
[root@k8s-master1 ~]# yum install -y nfs-utils.86_64
[root@k8s-master1 ~]# systemctl enable --now nfs
2> 配置NFS
# 创建挂载目录
[root@k8s-master1 ~]# mkdir -pv /nfs/v{1..3}
mkdir: created directory ‘/nfs’
mkdir: created directory ‘/nfs/v1’
mkdir: created directory ‘/nfs/v2’
mkdir: created directory ‘/nfs/v3’
# 查看挂载点
[root@k8s-master1 ~]# showmount -e
Export list for k8s-master1:
/nfs/v3 172.16.0.0/16
/nfs/v2 172.16.0.0/16
/nfs/v1 172.16.0.0/16
# 查看挂载点
[root@k8s-master1 ~]# exportfs -arv
exporting 172.16.0.0/16:/nfs/v3
exporting 172.16.0.0/16:/nfs/v2
exporting 172.16.0.0/16:/nfs/v1
3> 编写nfs测试清单
cat > test-nfs.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs
spec:
selector:
matchLabels:
app: nfs
template:
metadata:
labels:
app: nfs
spec:
nodeName: k8s-master1
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123"
volumeMounts:
- mountPath: /var/lib/mysql
name: nfs
volumes:
- name: nfs
nfs:
path: /nfs/v1
server: 172.16.1.11
EOF
4> 创建Pod并测试
- 测试结论:删除Pod并不会删除Pod内的数据,证明NFS已将Pod持久化,保证数据不丢失
# 创建Pod
[root@k8s-master1 ~]# kubectl apply -f configlist/test-nfs.yaml
deployment.apps/nfs created
# 运行正常
[root@k8s-master1 ~]# kubectl get pod -l app=nfs
NAME READY STATUS RESTARTS AGE
nfs-54cccf67b5-vxxgv 1/1 Running 0 8s
# 进入Pod创建库、表、插入数据并退出
[root@k8s-master1 ~]# kubectl exec -it nfs-54cccf67b5-vxxgv -- bash
root@nfs-54cccf67b5-vxxgv:/# mysql -p123
mysql> create table t1(id int);
Query OK, 0 rows affected (0.18 sec)
mysql> use nfs;
Database changed
mysql> insert t1 values(2);
Query OK, 2 rows affected (0.06 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from t1;
+------+
| id |
+------+
| 2 |
+------+
1 row in set (0.18 sec)
mysql> \q
Bye
root@nfs-54cccf67b5-vxxgv:/# exit
exit
# 删除Pod
[root@k8s-master1 ~]# kubectl delete -f configlist/test-nfs.yaml
deployment.apps "nfs" deleted
# 重新创建新Pod
[root@k8s-master1 ~]# kubectl apply -f configlist/test-nfs.yaml
deployment.apps/nfs created
# 进入Pod查看,发现数据还在,是因为NFS已将数据持久化
[root@k8s-master1 ~]# kubectl exec -it nfs-54cccf67b5-4xtr2 -- bash
mroot@nfs-54cccf67b5-4xtr2:/# mysql -p123
mysql> select * from nfs.t1;
+------+
| id |
+------+
| 2 |
+------+
1 row in set (0.12 sec)
4)访问模式与回收策略
1> 访问模式
全称:accessModes
模式 | 介绍 |
ReadWriteOnce(RWO) | 可读可写:但只支持被单个节点挂载 |
ReadOnlyMany(ROX) | 只读:可以被多个节点挂载。 |
ReadWriteMany(RWX) | 多路可读可写:这种存储可以以读写的方式被多个节点共享。不是每一种存储都支 持这三种方式,像共享方式,目前支持的还比较少,比较常用的是 NFS。在 PVC 绑 定 PV 时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。 |
2> 回收策略
全称:persistentVolumeReclaimPolicy
策略 | 介绍 |
Retain | 不清理,保留Volume(卷),需要手动清理 |
Recycle | 删除数据,即 rm -rf /thevolume/*(只有 NFS 和 HostPath 支持) |
Delete | 删除存储资源,比如删除 AWS EBS 卷(只有 AWS EBS, GCE PD, Azure Disk 和 Cinder 支持) |
3> PV的状态
状态 | 介绍 |
Available | 可用 |
Bound | 已经分配给 PVC |
Released PVC | 解绑但还未执行回收策略 |
Failed | 发生错误 |
4)创建并绑定PV
1> 编写配置清单
- 先创建一个pv
cat > pv.yaml <<EOF
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv1
spec:
nfs:
path: /nfs/v2
server: 172.16.1.11
capacity:
storage: 20Gi
persistentVolumeReclaimPolicy: Retain
accessModes:
- "ReadWriteOnce"
- "ReadWriteMany"
EOF
2> 运行测试
- 当前状态为Available(可用)
# 创建成功
[root@k8s-master1 ~]# kubectl apply -f configlist/pv.yaml
persistentvolume/pv1 created
# 访问模式为 RWO,RWX,回收策略为Retain(不清理)
[root@k8s-master1 ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv1 10Gi RWO,RWX Retain Available 84s
3> 绑定PV
- 编写配置清单,绑定需要3Gi为例
- 绑定就是需要空间的Pod来绑定借用空间,此处仅举例用法
cat > pvc1.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc1
spec:
accessModes:
- "ReadWriteMany"
resources:
requests:
storage: "3Gi"
EOF
4> 运行测试
- 当前状态为Bound(绑定)
[root@k8s-master1 ~]# kubectl apply -f configlist/pvc1.yaml
persistentvolumeclaim/pvc1 created
[root@k8s-master1 ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv1 10Gi RWO,RWX Retain Bound default/pvc1 99m
- 测试再绑定一个pvc,失败!一个pv只能绑定一个pvc,所以是一一对应的
[root@k8s-master1 ~]# kubectl apply -f configlist/pvc2.yaml
[root@k8s-master1 ~]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc1 Bound pv1 10Gi RWO,RWX 65s
pvc2 Pending
5)使用PV/PVC来管理NFS
cat > pvc-discuz.yaml <<EOF
##################################################
# 1、部署MySQL集群
# 1、创建命名空间
# 2、创建service提供负载均衡
# 3、使用控制器部署MySQL实例
###
# 2、部署Discuz应用
# 1、创建命名空间
# 2、创建Service提供负载均衡(Headless Service)
# 3、创建服务并挂载代码
# 4、创建Ingress,用于域名转发(https)
###
# 3、服务之间的互连
# 1、Discuz连接MySQL ---> mysql.mysql.svc.cluster.local
##################################################
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-mysql
spec:
nfs:
path: /nfs/v3
server: 172.16.1.11
capacity:
storage: 20Gi
persistentVolumeReclaimPolicy: Retain
accessModes:
- "ReadWriteOnce"
- "ReadWriteMany"
---
apiVersion: v1
kind: Namespace
metadata:
name: mysql
---
kind: Service
apiVersion: v1
metadata:
name: mysql-svc
namespace: mysql
spec:
ports:
- port: 3306
targetPort: 3306
name: mysql
protocol: TCP
selector:
app: mysql
deploy: discuz
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-mysql-pvc
namespace: mysql
spec:
accessModes:
- "ReadWriteMany"
resources:
requests:
storage: "20Gi"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
namespace: mysql
spec:
selector:
matchLabels:
app: mysql
deploy: discuz
template:
metadata:
labels:
app: mysql
deploy: discuz
spec:
nodeName: k8s-node2
containers:
- name: mysql
image: mysql:5.7
livenessProbe:
tcpSocket:
port: 3306
readinessProbe:
tcpSocket:
port: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123"
- name: MYSQL_DATABASE
value: "discuz"
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-data
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: pv-mysql-pvc
---
kind: Namespace
apiVersion: v1
metadata:
name: discuz
---
kind: Service
apiVersion: v1
metadata:
name: discuz-svc
namespace: discuz
spec:
clusterIP: None
ports:
- port: 80
targetPort: 80
name: http
selector:
app: discuz
deploy: discuz
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-discuz
spec:
nfs:
path: /nfs/v4
server: 172.16.1.51
capacity:
storage: 20Gi
persistentVolumeReclaimPolicy: Retain
accessModes:
- "ReadWriteOnce"
- "ReadWriteMany"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-discuz-pvc
namespace: discuz
spec:
accessModes:
- "ReadWriteMany"
resources:
requests:
storage: "18Gi"
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: discuz-deployment
namespace: discuz
spec:
replicas: 5
selector:
matchLabels:
app: discuz
deploy: discuz
template:
metadata:
labels:
app: discuz
deploy: discuz
spec:
nodeName: k8s-master1
containers:
- name: php
image: alvinos/php:wordpress-v2
livenessProbe:
tcpSocket:
port: 9000
readinessProbe:
tcpSocket:
port: 9000
volumeMounts:
- mountPath: /usr/share/nginx/html
name: discuz-data
- name: nginx
image: alvinos/nginx:wordpress-v2
livenessProbe:
httpGet:
port: 80
path: /
readinessProbe:
httpGet:
port: 80
path: /
volumeMounts:
- mountPath: /usr/share/nginx/html
name: discuz-data
volumes:
- name: discuz-data
persistentVolumeClaim:
claimName: pv-discuz-pvc
---
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: discuz-ingress
namespace: discuz
spec:
tls:
- hosts:
- pvc.discuz.com
secretName: discuz-secret
rules:
- host: pvc.discuz.com
http:
paths:
- backend:
serviceName: discuz-svc
servicePort: 80
EOF
4.StorageClass
- PV的自动化: 利用StorageClass实现,可以根据PVC需求,自动构建相对应的PV持久化存储卷,进一步简化运维管理成本
- StorageClass的作用,是充当PV的模板,从而可以动态创建需要的PV
1)准备下载Discuz包
[root@k8s-master1 ~]# wget https://gitee.com/3dming/DiscuzL/attach_files/644299/download
2)部署Discuz
1.部署discuz
[root@k8s-master1 ~]# kubectl apply -f storage-discuz.yaml
2.部署后生成两个空目录,当前还未有数据
[root@k8s-master1 ~]# ll /nfs/v3
total 8
drwxrwxrwx 13 root 22:25 discuz-pv-discuz-pvc-pvc-7b1083e7-58e1-4984-b61c-f130d332a26f
drwxrwxrwx 6 polkitd 22:24 mysql-pv-mysql-pvc01-pvc-d6ed3bd3-4a1a-4032-aec3-909d4a2aca3f
3.解压discuz,并授予upload目录内所有文件写权限
[root@k8s-master1 ~]# mkdir 1;mv download 1/discuz.zip;cd 1;unzip discuz.zip
[root@k8s-master1 ~]# chmod -R o+x upload/*
4.将upload内的所有文件拷贝进去
[root@k8s-master1 ~]# cp -ar discuz/upload/* /nfs/v3/discuz-pv-discuz-pvc-pvc-7b1083e7-58e1-4984-b61c-f130d332a26f/
3)使用StorageClass部署Discuz论坛
##################################################
# 1、部署MySQL集群
# 1、创建命名空间
# 2、创建service提供负载均衡
# 3、使用控制器部署MySQL实例
###
# 2、部署Discuz应用
# 1、创建命名空间
# 2、创建Service提供负载均衡(Headless Service)
# 3、创建服务并挂载代码
# 4、创建Ingress,用于域名转发(https)
###
# 3、服务之间的互连
# 1、Discuz连接MySQL ---> mysql.mysql.svc.cluster.local
##################################################
---
apiVersion: v1
kind: Namespace
metadata:
name: mysql
---
kind: Service
apiVersion: v1
metadata:
name: mysql-svc
namespace: mysql
spec:
ports:
- port: 3306
targetPort: 3306
name: mysql
protocol: TCP
selector:
app: mysql
deploy: discuz
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-mysql-pvc01
namespace: mysql
spec:
storageClassName: nfs-client
accessModes:
- "ReadWriteMany"
resources:
requests:
storage: "2Gi"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
namespace: mysql
spec:
selector:
matchLabels:
app: mysql
deploy: discuz
template:
metadata:
labels:
app: mysql
deploy: discuz
spec:
# 不指定节点,让其自动分配
# nodeName: k8s-master1
containers:
- name: mysql
image: mysql:5.7
livenessProbe:
tcpSocket:
port: 3306
readinessProbe:
tcpSocket:
port: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123"
- name: MYSQL_DATABASE
value: "discuz"
volumeMounts:
- mountPath: /var/lib/mysql
name: mysql-data
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: pv-mysql-pvc01
---
kind: Namespace
apiVersion: v1
metadata:
name: discuz
---
kind: Service
apiVersion: v1
metadata:
name: discuz-svc
namespace: discuz
spec:
clusterIP: None
ports:
- port: 80
targetPort: 80
name: http
selector:
app: discuz
deploy: discuz
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-discuz-pvc
namespace: discuz
spec:
storageClassName: nfs-client
accessModes:
- "ReadWriteMany"
resources:
requests:
storage: "1Gi"
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: discuz-deployment
namespace: discuz
spec:
replicas: 1
selector:
matchLabels:
app: discuz
deploy: discuz
template:
metadata:
labels:
app: discuz
deploy: discuz
spec:
# 不指定节点,让其自动分配
# nodeName: k8s-master1
containers:
- name: php
image: 18954354671/lnmp-php-wp:v3
livenessProbe:
tcpSocket:
port: 9000
readinessProbe:
tcpSocket:
port: 9000
volumeMounts:
- mountPath: /usr/share/nginx/html
name: discuz-data
- name: nginx
image: 18954354671/lnmp-nginx-wp:v3
livenessProbe:
httpGet:
port: 80
path: /
readinessProbe:
httpGet:
port: 80
path: /
volumeMounts:
- mountPath: /usr/share/nginx/html
name: discuz-data
volumes:
- name: discuz-data
persistentVolumeClaim:
claimName: pv-discuz-pvc
---
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: discuz-ingress
namespace: discuz
spec:
tls:
- hosts:
- linux.discuz.com
secretName: discuz-secret
rules:
- host: linux.discuz.com
http:
paths:
- backend:
serviceName: discuz-svc
servicePort: 80