Docker(Application Container)学习总结
Docker简介
什么是Docker
Dorcker是一个基于go语言编写的开源的PASS服务(Platform as a Service,平台即服务的缩写),Dorcker是基于Linux内核实现的,最早采用LXC技术(LinuxX Container),LXC是linux原生支持的容器技术,可以提高轻量级的虚拟化技术,Dorcker可以说就是基于LXC发展起来的,提供LXC的高级封装,发展标准的配置方法;后来采用自研技术runc运行容器(1.11.0以后版本);
Docker相比虚拟机的交付速度更快,资源消耗耕地,Docker采用C/S架构,使用远程API来管理与创建Docker容器,其可以轻松实现创建一个 轻量级的、可移植的、自给自足的容器;
Doecker的三大理念是:build(构建)、ship (运输)-> share(共享)、run(运行);
Doecker遵从apache 2.0协议,并通过namespace和cgroup等来提供容器的资源隔离与安全保障等,所以Docker容器 在运行时不需要类似虚拟机的额外资源开销(空运行的虚拟机占用宿主机的一部分额定资源),因此可以大幅提高资源利用率;
Docker的组成
#官网介绍
https://docs.docker.com/get-started/overview/
#官方仓库:
https://hub.docker.com/
名称 | 作用 |
---|---|
Docker 主机(Host) | 一个物理机或者虚拟机,用于运行Docker服务进程与容器 |
Docker 服务端(Server) | Dorcker守护进程,运行Docker容器 |
Docker 客户端(Client) | 客户端 使用docker命令或其他工具调用Docker API |
Docker 仓库(Registry) | 保存镜像的仓库,类似于git或SVN这样的 版本控制系 |
Docker 镜像(Images) | 镜像可以理解为创建实例使用的模板 |
Docker 容器(Container) | 容器是从镜像生成对外提供服务的一个或一组服务 |
Linux Namespace技术
Namespace(命名空间)是Linux系统的底层概念,在内核层实现,即有一些不同类型的命名空间被部署在内核内,各个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术实在一个 进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统空间、网络空间、进程空间等,目前还是通过以下技术实现容器运行空间的相互隔离;
Namespace 类型 | 功能 | 系统调用参数 | 内核版本(Linux) |
---|---|---|---|
Mount Namespace(Mount) | 提供磁盘挂载点和文件系统的隔离能力 | CLONE_NEWNS | 2.4.19 |
UTS Namespace(Inter-Process Communication) | 提高进程间通信的隔离能力 | CLONE_NEWUTS | 2.6.19 |
IPC Namespace(Unix Timesharing System) | 提高主机名隔离能力 | CLONE_NEWIPC | 2.6.19 |
PID Namespace(Process Idenification) | 提高进程隔离能力 | CLONE_NEWPID | 2.6.24 |
Network Namespace(Ntework) | 提高网络隔离能力 | CLONE_NEWNET | 2.6.29 |
User Namespace(user) | 提高用户隔离能力 | CLONE_NEWUSER | 3.8 |
Mount Namespace说明
每个容器都要有独立的根文件系统有独立的用户空间,以实现在容器里面启动服务并且使用容器的运行环境,即一个宿主机是ubantu的服务器,可以在里面 启动一个Centos运行环境的容器,并且在容器里面启动一个Nginx服务,此Nginx运行时使用的运行环境就是Centos系统目录的运行环境,但是在容器里面时不能访问宿主机的资源的,宿主机是使用了chroot技术将容器锁定到一个指定的运行目录中;
IPC Namespace说明
一个容器内的进程间通信,允许一个容器内的不同进程的(内存,缓存等)数据访问,但是不能跨容器访问其他容器的数据。
UTS Namespace说明
UTS Namespace(UNIX Timesharing System:包含了运行内核的名称、版本、底层体系结构类型等信息)用于系统标识、其中包含了hostname和域名domainname,它使得一个容器 拥有属于自己hostname标识,这个主机名称标识独立于宿主机系统和其上的其他容器。
PID Namespace(Process Idenification)说明
Linux系统中,有一个PID进程号为1的进程(init/systemd)是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理其他下属的子进程,那么多个容器的进程PID Namespace隔离化(比如:PID编号重复,容器内的主进程生成与回收子进程等);
Network Namespace说明
每个容器都类型于虚拟机医院有自己的网络环境(网卡、监听端口、TCP/IP协议栈等),Dorcker使用Network Namespace启动一个vethX接口(网卡子接口),这样你的容器将拥有它的桥接IP地址,通常是docker0,而docker0实质就是Linux的虚拟网桥,网桥实在OSI七层模型的数据链路层的网络设备 ,通过MAC地址对网络进行划分,并在不同网络直接传递数据
User Namespace
各个容器内可能都会出现重名的用户和用户组名称,或重复的UID或者GID,docker通过User Namespace允许在各个宿主机内的各个容器空间内创建相同的用户名以及相同的用户UID和GID,只是作用范围仅限制为各自容器内,即A容器内的用户和组B容器内可以有相同的用户和组,但是A容器无法访问B容器内的文件系统,即相互隔离,互补影响,永不相见;
Docker进程说明
进程名称 | 功能 |
---|---|
Containerd | 容器运行环境进程(Containerd-shim)的父进程,其允许在systemd下,作为systemd的子进程,会接受dockerd发送的socket文件,通过读取文件配置,来创建容器 |
Containerd-shim | 封装的容器的运行环境,对应ID的容器进程都作为该进程的子进程,如容器内是nginx服务,那么该运行nginx服务的容器,运行在对应的Containerd-shim进程沙箱内; |
bash | 容器进程,容器实际运行的进程ID,是所有wokerd进程的master进程,其下面的进程均为wokerd进程(工作进程) |
{Containerd-shim} | woker进程,容器实际的工作进程 |
dockerd | docker服务的进程名称,回去调用Containerd来创造容器,其主要功能是通过进程docker-proxy,完成容器的网络环境的运行 |
docker-proxy | 用来生成与维护iptables规则与对应容器的网络信息,如网卡子接口,网桥等信息;生成iptables规则是通过调用内核(kernel)实现,然后通过内核将配置信息与bash进程(master进程)同步与通信交换; |
{docker-proxy} | worker进程,实际容器网络维护的工作进程 |
进程原理与调用流程-图示
Linux Control Groups:
在一个容器 ,如果不对其做任何资源限制,则宿主机允许其占用无限大的内存空间,有时候会因为代码BUG程序会一直申请内存资源,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进程资源分配限制,比如 CPU、内存等资源,Linux Groups最主要的功能就是限制一个进程组能够使用的资源上限,包含:CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先设置,以及将进程挂起和恢复等操作;
验证系统cgroups
Cgroups在内核层默认已经开启,从centos和 ubantu对比结果来看,显然内核交心的ubuntu支持的功能更多;
cgroups模块参数
参数名称 | 功能说明 |
---|---|
blkio | 块设备 IO限制 |
cpu | 使用调度程序为cgroup任务提供CPU的访问 |
cpuacct | 产生cgroup任务的CPU资源 |
devices | 允许或拒绝cgroup任务对设备的访问 |
freezer | 暂停和恢复cgroup |
memory | 设置每个cgroup的内存限制以及产生内存资源报告 |
net_cls | 标记每个网络包以供cgroup方便使用 |
ns | 命名空间子系统 |
perf_evenf | 增加了对每group的检测跟踪的能力,可以检测属于某个特定的group的所有线程以及允许在特定CPU上的线程 |
容器管理工具
目前 主流使用docker工具对容器进行管理,早期使用lxc工具对容器进行管理
LXC管理工具
LXC:Linux Container的简写,可以提供轻量级的虚拟化,以便隔离进程和资源
官网:https://linuxcontainers.org/