背景:拟在Amazon EC2上部署nodejs应用集群。假设nodejs部署在A和B两台机器上,通过前端的ELB(Elastic Load Balancer)分发请求到A和B机器上,两台机器分别对请求做无状态响应,这样就要求A和B机器存取完全相同的数据。由于nodejs应用需要读写本地硬盘目录(对响应速度要求高,无法采用S3存储),而Amazon目前提供的存储方案中,只有EBS(Elastic Block Storage)存储可以挂载到具体机器上以提供本地路径,所以只能选取EBS作为应用集群的存储位置。但EBS类似SAN,只能挂载到一个EC2实例机器中,如果直接挂到A或B上的话,另一台机器就无法读取其中数据。所以采用的方案是启动第三个EC2实例机器C,将EBS挂载到C机器上后,该机作为NFS服务器共享EBS的挂载目录,A和B机器作为NFS客户端,分别加载共享出来的EBS路径到各自对应目录,从而保证nodejs集群能够实时读写相同的数据。如下图所示:
问题:在C机器上挂在EBS存储卷后,修改/etc/exports文件设置了NFS共享,并且有rw, no_root_squash选项。但在A机器和B机器上通过修改/etc/fstab文件并mount -a后,发现能够加载C机器上的EBS存储到指定目录,但写入文件时提示无权限。
解决办法:确保C机器(NFS服务器)上,EBS挂载路径的所有者,与A和B机器(NFS客户端)上准备写入数据的用户要拥有相同的UID和GID。具体来说,这三台机器都是从Amazon Linux的AMI启动的,所以默认用户都是ec2-user(非root用户)。C机器上EBS挂载点是/data,一开始该目录的所有者和组均为root(因为在根目录下建立目录需要root权限),所以导致在A和B机器上加载该共享目录后,加载目录的所有者和组也均为root用户。这样A和B机器上运行nodejs的ec2-user用户就无法写入数据了。解决的具体办法是在C机器上运行”sudo chmod –R ec2-suer:ec2-user /data”命令后,在A,B机器上重新加载NFS共享目录即可。
参考:How to properly set permissions for NFS folder? Permission denied on mounting end.
目前Amazon EC2上推出了公测版的EFS(Elastic File System)存储,类似NAS,在可以提供本地存储路径的前提下,还可以挂载到多台EC2实例上。但目前只有US West(Oregon)一个区域可用。在EFS全面推出前,采用上述方案,可保证应用集群横向扩展的情况下,依然能存取相同的数据。缺点是C机器是单故障点;但数据存储在单独的EBS上,至少保证数据的生命周期不依赖具体的EC2实例机器。