1.数据卷特性
-
Docker 镜像由多个只读层叠加而成,启动容器时,Docker 会加载只读镜像层并在镜像栈顶部添加一个读写层
-
如果运行中的容器修改了现有的一个已经存在的文件,那么该文件将会从读写层下面的的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,次即“写时复制”机制
1.1 写时复制
-
实际上在可写层写入数据时,相当于打开了一个在内存中的swp文件,如果文件内容没有发生改变,那么只会修改这个文件的状态时间,而如果发生了数据修改,那么这个swp文件就会落在现在的可写层中,本质上是从layer1中拷贝到内存中,再从内存中写入可写层,而如果这个文件很大,几个G,那么会占用很大的资源,所以不要再原有的镜像中修改特别大的文件!
-
所以在封装镜像的时候要考虑,不要把那些经常发生改变的文件封装在镜像中,那样来回拷贝会占用非常多的I/O资源,写的时候复制到上层,这就是写时复制
1.2 数据卷意义
关闭并重启容器,其数据不受影响;但删除 Docker 容器,则其改变将会全部丢失
存在的问题
存在于联合文件系统中,不易于宿主机访问
容器间数据共享不便
删除容器其数据会丢失解决方案:“卷”
“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某目录“绑定”
也就是说,宿主机上的目录就是容器内的目录
卷的定义:
卷的定义有很多,只要能将容器内的存储空间剥离出容器的可写层的,就都是卷,可以是目录或者ssh服务等等等
卷的定义:
- 卷的定义有很多,只要能将容器内的存储空间剥离出容器的可写层的,就都是卷,可以是目录或者ssh服务等等等
注意,数据卷不是整个可写层,而是特定的某个目录或者多个目录
2.容器中的数据卷的分类
在 Docker 中,有两种常见的数据卷(volumes)类型:Bind Mount 和 Docker 管理的数据卷(Docker managed volumes)。它们在处理容器中的数据持久化方面有一些区别。
Bind Mount(绑定挂载):
- Bind Mount 是将主机文件系统中的目录或文件直接挂载到容器中的一种方法。
使用 Bind Mount,可以在运行容器时将主机上的目录或文件夹挂载到容器的指定路径上。这意味着容器内部和主机之间的文件更改会相互影响。
Bind Mount 的路径和权限完全由主机决定,容器对其是透明的。
可以使用 -v 或 --volume 选项来创建 Bind Mount。例如:docker run -v /host/path:/container/path my-container
Docker Managed Volumes(Docker 管理的数据卷):
- Docker 管理的数据卷是 Docker 引擎在主机上创建和管理的持久化存储卷。
Docker 管理的数据卷存储在主机的特定位置(通常在 /var/lib/docker/volumes/)。
Docker 管理的数据卷是通过 Docker CLI 或 Docker Compose 创建和管理的,它们与容器解耦,可以在多个容器之间共享。
Docker 管理的数据卷可以具有自己的生命周期,即使容器被删除,数据卷仍然存在。
可以使用 -v 或 --volume 选项来创建 Docker 管理的数据卷。例如:docker run -v my-volume:/container/path my-container
2.1 绑定卷
- 就是在docker run 的时候加个 -v 物理机目录 :容器内目录
- **-v 不光可以绑目录,还可以绑定文件
- 指定共享文件,比如有一百台nginx直接绑定一个共享目录,里面放配置文件啥的
如果和管理卷冲突,-v的优先级比dockerfile的高,而且在容器内的修改只会写在-v的目录下
在原有的基础上进行共享持久化目录,但是目录太长,还需要先inspect查目录在哪,然后再-v 长目录:容器内目录,太磨叽,所以有了
docker run --name roc --volumes-from 容器名 roc/lamp:v1.0** - --volume-from 可以继承其他容器的绑定目录
2.2 docker管理卷
-
不需要管理员,docker去帮我们管理
-
创建——进入——touch——exit——find /var/lib/docker/volumes下可以找到
-
就是在dockerfile中写的volumes会自动帮你在 /var/lib/docker/volumes下的随机目录的_data目录随机关联
但是如果有多个volumes设置就不好固定了,而且固定目录的话被轻易找到很不安全。
也可以docker inspect 容器名 去看 -
当然这样会在 /var/lib/docker/volumes下产生大量的持久化文件
删除可以 docker rm -f -v 容器名 但是要慎用,毕竟是删除
3.存储驱动
Docker 存储驱动 ( storage driver ) 是 Docker 的核心组件,它是 Docker 实现分成镜像的基础
-
1、device mapper ( DM ):性能和稳定性存在问题,不推荐生产环境使用
DM是在容器之前推出的一个分层文件系统,在老版本中没得选,只能用Dm。目前来说overlayfs是碾压的 -
2、btrfs:社区实现了 btrfs driver,稳定性和性能存在问题
社区创建的分层文件系统,基本就Samba用,生产环境中基本见不到,人多了 -
3、overlayfs:内核 3.18 overlayfs 进入主线,性能和稳定性优异,第一选择
在docker中用的只有overlayfs
3.1 overlay
在overlay中,lowerdir就相当于镜像层,upperdir就是可写层,merged就是我们平时看见的观看层
mount -t overlay 挂载点名称 -olowerdir=./low,upperdir=./upper,workdir=./work ./merged
- 创建一个overlay文件系统,在随便一个目录下创建这几个目录,用tree可以验证
work是当前的缓存,不用管
在观看层可以看见可写层和目前观看层的文件,看不见镜像层的,如果要是rm -rf * (观看层的),
可以删除掉观看层和可写层的,镜像层没有权限删除,但是在可写层也有一个1,这个一就相当于是一个屏蔽罩,ll可以看见权限是c----------开头,就表示已经被删除了。看到这就拉到了,不要往下看了
扩展
扩展:
-
CSI: 类似于国家电网的充电桩,CSI就是众多服务,比如nfs,mfs,ssh等等服务都需要遵守的协议,这是一个接口,其他服务都有这个接口,docker也有这个接口,那么就可以对接到docker上,进而进行数据传输,但是在k8s中就有别的接口了。
-
不计代价的情况下,网络的I/O是比磁盘快的。
如果所有带宽拉满,那还是网络快的,因为它的延迟低,但是还是要考虑成本,万兆网卡或者十万兆网卡要比固态硬盘贵的多的多的多 -
目前行业内有两个争论
一种是一个环境的各种服务应该分开放,比如不应该把数据库放在容器内部
一种是all in one ,所有的都放在容器内
原因有两点:- 1.一提到容器虚拟化就会觉得不稳定,一旦数据库的数据丢了就很难搞
- 2.磁盘的I/O问题
联合文件系统需要联合叠加,读取也是一层一层的需要合并在一起看,是一定没有直接写在物理磁盘上快的,哪怕有卷的方案将一些平常读取的数据放在磁盘的目录中,也总是会有一些分层文件放在lib库中,还是有一点差距的
-
在大型关系型数据中怎么自愈的问题
传统服务中Apache或者nginx死就死了,在启动就是了,没有太多的关系依赖,但是容器中数据库死了再启动要涉及到数据恢复,如果文件出现问题的话,很可能会导致数据库启动不成功,所以阿里目前在开发云数据库,这种数据库的恢复不是很方便,但是MySQL官方目前已经在k8s中编写出一套初始过程了,官方还是支持容器化的 -
语言性能:编译刑语言性能远大于解释型语言
C语言——c++——R语言——golang(他多核心),java——。。。。。。——python(效率高,累积木,啥都有,调用就行,但是他性能比pool还低) -
垃圾回收:进程申请占用内存,把数据写进去,在C语言中是需要管理员自己去释放内存的,golang和Java就会自动帮你内存回收和释放(GC),但是他会短暂的暂停一下去回收,所以它的性能不如C语言