2018年3月29日 11:02:33 关于docker分享之分布式存储 glusterfs 经典语录:

实际实验搭建: 前提 是要保证 一个 /data目录不和根分区在同一个磁盘! 1、centos7安装glusterfs 参考链接:https://wiki.centos.org/SpecialInterestGroup/Storage/gluster-Quickstart #To Use the RPMs from Storage SIG, you need to install the centos-release-gluster RPM as it will provide the required YUM repository files. This RPM is available from CentOS Extras.

yum install centos-release-gluster -y
yum --enablerepo=centos-gluster*-test install glusterfs-server -y
systemctl enable glusterd
systemctl start glusterd
systemctl status glusterd

2、组建集群(配置信任存储池): #从glusterfs官网跳转过来的

[root@docker1 ~]# ping docker2       #确保hostname可以通讯
PING dubbo2 (192.168.0.78) 56(84) bytes of data.
64 bytes from dubbo2 (192.168.0.78): icmp_seq=1 ttl=64 time=0.200 ms
64 bytes from dubbo2 (192.168.0.78): icmp_seq=2 ttl=64 time=0.167 ms
64 bytes from dubbo2 (192.168.0.78): icmp_seq=3 ttl=64 time=0.191 ms
^C
--- dubbo2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.167/0.186/0.200/0.013 ms
[root@docker1 ~]# gluster peer probe docker2
peer probe: success.                           #建立集群成功!
#验证检查  docker2和docker1建立集群成功!
[root@docker1 ~]# gluster peer status
Number of Peers: 1
Hostname: docker2
Uuid: e675b971-b503-4342-82ff-182858656282
State: Peer in Cluster (Connected)

[root@docker2 ~]# gluster peer status
Number of Peers: 1
Hostname: docker1
Uuid: 283ff245-7adf-4359-98c7-873cfcaa4a13
State: Peer in Cluster (Connected)

3、建立 GlusterFS volume

On both docker1 and docker2:

[root@docker1 ~]# mkdir -p /data/brick1/gv0

[root@docker2 ~]# mkdir -p /data/brick1/gv0

From any single server:

[root@docker1 ~]# gluster volume create gv0 replica 2 docker1:/data/brick1/gv0
Replica 2 volumes are prone to split-brain. Use Arbiter or Replica 3 to avoid this. See: http://docs.gluster.org/en/latest/Administrator%20Guide/Split%20brain%20and%20ways%20to%20deal%20with%20it/.
Do you still want to continue?           #上述提示是2台集群有脑裂的风险,建议3台建群,有自动选举决策能力
(y/n) y
volume create: gv0: success: please start the volume to access data
[root@docker1 ~]# gluster volume start gv0
volume start: gv0: success

#查看一下
[root@docker1 ~]# gluster volume info
Volume Name: gv0
Type: Replicate
Volume ID: 47a40786-eb5e-4845-b324-6feb4557d428
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 2 = 2
Transport-type: tcp
Bricks:
Brick1: docker1:/data/brick1/gv0
Brick2: docker2:/data/brick1/gv0
Options Reconfigured:
transport.address-family: inet
nfs.disable: on
performance.client-io-threads: off

4、客户端使用

yum install centos-release-gluster -y
yum -y install glusterfs-fuse  #glusterfs-client和glusterfs-fuse等价,其实都是安装的glusterfs-fuse!

#如果客户端不安装gluster-fuse,其实还可以以nfs协议传输,也就是把glusterfs当作nfs来用!(这里埋个伏笔,马上后面有讲到)

原理等: 拓展研究的网址: http://gluster.readthedocs.io/en/latest/Quick-Start-Guide/Architecture/ #英文讲解,最正宗!(其实网页翻译后一样 0.0) https://www.ibm.com/developerworks/cn/opensource/os-cn-glusterfs-docker-volume/index.html #中文版可能好看些

