Docker 为什么出现 解决哪些问题 VS 虚拟机

网友投稿 761 2022-11-30

Docker 为什么出现 解决哪些问题 VS 虚拟机

Docker 为什么出现 解决哪些问题 VS 虚拟机

传统分层架构 vs 微服务

对于微服务来说,有些服务可能依赖于数据,如果你需要依赖于数据存储,依赖于数据库,它推从的就是每个微服务维护自己的数据库,微服务和微服务之间只是通过网络调用去完成通信。

先从应用架构来看,容器解决了什么问题。

左边是单体架构,单体架构有什么特点呢?单体架构其实最早期的时候,开设一个网站,可能就一个war包,所有的业务逻辑都揉在一起。

这种紧耦合应用架构会导致,随着业务的复杂性提升,整个网站的维护成本会变的很高,比如修改一点功能,那么整个部分都得更新。(所有的功能逻辑都糅合在一起)

这样在业务架构上面就需要考虑A服务调用B服务的时候,服务发现怎么做。一般想要调用,那么得知道服务的地址是什么,一般都是IP地址加上端口。所以在服务发布的时候,不管部署在虚拟机还是物理机,要有独立的IP和端口,有一个固定访问的URL。这样将服务发布出去就可以来调用了。

上面就是服务发布所需要了解的。

传统方式是有一个物理机,这个物理机可以将很多应用放上去,这个机器有一个IP但是可以有多个端口,所以可以将很多不同的服务根据端口不同发布到这个机器上面,带来的挑战就是因为IP只有一个,8080端口被占用,多个web服务就需要换端口。

随着时间发展就出现了虚拟化技术,一个物理机很大,我需要部署很多应用,就可以切成不同的虚拟机。每个虚拟机是独立的一个操作系统,这样的话其实就是每一个虚拟机都有自己独立的IP。所以可以在第一个虚拟机里面安装web应用,因为IP不一样可以在第二个虚拟机里面也安装web应用。这样就可以都占用8080端口。

通过这样就将资源做了一个切分,服务可以运行在默认的端口上面,因为都有独立的IP。

虚拟化引入的复杂性使我们运维成本和应用的性能都会有所下降。

有没有轻量级的方法实现这个目的?

传统的服务打包部署都非常简单,因为要将整个系统打包到一起了,一个配置文件和强悍的机器就可以将其启动起来了,但是还是有一些问题,比如一个系统用的功能是比较多的,有些功能用的比较少,对有些功能比较重要,可能要部署多份,那么所有的组件都需要被重复部署。

同时启动慢,调用关系混乱,修改一个bug引入10个bug。

微服务和微服务之间是基于网络调用去通信的,

微服务改造

分离微服务的方法建议∶

审视并发现可以分离的业务逻辑业务逻辑(高内聚,低耦合,看看哪些业务是相对集中的,它们是一套业务逻辑,这些业务逻辑就天然的就应该是同一个组件)寻找天生隔离的代码模块,可以借助于静态代码分析工具

不同并发规模,不同内存需求的模块都可以分离出不同的微服务,此方法可提高资源利用率,节省成本一些常用的可微服务化的组件∶

用户和账户管理授权和会话管理系统配置通知和通讯服务照片,多媒体,元数据等

有些业务模块没有很直接的方法去理解,有些工具可以去做代码扫描,去看哪些代码它们之间包调用的很少,如果两个包完全没有调用,往往意味着它们两个的逻辑是独立的,如果逻辑独立,那么其实它天然的就可以切分为不同的业务

分解原则∶基于 Size, Scope and capabilities

很多时候,我们会去探讨第一要将微服务切分到多维,这样就要探讨微服务的大小了,第二微服务的范围,第三微服务提供的能力。就是一个微服务平台,微服务子系统所支持的功能范围是什么,先确定好功能范围,再确定多维。

举个例子:listio是基于kubernetes上面一个服务网格治理平台,早期追求架构的纯粹性,一个控制面很多组件,好多组件从架构来说非常清晰,设计的非常好,后面就陷入了困境,一个控制面很多组件,当你做系统升级的时候,这个升级就陷入了困境,先升级哪个组件,后升级哪个组件,中间是否会有业务中断,这就会造成很多的困扰。

所以做个取舍,比如一些组件是一个团队维护的,那就合并好了,将一些组件变为一个组件了,这样升级的风险降低了,维护成本降低,这里面没有绝对的原则,完全看你的业务场景。

当去定义一个微服务的时候,功能的切分是一个方面,同时要考虑多种因素,比如团队的范围是什么,以及微服务未来升级的可维护性。

微服务之间通信

点对点:系统里面有很多微服务,这些微服务之间可以彼此通信,微服务都可以对外暴露接口,作为客户端可以直接访问任意一个服务,这些好处是更加自制了,对其他组件依赖少了,缺点如上。

点对点最佳实践是集群内部通过点对点。

通常来说微服务最佳实践就是点对点和api网官结合起来,外部有个客户端,要访问不同点内部服务,它的请求不会直接发到这个服务里面去,而是通过一个集中的api网关发起,这个客户端就直接将请求发到api网关,是一个集中的入口,在它的请求里面无论是通过header还是url来告诉api网关要访问哪个后端服务。那么这样的话api网关就可以将这个服务直接转到后端服务,这样api网关就可以做很多事情,比如说认证,比如说鉴权,比如说审计等,这些事情都可以在api网关当中集中去做掉。

请求给到后端的服务,那么微服务之间也有互相调用,那么它们之间可以互相调用,不要求每次调用都经过api网关。

