Kubernetes Local Volume 使用

Posted by Sunday on 2019-10-25

有时,由于服务器数量有限,您可能不愿意使用GlusterFS和CephFS来设置动态存储配置。

在这种情况下,除了必须首先创建自己的PV外,几乎可以采用与动态卷配置相同的方式来使用本地卷。与主机路径卷不同,使用本地卷的Pod将自动计划在定义了本地卷的节点上运行。

让我们测试一下。

创建 Local Volume和Storage Class 的PV

Local Volume
Storage Classes
使用以下示例创建一个PV和该PV的StorageClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
cat <<EOF > my-local-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-local-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
storageClassName: my-local-pv
local:
path: /icp/local-dir
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- demo20
- demo21
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: my-local-pv
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
EOF
kubectl apply -f my-local-pv.yaml

kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
my-local-pv 5Gi RWO Retain Available my-local-pv 28s

PV使用的是local卷类型。 volumeMode设置为FileSystem,文件路径是目标服务器上目录的位置。您也可以使用Block来使用原始磁盘。

1
2
ssh root@demo20 "mkdir -p /icp/local-dir"
ssh root@demo21 "mkdir -p /icp/local-dir"

另一方面,登录demo20demo21的服务器,创建目录/icp/local-dir。我们还需要设置nodeAffinity来告诉Kubernetes该本地卷仅在demo20demo21的节点中可用。请注意,此约束也将适用于将使用此PV的pods。此功能消除了HostPath的负担,您需要手动管理节点关联性。

我们使用与PV对象中定义的storageClassName相同的名称创建一个存储类。

注意volumeBindingMode的WaitForFirstConsumer,这意味着绑定仅在pod创建之后发生。
Volume Binding Mode

使用PV

一旦我们使用local创建了StorageClass,与使用动态存储配置相比就没有区别。

首先创建一个PVC,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat << EOF > pvc-local-test.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-local-test
spec:
accessModes:
- ReadWriteOnce
storageClassName: my-local-pv
resources:
requests:
storage: 2Gi
EOF
kubectl apply -f pvc-local-test.yaml

# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-local-test Pending my-local-pv 22s

#此时STATUS:Pending,待创建下面的deployment后,STATUS才会改变。

使用上述PVC创建deployment,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
cat <<EOF>local-pv-test-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: local-pv-test
labels:
app: local-pv-test
spec:
replicas: 3
selector:
matchLabels:
app: local-pv-test
template:
metadata:
labels:
app: local-pv-test
spec:
containers:
- name: local-pv-test
image: busybox
imagePullPolicy: IfNotPresent
command: ["sh"]
args: ["-c", "while true; do sleep 60; done"]
volumeMounts:
- name: pv-data
mountPath: /data
volumes:
- name: pv-data
persistentVolumeClaim:
claimName: pvc-local-test
EOF
kubectl apply -f local-pv-test-deployment.yaml

# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-local-test Bound my-local-pv 5Gi RWO my-local-pv 4m47s

测试

1
2
3
4
5
6
7
8
9
10
11
# kubectl get pod -owide | grep local-pv-test
local-pv-test-96f76cbf9-4bl8g 1/1 Running 0 73s 10.244.40.105 demo21 <none> <none>

# kubectl exec -it local-pv-test-96f76cbf9-4bl8g -- sh
/ # echo $(hostname) > /data/aa
/ # cat /data/aa
local-pv-test-96f76cbf9-4bl8g
/ # exit

# cat /icp/local-dir/aa
local-pv-test-96f76cbf9-4bl8g

现在,将deployment扩展到3个副本。您会注意到,所有Pod都将在本地卷所在的正确节点上运行,尽管我们尚未在部署对象中定义任何Pod亲缘关系

1
2
3
4
5
# kubectl scale deployment local-pv-test --replicas 3
# kubectl get pod | grep local-pv-test
local-pv-test-96f76cbf9-djjbm 1/1 Running 0 6s 10.244.40.106 demo21 <none> <none>
local-pv-test-96f76cbf9-h9pl9 1/1 Running 0 6s 10.244.134.147 demo20 <none> <none>
local-pv-test-96f76cbf9-qqcj8 1/1 Running 0 17m 10.244.40.104 demo21 <none> <none>

我们使用多个副本来证明调度。在生产中,不建议使用local volume + deployment这么操作,因为可能存在并发评估问题。建议配合StatefulSet使用

由于PVC没有任何区别,因此可以将storageClass用于helm chart动态存储配置

https://medium.com/@zhimin.wen/local-volume-provision-242affd5efe2