为了防止pod在删除后不让数据的丢失,需要对数据做持久化操作
EmptyDir
EmptyDir是一个空目录,他的生命周期和所属的 Pod 是完全一致的,EmptyDir主要作用可以在同一 Pod 内的不同容器之间共享工作过程中产生的文件。如果Pod配置了emptyDir类型Volume, Pod 被分配到Node上时候,会创建emptyDir,只要Pod运行在Node上,emptyDir都会存在(容器挂掉不会导致emptyDir丢失数据),但是如果Pod从Node上被删除(Pod被删除,或者Pod发生迁移),emptyDir也会被删除,并且永久丢失
#emptyDir模板vim nginx_busybox_emptyDir.yamlapiVersion: v1kind: Podmetadata:name: nginx-emptydirnamespace: defaultlabels:app: nginxrelease: webspec:containers:- name: webimage: ikubernetes/myapp:v1imagePullPolicy: IfNotPresentports:- name: httpcontainerPort: 80volumeMounts:- name: webpagemountPath: /usr/share/nginx/html/- name: busyboximage: busybox:latestimagePullPolicy: IfNotPresentvolumeMounts:- name: webpagemountPath: /data/command: ["/bin/sh","-c","while true;do echo $(date) >> /data/index.html;sleep 3;done"]volumes:- name: webpageemptyDir: {}
HostPath
Hostpath会把宿主机上的指定卷加载到容器之中,如果 Pod 发生跨主机的重建,其内容就难保证了。这种卷一般和DaemonSet搭配使用。hostPath允许挂载Node上的文件系统到Pod里面去。如果Pod有需要使用Node上的东西,可以使用hostPath,不过不过建议使用,因为理论上Pod不应该感知Node的。
#hostpath共享模板
apiVersion: v1
kind: Pod
metadata:
name: nginx-hostpath-vol
namespace: default
spec:
containers:
- name: nginx-hostpath-vol
image: ikubernetes/myapp:v1
volumeMounts:
- name: hostpath
mountPath: /usr/share/nginx/html/
volumes:
- name: hostpath
hostPath:
path: /data/hostpath/
type: DirectoryOrCreate
----------------------------------------------
#type类型有以下几种
#DirectoryOrCreate 目录不存在就创建
#Directory 目录必须存在
#FileOrCreate 文件不存在不创建
#File 文件必须存在
#Socket socket类型的文件
#CharDevice 字符类型的文件
#BlockDevice 块类型的文件
emptyDir和hostPat很多场景是无法满足持久化需求,因为在Pod发生迁移的时候,数据都无法进行转移的,这就需要分布式文件系统的支持。
Nfs存储方案
NFS 是Network File System的缩写,即网络文件系统。Kubernetes中通过简单地配置就可以挂载NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持同时写操作。
# yum -y install nfs-utilsvol{0...03
#mkdir /data/wd/vol{01..03} -p
#vim /etc/exports/
/data/wd 10.0.0.0/16(rw,no_root_squash)
cat > /data/wd/index.html << EOF
<h1>NFS server!</h1>
EOF
使用pod直接挂载nfs
要保证集群内所有的node节点都可以挂载nfs
#nfs共享模板
apiVersion: v1
kind: Pod
metadata:
name: nginx-nfs-vol
namespace: default
spec:
containers:
- name: nginx-nfs-vol
image: ikubernetes/myapp:v1
volumeMounts:
- name: nfs
mountPath: /usr/share/nginx/html/
volumes:
- name: nfs
nfs:
path: /data/wd/
server: nfs #服务器的名称或ip地址
使用PV和PVC
在实际的使用中,我们通常会将各存储划分成PV,然后和PVC绑定给pod使用。
PV:PersistentVolume
PVC:PersistentVolumeClaim
PV和PVC的生命周期:
供应准备:通过集群外的存储系统或者公有云存储方案来提供存储持久化支持。
静态提供:管理员手动创建多个PV,供PVC使用。
动态提供:动态创建PVC特定的PV,并绑定。
绑定:用户创建pvc并指定需要的资源和访问模式。在找到可用pv之前,pvc会保持未绑定状态。
使用:用户可在pod中像使用volume一样使用pvc。
释放:用户删除pvc来回收存储资源,pv将变成“released”状态。由于还保留着之前的数据,这些数据需要根据不
同的策略来处理,否则这些存储资源无法被其他pvc使用。
回收(Reclaiming):pv可以设置三种回收策略:保留(Retain),回收(Recycle)和删除(Delete)
保留策略:允许人工处理保留的数据。(默认)
删除策略:将删除pv和外部关联的存储资源,需要插件支持。
回收策略:将执行清除操作,之后可以被新的pvc使用,需要插件支持。
PV卷阶段状态:
Available – 资源尚未被PVC使用
Bound – 卷已经被绑定到PVC了
Released – PVC被删除,PV卷处于释放状态,但未被集群回收。
Failed – PV卷自动回收失败
创建pv资源,在定义pv时不需要指定名称空间,它属于集群级别的资源,也k8s标准的资源
selector字段
pvc可以使用标签来选择要绑定那种类型的pv(pv也有标签),如果不指定标签,就会找所有的pv然后匹配最适合自己的pv。
pvc和pv是一一对应的,一旦绑定就不会被其它pvc再选重,状态是binding,多个pod可以访问一个pvc(一对多的关系由accessmode来决定)
创建pv资源代码
vim pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/wd/vol1
server: 10.0.0.70
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
accessModes 访问类型
#ReadWriteOnce 单路读写
#ReadOnlyMany 多路只读
#ReadWriteMany 多路读写
#resources 资源的限制,比如至少5G
创建pvc资源代码
#pvc模板
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo
namespace: default #一定要和pod在同一个名称空间
spec:
accessModes: ["ReadWriteMany"] #这个访问模式一定是pv的子集
resources:
requests:
storage: 6Gi
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-pvc-vol
namespace: default
labels:
app: nginx-pvc
release: canary
spec:
containers:
- name: nginx-pvc-vol
image: nginx:1.15-alpine
volumeMounts:
- name: pvc
mountPath: /usr/share/nginx/html/
volumes:
- name: pvc
persistentVolumeClaim:
claimName: pvc-demo
volumeName 精确匹配
#capacity 限制存储空间大小
#reclaim policy pv的回收策略
#retain pv被解绑后上面的数据仍保留
#recycle pv上的数据被释放,这个pv这空的
#delete pvc和pv解绑后pv就被删除
备注:用户在创建pod所需要的存储空间时,前提是必须要有pv存在才可以,这样就不符合自动满足用户的需求,而且之前在k8s 9.0版本还可删除pv,这样造成数据不安全性
创建一个service资源测试
cat > svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
name: nginx-pod
spec:
selector:
app: nginx-pvc
release: canary
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 80
EOF
访问测试
cat > /data/wd/vol03/index.html << EOF
<h1>NFS server!</h1>
EOF
curl 10.0.0.70
#PV的回收策略默认设置为Retain.
虽然pv中的数据得到了保留,但其PV状态会一直处于Released,不能被其他PVC申请。
为了重新使用存储资源,可以删除并重新创建mypv1.删除操作只是删除了PV对象,存储空间中的数据并不会被删除。
kubectl delete pod nginx-pvc-vol
kubectl delete pvc pvc-demo
kubectl apply -f pv.yml
重新加载的pv,状态为Available,已经可以被PVC申请
ConfigMap
configMap也是一种标准的资源,用于动态更新文件信息.
创建一个configmap资源
命令创建:
#创建一个www.conf文件
cat > /data/www.conf <<EOF
server {
server_name yy.edu.com;
listen 80;
root /data/web/html/;
}
EOF
kubectl create configmap nginx-configmap --from-file=www.conf=/data/www.conf
#www.conf#是一个键的名称,后面的www.conf是键值
资源清单创建:
cat > configmap.yml <<EOF
apiVersion: v1
data:
www.conf: |
server {
server_name yy.edu.com;
listen 80;
root /data/web/html/;
}
kind: ConfigMap
metadata:
creationTimestamp: null
name: nginx-configmap
EOF
创建一个pod和对应的svc资源
cat > configmap-pod-nginx.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
namespace: default
labels:
app: configmap-pod
spec:
containers:
- name: configmap-pod
image: 10.0.0.70:5000/nginx:1.15-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
volumeMounts:
- name: nginx-configmap
mountPath: /etc/nginx/conf.d/
readOnly: true
volumes:
- name: nginx-configmap
configMap:
name: nginx-configmap
---
apiVersion: v1
kind: Service
metadata:
name: configmap-pod-svc
namespace: default
spec:
selector:
app: configmap-pod
ports:
- name: http
port: 80
targetPort: 80
nodePort: 88
protocol: TCP
type: NodePort
EOF
修改configmap的配置文件,检查www.conf中的内容是否是发生变化
kubectl edit cm nginx-configmap
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
www.conf: "server {\n server_name yy.edu.com;\n\t listen 80;\n\t
\ root /data/web/html/;\n }\n"
kind: ConfigMap
metadata:
creationTimestamp: "2019-11-25T02:17:09Z"
name: nginx-configmap
namespace: default
resourceVersion: "1140123"
selfLink: /api/v1/namespaces/default/configmaps/nginx-configmap
uid: 318aada8-d529-4f6b-a5dd-c70ca9d9ebd3
#修改server_name的值 yy.edu.com为 server_name oldboywd.edu.com
#检查是否修改成功
工作案例:实现mysql数据持久化
创建一个pv资源
cat > mysql_pv.yml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
labels:
name: pv001
spec:
nfs:
path: /data/wd/vol01
server: 10.0.0.70
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
EOF
创建一个mysql_pvc资源
cat > mysql_pvc << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-mysql
namespace: default
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
EOF
创建一个mysql_deploy资源
cat > mysql-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: 10.0.0.70:5000/mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumeMounts:
- name: mysql-volume
mountPath: /var/lib/mysql
volumes:
- name: mysql-volume
persistentVolumeClaim:
claimName: pvc-mysql
创建mysql_service资源
cat > mysql-svc.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
EOF
创建一个tomcat的deploy资源和service资源
cat > tomcat_peploy_svc.yml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat
spec:
replicas: 2
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: tomcat
image: 10.0.0.70:5000/tomcat-app:v2
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
value: 'mysql'
- name: MYSQL_SERVICE_PORT
value: '3306'
imagePullSecrets:
- name: harbor-secret
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc
spec:
type: NodePort
ports:
- port: 8080
nodePort: 8080
selector:
app: tomcat
测试:
浏览器访问10.0.0.70:8080/demo添加数据
把以前的资源删除重新创建,浏览器查看数据是否还在
storageClass存储类
- pod创建时所指定的卷的大小不确定,当pvc和下面的pv绑定时,会根据pod的需要动态的创建一个符合pod的一个pv.而这种动态的实现的方法是存储类(storageClass)
- 后端的存储设备必须支持resfull封装的api接口(glusterfs),当有用户请求时,会动态的生成一个pv