Docker

基于 Linux 内核的 Cgroup,Namespace,以及Union FS 等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术,由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 以后开始去除 LXC,转而使用自行开发的 Libcontainer,从1.11 开始,则进一步演进为使用 runC 和 Containerd。Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极 大的简化了容器的创建和维护,使得 Docker 技术比虚拟机技术更为轻便、快捷。

虚拟机和容器运行态的对比

来看一个完整的虚拟机技术栈:最下面是服务器,在这个服务器基础之上需要安装一个host os,host os上面是hypervisor(hypervisor是用来启动各个虚拟机的)。这个是在物理机上面需要安装的软件。

要在上面启动一个虚拟机,会去再去启动一个gust os,它会去模拟一个完整的操作系统,如果需要部署应用需要在上面安装中间件,依赖,最后部署应用。

可以看到这里面有两次操作系统,针对虚拟化技术来讲,最大的挑战是 任何问题的分析变的复杂。

比如一个网络问题,可能出现在上面这层,也可能出现在下面这层。调试就变得复杂。然后性能也不会很好,就比如网络,任何的数据包进来要在主机的hostos走一遍,然后gustos再走一遍。由于gustos是一个完整的操作系统,所以需要保留一些资源去支撑这个操作系统。这样资源利用率就降低了,因为会将一部分资源来支撑这个操作系统。

容器就变的简单多了,安装好操作系统之后,上面就是一个轻量级的docker引擎,再上面是就是你的应用了,所以只有一层操作系统。

整个操作系统资源基本上都是给应用的,因为docker engine是不吃资源的,所有资源都是给应用的。

所以相比虚拟机来说性能和资源利用率都提高了。(虚拟机技术需要虚拟一个操作系统的,这就需要完整的操作系统的加载,这个是需要占用内存,要维护系统需要有自己kernel,这块需要占用CPU,所以会有一部分资源来支撑这个操作系统,这些资源是不能给业务使用的,所以从整体来看,资源利用率会比较低)

docker本身就是在主机上面启动进程这样一个过程,所以它就是一个简单的fork,在排查问题的时候也是相对简单的,因为整个技术栈很短。

性能对比

容器秒级启动,甚至更短的毫秒级启动,反正也就是一个fork操作。但马是虚拟机需要分钟级别才启动起来。

对于硬盘使用容器有个非常聪明的办法,容器镜像那块细说,一般来说基础镜像并且还是共享的。

但是虚拟机动不动镜像几百兆,几个G,这样硬盘的使用容器更加占用优势。

容器本来就是在主机上跑的原生的这种进程,你可以将其理解为裸金属的机器上系统性能,如果慢要具体排查一下具体什么问题,比如给的资源少了,网络传输慢了。

虚拟机是弱于物理机的,因为有一个虚拟层,虚拟层意味着针对虚拟化的特殊处理,比如网络包,协议栈可能需要多次处理,这样的性能就不会很好,虚拟机一台机器可能最多支持几十个了,

为什么要用 Docker

更高效的利用系统资源(所有系统资源都是给应用的)更快速的启动时间(任何容器里面运行的应用,它只是在主机上面普通的进程,所以应用启动的时间就是主机启动应用的时间,而不需要启动额外的os)一致的运行环境持续交付和部署更轻松的迁移更轻松的维护和扩展

容器操作

启动:

docker run-it 交互的方式去运行-d 后台运行,以daemon的方式去运行这个服务-p 端口映射-v 磁盘挂载[root@docker ~]# docker run -itd -p 88:80 nginxe70a5541fa9992b1b7b663c359fed63722eff2ce1e29665a6f6bba9993716c0d[root@docker ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESe70a5541fa99 nginx "/docker-entrypoint.?? 3 seconds ago Up 2 seconds 0.0.0.0:88->80/tcp, :::88->80/tcp hardcore_ride

启动已终止容器

docker start

停止容器

docker stop

查看容器进程

docker ps

你只需要通过一条简单的命令就可以按照你的要求,,启动一个新的容器进程。

docker有镜像的概念,就像就像虚拟机的镜像类似。

查看容器细节:

docker inspect

进入容器:

docker attachdocker exec[root@docker ~]# docker exec -it e70a5541fa99 bashroot@e70a5541fa99:/# cat /etc/resolv.conf # Generated by NetworkManagersearch sh1.qingcloud.comnameserver 100.64.7.3

通过 nsenter:

PID=$(docker inspect --format "{{ .State.Pid }}" )$ nsenter --target $PID --mount --uts --ipc --net --pid

拷贝文件至容器内:

docker cp file1 :/file-to-path[root@docker ~]# docker cp file e70a5541fa99:/root@e70a5541fa99:/# exitexit

先将基础镜像从dockerhub上面拉取下来,可以通过env来指定一些环境变量,可以通过add的操作将之前编译好的文件添加到这个容器镜像里面去,那么它实际上做了一个copy,最后通过entrypoint命令来指定容器镜像在运行的时候启动哪个程序。

之后通过构建镜像和推送镜像到镜像仓库,那么就可以使用docker run的命令来拉取这个镜像并且运行了。

容器启动的时候会有一个entrypoint的进程,入口进程,那个进程就是在你的pid namspace里面看到1的进程号,其他进程都是那个进程fork出来的。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Docker NameSpace 对 进程 ID、主机名、用户 ID、文件名、网络和进程间通信等资源隔离
下一篇:Kubernetes Pod 镜像拉取策略 imagePullPolicy
相关文章

 发表评论

暂时没有评论,来抢沙发吧~