容器技术介绍和特性
容器技术和 Docker 介绍
容器和虚拟机,物理主机

容器和虚拟机技术比较

传统虚拟机是虚拟出一个主机硬件,并且运行一个完整的操作系统 ,然后在这个系统上安装和运行软件
容器内的应用直接运行在宿主机的内核之上,容器并没有自己的内核,也不需要虚拟硬件,相当轻量化
每个容器间是互相隔离,每个容器内都有一个属于自己的独立文件系统,独立的进程空间,网络空间,用户空间等,所以在同一个宿主机上的多个容器之间彼此不会相互影响
容器和虚拟机比较

资源利用率更高: 开销更小,不需要启动单独的虚拟机OS内核占用硬件资源,可以将服务器性能压榨至极致.虚拟机一般会有5-20%的损耗,容器运行基本无损耗,所以生产中一台物理机只能运行数十个
虚拟机,但是一般可以运行数百个容器
启动速度更快: 可以在数秒内完成启动
占用空间更小: 容器一般占用的磁盘空间以MB为单位,而虚拟机以GB
集成性更好: 和 CI/CD(持续集成/持续部署)相关技术结合性更好,实现打包镜像发布测试可以一键运行,做到自动化并快速的部署管理,实现高效的开发生命周期
使用虚拟机是为了更好的实现服务运行环境隔离,每个虚拟机都有独立的内核,虚拟化可以实现不同操
作系统的虚拟机,但是通常一个虚拟机只运行一个服务,很明显资源利用率比较低且造成不必要的性能
损耗,我们创建虚拟机的目的是为了运行应用程序,比如Nginx、PHP、Tomcat等web程序,使用虚拟
机无疑带来了一些不必要的资源开销,而容器技术则基于减少中间运行环节带来较大的性能提升。
容器的核心技术
Namespace
https://man7.org/linux/man-pages/man7/namespaces.7.html
https://en.wikipedia.org/wiki/Linux_namespaces
一个宿主机运行了N个容器,多个容器共用一个 OS,必然带来的以下问题:
怎么样保证每个容器都有不同的文件系统并且能互不影响?
一个docker主进程内的各个容器都是其子进程,那么如果实现同一个主进程下不同类型的子进程?
各个容器子进程间能相互通信(内存数据)吗?
每个容器怎么解决IP及端口分配的问题?
多个容器的主机名能一样吗?
每个容器都要不要有root用户?怎么解决账户重名问题?

namespace是Linux系统的底层概念,在LInux内核层实现,即有一些不同类型的命名空间被部署在内
核,各个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在
宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个
进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件
系统空间、网络空间、进程空间等,目前主要通过以下技术实现容器运行空间的相互隔离:
隔离类型 功能 系统调用参数 内核
版本
MNT Namespace(mount)
提供磁盘挂载点和文件系统的
隔离能力 CLONE_NEWNS 2.4.19
PID Namespace(Process
Identification) 提供进程隔离能力 CLONE_NEWPID 2.6.24
IPC Namespace(InterProcess Communication)
提供进程间通信的隔离能力,
包括信号量,消息队列和共享
内存
CLONE_NEWIPC 2.6.19
Net Namespace(network) 提供网络隔离能力,包括网络
设备,网络栈,端口等 CLONE_NEWNET 2.6.29
UTS Namespace(UNIX
Timesharing System)
提供内核,主机名和域名隔离
能力 CLONE_NEWUTS 2.6.19
User Namespace(user)
提供用户隔离能力,包括用户
和组 CLONE_NEWUSER 3.8
Pid namespace
- 不同用户的进程就是通过Pid namespace 隔离开的,且不同namespace 中可以有相同Pid。
- 有了Pid namespace, 每个namespace 中的Pid 能够相互隔离。
net namespace
- 网络隔离是通过net namespace 实现的, 每个net namespace 有独立的network devices, IPaddresses, IP routing tables, /proc/net 目录。
- Docker 默认采用veth 的方式将container 中的虚拟网卡同host 上的一个docker bridge: docker0连接在一起。
ipc namespace
- Container 中进程交互还是采用linux 常见的进程间交互方法(interprocess communication –IPC), 包括常见的信号量、消息队列和共享内存。
- container 的进程间交互实际上还是host上具有相同Pid namespace 中的进程间交互,因此需要在IPC 资源申请时加入namespace 信息- 每个IPC 资源有一个唯一的32 位ID。
mnt namespace
mnt namespace 允许不同namespace 的进程看到的文件结构不同,这样每个namespace 中的进程所看到的文件目录就被隔离开了
uts namespace
UTS(“UNIX Time-sharing System”) namespace允许每个container 拥有独立的hostname 和domain name, 使其在网络上可以被视作一个独立的节点而非Host 上的一个进程。
user namespace
每个container 可以有不同的user 和group id, 也就是说可以在container 内部用container 内部的用户执行程序而非Host 上的用户。
范例:内核的 namespace
[root@master1 ~]# [root@master1 ~]# uname -r 5.14.0-611.5.1.el9_7.x86_64 [root@master1 ~]# grep -A10 CONFIG_NAMESPACES /boot/config-5.14.0-611.5.1.el9_7.x86_64 CONFIG_NAMESPACES=y CONFIG_UTS_NS=y CONFIG_TIME_NS=y CONFIG_IPC_NS=y CONFIG_USER_NS=y CONFIG_PID_NS=y CONFIG_NET_NS=y CONFIG_CHECKPOINT_RESTORE=y CONFIG_SCHED_AUTOGROUP=y CONFIG_RELAY=y CONFIG_BLK_DEV_INITRD=y
Control groups
Linux Cgroups的全称是Linux Control Groups,是Linux内核的一个功能.最早是由Google的工程师(主要是Paul Menage和Rohit Seth)在2006年发起,最早的名称为进程容器(process containers)。
在2007年时,因为在Linux内核中,容器(container)这个名词有许多不同的意义,为避免混乱,被重
命名为cgroup,并且被合并到2.6.24版的内核中去。自那以后,又添加了很多功能。
如果不对一个容器做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug
程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资
源分配限制,比如CPU、内存等
Cgroups 最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽
等等。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(比如:将进程挂起和恢复等操
作)。
Cgroups在内核层默认已经开启,从CentOS 和 Ubuntu 不同版本对比,显然内核较新的支持的功能更多。
范例
[root@master1 ~]# grep CGROUP /boot/config-5.14.0-611.5.1.el9_7.x86_64 CONFIG_CGROUPS=y # CONFIG_CGROUP_FAVOR_DYNMODS is not set CONFIG_BLK_CGROUP=y CONFIG_CGROUP_WRITEBACK=y CONFIG_CGROUP_SCHED=y CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_RDMA=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_HUGETLB=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_PERF=y CONFIG_CGROUP_BPF=y CONFIG_CGROUP_MISC=y # CONFIG_CGROUP_DEBUG is not set CONFIG_SOCK_CGROUP_DATA=y CONFIG_BLK_CGROUP_RWSTAT=y CONFIG_BLK_CGROUP_IOLATENCY=y CONFIG_BLK_CGROUP_FC_APPID=y CONFIG_BLK_CGROUP_IOCOST=y # CONFIG_BLK_CGROUP_IOPRIO is not set # CONFIG_BFQ_CGROUP_DEBUG is not set CONFIG_NETFILTER_XT_MATCH_CGROUP=m CONFIG_NET_CLS_CGROUP=y CONFIG_CGROUP_NET_PRIO=y CONFIG_CGROUP_NET_CLASSID=y # CONFIG_DEBUG_CGROUP_REF is not set
浙公网安备 33010602011771号