# Create ReadWriteMany Persistent Volume in Google Kubernetes Engine
Familiarity with [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) is suggested.
## Introduction
**Terminologies**:
- Persistent Volume (PV):在 cluster 中已由管理員提供或使用 [Storage Classes](https://kubernetes.io/docs/concepts/storage/storage-classes/) 動態提供的一部分的儲存(storage)。它是 cluster 內的資源就像是 node 是一種 cluster 資源一樣。PV 擁有獨立於使用該 PV 的 pod 的生命週期。
- Persistent Volume Claim (PVC):使用者對於儲存的請求。類似於 pod 消耗 node 的資源,而 PVCs 消耗 PV 的資源。Pod 請求特定級別的資源(CPU 和記憶體)。Claims 可以請求特定大小和存取模式。
*PersistentVolume* 有以下幾種[存取模式](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes):
- ReadWriteOnce
- ReadOnlyMany
- ReadWriteMany
- ReadWriteOncePod
但目前 [Google Compute Engine persistent disk](https://kubernetes.io/docs/concepts/storage/volumes/#gcepersistentdisk) 只支援 RWO 和 ROX。因此想要擁有一個所有 nodes 都能夠讀寫的空間,最好的方法是使用 [Filestore](https://cloud.google.com/filestore)。但若是資料量較小的話,Filestore 則不太適合,因為它提供最小的空間為 1 TB,一個月就需要約 NT$ 6,000。
因此比較適合的方法就是在 K8s 建立一個網路檔案系統(NFS)。
## Steps
[GitHub Example](https://github.com/kubernetes/examples/tree/master/staging/volumes/nfs)
1. 先建立一個 GCE PD 作為 NFS 的掛載 volume
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
resources:
requests:
storage: 20Gi
accessModes:
- ReadWriteOnce
```

2. 建立 NFS 並設定相關 ports,並連上剛建立的 Volume
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-server
spec:
replicas: 1
selector:
matchLabels:
role: nfs-server
template:
metadata:
labels:
role: nfs-server
spec:
containers:
- name: nfs-server
image: gcr.io/google_containers/volume-nfs:0.8
ports:
- name: nfs
containerPort: 2049
- name: mountd
containerPort: 20048
- name: rpcbind
containerPort: 111
securityContext:
privileged: true
volumeMounts:
- mountPath: /exports
name: mypvc
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: nfs-pvc
```

3. 將此 NFS pod 對外開放,設定叢集 IP
```yaml
apiVersion: v1
kind: Service
metadata:
name: nfs-server
spec:
ports:
- name: nfs
port: 2049
- name: mountd
port: 20048
- name: rpcbind
port: 111
selector:
role: nfs-server
```

4. 建立 RWX 的 PV & PVC 供其他人使用
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
nfs:
server: nfs-server.default.svc.cluster.local
path: "/"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs-pvc1
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 1Gi
volumeName: nfs-pv1
```
可使用 `kubectl get pv ; kubectl get pvc` 檢查

5. 將剛建立的 PVC 掛進你需要的 pod 即完成
```yaml
apiVersion: v1
kind: Deployment
metadata:
name: nfs-busybox
spec:
replicas: 2
selector:
name: nfs-busybox
template:
metadata:
labels:
name: nfs-busybox
spec:
containers:
- image: busybox
command:
- sh
- -c
- 'while true; do date > /mnt/index.html; hostname >> /mnt/index.html; sleep $(($RANDOM % 5 + 5)); done'
imagePullPolicy: IfNotPresent
name: busybox
volumeMounts:
# name must match the volume name below
- name: nfs
mountPath: "/mnt"
volumes:
- name: nfs
persistentVolumeClaim:
claimName: nfs-pvc1
```
以上就完成一個在 GKE 的 ReadWriteMany volume
###### tags: `gke` `persistent-volume` `volume` `k8s`