天天看點

kubernetes(k8s) 配置nfs動态卷實作StatefulSet的持久化存儲概述正文結束

概述

    我們知道,平時kubernetes在部署無狀态服務的時候,并不需要太多考慮持久化存儲的事情,直接通過volume挂載網絡存儲,比如常見的nfs就能實作檔案共享存儲。

    但是如果在有狀态服務中,你就會需要很多的問題,比如:當你部署一些叢集服務的時候:

1. 不可以用共享存儲,因為每個服務的資料都不能相同。

2. 不可以直接用node的本地路徑進行挂載,因為pod的随機性,一個node可能會跑多個pod副本,則會造成沖突。

3. 資料量可能會很大,可能需要使用外部存儲,或者獨立的磁盤,雲盤等

4. 就算用pv,pvc也很不友善,需要你提前手動建立,不友善擴充。

   然後我們細數一下k8s裡的持久化存儲,總的分為兩種,靜态卷和動态卷。靜态卷就是剛才我們說的,volume挂載,或者通過手動建立pv,pvc進行挂載。都屬于靜态卷。而動态卷,則是将一個網絡存儲作為一個StorageClass類,通過自己的配置,來動态的建立pv,pvc并進行綁定,這樣就可以實作動态的存儲生成與持久化儲存。

    具體詳細的k8s的存儲系統知識我這裡就不想洗說明,有興趣的自行百度,谷歌就可以了,先了解一下k8s的存儲,再來看如何實作

   下面我們就說一下,怎麼通過nfs動态卷來實作有狀态服務的儲存。

正文

環境:

kubernetes  v1.12.2 

centos7

這裡以搭建neo4j 因果叢集為例,展示nfs動态卷的使用,namespace為neo4j。

nfs動态卷的整體結構大緻如下圖,使用者通過yaml建立StatefulSet,StatefulSet找到StorageClass,StorageClass指定到nfs-provisioner為nfs的pv提供者,這是一個pod的服務,用來自動生成pv的,此pod來綁定到對應的nfs服務。以此來通過nfs服務進行動态的pv生成,然後通過StatefulSet的pvc,與pod進行綁定,實作資料的持久化存儲。

kubernetes(k8s) 配置nfs動态卷實作StatefulSet的持久化存儲概述正文結束

1.  搭建好nfs服務

nfs服務的搭建,請看:《centos7.2 配置NFS檔案伺服器,遠端共享檔案》

我這裡搭建好nfs後,建立檔案夾 /opt/nfs 作為主目錄進行,配置如下: 

# 172.18.0.0/16是我的内網網段,自己根據情況自定義
/opt/nfs 172.18.0.0/16(rw,sync,no_root_squash)
           

nfs服務的ip為:172.18.196.238

2. 配置rbac權限

由于我這裡以neo4j為namespace,是以先建立namespace.yaml 檔案,内容如下:

---
apiVersion: v1
kind: Namespace
metadata:
   name: neo4j
   labels:
     name: neo4j
           

執行此yaml檔案,建立neo4j的命名空間,以保證下面的使用

kubectl create -f namespace.yaml
           

然後開始建立rbac.yaml,進行賬号的授權,内容如下:

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
  namespace: neo4j
---
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: neo4j
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
           

執行此yaml檔案,執行賬号建立與授權,必須進行賬号的授權,否則無法自動建立pv和pvc

kubectl create -f rbac.yaml
           

3. 建立nfs-provisioner

建立deployment.yaml 檔案,内容如下:

---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-client-provisioner
  namespace: neo4j
  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: 172.18.196.238
            - name: NFS_PATH
              value: /opt/nfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: 172.18.196.238
            path: /opt/nfs
           

執行此yaml檔案,建立nfs-provisioner,此nfs-provisioner通過授權的賬号實作自動建立pv,pvc

kubectl create -f deployment.yaml
           

3. 建立storageclass

建立storageclass.yaml ,内容如下:

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: nfs-provisioner
parameters:
  archiveOnDelete: "true"    # 這裡為true,表示pv删除後,會自動歸檔,不會删除檔案
           

執行此yaml檔案,建立storageclass,指定使用的provisioner為nfs-provisioner

kubectl create -f storageclass.yaml
           

4. 測試使用

在StatefulSet中,通過配置volumeClaimTemplates來配置使用動态卷,這裡以搭建neo4j的因果叢集為例子,進行測試,建立demo.yaml 檔案,内容如下:

