架构杂谈《八》
Docker 架构
一、Docker 引擎的三大组件
1)Docker 后台服务(Docker Daemon):是长时间运行在后台的守护进程,是Docker的核心服务,可以通过命令dockerd与它进行交互通信。
2)REST 接口(REST API):程序可以通过REST的接口来访问后台服务或向它发送操作指令。
3)交互式命令行界面(Docker CLI):我们大多数时间都在使用命令行界面与Docker进行交互(以docker为开头的所有命令的操作)而命令行界面又是通过调用REST的接口来控制和操作Docker后台服务的。
Docker 是C/S结构的架构,客户端通过与后台服务交互来编译、运行和发布容器。Docker的客户端可以连接到本机的Docker服务上也可以连接到远程的Docker服务上。Docker客户端是使用REST接口来和后台服务通信的,它通过使用UNIX Socket连接或者网络接口实现。
(1)Docker 后台服务监听REST接口的请求,管理Docker的对象(如:Docker的镜像、容器、网络和磁盘卷)。一个Docker后台服务可以和其他Docker后台服务进行通信。从而对它们进行管理。
(2)Docker客户端(Docker Client)是我们和Docker后台服务交互的主要工具,在使用docker run 命令时,客户端把命令发送到Docker后台服务,再由后台服务执行该命令。Docker客户端可以连接多个后台服务并与它们通信。
(3)Docker仓库(Docker Registry)是用来存储Docker镜像的,Docker Hub和Docker Cloud是所有人都能够使用的公共的Docker仓库。Docker默认从Docker Hub下载镜像,当然我们也可以自己搭建私有仓库。当我们使用 docker pull 或 docker run 命令时,就会从我们配置的 Docker 仓库下载镜像,当使用 docker push 命令时,我们的镜像会被推送到Docker仓库中。
(4)Docker对象(Docker Object)包括镜像、容器、网络、磁盘卷和插件等。我们在使用Docker时,就会创建和使用Docker对象。
a)镜像(image)是只读的指令模板,用于创建Docker容器(container)通常一个镜像会继承另一个镜像,然后扩展自定义的指令,如,我们可以创建一个继承自Ubuntu的镜像,再安装一个 Apache Tomcat服务和自己的应用程序,同时修改些配置使我们的程序能够运行起来。为了创建自己的镜像,我们可以创建一个Dockerfile文件,通过一些简单的指令来定义如何创建和运行镜像,Dockerfile中的每个指令在镜像中都会创建为一个层(layer),当我们修改Dockerfile文件然后重新编译它时,仅有那些被修改的层(layer)才会被重新编译,这就是Docker镜像是轻量级的、体积非常小、速度非常块的原因。
b)容器(container)是镜像运行的一个实例,我们可以使用Docker的API或CLI来创建、运行、停止、移动或者删除容器。我们可以为容器绑定一个或多个网络(network)或挂载一个磁盘卷(volume),也可以通过继承它来创建一个新的镜像。通常一个容器与另一个容器或它的宿主机都是相对独立和隔离的。在容器停止运行后,它其中的所有改变的状态如果没有保存则都会消失。
c)Docker服务(server)允许我们在多个Docker后台服务中伸缩扩展容器,这些容器组成一个拥有多主多从模式的集群。集群中的每个成员都是一个Docker后台服务,它们之间通过Docker接口通信。我们可以通过Docker服务来定义集群的参数,如:集群中容器的副本个数。在默认情况下,集群的负载是面向所有容器节点的。而对于使用者来说,Docker集群就像一个大实例。
(5)命名空间(Namespace),Docker使用命名空间为容器提供了很好的隔离性,当我们运行容器时,Docker会为容器创建一组命名空间,每个容器都是一个独立的命名空间,容器仅仅限制于在自己的命名空间中访问权限。Docker使用了Linux的如下命名空间:
a)pid 命名空间(pid namespace):用来隔离进程的ID空间,使得不同的pid命名空间里的进程ID可以重复且相互之间不受影响。
b)net 命名空间(net namespace):用于管理网络协议栈的多个实例。
c)ipc 命名空间(ipc namespace):用于管理和访问IPC资源。
d)mnt 命名空间(mnt namespace):用于管理 文件系统的挂载点。
e)uts 命名空间(uts namespace):用于隔离内核和版本信息。
(6)cgroups(control groups),Docker 采用了一种被称为 cgroups 的技术,实现了不同应用之间的隔离性。让每个应用只能访问属于自己的资源。cgroups 可以确保将可用的硬件资源共享给所有容器,并且可以对容器限制硬件资源,如:可以限制每个容器访问的内存大小。
(7)UnionFS(Union File Systems),是Docker在创建层时采用的文件系统。这种文件系统使Docker变得很轻量级并且执行速度非常快。Docker可以使用多种类型的UnionFS,如:AUFS、vfs、btrfs和DeviceMapper。
(8)容器格式(container format),Docker 将namespace、contor groups 和 UnionFS 封装成 container format,我们将其称为容器,默认的容器类型是libcontainer。
二、Docker的安装
(1):Ubuntu Docker 安装:https://www.runoob.com/docker/ubuntu-docker-install.html
(2):Centos Docker 安装:https://www.runoob.com/docker/centos-docker-install.html
(3):Windows Docker 安装:https://www.runoob.com/docker/windows-docker-install.html
(4):MacOS Docker 安装:https://www.runoob.com/docker/macos-docker-install.html
三、Docker 的简单使用
https://www.runoob.com/docker/docker-hello-world.html
四、容器化项目
Docker 为应用程序的打包和运行提供了一种便捷的方式,使用Docker容器进行构建、运行、停止、启动、修改、更新等操作都非常简单,容器化技术也可以让应用程序像云环境的部署变得更为高效,再加上容器本身已经包含应用程序运行所需的大部分依赖,所以运行容器的操作系统也能很好的瘦身,从而运行更快,占用资源更少。
1)传统的应用部署
传统的应用程序部署为直接将应用程序安装到宿主计算机的文件系统上,然后编写命令脚本来运行它。从应用程序的视角来看,其环境包括宿主机上的操作系统、运行环境、文件系统、网络配置、端口及各种依赖等。
要让应用程序运行起来,通常需要安装与应用程序搭配的额外软件包,一般来说,这不是问题。但在某些情况下,可能想在同一个系统上运行相同软件包的不同版本,这可能会引起冲突。应用程序与应用程序之间也会以某种方式发生冲突。如果应用程序是服务,则它可能会默认绑定特定的网络端口。在服务启动时,它可能还会读取公共配置文件,这会导致无法在同一宿主机上运行该服务的多个实例,或者非常棘手,这还让那些想要绑定到同一端口的其他服务难以运行。直接在宿主机上运行应用程序还有一个缺点,那就是难以迁移应用程序。如果宿主机需要关机或者应用程序需要更多的计算能力,那么从宿主计算机上获取所有依赖并将其迁移到另一台宿主机上也相当困难。
2)将应用程序部署到虚拟机上
使用虚拟机来运行应用程序,能够避免直接在宿主机操作系统上运行应用程序所带来的麻烦。虚拟机是位于宿主机之上的,它作为独立的系统运行,同时包含了自己的内核、文件系统、网络系统等。这样可以很好地将应用程序和宿主机的操作系统隔离开来,减少了资源、网络、端口等的冲突,因此不会出现那种直接在宿主机上运行应用程序而产生的弊端 。
比如,可以在宿主机上启动 5 个不同的虚拟机来运行 5 个相同的应用程序,虽然每个虚拟机上的服务监昕了同一个端口号,但是因为每个虚拟机拥有不同的 IP 地址 , 所以并不会引起冲突 。
又比如,由于各种原因,如果需要关闭宿主计算机,可以将虚拟机迁移到其他宿主机上或者直接关闭虚拟机并在新宿主机上再次启动它。
然而, 一个虚拟机运行一个应用程序的缺点是耗费资源。我们的应用程序可能只需要几十兆的磁盘空间来运行,但是整个虚拟机要耗费 GB 级别的空间 。更严重的是虚拟机的启动时间和 CPU 的使用肯定会比应用程序自身消耗得多很多。
容器提供了一种在宿主机上或虚拟机内直接运行应用程序的方式,这种方式能使应用程序运行更快、可移植性更好,更具有扩展性。
3)容器化部署
容器化部署应用具有灵活、高效的使用资源,容器可以包含其所需的全部文件,如同在虚拟机上部署应用程序一样,可以拥有自己的配置文件和依赖库,还可以拥有自己的网络接口。 因此,与在虚拟机上运行应用程序一样,容器化应用比直接安装的应用程序更容易迁移,而且因为应用程序所运行的每个容器均拥有独立的网络接口,所以也不会出现争用同一端口的问题 。
容器在启动时间、磁盘空间占用和 CPU 处理能力方面更具有优势,因为它既没有运行独立的操作系统,也没有包含运行整个操作系统所需的大量软件。它只包含了应用程序运行所需的软件,以及其他想随容器一起运行的工具和少量描述容器的元数据。容器的管理工具也比较完善,目前比较主流的管理工具有 : Swarm、 Kubernetes 和 Apache Mesos 。
(1) Swarm 是 Docker 的原生集群工具,它使用标准的 Docker API,这意味着容器能够使用 docker run 命令启动, Swarm 会选择合适的主机来运行容器,这也意味着其他使用 Docker API的工具比如 Compose 也能在 Swarm 上使用,从而利用其进行集群而不是在单个主机上运行 。
(2) Kubemetes (经常被缩写成 K8s )是 Google 开源的一套自动化容器管理平台,前身是 Borg ,用于容器的部署、自动化调度和集群管理。目前 Kubemetes 有以下特性:容器的自动化部署、自动化扩展或者缩容、自动化应用及服务升级、容器成组,对外提供服务,支持负载均衡 、 服务的健康检查、自动重启。
(3)Apache Mesos 是由加州大学伯克利分校的 A岛。Lab 首先开发的一款开源集群管理软件,支持 Hadoop 、Elasticsearch、 Spark、 Storm 和 Kafka 等应用架构 。
说明:
1、参考书籍:《分布式服务架构:原理、设计与实战》
2、如有不合适的地方请反馈。综合后更改。
3、https://www.runoob.com/docker/docker-tutorial.html(Docker 入门教程)
4、Docker:https://www.docker.com/