在生产环境使用 Kubernetes ,绕不过去的一个问题就是持久化卷。
如果是使用阿里 ACK 托管平台的话,可以用 OSS 来持久化卷,如果是自搭的 kubernetes,那么存储就需要仔细考虑了。
ceph比较复杂,容易出故障。nfs 也不可用,毛病多多。minio倒是可以。
这种情况下使用双副本的 GlusterFS 就是不错的选择。
生产环境就不能随意了,最好不要使用 Heketi,因为凡是要持久化的东西,都是比较重要的东西,最好都有 yaml 记录。
GlusterFS 的搭建就不说了。说说实际使用过程:
一、装GFS,生产新卷
安装就不说了,我们的GFS有两个节点,172.19.20.18 和 172.19.20.36,我们强制建立一个两副本的卷: kuaijian-vol
gluster volume create kuaijian-vol replica 2 transport tcp 172.19.20.18:/glusterfs/kuaijian-vol 172.19.20.36:/glusterfs/kuaijian-vol force
二、为k8s产生GFS的endingpoint和service
cat << EOF >> ep-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: gfs-cluster_svc
spec:
ports:
- port: 1
---
apiVersion: v1
kind: Endpoints
metadata:
name: gfs-cluster_svc
subsets:
- addresses:
- ip: 172.19.20.18
ports:
- port: 1
- addresses:
- ip: 172.19.20.36
ports:
- port: 1
EOF
kubectl apply -f ep-svc.yaml
这里要提一个概念,通常情况下 service 是通过 selector 标签来选择对应的 pod 来增加 endingpoint 的。如下:
apiVersion: v1
kind: Service
metadata:
name: go-api_svc
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: go-api
type: ClusterIP
而上面,我们没有通过标签,而是让 endingpoint 和 svc 同名而手动增加 endingpoint 到 svc 的。
三、为k8s生产创建 PV和PVC
静态环境不使用 Storageclass 持久化卷的图解如下,pod做pvc声明,pvc连接到pv,pv从GFS中拿到卷。

首先声明一个 pv:
cat << EOF >> kuaijian-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: gfs-kuaijian-50G_pv
labels:
name: gfs-kuaijian-50G_pv
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
glusterfs:
endpoints: gfs-cluster_svc
path: kuaijian-vol
readOnly: false
persistentVolumeReclaimPolicy: Retain
EOF
kubectl apply -f kuaijian-pv.yaml
然后声明一个 pvc 通过 matchLabels 来跟之前的 pv 绑定。
cat << EOF >> kuaijian-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: gfs-kuaijian-50G_pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Gi
selector:
matchLabels:
name: gfs-kuaijian-50G_pv
EOF
kubectl apply -f kuaijian-pvc.yaml
注意上面的 pvc,我们一下子申请了50G,把整个 pv 空间全用光了;当然我们也可以只申请个 10Gi,下个 pvc 再 10Gi,这样也是行的通的。
四、POD使用PVC
声明一个 Nginx 的 Deployment 来使用这个 pvc
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: data-www
mountPath: /data/www
volumes:
- name: data-www
persistentVolumeClaim:
claimName: gfs-kuaijian-50G_pvc
这样 kubernetes 的存储部分就搞定了。GFS 用于生产非常稳定,基本跑了 7 年了没有大毛病。