前面是基础部分了,相信群里大家都会安装的了,很简单的分布式存储,其实比起nfs来说可能还要更加的简单! 为了填充下篇幅,特盗取上述网址的图片来讲讲glusterfs的原理和我的理解(其实还参考了老男孩架构班glusterfs的讲解):

企业级的容器应用常常需要将重要的数据持久化,方便在不同容器间共享。为了能够持久化数据以及共享容器间的数据,Docker 提出了 Volume 的概念。单机环境的数据卷难以满足 Docker 集群化的要求,因此需要引入分布式文件系统。目前开源的分布式文件系统有许多,例如 GFS,Ceph,HDFS,FastDFS,GlusterFS 等。GlusterFS 因其部署简单、扩展性强、高可用等特点,在分布式存储领域被广泛使用。本文主要介绍了如何利用 GlusterFS 为 Docker 集群提供可靠的分布式文件存储。

GlusterFS 概述 GlusterFS (Gluster File System) 是一个开源的分布式文件系统。 GlusterFS 总体架构与组成部分如图1所示,它主要由存储服务器(Brick Server)、客户端以及 NFS/Samba 存储网关组成。 不难发现,GlusterFS 架构中没有元数据服务器组件(这个是对比fastdfs来说的,其实我对那个也了解不深,姑且认为会一个就得了把,其实可以理解这段是废话,你就认为它性能好就行了!),这是其最大的设计这点,对于提升整个系统的性能、可靠性和稳定性都有着决定性的意义。 * GlusterFS 支持 TCP/IP 和 InfiniBand RDMA 高速网络互联。 * 客户端可通过原生 GlusterFS 协议访问数据,其他没有运行 GlusterFS 客户端的终端可通过 NFS/CIFS 标准协议通过存储网关访问数据(存储网关提供弹性卷管理和访问代理功能)。 * 存储服务器主要提供基本的数据存储功能,客户端弥补了没有元数据服务器的问题,承担了更多的功能,包括数据卷管理、I/O 调度、文件定位、数据缓存等功能,利用 FUSE(File system in User Space)模块(所以客户端使用需要安装glusterfs-fuse)将 GlusterFS 挂载到本地文件系统之上,实现 POSIX 兼容的方式来访问系统数据。

** 重点来了, GlusterFS卷类型** 为了满足不同应用对高性能、高可用的需求,GlusterFS 支持 7 种卷,即 distribute 卷、stripe 卷、replica 卷、distribute stripe 卷、distribute replica 卷、stripe Replica 卷、distribute stripe replica 卷。其实不难看出,GlusterFS 卷类型实际上可以分为 3 种基本卷和 4 种复合卷,每种类型的卷都有其自身的特点和适用场景。(怎么说呢,我的理解就是raid磁盘系列,每种都有自己的优缺点,你根据需求是性能还是扩容,随便选用即可! 只要关注前面的三种基本卷就行了,后面的反正也是前面的组合混搭,至少我觉得后面几种卷用的应该不太多把。。。)

###For example to create a distributed volume with four storage servers using TCP.
gluster volume create test-volume server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4 Creation of test-volume has been successful Please start the volume to access data

别人的小结:基于 Hash 算法将文件分布到所有 brick server,只是扩大了磁盘空间,不具备容错能力。由于distribute volume 使用本地文件系统,因此存取效率并没有提高,相反会因为网络通信的原因使用效率有所降低,另外本地存储设备的容量有限制,因此支持超大型文件会有一定难度。

###For example, to create a replicated volume with two storage servers:
gluster volume create test-volume replica 2 transport tcp server1:/exp1 server2:/exp2
Creation of test-volume has been successful
Please start the volume to access data

别人的小结:文件同步复制到多个 brick 上,文件级 RAID1,具有容错能力,写性能下降,读性能提升。Replicated 模式,也称作 AFR(Auto File Replication),相当于 RAID1,即同一文件在多个镜像存储节点上保存多份,每个 replicated 子节点有着相同的目录结构和文件,replica volume 也是在容器存储中较为推崇的一种。

