MONAIVE

Kubernetes使用NFS做持久化存储
Kubernetes给大家的印象是部署编排无状态的服务非常强,从Replication Controller、Re...
扫描右侧二维码阅读全文
12
2019/08

Kubernetes使用NFS做持久化存储

Kubernetes给大家的印象是部署编排无状态的服务非常强,从Replication ControllerReplica Set到现在的Deployment,无状态的服务一般也不需要持久化存储,常见的SpringBootSpringCloud基本都是运行JDK服务,本身也无存储。
但是对于有状态的服务,比如想在Kubernetes部署MySQLEFKPrometheus之类的需要存储的,就需要持久化存储了,从几年前刚刚接触Kubernetes开始就很好奇到底该用什么,几年前搞过Ceph,搞到头大放弃了,前段时间搞Glusterfs,建立PV、PVC很顺畅,但是光靠它没办法实现Statefulset的动态伸缩,还需要部署Heketi才可以,但是这个Heketi需要节点机器存在裸盘。
后来又看了Ceph的容器化实现Rook,但是搞了一天都没搞定,最后去搞个最简单的NFS。Rook作为CNCF成员,未来不可限量,预计为以后的主流,因为它把复杂的Ceph简单化了,刚刚啰嗦了那么多,目前可以做Kubernetes持久化存储(集群)的主要有以下方案:

  • Gluster+Heketi
  • Ceph
  • Rook-Ceph

而我们这次用的只是单机NFS。

1.部署NFS服务器

全新安装CentOS,然后关闭Selinux与防火墙。

# 命名
echo NFS >/etc/hostname

# 关闭Selinux
sed -i 's/enforcing/disabeld/g' /etc/selinux/config

# 临时关闭
setenforce 0

# 关闭防火墙自启动
systemctl disable firewalld

# 关闭防火墙
systemctl stop firewalld

# 安装NFS
yum install -y rpcbind nfs-utils

# 建立共享文件夹
mkdir /kubedata

# 编辑共享文件夹权限,我这里用了*通配符允许所有Ip访问,请更换为Kubernetes nodes地址,支持多条
vi /etc/exports
/kubedata *(rw,no_root_squash,no_all_squash,sync)

# 启动NFS
systemctl start rpcbind
systemctl start nfs
systemctl enable rpcbind
systemctl enable nfs

理论上现在NFS服务器已经可以提供服务了,如果你想直接挂在目录,可以这么操作,但是我们用的是Kubernetes,使用StorageClass挂载。

# 安装nfs-utils
yum install -y nfs-utils

# 创建文件夹
mkdir /nfsdata

# 挂载
mount -t nfs nfs-server:/kubedata /nfsdata
 
# 开机挂载,末尾添加
vi /etc/fstab

nfs-server:/kubedata    /nfsdata    nfs     defaults 0 0

# 修改fstab需要reload daemon
systemctl daemon-reload

2.StorageClass

nfs-client-provisioner 是一个Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储。
Kubernetes从1.6版本开始就默认开启了RBAC,所以同时我们还需要配置RBAC,以下配置均为官方的Sample文件略微修改而来。
external-storage/nfs-client/deploy at master · kubernetes-incubator/external-storage · GitHub
首先创建namespace,这里我们所有的操作都在namespace:nfs中完成。

kubectl create namespace nfs

2.1 RBAC

创建SA nfs-client-provisioner
需要替换其中两处namespace,最后保存为nfs-rbac.yaml

kind: ServiceAccount
apiVersion: v1
metadata:
  name: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-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: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    namespace: nfs
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
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-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: nfs
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

2.2 Deployment

保存为nfs-deploy.yaml

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: nfs-client-provisioner
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-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: fuseim.pri/ifs
            - name: NFS_SERVER
              value: nfs-server-ip  # 替换为你的NFS服务器
            - name: NFS_PATH
              value: /kubedata  # 替换为你的NFS文件夹
      volumes:
        - name: nfs-client-root
          nfs:
            server: nfs-server-ip  # 替换为你的NFS服务器
            path: /kubedata  # 替换为你的NFS文件夹

2.3 StorageClass

这里的provisioner值要与deploy文件中的PROVISIONER_NAME值相同。
保存为nfs-sc.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: fuseim.pri/ifs

这里注解设定此SC为默认SC,如果一开始并未添加,可修改添加:

kubectl edit sc managed-nfs-storage

开始部署

kubectl create -f nfs-rbac.yaml -n nfs
kubectl create -f nfs-deploy.yaml -n nfs
kubectl create -f nfs-sc.yaml -n nfs

现在已经部署完毕,现在需要持久化存储,只需要在PVC中指定storageClassName: managed-nfs-storage即可申请空间,测试一下。

验证

家境贫寒,申请个500M存储:

# 编辑文件
vi spex-pvc.yaml 

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: spex-pvc
spec:
  storageClassName: managed-nfs-storage
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Mi
      
# 申请在default中
kubectl create -f spex-pvc.yaml
persistentvolumeclaim/spex-pvc created

# 成功
kubectl get pvc
NAME       STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
spex-pvc   Bound    pvc-eba3f11b-0600-4034-9a1d-dc6a62ead329   500Mi      RWX            managed-nfs-storage   38s

这样我们就可以使用Statefulset进行有状态服务部署了,比如MySQL集群、EFK。

Last modification:August 16th, 2019 at 12:49 pm

Leave a Comment