容器
对于容器,它首先是一个相对独立的运行环境,在这一点有点类似于虚拟机,但是不像虚拟机那样彻底。在容器内,应该最小化其对外界的影响,比如不能在容器内把宿主机上的资源全部消耗,这就是资源控制。
-
容器与虚拟机
容器和虚拟机之间的主要区别在于虚拟化层的位置和操作系统资源的使用方式。
容器与虚拟机拥有着类似的使命:对应用程序及其关联性进行隔离,从而构建起一套能够随处运行的自容纳单元。此外,容器与虚拟机还摆脱了对物理硬件的需求,允许我们更为高效地使用计算资源,从而提升能源效率与成本效益。
虚拟机会将虚拟硬件、内核(即操作系统)以及用户空间打包在新虚拟机当中,虚拟机能够利用“虚拟机管理程序”运行在物理设备之上。虚拟机依赖于hypervisor,其通常被安装在“裸金属”系统硬件之上,这导致hypervisor在某些方面被认为是一种操作系统。一旦 hypervisor安装完成, 就可以从系统可用计算资源当中分配虚拟机实例了,每台虚拟机都能够获得唯一的操作系统和负载(应用程序)。简言之,虚拟机先需要虚拟一个物理环境,然后构建一个完整的操作系统,再搭建一层Runtime,然后供应用程序运行。
对于容器环境来说,不需要安装主机操作系统,直接将容器层(比如 LXC 或 libcontainer)安装在主机操作系统(通常是 Linux 变种)之上。在安装完容器层之后,就可以从系统可用计算资源当中分配容器实例了,并且企业应用可以被部署在容器当中。但是,每个容器化应用都会共享相同的操作系统(单个主机操作系统)。容器可以看成一个装好了一组特定应用的虚拟机,它直接利用了宿主机的内核,抽象层比虚拟机更少,更加轻量化,启动速度极快。
相比于虚拟机,容器拥有更高的资源使用效率,因为它并不需要为每个应用分配单独的操作系统——实例规模更小、创建和迁移速度也更快。这意味相比于虚拟机,单个操作系统能够承载更多的容器。云提供商十分热衷于容器技术,因为在相同的硬件设备当中,可以部署数量更多的容器实例。此外,容器易于迁移,但是只能被迁移到具有兼容操作系统内核的其他服务器当中,这样就会给迁移选择带来限制。
因为容器不像虚拟机那样同样对内核或者虚拟硬件进行打包,所以每套容器都拥有自己的隔离化用户空间,从而使得多套容器能够运行在同一主机系统之上。我们可以看到全部操作系统层级的架构都可实现跨容器共享,惟一需要独立构建的就是二进制文件与库。正因为如此,容器才拥有极为出色的轻量化特性。
-
容器技术构架
- 服务器层
当运行容器镜像时,容器本身需要运行在传统操作系统之上,而这个操作系统既可以是基于物理机,也可以是基于 VM。服务器层包含了这两种场景,泛指了容器运行的环境,同时容器并不关心服务器层如何提供和管理,它的期望只是能获得这些服务器资源。
- 资源管理层
资源管理包含了服务器、操作系统等资源的管理。其中如果是物理服务器的话,需要涉及物理机管理系统(例如Rocks等);如果是虚拟机的话,需要使用虚拟化平台。
- 运行引擎层
容器运行引擎层主要指常见的容器系统,包括 Docker、rkt、Hyper、CRI-O。这些容器系统的共通作用包括启动容器镜像、运行容器应用和管理容器实例。运行引擎又可以分为管理程序和运行时环境两个模块。 需要注意的是,运行引擎是单机程序,类似虚拟化软件的KVM和Xen,不是集群分布式系统。引擎运行于服务器操作系统之上,接受上层集群系统的管理。
- 集群管理
可以把容器的集群管理系统类和针对 VM 的集群管理系统划等号,都是通过对一组服务器运行分布式应用。而这两者的细微区别在于,VM 的集群管理系统需要运行在物理服务器上,而容器集群管理系统既可以运行在物理服务器上,也可以运行在 VM 上。
- 应用层
泛指所有运行于容器之上的应用程序,以及所需的辅助系统,包括:监控、日志、安全、编排、镜像仓库等等。
-
容器底层技术
容器底层的核心技术包括 Linux 上的名称空间(Namespaces)、控制组(Control groups)、切根(chroot)
名称空间(NameSpace)
名字空间是 Linux 内核一个强大的特性。每个容器都有自己单独的名字空间,运行在其中的应用都像是在独立的操作系统中运行一样。名字空间保证了容器之间彼此互不影响。
- PID
不同用户的进程就是通过 pid 名字空间隔离开的,且不同名字空间中可以有相同 pid。
- Net
网络隔离是通过 Net 实现, 每个 Net 有独立的网络设备, IP 地址, 路由表, /proc/net 目录。这样每个容器的网络就能隔离开来。
- IPC
容器中进程交互还是采用了 Linux 常见的进程间交互方法(interprocess communication – IPC), 包括信号量、消息队列和共享内存等。然而同 VM 不同的是,容器的进程间交互实际上还是 host 上具有相同 pid 名字空间中的进程间交互,因此需要在 IPC 资源申请时加入名字空间信息,每个 IPC 资源有一个唯一的 32位 id。
- Mount
类似 chroot,将一个进程放到一个特定的目录执行。Mount 允许不同名称空间的进程看到的文件结构不同,这样每个名称空间中的进程所看到的文件目录就被隔离开了。同 chroot 不同,每个名称空间中的容器在 /proc/mounts 的信息只包含当前名称空间的挂载点。
- UTS
UTS(“UNIX Time-sharing System”) 允许每个容器拥有独立的 hostname 和 domain name, 使其在网络上可以被视作一个独立的节点而非主机上的一个进程。
- User
每个容器可以有不同的用户和组 id, 也就是说可以在容器内用容器内部的用户执行程序而非主机上的用户。
控制组(Control groups)
Cgroups 是 Linux 内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源的机制。
- 任务(task)
在cgroups中,任务就是系统的一个进程
- 控制族群(control group)
控制族群就是一组按照某种标准划分的进程。Cgroups中的资源控制都是以控制族群为单位实现。一个进程可以加入到某个控制族群,也从一个进程组迁移到另一个控制族群。一个进程组的进程可以使用cgroups以控制族群为单位分配的资源,同时受到cgroups以控制族群为单位设定的限制
- 层级(hierarchy)
控制族群可以组织成hierarchical的形式,既一颗控制族群树。控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性
- 子系统(subsystem)
一个子系统就是一个资源控制器。子系统必须附加(attach)到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制
blkio 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等等)
cpu 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问
cpuacct 这个子系统自动生成 cgroup 中任务所使用的 CPU 报告
cpuset 这个子系统为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点
devices 这个子系统可允许或者拒绝 cgroup 中的任务访问设备
freezer 这个子系统挂起或者恢复 cgroup 中的任务
memory 这个子系统设定 cgroup 中任务使用的内存限制,并自动生成由那些任务使用的内存资源报告
net_cls 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包
perf_event 这个子系统对 cgroup 中的任务进行统一的心跟那个测试
切根(chroot)
chroot(change to root) 其中 root 是根目录的意思,也就是改变(linux 根目录是/,也可以理解为设置)一个程序运行时参考的根目录的位置
chroot 机制因为安全问题才被引入的,但是在 LXC 中却启动了举足轻重的作用,因为 chroot 机制可以指定虚拟根目录,让不同的容器在不同的根目录下工作
不同的容器进程参考的根目录不同,相互直接不影响
不同的容器因为共享linux 底层的文件系统,所以容器集成os的功能,实现轻量级
Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
集装箱 | Docker | |
无关内容 | 集装箱几乎支持所有类型的货物 | 能压缩任何负载和依赖 |
无关硬件 | 标准化的尺寸和交接使得集装箱可以通过货船火车货车运输,用起重机交接不需要换一个容器或者打开集装箱 | 使用操作系统的基本体(像LXC)能一致的跑在几乎任何硬件下,不需要对硬件做额外的修改 |
内容隔离和相互作用 | 不需要关心铁锹会砸坏香蕉。集装箱可以一起堆放一起运输 | 资源、网络和内容的独立避免了依赖问题 |
自动化 | 标准化使得自动化装载卸货和移动变得方便 | 使用标准的操作指令去跑start/stop/commit/search等等。对运营人员:CI、CD、自动化测试、hybrid clouds |
高效 | 不需要打开不需要改动什么,高效的点对点的方式 | 轻量级,几乎没有启动的消耗,高效的移植性和操控性 |
职责分离 | 发货人只需要关心箱子内部的事情,托运人只需要关心箱子外部的东西 | 开发者只需要关心代码层面,运营人员只需要关心服务器的基础环境 |
-
Docker对象
镜像
Docker 镜像就是一个只读的模板。
例如:一个镜像可以包含一个完整的 CentOS 操作系统环境,里面仅安装了 Nginx 或用户需要的其它应用程序。
镜像可以用来创建 Docker 容器。
容器
Docker 利用容器来运行应用。
容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
注意:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。
仓库
仓库是集中存放镜像文件的场所。有时候会把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
-
安装Docker
Docker 的运行环境依赖于 Linux Kernel 3.10+ 与 64 bits CPU,所以推荐使用 CentOS 7 系统。
配置 yum 仓库
确保系统自带的 extras 仓库的正常
[root@CentOS74 yum.repos.d]# yum repoinfo extras
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
Repo-id : extras/7/x86_64
Repo-name : CentOS-7 - Extras - mirrors.aliyun.com
Repo-status : enabled
Repo-revision: 1531861428
Repo-updated : Wed Jul 18 05:06:25 2018
Repo-pkgs : 363
Repo-size : 684 M
Repo-baseurl : http://mirrors.aliyun.com/centos/7/extras/x86_64/, http://mirrors.aliyuncs.com/centos/7/extras/x86_64/
Repo-expire : 21,600 second(s) (last: Wed Aug 1 16:23:39 2018)
Filter : read-only:present
Repo-filename: /etc/yum.repos.d/CentOS-Base.repo
repolist: 363
配置 docker-ce 库
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
使用 yum 命令安装 docker-ce,然后启动服务查看 docker 的版本信息
[root@CentOS74 ~]# docker version
Client:
Version: 18.06.0-ce
API version: 1.38
Go version: go1.10.3
Git commit: 0ffa825
Built: Wed Jul 18 19:08:18 2018
OS/Arch: linux/amd64
Experimental: false
Server:
Engine:
Version: 18.06.0-ce
API version: 1.38 (minimum version 1.12)
Go version: go1.10.3
Git commit: 0ffa825
Built: Wed Jul 18 19:10:42 2018
OS/Arch: linux/amd64
Experimental: false
配置 Docker 镜像加速
[root@CentOS74 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://xet4hxm8.mirror.aliyuncs.com"]
}