---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: neo4j-core
  namespace: neo4j
  labels:
    app: neo4j-core
spec:
  replicas: 2
  selector:
    matchLabels:
      app: neo4j-core
  serviceName: neo4j-core
  template:
    metadata:
      labels:
        app: neo4j-core
    spec:
      nodeSelector:
        neo4j-core: "yes"
      containers:
      - name: neo4j-core
        image: neo4j:3.5.5-enterprise
        imagePullPolicy: IfNotPresent
        env:
          - name: NEO4J_ACCEPT_LICENSE_AGREEMENT
            value: "yes"
          - name: NEO4J_dbms_connectors_default__advertised__address
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
          - name: NEO4J_dbms_mode
            value: "CORE"
          - name: NEO4J_causal__clustering_minimum__core__cluster__size__at__formation
            value: "2"
          - name: NEO4J_causal__clustering_minimum__core__cluster__size__at__runtime
            value: "2"
          - name: NEO4J_causal__clustering_discovery__type
            value: "LIST"
          - name: NEO4J_causal__clustering_initial__discovery__members
            value: "neo4j-core-0.neo4j-core.neo4j.svc.cluster.local:5000,neo4j-core-1.neo4j-core.neo4j.svc.cluster.local:5000"
          - name: NEO4J_causal__clustering_discovery__advertised__address
            value: $(NEO4J_dbms_connectors_default__advertised__address):5000
          - name: NEO4J_causalClustering_transactionAdvertisedAddress
            value: $(NEO4J_dbms_connectors_default__advertised__address):6000
          - name: NEO4J_causalClustering_raftAdvertisedAddress
            value: $(NEO4J_dbms_connectors_default__advertised__address):7000
        volumeMounts:
        - name: neo4j-core    # 這裡的name要和 下面volumeClaimTemplates的metdata中name一緻
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: neo4j-core
      annotations:
        volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"    # 這裡managed-nfs-storage就是我們建立的storageclass的name
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 2Gi
---
apiVersion: v1
kind: Service
metadata:
  name: neo4j-core
  namespace: neo4j
spec:
  selector:
    app: neo4j-core
  type: NodePort
  ports:
    - protocol: TCP
      name: http
      port: 7474
      nodePort: 27474
      targetPort: 7474
    - protocol: TCP
      name: blot
      port: 7687
      nodePort: 27687
      targetPort: 7687
           

執行此demo.yaml

kubectl create -f demo.yaml
           
執行過後,等待片刻,檢視pvc已經生成,并與pv進行了綁定。
           
kubernetes(k8s) 配置nfs動态卷實作StatefulSet的持久化存儲概述正文結束

檢視pv

kubernetes(k8s) 配置nfs動态卷實作StatefulSet的持久化存儲概述正文結束

這裡pv的回收政策是delete,就是說pod删除後,pv,pvc與自動删除,但是資料檔案并不會删除,會進行歸檔,因為在storageclass中設定了對删除PV的檔案的歸檔。

我們檢視一下nfs服務的目錄,會發現生成了兩個檔案夾,名字為 pvc的name加上pv的name:

kubernetes(k8s) 配置nfs動态卷實作StatefulSet的持久化存儲概述正文結束

進入檔案夾,檢視資料存在。 

kubernetes(k8s) 配置nfs動态卷實作StatefulSet的持久化存儲概述正文結束

然後現在我們删掉此neo4j的叢集,檢視資料是否會被删除

kubectl delete -f demo.yaml
           

删除後,檢視pv,pvc,會發現,pv,pvc都被删除掉了,然後到nfs目錄中檢視:

kubernetes(k8s) 配置nfs動态卷實作StatefulSet的持久化存儲概述正文結束

會發現,檔案夾還在,且其名稱前面多一個archived,這是歸檔的意思,表示此檔案夾的pv已經被删除了,進去檢視檔案是否存在

kubernetes(k8s) 配置nfs動态卷實作StatefulSet的持久化存儲概述正文結束

ok,到此測試通過,就可以使用volumeClaimTemplates來配置動态卷的使用,非常友善簡單。當然動态卷不止支援nfs,還支援很多的儲存插件來提供PV,詳細可檢視Storage Classes 官方文檔 provisioner部分。

結束

    我這裡并沒有講很多的k8s的存儲系統相關的東西,隻是主要實作了nfs動态卷的配置和使用。使用則主要是demo.yaml檔案檔案中的volumeClaimTemplates來進行配置。有任何不明白的,歡迎留言

繼續閱讀