GlusterFS与Kubernetes持久卷
GlusterFS是一个网络文件系统。跟NFS比,它严格实现了POSIX文件锁。
文件锁
这里我们构建一个脚本,来测试文件系统是否支持POSIX文件锁。
此脚本保证自己单例执行。如有并发发生,等待正在跑的实例完成。
在NFS文件系统上,会报错误:
flock: failed to execute ./lock-date.sh: Text file busy
这说明NFS文件系统不支持文件锁。
lock-date.sh代码如下:
#!/bin/bash [ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock "$0" "$0" "$@" date +"[%T] $$ Running" sleep 10 date +"[%T] $$ Done"
因此如果你想在多节点执行sqlite,就可以把它的数据库文件放到glusterfs上。
以下简单介绍GlusterFS安装配置,以及在Kubernetes里的应用。
安装包
GlusterFS在Ubuntu 1804里版本较旧,需要加装额外的源:
apt-get install -qq software-properties-common add-apt-repository -y ppa:gluster/glusterfs-5
在CentOS 7.7可以选CentOS认证的源:
yum install centos-release-gluster
以下是安装
包 | Ubuntu | CentOS |
client | glusterfs-client | glusterfs-cli |
server | glusterfs-server | glusterfs-server |
服务端
yum install glusterfs-cli glusterfs-server systemctl enable glusterd systemctl start glusterd
服务端有几个概念:
1. 节点,
2. 集群,
3. 砖块,
4. 卷。
下面分别介绍。
节点
gluster服务起来就是一个peer,比如:
192.144.99.220 gluster00 192.144.99.221 gluster01 192.144.99.222 gluster02
集群
可选gluster00为主节点,组集群:
# on gluster00 gluster peer probe 192.144.99.221:/bricks/brick1/data gluster peer probe 192.144.99.222:/bricks/brick1/data
注意这里直接用ip加peer。如果用hostname加peer要保证各个客户端机器都可以 解析机器名。
做砖
要保证目录/bricks/brick1/data在个节点存在,且不能为挂载根节点。我是 这么组织/bricks/brick1/data的:
pvcreate /dev/vdb vgcreate gluster /dev/vdb lvcreate -n brick1 -l 100%free gluster mkfs.xfs /dev/mapper/gluster-brick1 mkdir -p /bricks/brick1 mount /dev/mapper/gluster-brick1 /bricks/brick1 mkdir -p /bricks/brick1/data
注意/bricks/brick1为挂载根节点。
可以用gluster peer status列一下个peer状态:
Number of Peers: 2 Hostname: 192.144.99.221 Uuid: 53442d56-2244-45bc-a9a1-3f7e7cc17466 State: Peer in Cluster (Connected) Hostname: 192.144.99.222 Uuid: 5d9d1066-cfa5-4e0f-bbe6-6455c957cb28 State: Peer in Cluster (Connected)
之后可创建卷。
卷
Volume创建、启动:
gluster volume create data 192.144.99.220:/bricks/brick1/data \ 192.144.99.221:/bricks/brick1/data \ 192.144.99.222:/bricks/brick1/data gluster volume start data
这就有了一个叫data的volume。
加减节点
Peer可以detach,但要保证没有卷用这个Peer:
gluster volume stop data gluster volume delete data gluster peer detach gluster01 gluster peer detach gluster02
detach后同一个目录再次加入,需要清理一下:
setfattr -x trusted.glusterfs.volume-id /bricks/brick1/data setfattr -x trusted.gfid /bricks/brick1/data rm -rf /bricks/brick1/data/.glusterfs
此清理动作需要在每个节点上执行。
客户端
在客户端需要安装glusterfs client。安装后会有mount.glusterfs存在。 注意ubuntu自带的gluster client不可用,需要更新。
可以到一个客户端机器上测试一下这个volume:
mount.glusterfs 192.144.99.220:data /mnt
如命令出错可以到/var/log/glusterfs/看日志。
没出错就表示成功了。
Kubernetes
Kubernetes里的PersistentVolume可以用glusterfs来做。需要在每个几点上 安装gluster client,保证mount.glusterfs存在并工作。
apt-get install glusterfs-client mount.glusterfs 192.144.99.220:data /mnt umount /mnt
Gluster Endpoint
--- kind: Endpoints apiVersion: v1 metadata: {name: glusterfs-cluster} subsets: - addresses: - {ip: 192.144.99.220} ports: - {port: 1} - addresses: - {ip: 192.144.99.221} ports: - {port: 1} - addresses: - {ip: 192.144.99.222} ports: - {port: 1}
持久卷
PersistentVolume有三种类型:
1. ReadWriteOnce,
2. ReadWriteMany,
3. ReadOnlyMany。
下面每种类型创建10个。在gluster上先把目录创建出来:
mount -t glusterfs 192.144.99.220:data /mnt mkdir -p /mnt/{rwm,rwo,rom}/{01..10} umount /mnt
用如下脚本生成PersistentVolume池(gluster-pvs.sh):
#!/bin/bash declare -A modes=([rwm]=ReadWriteMany [rwo]=ReadWriteOnce [rom]=ReadOnlyMany) for m in rwm rwo rom; do mode=${modes[$m]} for n in {01..10}; do cat <<EOF --- apiVersion: v1 kind: PersistentVolume metadata: name: ${m}-${n} spec: capacity: storage: 100Gi accessModes: - ${mode} glusterfs: endpoints: glusterfs-cluster path: data/${m}/${n} readOnly: false persistentVolumeReclaimPolicy: Retain EOF done done
创建:
./gluster-pvs.sh | kubectl apply -f -
持久卷声明
PersistentVolumeClaim --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nginx-claim spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi
如上,PersistentVolumeClaim会找一个访问模式为ReadWriteMany,容量不 小于1Gi的PersistentVolume绑定:
kubectl get pvc #=> NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE nginx-claim Bound rwm-01 100Gi RWX 4m59s
卷挂载
可以用nginx测试一下:
--- apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: http selector: app: nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx namespace: default spec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: - name: storage001 mountPath: "/usr/share/nginx/html" volumes: - name: storage001 persistentVolumeClaim: claimName: nginx-claim
测试:
mount -t glusterfs 192.144.99.220:data/rwm/01 /mnt echo hi > index.html kubectl port-forward service/nginx 80:80 & curl http://localhost #=> hi
有状态集
有状态集里有一个隐含的持久卷声明,比如:
--- apiVersion: apps/v1 kind: StatefulSet metadata: name: rg spec: serviceName: random-generator replicas: 2 selector: matchLabels: app: random-generator template: metadata: labels: app: random-generator spec: containers: - image: k8spatterns/random-generator:1.0 name: random-generator env: - name: LOG_FILE value: /opt/logs/random.log ports: - containerPort: 8080 name: http volumeMounts: - name: logs mountPath: /opt/logs volumeClaimTemplates: - metadata: name: logs spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 10Mi
可以看到其匹配到两个持久卷,kubectl get pvc:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE logs-rg-0 Bound rwo-05 100Gi RWO 15s logs-rg-1 Bound rwo-01 100Gi RWO 12s
有状态集删除之后,持久卷声明还在,需要手工清理。
- 点赞
- 收藏
- 关注作者
评论(0)