介绍
FastDFS是一款开源的轻量级分布式文件系统纯C实现,支持Linux、FreeBSD等UNIX系统类google FS,不是通用的文件系统,只能通过专有API访问,目前提供了C、Java和PHP API为互联网应用量身定做,解决大容量文件存储问题,追求高性能和高扩展性FastDFS可以看做是基于文件的key value pair存储系统,称作分布式文件存储服务更为合适.
tracker-server:
跟踪服务器, 主要做调度工作, 起负载均衡的作用。 在内存中记录集群中所有存储组和存储服务器的状态信息, 是客户端和数据服务器交互的枢纽。 相比GFS中的master更为精简, 不记录文件索引信息, 占用的内存量很少。
storage-server:
存储服务器( 又称:存储节点或数据服务器) , 文件和文件属性( metadata) 都保存到存储服务器上。 Storage server直接利用OS的文件系统调用管理文件。
group:
组, 也可称为卷。 同组内服务器上的文件是完全相同的 ,同一组内的storage server之间是对等的, 文件上传、 删除等操作可以在任意一台storage server上进行 。
meta data:
meta data:文件相关属性,键值对( Key Value Pair) 方式,如:width=1024,heigth=768 。
部署
由于应用全部迁移到kubernetes平台部署,之前用的fastdfs也不例外需要进行迁移,中间遇到的问题很多,后面会提到,总之fastDFS当前版本不是很适合在K8S平台部署,官方好像也很久没更新了。。。可以理解为不适合吧
本次部署的版本为6.0.7,镜像基于alpine制作。部署1个tacker和2个storage,部署2套。
先部署headlessservice,给后面的statefulset服务用.这里有一点,storage在注册到tracker的时候默认是使用的podIP而不会使用clusterIP,所以storage是支持使用域地址的,因而直接使用了无头的网络服务,通过域地址链接到tracker。docker上部署的时候一般使用–network=host,也是这个原因。
apiVersion: v1
kind: Service
metadata:
name: fdfs1
labels:
name: fdfs1
spec:
clusterIP: None
ports:
- name: tracker
port: 22122
targetPort: 22122
selector:
app: fdfs1
---
apiVersion: v1
kind: Service
metadata:
name: fdfs2
labels:
name: fdfs2
spec:
clusterIP: None
ports:
- name: tracker
port: 22122
targetPort: 22122
selector:
app: fdfs2
再创建nodePort给外网访问storage的文件时使用
apiVersion: v1
kind: Service
metadata:
name: fdfs1-ngx
labels:
app: fdfs1-ngx
spec:
type: NodePort
ports:
- name: group1
port: 8888
targetPort: 8888
nodePort: 30009
- name: group2
port: 8889
targetPort: 8889
nodePort: 30010
selector:
app: fdfs1
---
apiVersion: v1
kind: Service
metadata:
name: fdfs2-ngx
labels:
app: fdfs2-ngx
spec:
type: NodePort
ports:
- name: group1
port: 8888
targetPort: 8888
nodePort: 30011
- name: group2
port: 8889
targetPort: 8889
nodePort: 30012
selector:
app: fdfs2
部署fdfs1
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: fdfs1
labels:
app: fdfs1
spec:
serviceName: fdfs1
replicas: 1
selector:
matchLabels:
app: fdfs1
template:
metadata:
labels:
app: fdfs1
spec:
containers:
- name: tracker
image: pilgrima/fastdfs:6.0.7
imagePullPolicy: IfNotPresent
args: ["tracker"]
ports:
- containerPort: 22122
- name: fdfsstorage
image: pilgrima/fastdfs:6.0.7
imagePullPolicy: IfNotPresent
args: ["storage"]
env:
- name: GROUP_NAME
value: group1
- name: TRACKER_SERVER2
value: fdfs2-0.fdfs2.default.svc.cluster.local:22122
livenessProbe:
tcpSocket:
port: 23000
initialDelaySeconds: 50
volumeMounts:
- name: storagedata1
mountPath: /var/local/fdfs/storage/data
- name: fdfsstorage2
image: pilgrima/fastdfs:6.0.7
imagePullPolicy: IfNotPresent
args: ["storage"]
env:
- name: GROUP_NAME
value: group2
- name: PORT
value: "23001"
- name: LISTEN_PORT
value: "8889"
- name: TRACKER_SERVER2
value: fdfs2-0.fdfs2.default.svc.cluster.local:22122
livenessProbe:
tcpSocket:
port: 23001
initialDelaySeconds: 50
volumeMounts:
- name: storagedata2
mountPath: /var/local/fdfs/storage/data
volumes:
- name: storagedata1
nfs:
server: 192.168.177.70
path: /data1/fastdfs/storage_data1/data
- name: storagedata2
nfs:
server: 192.168.177.79
path: /data1/fastdfs/storage_data2/data
部署fdfs2
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: fdfs2
labels:
app: fdfs2
spec:
serviceName: fdfs2
replicas: 1
selector:
matchLabels:
app: fdfs2
template:
metadata:
labels:
app: fdfs2
spec:
containers:
- name: tracker
image: pilgrima/fastdfs:6.0.7
imagePullPolicy: IfNotPresent
args: ["tracker"]
ports:
- containerPort: 22122
- name: fdfsstorage
image: pilgrima/fastdfs:6.0.7
imagePullPolicy: IfNotPresent
args: ["storage"]
env:
- name: GROUP_NAME
value: group1
- name: TRACKER_SERVER2
value: fdfs1-0.fdfs1.default.svc.cluster.local:22122
livenessProbe:
tcpSocket:
port: 23000
initialDelaySeconds: 50
volumeMounts:
- name: storagedata1
mountPath: /var/local/fdfs/storage/data
- name: fdfsstorage2
image: pilgrima/fastdfs:6.0.7
imagePullPolicy: IfNotPresent
args: ["storage"]
env:
- name: GROUP_NAME
value: group2
- name: PORT
value: "23001"
- name: LISTEN_PORT
value: "8889"
- name: TRACKER_SERVER2
value: fdfs1-0.fdfs1.default.svc.cluster.local:22122
livenessProbe:
tcpSocket:
port: 23001
initialDelaySeconds: 50
volumeMounts:
- name: storagedata2
mountPath: /var/local/fdfs/storage/data
volumes:
- name: storagedata1
nfs:
server: 192.168.177.79
path: /data1/fastdfs/storage_data1/data
- name: storagedata2
nfs:
server: 192.168.177.70
path: /data1/fastdfs/storage_data2/data
由于fastDFS的storage同一group注册的时候不允许storage的IP相同,所以采用了交叉的方式,fdfs1的是group1的storage1和group2的storage2,fdfs2的是group2的storage1和group1的storage2。然后这里用了NFS的挂在方式,用了两台服务器,交叉存放本身也可以防止数据丢失。
坑点
部署过程中遇到了很多坑,具体如下
- 前面说的storage注册到tacker的时候,如tracker和storage在同一个pod下,那么不论使用clusterIP还是使用域地址,tracker会记录到node节点的cni0桥的IP地址,到不了指定的pod。跨Pod的时候会记录到Pod的ip地址。K8S同Pod的容器会共享NET名称空间,因此本次部署容器不指定TRACKER_SERVER的时候会获取本地eth0的IP为tacker_server。这种情况下任何一个pod重新调度了,PodIP必定会发生变化,storage没办法重新恢复,只会注册新的storage到tacker,引发灾难性问题。
- fastDFS的storage启动时会检查tracker_server的连通性,任何一个tracker_server无法连接了都会报错导致当前storage无法启动,因此部署启动时最好采用先部署tracker后部署storage的方式,此处为了减少Pod部署量,保持statefulset的启动顺序,增加了存活性探测livenessProbe,探测storage_port的存活性,在探测到端口为启动时重新启动容器,因为storage启动时会创建目录需要时间,因此需要延迟探测,此处设置了50秒
- 1的pod重新调度导致podIP改变问题出现后,一般情况下可能需要删除整个集群重新部署,这时候相当于重新部署集群,需要等前面的pod都删除完毕后重新创建pod,否则storage可能会注册到之前的tacker上,同时因为集群的验证需要删除storage数据目录上的.fastdfs_vars文件,否则storage会持续报错重启。
至此部署完毕,个人觉得当前版本的fastDFS真心不适合到K8S部署,下次试一下go-fastdf和minio试试。