kubernetes(k8s) 配置nfs动态卷实现StatefulSet的持久化存储

参考:

1、https://blog.csdn.net/weixin_41004350/article/details/90168631

2、https://blog.csdn.net/weixin_41004350/article/details/78492351

我们知道,平时kubernetes在部署无状态服务的时候,并不需要太多考虑持久化存储的事情,直接通过volume挂载网络存储,比如常见的nfs就能实现文件共享存储。

但是如果在有状态服务中,你就会需要很多的问题,比如:当你部署一些集群服务的时候:

  1. 不可以用共享存储,因为每个服务的数据都不能相同。

  2. 不可以直接用node的本地路径进行挂载,因为pod的随机性,一个node可能会跑多个pod副本,则会造成冲突。

  3. 数据量可能会很大,可能需要使用外部存储,或者独立的磁盘,云盘等

  4. 就算用pv,pvc也很不方便,需要你提前手动创建,不方便扩展。

    然后我们细数一下k8s里的持久化存储,总的分为两种,静态卷和动态卷。静态卷就是刚才我们说的,volume挂载,或者通过手动创建pv,pvc进行挂载。都属于静态卷。而动态卷,则是将一个网络存储作为一个StorageClass类,通过自己的配置,来动态的创建pv,pvc并进行绑定,这样就可以实现动态的存储生成与持久化保存。

具体详细的k8s的存储系统知识可以查看官方文档

下面我们就说一下,怎么通过nfs动态卷来实现有状态服务的储存。

1. centos7.6 配置NFS文件服务器,远程共享文件

NFS 文件服务器,是可以远程共享文件,将远程文件挂载到本地,然后就可以作为本地文件一样进操作,所做更改则会同步到nfs远程服务器上,在跨主机的共享文件上非常方便,比建立一个集中的ftp服务器要方便很多。之前的FTP文件文件服务器用于远程验证下载,上传文件,但是需要验证并登陆,才能进行操作,而且不能直接在另外一台主机上直接下载网络文件并保存在ftp上,而要先保存在本地,然后传到ftp服务器上,繁琐而不方便。

1.1 服务端安装配置(也就是文件实际存放的位置)

1.1.1 安装nfs 和 rpcbind(使用nfs服务,都需要安装的rpc服务),并配置开机启动

yum install nfs-utils
yum install rpcbind
systemctl enable nfs-server
systemctl enable rpcbind

1.1.2 启动nfs 和rpcbind

systemctl start nfs
systemctl start rpcbind
systemctl status rpcbind # 查看服务状态

1.1.3 创建要共享的文件,也可以是原先已经存在的文件夹

mkdir /mydata

1.1.4 为文件夹设置用户和用户组,需要设为nfsnobody

chown nfsnobody.nfsnobody /mydata

1.1.5 编辑nfs配置文件

添加配置,将本机的这个路径的文件作为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)

1.1.6 重载配置

exportfs -rv

1.1.7 查看本地挂载情况

showmount -e localhost

1.2 客户端安装与配置(需要在nfs-provisioner pod所在节点安装)

1.2.1 同样需要先下载安装nfs,rpcbind,并设为开机启动

yum install nfs-utils
yum install rpcbind
systemctl enable nfs
systemctl enable rpcbind

1.2.2 创建想要挂载的目录文件

mkdir /usr/local/mydata

1.2.3 将服务端的目录挂载到本地的对应目录下

mount -t nfs xxx.xxx.xxx.xxx:/usr/local/mydata usr/local/mydata # xxx.xxx.xxx.xxx为nfs服务IP

1.2.4 查看挂载情况

df -h 

1.2.5 卸载挂载方式

umount /usr/local/mydata

注意:

(1)如果没有关闭nfs服务端的防火墙,则会挂载失败。需要在服务端开启需要的端口,在centos7上,用firewalld防火墙直接开放nfs服务即可自动通过。

firewall-cmd --add-service=nfs --permanent
firewall-cmd --reload

1.3 服务端参数详解

1.3.1 配置可参考的参数如下

NFS客户端地址:
指定IP: 192.168.0.1
指定子网所有主机: 192.168.0.0/24
指定域名的主机: test.com
指定域名所有主机: *.test.com
所有主机: *

1.3.2 参数

ro:目录只读
rw:目录读写

1.3.3 这两个影响性能的设置

sync:将数据同步写入内存缓冲区与磁盘中,效率低,但可以保证数据的一致性
async:将数据先保存在内存缓冲区中,必要时才写入磁盘

1.3.4 其他参数解释

all_squash:将远程访问的所有普通用户及所属组都映射为匿名用户或用户组(nfsnobody)
no_all_squash:与all_squash取反(默认设置)
root_squash:将root用户及所属组都映射为匿名用户或用户组(默认设置)
no_root_squash:与rootsquash取反
anonuid=xxx:将远程访问的所有用户都映射为匿名用户,并指定该用户为本地用户(UID=xxx)
anongid=xxx:将远程访问的所有用户组都映射为匿名用户组账户

2. k8s配置使用nfs作为网络存储

2.1 创建namespace,用作测试的命名空间

apiVersion: v1
kind: Namespace
metadata:
   name: test
   labels:
     name: test

2.2 创建RBAC授权

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

2.3 创建nfs-provisioner

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

2.4 创建storageclass

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: nfs-provisioner
parameters:
  archiveOnDelete: "true"

2.5 测试使用

在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
Logo

开源、云原生的融合云平台

更多推荐