概述
我們知道,平時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進行綁定,實作資料的持久化存儲。
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進行了綁定。
檢視pv
這裡pv的回收政策是delete,就是說pod删除後,pv,pvc與自動删除,但是資料檔案并不會删除,會進行歸檔,因為在storageclass中設定了對删除PV的檔案的歸檔。
我們檢視一下nfs服務的目錄,會發現生成了兩個檔案夾,名字為 pvc的name加上pv的name:
進入檔案夾,檢視資料存在。
然後現在我們删掉此neo4j的叢集,檢視資料是否會被删除
kubectl delete -f demo.yaml
删除後,檢視pv,pvc,會發現,pv,pvc都被删除掉了,然後到nfs目錄中檢視:
會發現,檔案夾還在,且其名稱前面多一個archived,這是歸檔的意思,表示此檔案夾的pv已經被删除了,進去檢視檔案是否存在
ok,到此測試通過,就可以使用volumeClaimTemplates來配置動态卷的使用,非常友善簡單。當然動态卷不止支援nfs,還支援很多的儲存插件來提供PV,詳細可檢視Storage Classes 官方文檔 provisioner部分。
結束
我這裡并沒有講很多的k8s的存儲系統相關的東西,隻是主要實作了nfs動态卷的配置和使用。使用則主要是demo.yaml檔案檔案中的volumeClaimTemplates來進行配置。有任何不明白的,歡迎留言