这个用法需要注意的地方就是 中间指定卷类型如果为n个副本,则后面必须接对应n个 节点地址; 假如你前面指定4个副本,后面接的2个pv地址,那么就是raid0+1了,即后面所谓的复合卷 distribute stripe volume. 假如你前面指定2个副本,后面接的4个节点地址,即下面所谓的基础卷 Distributed Replicated Glusterfs Volume.

###For example, four node distributed (replicated) volume with a two-way mirror:
gluster volume create test-volume replica 2 transport tcp server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4 
Creation of test-volume has been successful Please start the volume to access data

别人的小结:Brick server 数量是条带数的倍数,兼具 distribute 和 stripe 卷的特点。分布式的条带卷,volume 中 brick 所包含的存储服务器数必须是 stripe 的倍数(>=2倍),兼顾分布式和条带式的功能。每个文件分布在四台共享服务器上,通常用于大文件访问处理,最少需要 4 台服务器才能创建分布条带卷。

###For example, to create a striped volume across two storage servers:
gluster volume create test-volume stripe 2 transport tcp server1:/exp1 server2:/exp2
Creation of test-volume has been successful
Please start the volume to access data

别人的小结:类似 RAID0,文件分成数据块以 Round Robin 方式分布到 brick server 上,并发粒度是数据块,支持超大文件,大文件的读写性能高。

GlusterFS 客户端常用命令: (创建信任集群后,在任意一个节点执行下面命令,集群全部配置生效,这句话或许说的不够准确呢!)

命令 功能 gluster peer probe 添加节点 gluster peer detach 移除节点 gluster volume create 创建卷 gluster volume start 启动卷 gluster volume stop 停止卷 gluster volume delete 删除卷


其实上面说了这么多,也就是打个基础和铺垫,对于今天的标题来说,这才是重点!!!

基于docker的持久化,如果要使用到glusterfs必须安装别人写的第三方插件,(我觉得主要是docker懒,没有出系统化的持久化方案,或许未来更新迭代应该也不会有了,因为有k8s了,哈哈哈!) 摘抄如下:接下来,我们再来看GlusterFS如何作为Docker的存储。Docker Volume是一种可以将容器以及容器生产的数据分享开来的数据格式,我们可以使用宿主机的本地存储作为Volume的提供方,也可以使用Volume Plugin接入许多第三方的存储。 GitHub就有一个Docker GlusterFS Volume Plugin,方便我们将GlusterFS挂载到容器中。 原文:https://www.ibm.com/developerworks/cn/opensource/os-cn-glusterfs-docker-volume/index.html (也就是上面的中文拓展网址)

基于k8s编排工具的持久化,k8s是原生就支持glusterfs的存储驱动的,当然k8s还支持别的很多种存储驱动,今天就讲讲它算了。 安装好k8s后,直接部署下面几个文件即可!

[root@docker3 glusterfs]# cat glusterfs-pvc.yaml    #先创建pv,再创建pvc。比如创建个100G的大磁盘,里面分个50G的分区出来!用的是分区名字。
apiVersion: v1
kind: PersistentVolume
metadata:
  name: gluster-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: "glusterfs-cluster"
    path: "gv0"
    readOnly: false
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: glusterfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

[root@docker3 glusterfs]# cat glusterfs-endpoints.json  #ep的意思其实就是指定glusterfs集群的节点ip地址
{
  "kind": "Endpoints",
  "apiVersion": "v1",
  "metadata": {
    "name": "glusterfs-cluster"
  },
  "subsets": [
    {
      "addresses": [
        {
          "ip": "192.168.0.78"
        }
      ],
      "ports": [
        {
          "port": 1
        }
      ]
    },
    {
      "addresses": [
        {
          "ip": "192.168.0.101"
        }
      ],
      "ports": [
        {
          "port": 1
        }
      ]
    }
  ]
}

