该项目要用于生产环境了,完善加固了一下代码,顺便更新一下文章。
在加固项目的代码时候 ,调整了卷创建的顺序,调用docker volume create的时候,就把lv创建出来,并挂载到了本地目录,中间遇到了一个很奇怪的问题,挂载lv代码
1 | err = syscall.Mount(lvdiskname, mountPoint, "xfs", syscall.MS\_NOSUID|syscall.MS\_STRICTATIME, "") |
使用该代码挂载完成后,在命令行执行df -h 命令是无法查看到挂载信息的,代码也没有报错,尝试把lv删除时,会出现 Device busy的错误。数据并没有丢失,可以在容器内正常使用。
google到了 mount namespace的概念。
``
mnt namespace为进程提供独立的文件系统视图。当clone()函数中带有CLONE_NEWNS标志时,新的mnt ns在子进程中被创建,新的mnt ns是一份父mnt ns的拷贝,
但是在子进程中调用mount安装的文件系统,将独立于父进程的mnt ns,只出现在新的mnt ns上
使用syscall.Mount 函数应该是在另一个namespace 中进行了挂载,因此我是无法查看到。
前期的项目需求,需要合理利用宿主机的存储,利用在宿主机部署Agent的方式,实现了基于LVM分配docker数据卷的方式,随着开发的进行,项目想要集成docker compose 完成应用的自动编排,需要在docker compose中为容器创建数据卷并且指定卷大小,之前的采用agent的模式已经无法满足目前的需求。参考docker 官方文档 和 Local-Persist项目,实现了一个基于LVM的volume 插件 docker-volume-plugin-lvm。
docker Volume Plugin 提供了标准的卷管理API,第三方只需要实现这些API就可以了。
插件加载方式,将自己实现的Driver注册,启动main函数,实际上是启动了一个监听端口,sock文件:/var/run/docker/plugins/LVM.sock
1 | func main() { |
查询卷API:
1 | func (driver \*LvmPersistDriver) Get(req volume.Request) volume.Response |
创建卷API:根据入参获取卷名称和卷大小,在LVM的VG中分配LV,并将卷的元数据保存到内存并持久化,若没有设置卷大小,可以设置默认值(目前只能通过代码修改) PS:在使用docker create 命令创建容器时,无法指定卷大小比较坑,还好docker compose支持
1 | func (driver \*LvmPersistDriver) Create(req volume.Request) volume.Response |
func (driver *LvmPersistDriver) Mount(req volume.Request) volume.Response
1 |
|
func (driver *LvmPersistDriver) Unmount(req volume.Request) volume.Response
1 |
|
func (driver *LvmPersistDriver) Remove(req volume.Request) volume.Response
```
具体实现可以参考代码实现。docker-volume-plugin-lvm
代码目前不是很完善,测试代码,部署运行代码 还没有实现。我比较懒。。。