本章内容:
1、container是什么?
2、LXC技术介绍
3、namespaces-名称空间,实现资源隔离
4、容器的资源分配--Cgroup,实现资源分配
5、LXC与dockers
-------------------------------------------------------------------
基于虚拟化基础知识,我们这一节开始介绍docker技术的相关内容:docker技术可以理解为我们所学习的虚拟化基础知识的一个延申;
1、container是什么?
容器是一种基础工具;泛指任何可以用于容纳其他物品的工具,可以部分或完全封闭,被用于容纳、存储、运输物品;物体可以被放置在容器中,而容器则可以保护内容物;
人类使用容器的历史至少有十万年,甚至可能有数百万年的历史
容器类型:
瓶、罐、箱、篮、桶、袋、瓮、碗、柜、鞘
2、LXC技术介绍
在了解LXC之前,我们先回顾下主机虚拟化技术:主机虚拟化分为两类:
type-I、type-II(有VMM管理平台)
不管是哪一类,我们都需要通过虚拟技术实现一个系统平台,目的就是为了在这个系统平台上去运行对应的应用进程(例如httpd),来提供服务;
所以,为了运行一个应用进程,我们不得不在其下面去跑一个内核系统,来支持这个进程的正常运行,如果我们可以跳过这个运行的内核,从而直接去运行一个虚拟机的应用进程,这样岂不是更加节约资源。所以,这样,就出现了我们的容器技术--LXC(LinuX container);
LXC技术的目的:抽调虚拟的内核层;直接去虚拟进程,提供系统硬件设备的资源利用率!
这样的话,就带来对应的问题:如果你想运行两个同样的服务,这样,如何在LXC环境下区分这两个一样的进程呢?如下图:
3、namespaces-名称空间,实现资源隔离
我们知道,Linux的底层内核依靠的是C语言进行开发的,而C语言中有个函数模块namespace就是专门用来进行资源隔离--从内核处开始,进行资源隔离;也可以说是,避免资源冲突;
它是Linux kernel内核默认的功能之一;
隔离的资源如下:
1、独立的主机名和域名--UTS
2、需要有自己的独立的挂载数--Mount
3、IPC隔离,实现进行间通讯--信号、消息队列和共享存储的隔离
4、所有的进程都属于init进程--每个独立空间的init进程要独立隔离
5、为每一个空间微赚一个root用户,对于自己空间而言,是root用户,而对于其他空间而言是普通用户;
6、虚拟自己的专用网卡,或者tcp/ip协议栈,网络隔离;
容器技术需要满足以上隔离条件,才能真正实现;所以,namespaces技术是容器技术的基础,如下图:
【内核开始默认支持6种namespaces的最早的内核版本】
此时,我们就可以基于内核抽调资源,同时使用namespaces技术进行资源隔离,而这种技术,我们就叫做容器技术;
容器技术为了调用这些namespaces资源,namespaces提供了相应的API接口,例如:
clone() 创建新进程。根据系统调用参数来判断哪种类型的namespace被创建,而且它们的子进程也会被包含到namespace中
unshare() 将进程移出某个namespace
setns() 将进程加入到namesp中
4、容器的资源分配--Cgroup,实现资源分配
有了资源隔离,我们就要实现资源分配;内核提供资源分配技术--Control Groups(Cgroups技术)
Cgroups实现资源分配包括:
blkiq:块设备IO
CPU:CPU
cpuacct:CPU资源使用报告
cpuset:多处理器平台上的CPU集合
devices:设备访问
freezer:挂起或恢复任务
memory:内存用量及报告
perf_event:对cgroup中的任务进行统一性能测试
net_cls:CGroup中的任务创建的数据报文的类标识符
Cgroup对应的功能参数:
针对于不同的组,我们使用CGroup技术进行不同的资源分配;(不是大锅饭,而是精细的进行资源分配,满足每个容器的资源利用)
5、LXC与dockers
最早的容器技术来自于BSD的jail技术,目的就是为了实现进程隔离,使得一个进程被攻陷后不会影响到其他进程,这是出于安全的目录;
而Linux将该技术移植到自己的系统之上,叫做vserver(功能类似于chroot),创建一个自己的更目录,区分与当前的目录系统;
我们知道,为了使用Linux的内核资源,namespaces提供了相应的API接口(clone(),unshare(),setns(),);这样就是我们的容器技术;
真正的容器技术--LXC、docker等,则是为namespaces、cgroup封装了一个更好管理的接口;
LXC
这个技术就是最早的容器技术;它方便了容器的管理,例如:
lxc-create 可以用来创建虚拟的用户空间; template 可以用来创建模板【模板可以选择应用创建在那些不同的发型版系统上】
然后,我们需要找到一个目录空间,将这个目录制定为该用户空间的根目录,应用则运行在这个所谓的“根目录”下,这就是所谓的容器技术;
lxc技术对于容器技术的发张功不可没,但是它有着与生俱来的缺点--无法实现大规模部署;
于是,出现了docker技术;
docker
为了解决lxc对于批量化管理容器的缺陷,我们对lxc进行二次封装,这样得到的管理工具就是我们的docker了;
docker的工作原理:
docker环境下,我们将一个系统所需要的所有的文件集中打包,这就是一个镜像文件,我们将这个镜像放在仓库中,而这个镜像文件可以不是系统,而且可以是具体的服务文件,比如NGINX服务文件;
然后将这个镜像文件从“仓库”中下载到本地,运行run命令,这样就可以启动这个仓库(类似于运行了一个命令);
系统在基于一些列的机制对docker启动的容器进行资源份分配;这种环境下,我们运行的docker进程就是一个进程;且多个容器就是多个隔离进程,相互之间不会影响;
如上图:各种进程的运行,运行在自己的独立的容器之中,容器之间相互独立,相互隔离!这样大大加强了进程之间的安全性,且docker下进程所需要的资源,都由docker环境来提供;
批量创建容器:分层构建、灵活挂载的方式来创建容器;
例如,底层提供一个centos,上层运行进程即可。多个进程可以共享一个centos底层即可;然后将服务挂在到两个目录下,就是两个容器!且,挂在的文件是只读文件;然后再在本地目录添加一层,去满足该容器需要修改文件的需求;
这样迁移又会有困难;所以在真正使用的时候,真正数据并不保存于本地,而是存放于后面的共享存储中;
如下图:
另外一个问题则是,如果关联进程启动顺序如何确定?
例如:nmp NGINX MySQL PHP进程运行顺序如何来决定启动?这就涉及到容器的编排问题;常见的解决方案如下:
machine + swarm + compose 来进行系统编排;
mesos + marathon 方案;
kubernetes --> k8s;
以上工具都是用来进行容器进程编排的工具;
容器技术的缺点:
1、不管怎么说,系统启动容器,比直接启动进程是消耗了更多的资源空间;
2、调试工具;本身一个系统下运行多个进程,这些进程使用一套调试工具即可。但是现在进程之间相互隔离,则每个容器都需要提供一套调试工具;
3、调试进程得进入到容器中进行调试,相对于原本只需要在系统下调试,相对而言更加困难!
总结:
容器给运维带来了极大的不便,但是给开发带来了极大的便利,它真正让代码实现了一次编写多环境运行,它极大的节约了软件开发的成本;
这也是当今社会容器技术如此火的原因;
原文地址:https://www.cnblogs.com/BurnovBlog/p/11141129.html