[root@docker3 glusterfs]# cat glusterfs-service.json   #svc主要就是把容器和应用给发布出去,比如通过cluster(集群)的port(端口) 1就能访问到了
{
  "kind": "Service",
  "apiVersion": "v1",
  "metadata": {
    "name": "glusterfs-cluster"
  },
  "spec": {
    "ports": [
      {"port": 1}
    ]
  }
}

[root@docker3 glusterfs]# cat nginx-deployment.yaml #dep主要的作用就是部署任务了。
apiVersion: extensions/v1beta1
kind: Deployment      #部署一个nginx到k8s集群
metadata:
  name: nginx-deployment
spec:
  replicas: 3                #副本为3
  template:
    metadata:
      labels:
        app: nginx          #标签是app:nginx
    spec:
      containers:
      - name: nginx
        image: nginx       #镜像是nginx:laster,拉取最新的nginx镜像
        volumeMounts:
        - name: glusterfsvol
          mountPath: /usr/share/nginx/html   #挂载到容器的位置
        ports:
        - containerPort: 80
      volumes:
      - name: glusterfsvol
        glusterfs:
          endpoints: glusterfs-cluster  #这里就和上面第三步创建的的ep的name必须对应,不然就报错!
          path: gv0                               #这是glusterfs的pvc名称,也就是第一步创建的那个
          readOnly: false                      #并不是只读

---

apiVersion: v1
kind: Service             #发布服务svc,让外界能访问到容器
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx             #这个标签就是匹配上面发布nginx的那个标签!
  ports:
  - name: http
    port: 80                 #外界访问cluster集群的 端口是80
    protocol: TCP        
    targetPort: 80       #外界访问pod的端口是 80
  type: NodePort       #其实这里还有个nodeport,也就是访问node节点的端口,既然没有指定端口的话,部署就应该是随机指定一个,特点好像是5位数的端口。(后面验证了一下,Kubernetes 会从 30000-32767 中分配一个可用的端口??? 我也不懂为啥我的实验不一致呢?或者说前面这个说法是错的。埋坑!!!)

填坑: 我自己自定义了端口范围。。。 总的来说,port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPod,从而到达pod上的容器内。

实验结果:

[root@docker3 PV]# kubectl get all -o wide
NAME                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE       CONTAINERS   IMAGES    SELECTOR
deploy/nginx-deployment   3         3         3            3           22m       nginx        nginx     app=nginx

NAME                             DESIRED   CURRENT   READY     AGE       CONTAINERS   IMAGES    SELECTOR
rs/nginx-deployment-5b87cb9b85   3         3         3         22m       nginx        nginx     app=nginx,pod-template-hash=1643765641

NAME                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE       CONTAINERS   IMAGES    SELECTOR
deploy/nginx-deployment   3         3         3            3           22m       nginx        nginx     app=nginx

NAME                             DESIRED   CURRENT   READY     AGE       CONTAINERS   IMAGES    SELECTOR
rs/nginx-deployment-5b87cb9b85   3         3         3         22m       nginx        nginx     app=nginx,pod-template-hash=1643765641

NAME                                   READY     STATUS    RESTARTS   AGE       IP            NODE
po/nginx-deployment-5b87cb9b85-49lmx   1/1       Running   0          22m       172.17.23.7   192.168.0.101
po/nginx-deployment-5b87cb9b85-8php8   1/1       Running   0          22m       172.17.23.2   192.168.0.101
po/nginx-deployment-5b87cb9b85-phl87   1/1       Running   0          22m       172.17.35.3   192.168.0.78

NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE       SELECTOR
svc/glusterfs-cluster   ClusterIP   10.10.10.246   <none>        1/TCP          8d        <none>
svc/kubernetes          ClusterIP   10.10.10.1     <none>        443/TCP        12d       <none>
svc/nginx-service       NodePort    10.10.10.149   <none>        80:36914/TCP   22m       app=nginx

That's ALL!
Thankyou!