前言
对于原来使用本地目录访问数据的应用程序,比如使用本地磁盘或网络共享盘保存数据的应用系统,如果用户希望把数据放到S3上,则需要修改数据的访问方式,比如修改为使用AWS SDK 或CLI访问S3中存储的数据。
同时在AWS上实现kubernetes集群是很多用户的需求,无论是使用托管服务还是自建kubernetes集群,存储都是kubernetes集群搭建的重点。并且docker的部署方式也让客户程序减少了对于底层环境的依赖。为了让用户原来的应用系统能在不做修改的情况下直接使用Amazon S3服务,需要把S3存储桶作为目录挂载到用户EKS集群中的worker结点上。
这里主要介绍如何利用S3fs将S3存储桶在EKS平台上以sidecar
方式挂载到Amazon EKS的worker实例上的pod中,挂载后需要读写此存储桶的pod都可以对此桶进行读写,以实现共享存储功能。
什么是 S3FS
S3fs是基于FUSE的文件系统,允许Linux和Mac Os X 挂载S3的存储桶在本地文件系统,S3fs能够保持对象原来的格式,S3FS是POSIX的大子集,包括读/写文件、目录、符号链接、模式、uid/gid和扩展属性,与AmazonS3、Google云存储和其他基于S3的对象存储兼容。关于S3fs的详细介绍,请参见:https://github.com/s3fs-fuse/s3fs-fuse
K8s pod 中使用S3FS架构图
前提条件
- 已经搭建完成k8s 集群;
- 镜像仓库,存放构建的kube-s3 镜像;
- 准备好S3存储桶;
- IAM用户具备S3桶读写权限。
实施过程
1.下载S3fs 代码
下载S3fs代码到kubectl 可与k8s master结点交互执行的机器上
1 | # git clone https://github.com/freegroup/kube-s3.git |
2.配置configmap
将configmap_secrets_template.yaml复制到configmap_secrets.yaml并将您的aksk,s3 backet放置在正确的位置
1 | # cd kube-s3/yaml/ |
这里挂载的是test-backut
存储桶的根目录,如果要挂载test-backut/data
目录,可以写成test-backut:/data
3.构建镜像
如果懒得构建,也可以使用我构建好的镜像:chenzz/kube-s3:v1.0
3.1 构建镜像前修改Dockerfile 将 apk del git automake autoconf;
这行注示掉,否则镜像运行时会报错找不到aclocal
命令
3.2 将apline镜像版本修改为alpine:3.13
,默认latest
会报 make: /bin/sh: Operation not permitted
错误
3.3 根据情况修改build.sh脚本,允许执行哪些步骤,以及配置好镜像仓库地址
1 |
|
3.4 修改 docker-entrypoint.sh
经过测试,当需要把另一个存储桶挂载到集群中以替换test-backut
存储桶时,会报错HTTP response code 403, returning EPERM.
根据错误google查找时可能有人会告诉你添加-o url=https://s3-us-west-1.amazonaws.com
参数可以解决问题(s3-us-west-1是你AWS所在区域),但在我的环境中并没有得到解决,需要修改docker-entrypoint.sh
文件添加-o passwd_file="/etc/passwd-s3fs"
参数明确指定IAM key文件位置
1 | /usr/bin/s3fs ${S3_BUCKET} ${MNT_POINT} -d -d -f -o passwd_file="/etc/passwd-s3fs" -o endpoint=${S3_REGION},allow_other,retries=5 |
3.5 构建镜像
1 | # ./build.sh v1.0 |
4.部署
我这里将构建和部署分开了,部署的时候需要修改yaml/daemonset.yaml
文件中的镜像名称
1 | # cat yaml/daemonset.yaml |
1 | # kubectl apply -f yaml/daemonset.yaml |
检查pod是否正常运行
1 | # kubectl get pod |grep s3 |
也可以去任意node节点查看S3fs挂载情况
1 | # df -hT|egrep -v "tmpfs|overlay" |
S3fs已经挂载到了/mnt/data-s3-fs
目录
注:
如果在配置和挂载过程中遇到问题,可以使用docker方式运行进行调试
1 | # docker run -it --name=s3 --cap-add SYS_ADMIN --device /dev/fuse -v /mnt/data-s3-fs:/var/s3:shared docker.chenzz.local/public/kube-s3:v1.0 /bin/bash |
进入容器声明挂载所需参数
1 | # export AWS_KEY=*********** |
1 | # /usr/bin/s3fs ${S3_BUCKET} ${MNT_POINT} -d -d -f -o f2 -o passwd_file=/etc/passwd-s3fs,allow_other,retries=5 |
5.验证S3fs
创建demo pod来验证S3fs是否可以正常工作
1 | # kubectl apply -f yaml/example_pod.yaml |
1 | # kubectl exec -ti test-pd sh |
S3fs挂载到了pod中的/var/s3
目录下,下面来创建文件测试S3fs
1 | # dd if=/dev/zero of=/var/s3/data1/test1G-3 bs=1M count=1000 |
因为k8s运行在AWS,所以挂载S3fs可以得到不错的写入速度,至于AWS之外的环境就没有做测试了,感兴趣的朋友可以测试一下
然后去S3页面查看文件是否存在
S3fs 的不足
通常,S3 无法提供与本地文件系统相同的性能或语义。进一步来说:
- 随机写入或附加到文件需要重写整个对象,优化多部分上传副本
- 由于网络延迟,元数据操作(例如列出目录)性能不佳
- 非 AWS 提供商可能具有最终一致性,因此读取可以暂时产生陈旧数据(AWS自 2020 年 12 月起提供先写后读一致性)
- 没有文件或目录的原子重命名
- 安装同一个存储桶的多个客户端之间没有协调
- 没有硬链接
- inotify 仅检测本地修改,而不检测其他客户端或工具的外部修改