在生产环境使用 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中拿到卷。

image-20211110133300785

首先声明一个 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 年了没有大毛病。