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)