参考:
1、https://blog.csdn.net/weixin_41004350/article/details/90168631
2、https://blog.csdn.net/weixin_41004350/article/details/78492351
我们知道,平时kubernetes在部署无状态服务的时候,并不需要太多考虑持久化存储的事情,直接通过volume挂载网络存储,比如常见的nfs就能实现文件共享存储。
但是如果在有状态服务中,你就会需要很多的问题,比如:当你部署一些集群服务的时候:
不可以用共享存储,因为每个服务的数据都不能相同。
不可以直接用node的本地路径进行挂载,因为pod的随机性,一个node可能会跑多个pod副本,则会造成冲突。
数据量可能会很大,可能需要使用外部存储,或者独立的磁盘,云盘等
就算用pv,pvc也很不方便,需要你提前手动创建,不方便扩展。
然后我们细数一下k8s里的持久化存储,总的分为两种,静态卷和动态卷。静态卷就是刚才我们说的,volume挂载,或者通过手动创建pv,pvc进行挂载。都属于静态卷。而动态卷,则是将一个网络存储作为一个StorageClass类,通过自己的配置,来动态的创建pv,pvc并进行绑定,这样就可以实现动态的存储生成与持久化保存。
具体详细的k8s的存储系统知识可以查看官方文档
下面我们就说一下,怎么通过nfs动态卷来实现有状态服务的储存。
NFS 文件服务器,是可以远程共享文件,将远程文件挂载到本地,然后就可以作为本地文件一样进操作,所做更改则会同步到nfs远程服务器上,在跨主机的共享文件上非常方便,比建立一个集中的ftp服务器要方便很多。之前的FTP文件文件服务器用于远程验证下载,上传文件,但是需要验证并登陆,才能进行操作,而且不能直接在另外一台主机上直接下载网络文件并保存在ftp上,而要先保存在本地,然后传到ftp服务器上,繁琐而不方便。
yum install nfs-utils
yum install rpcbind
systemctl enable nfs-server
systemctl enable rpcbind
systemctl start nfs
systemctl start rpcbind
systemctl status rpcbind # 查看服务状态
mkdir /mydata
chown nfsnobody.nfsnobody /mydata
添加配置,将本机的这个路径的文件作为nfs共享文件,共享给指定IP,或指定IP段
cat > /etc/exports <<\EOF
/mydata xxx.xxx.xxx.xxx(rw,sync,all_squash)
EOF
比如:
/mydata 10.177.106.0/24(rw,sync,all_squash)
exportfs -rv
showmount -e localhost
yum install nfs-utils
yum install rpcbind
systemctl enable nfs
systemctl enable rpcbind
mkdir /usr/local/mydata
mount -t nfs xxx.xxx.xxx.xxx:/usr/local/mydata usr/local/mydata # xxx.xxx.xxx.xxx为nfs服务IP
df -h
umount /usr/local/mydata
注意:
(1)如果没有关闭nfs服务端的防火墙,则会挂载失败。需要在服务端开启需要的端口,在centos7上,用firewalld防火墙直接开放nfs服务即可自动通过。
firewall-cmd --add-service=nfs --permanent firewall-cmd --reload
NFS客户端地址:
指定IP: 192.168.0.1
指定子网所有主机: 192.168.0.0/24
指定域名的主机: test.com
指定域名所有主机: *.test.com
所有主机: *
ro:目录只读
rw:目录读写
sync:将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性
async:将数据先保存在内存缓冲区中,必要时才写入磁盘
all_squash:将远程访问的所有普通用户及所属组都映射为匿名用户或用户组(nfsnobody)
no_all_squash:与all_squash取反(默认设置)
root_squash:将root用户及所属组都映射为匿名用户或用户组(默认设置)
no_root_squash:与rootsquash取反
anonuid=xxx:将远程访问的所有用户都映射为匿名用户,并指定该用户为本地用户(UID=xxx)
anongid=xxx:将远程访问的所有用户组都映射为匿名用户组账户
apiVersion: v1
kind: Namespace
metadata:
name: test
labels:
name: test
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
namespace: test
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-provisioner-runner
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: ["list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "endpoints"]
verbs: ["get","create","list", "watch","update"]
- apiGroups: ["extensions"]
resources: ["podsecuritypolicies"]
resourceNames: ["nfs-provisioner"]
verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-provisioner
subjects:
- kind: ServiceAccount
name: nfs-provisioner
namespace: test
roleRef:
kind: ClusterRole
name: nfs-provisioner-runner
apiGroup: rbac.authorization.k8s.io
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
namespace: test
labels:
app: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: nfs-provisioner
- name: NFS_SERVER
value: xxx.xxx.xxx.xxx
- name: NFS_PATH
value: /mydata
volumes:
- name: nfs-client-root
nfs:
server: xxx.xxx.xxx.xxx
path: /mydata
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-nfs-storage
provisioner: nfs-provisioner
parameters:
archiveOnDelete: "true"
在StatefulSet中,通过配置volumeClaimTemplates来配置使用动态卷
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: tomcat
namespace: test
labels:
app: statefulset
spec:
serviceName: tomcat-svc-headless
replicas: 4
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 3
template:
metadata:
labels:
app: tomcat
spec:
containers:
- name: tomcat
image: hub.c.163.com/library/tomcat:8.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: tomcat
volumeMounts:
- name: webpath
mountPath: /usr/local/tomcat/webapps/test
volumeClaimTemplates:
- metadata:
name: webpath
annotations:
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage" #这里managed-nfs-storage就是我们创建的storageclass的name
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc-headless
namespace: test
labels:
app: statefulset
spec:
ports:
- port: 8080
name: tomcat
clusterIP: None
selector:
app: statefulset