容器虚拟化原理

目录

      • 容器简介
      • 容器技术优缺点
      • 容器的组成
      • 基本技术
      • namespace
        • 创建namespace的三种方法
        • PID namespace
        • IPC namespace
        • mount namespace
        • network namespace
        • UTC namespace
      • cgroup(control group)
      • rootfs
        • 镜像分层
      • 容器创建原理

容器简介

容器是一种打包应用及其运行环境的方式,为应用打包所有软件及其所依赖的环境,并且可以实现跨平台部署,它是一系列内核特性的统称。

容器技术优缺点

相比先前的各种技术,容器技术具有以下优点。

轻量化: 相比虚拟机,容器提供了更小的镜像,因此可以更快速地对容器进行构建和启动。容器更适合需要批量快速上线和快速弹性伸缩的应用。

细粒度(资源管控): 容器是一个沙箱运行进程,这个沙箱起到了细粒度管控资源的作用。在创建容器时,可以指定CPU、内存及I/O资源。在运行容器时强制执行这些资源限制,可防止容器占用其他资源。

高性能(资源利用率高): 容器使用更轻量级的运行机制,它是一种操作系统级别的虚拟化机制。由于容器是以进程形态运行的,因此其性能更接近裸机的性能。对于对性能有较高要求的应用,如高性能计算等,容器更为合适。

环境一致性: 容器实现了操作系统的解耦,它打包了整个操作系统,保证应用运行的本地环境和远端环境的高度一致性,从而保证一次容器打包可以到处运行,对跨平台、不同环境的应用部署有显著的帮助。

管理便捷性: 使生命周期管理,包括迁移、扩展、运维等更加便捷。

但不可否认,安全隔离一直是容器技术的一大弊端。容器只是运行在宿主机上的一种特殊进程,因此多个容器之间共享的还是同一台宿主机的操作系统内核,从而大大增加了安全攻击面。

容器的组成

容器=cgroup+namespace+rootfs+容器引擎(用户态工具)

  • cgroup:资源控制
  • namespace:访问隔离
  • rootfs:文件系统隔离
  • 容器引擎:生命周期控制

基本技术

一个应用程序的运行环境的总和(内存中的数据、寄存器里的值、堆栈中的指令、被打开的文件,以及各种设备的状态信息的集合)被称为一个进程。容器技术的核心就是通过约束和修改进程的动态表现,从而为其创造出一个逻辑的“边界”。

容器技术本质上为应用解决了两个核心问题:应用的资源隔离限制和应用的可移植性(即在新的环境中可以直接运行)。容器将替代进程,成为今后主流的应用运行形态。

namespace

namespace是Linux用来隔离系统资源的方式,它使得PID、IPC、network等系统资源不再是全局性的,而是属于特定namespace 的,其中的进程好像拥有独立的“全局”系统资源。每个namespace里面的资源对其他namespace都是透明的、互不干扰的,改变一个namespace中的系统资源只会影响当前namespace中的进程,对其他namespace中的进程没有影响。

本质上,namespace建立了系统的不同视图,此前的每一项全局资源都必须被包装到namespace数据结构中。

创建namespace的三种方法
  • 在用fork或clone系统调用创建新进程时,可通过特定的选项控制,是与父进程共享命名空间,还是建立新的命名空间。
  • setns系统调用让进程加入已经存在的namespace中,Docker exec就采取了该方法。
  • unshare系统调用让进程离开当前的namespace,加入新的namespace中。
PID namespace

如果在调用clone时设定了CLONR_NEWPID,就会创建一个新的PID namespace,创建的新进程将会成为该namespace里的第一个进程,在当前PID namespace中这个进程的PID从1开始,该namespace内的进程都将以该进程为父进程,当该进程结束时,其中所有的进程都会结束。

PID namespace 是有层次的,新创建的 namespace 将会是创建该 namespace 的进程所属的namespace的子namespace。子namespace中的进程对父namespace是可见的,一个进程将拥有不止一个PID,其所在的namespace及所有直系祖先namespace中都将有一个PID。系统启动时,内核将创建一个默认的PID namespace,该namespace是所有以后创建的namespace的祖先,因此系统的所有进程在该namespace内都是可见的。

IPC namespace

在一个IPC(Inter-Process Communication 进程间通信) namespace中创建的IPC object对该 namespace 内的所有进程可见,但是对其他 namespace 中的进程不可见,这就使得不同namespace之间的进程不能直接通信。

PID namespace 和 IPC namespace 可以组合使用,只需在调用 clone 系统时同时指定CLONE_NEWPID和CLONE_NEWIPC,这样新创建的namespace就既是一个独立的PID命名空间,又是一个独立的IPC命名空间。不同namespace中的进程彼此不可见,也不能互相通信,这样就实现了进程间的隔离。

mount namespace

每个进程都存在于一个mount namespace中,mount namespace为进程提供了一个文件层次视图,用于让被隔离的进程只看到当前namespace里的挂载点信息。只有在“挂载”这个操作发生之后,进程的视图才会被改变,而在此之前新创建的容器会直接继承宿主机的各个挂载点。

如果不设定这个flag,子进程和父进程将共享一个mount namespace,其后子进程调用mount或umount将会对该namespace内的所有进程可见。如果子进程在一个独立的mount namespace中,就可以调用mount或umount建立一个新的文件层次视图,mount、unmount只对该namespace内的进程可见。该flag配合chroot、pivot_root系统调用,可以为进程创建一个独立的目录空间,chroot实现目录独享,mount namespace实现挂载点独享。

network namespace

如果在调用 clone 时设定了 CLONE_NEWNET,就会创建一个新的 network namespace。network namespace为进程提供了一个完全独立的网络协议栈视图,其包括网络设备接口、IPv4和IPv6协议栈、IP地址路由表、防火墙规则、Socket等。一个network namespace提供了一个独立的网络环境,就跟一个独立的系统一样。**一个物理设备只能存在于一个network namespace中,但它可以从一个 namespace 移动到另一个namespace 中。虚拟网络设备(Virtual Network Device)提供了一种类似于管道的抽象,可以在不同的 namespace 之间建立隧道。利用虚拟网络设备,我们可以建立某个 namepace 与其他 namespace 中物理设备的桥接。**当一个 network namespace 被销毁时,物理设备会被自动移回初始的 network namespace,即系统最开始的namespace中。

UTC namespace

如果在调用clone时设定了CLONE_NEWUTS,就会创建一个新的UTS namespace。一个 UTS namespace 就是一组被 uname 返回的标识符。新的 UTS namespace中的标识符通过复制调用进程所属的namespace的标识符来初始化,clone出来的进程可以通过相关系统调用改变这些标识符,比如调用sethostname来改变该namespace的主机名。

总结来说,Linux中的每个进程都包含以上多种namespace。

一个容器就是一个虚拟的运行环境,它对容器里的进程是透明的,进程会以为自己是直接在一个系统上运行的。实际上,容器在创建容器进程时,指定了这个进程所需启用的一组namespace参数,这样容器进程就只能“看到”当前namespace所限定的资源、文件、设备、状态或配置,而对于宿主机及其他不相关的应用,它就完全看不到了。这时,容器进程就会觉得自己是各自PID namespace里的第1号进程,只能看到各自mount namespace里挂载的目录和文件,只能访问各自network namespace里的网络设备,就好像运行在一个“容器”里面。

Linux namespace机制本身就是为实现容器虚拟化而开发的,它实际上修改了应用进程看待整个系统资源的“视角”,即它的“视线”被namespace做了限制,只能看到某些指定的内容。但对于宿主机来说,这些被隔离的进程与其他进程并没有太大的区别,所以 namespace 提供了一套轻量级、高效率的系统资源隔离方案,其远比传统的虚拟化技术开销小。不过,它也不是完美的,它为内核的开发带来了更大的复杂性,在隔离性和容错性上与传统的虚拟化技术相比也有差距。

cgroup(control group)

cgroup是Linux内核中的一项功能,它可以对进程进行分组,并在分组的基础上限制进程组能够使用的资源上限(如 CPU 时间、系统内存、网络带宽等)。cgroup的作用和namespace不一样,namespace是为了隔离进程之间的资源,而cgroup是为了对一组进程进行统一的资源监控和限制。

cgroup实现了一个通用的进程分组框架,而不同资源的具体管理则是由各个cgroup子系统实现的:

子系统描述
devices设备权限控制
cpuset分配指定的cpu和内存节点
cpu控制cpu占用率
cpuacct统计cpu使用情况
memory限制内存的使用上限
freezer暂停cgroup中的进程
net_cls配置(tc)限制网络带宽
net_prio设置进程的网络流量优先级
huge_tlb限制HugeTLB的使用
pref_event允许perf工具基于cgroup分组做性能检测

cgroup和进程的关系?

Cgroup和进程之间的关系是,Cgroup可以将一组进程组绑定到一个特定的Cgroup中,并对这些进程组的资源使用进行限制和控制。这样,Cgroup实际上是对一组进程进行资源管理的工具。

当一个进程被创建时,它可以被分配到特定的Cgroup中,这样就可以受到该Cgroup所施加的资源限制和控制。这样就实现了对进程的资源隔离和管理。

rootfs

为了实现应用运行环境的一致性,容器使用了 rootfs 技术,这使得容器镜像中打包的内容不只有应用本身,还包括整个操作系统的文件和目录,即应用及其所需的依赖都被封装在一起,实现了应用环境的强一致性。

容器就是一个进程,所以可以通过chroot为容器进程提供一个新的根目录及新的文件系统。为了能够让容器的根目录看起来更像是一个真实的操作系统的根目录,一般会在容器启动时在其根目录下挂载一个完整的操作系统的文件系统,比如Ubuntu 16.04的ISO。这样在容器启动之后,在容器内执行“ls/”命令就可以查看整个根目录下的内容,也就是Ubuntu系统的所有目录和文件。

在Linux中有一个chroot命令,它的作用就是将进程的根目录变更到指定的位置(change root file system)

这个被挂载在容器根目录下,用来为容器进程提供隔离后运行环境的文件系统,就是容器镜像,被称为rootfs(根文件系统)。rootfs只是一个操作系统的文件系统,其中包括文件、配置和目录等,但并不包括操作系统内核。

同一台宿主机上的所有容器,都共享宿主机操作系统的内核。这就意味着,如果容器中的应用程序需要配置内核参数、加载额外的内核模块,以及与内核进行直接的交互等,那么这些都是对宿主机操作系统内核的操作,其对于该宿主机上的所有容器来说是全局操作。

镜像分层

Docker镜像的制作并没有沿用以前制作rootfs的标准流程,而是在镜像的设计过程中引入了层(layer)的概念。用户制作镜像的每一步操作都会生成一个层,整个文件系统的增量机制是基于UnionFS的。UnionFS是Linux内核中的一项技术,它将多个处于不同位置的目录联合挂载到同一个目录下。而Docker就是利用这种联合挂载的能力,将容器镜像里的多层内容呈现为统一的rootfs的。在Docker中使用的UnionFS是通过aufs来实现的,虽然aufs还未进入Linux内核主干,但是它在Ubuntu、Debain等发行版本中均有使用。

以Docker为例,其镜像主要分为三层:

  • 只读层:同期的rootfs最下面五层,以增量的方式分别包含整个文件系统;
  • 可读/写层:容器的rootfs最上面的一层,在没有写入文件之前,这个层是空的。一旦在容器里进行了写操作,由此产生的内容就会以增量的方式出现在这一层中。可读/写层就是专门用来存放修改 rootfs 后产生的增量内容的——无论是增加、删除还是修改产生的增量内容。当使用完这个被修改过的容器之后,还可以使用“docker commit”和“push”命令保存这个被修改过的可读/写层,而只读层里的内容不会有任何变化,这就是增量rootfs的好处。
  • init层:这是 Docker/Kubernetes 单独生成的一个内部层,专门用来存放/etc/hosts、/etc/resolv.conf等配置信息。这些文件本来属于只读层,但是在启动容器时每次都会自动写入一些指定的参数,比如hostname,所以理论上需要在可读/写层对它们进行修改。但这些修改往往只对当前的容器有效,并不希望执行“docker commit”命令时,需将这些信息连同可读/写层一起提交,所以设置了额外的 init 层,init 层的内容在执行“docker commit”命令时会被忽略。

容器创建原理

pid = clone(fun, stack, flags, clone_arg);
(flags: CLONE_NEWPID  | CLONE_NEWNS  |CLONE_NEWUSER | CLONE_NEWNET |CLONE_NEWIPC  | CLONE_NEWUTS |)

通过clone系统调用,并传入各个Namespace对应的clone flag,创建了一个新的子进程,该进程拥有自己的Namespace。根据以上代码可知,该进程拥有自己的pid、mount、user、net、ipc、uts namespace。

echo $pid > /sys/fs/cgroup/cpu/tasks
echo $pid > /sys/fs/cgroup/cpuset/tasks
echo $pid > /sys/fs/cgroup/blkio/tasks
echo $pid > /sys/fs/cgroup/memory/tasks
echo $pid > /sys/fs/cgroup/devices/tasks
echo $pid > /sys/fs/cgroup/freezer/tasks

将代码一中产生的进程pid写入各个Cgroup子系统中,这样该进程就可以受到相应Cgroup子系统的控制。

fun()
{pivot_root("path_of_rootfs/", path);exec("/bin/bash");}

该fun函数由上面生成的新进程执行,在fun函数中,通过pivot_root系统调用,使进程进入一个新的rootfs,之后通过exec系统调用,在新的Namespace、Cgroup、rootfs中执行“/bin/bash”程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/176016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

抽象类的使用—模板设计模式 Java

模板设计模式 一、引入二、改进 一、引入 需求 ① 有多个类,完成不同的任务 job ② 要求统计得到各自完成任务的时间 ③ 请编程实现 >最容易想到的方法,写类,统计时间 AA BB中的 job 方法中是有重复的。 >改进1:每个类中&…

SpringBoot整合EasyExcel实现复杂Excel表格的导入导出功能

文章目录 🎉SpringBoot整合EasyExcel实现复杂Excel表格的导入&导出功能 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系列文章专栏:架构设计📜其他专栏:Java学习路线 Jav…

集成IDE开发环境,Java开发工具IntelliJ IDEA 2023中文

IntelliJ IDEA 2023是一款功能强大的软件,其为程序员提供了一款先进的集成开发环境。它以智能、高效和人性化为主要特点,致力于提高开发人员的生产力,帮助程序员更快、更好地编写代码。IntelliJ IDEA 2023支持多种语言和框架,包括…

继承JsonSerializer+注解实现自定义数据脱敏方案

1、数据脱敏 数据脱敏是一种保护隐私数据的技术,通过将敏感信息转化为非敏感信息来实现对数据的保护,以保护敏感隐私数据的可靠性和安全性。 数据脱敏可以分为可恢复和不可恢复两类: 可恢复类可以通过一定的方式恢复成原来的敏感数据。不可恢复类则无…

村村通工程(Kruskal算法)/最小生成树Kruskal算法【数据结构】

村村通工程(Kruskal算法) 题目描述 "村村通"是国家一个系统工程,其包涵有:公路、电力、生活和饮用水、电话网、有线电视网、互联网等等。 村村通公路工程,是国家为构建和谐社会,支持新农村建设…

【Shell】Shell基础学习

一、shell脚本 (1)第一个shell脚本 #!/bin/bash #this is a comment echo "hello world"一个shell脚本永远以“#!”开头,这是一个脚本开始的标记,它是告诉系统执行这个文件需要用某个解释器,后面的/bin/bash就是指明解释器的具体位置。 “#”开头是注释 …

P8A003-系统加固-系统管理员账户安全

【预备知识】 Administrator 原意为管理人或行政官员或遗产管理人,在计算机名词中,它的意思是系统超级管理员或超级用户。但是在Windows系统中此用户名只在安全模式中使用。 【实验步骤】 网络拓扑:server2008-basic windows server 2008 …

LeetCode [简单]118. 杨辉三角

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 public class Solution {public IList<IList<int>> Generate(int numRows) {List<IList<int>> res new …

交流负载测试使用场景

交流负载测试是一种在特定环境下&#xff0c;对电力设备、汽车电子部件&#xff0c;工业自动化设备、网络设备、家电产品&#xff0c;航空航天设备以及医疗器械等产品进行测试的方法&#xff0c;该测试的目的是评估这些设备在实际运行条件下的性能和可靠性。 1电力设备测试 交…

Zabbix 6.0 详细基础介绍

目录 一、如何选择自己的运维监控平台 1.1 常用的开源运维监控工具 1.1.1 Cacti 1.1.2 Nagios 1.1.3 Ganglia 1.1.4 Centreon 1.1.5 Grafana 1.1.6 Prometheus 1.1.7 Zabbix 1.2 监控工具选型经验 1.2.1 中小企业传统监控选择 Zabbix 1.2.2 云原生监控选择 Prometh…

虚幻学习笔记2—点击场景3D物体的两种处理方式

一、前言 本文使用的虚幻引擎为5.3.2&#xff0c;两种方式分别为&#xff1a;点击根物体和精准点击目标物体。 二、实现 2.1、玩家控制器中勾选鼠标点击事件&#xff1a;这一步很重要&#xff0c;如图2.1.1所示&#xff1a;在自定义玩家控制器中勾 图2.1.1 选该项&#xff0c…

GPT实战系列-GPT训练的Pretraining,SFT,Reward Modeling,RLHF

GPT实战系列-GPT训练的Pretraining&#xff0c;SFT&#xff0c;Reward Modeling&#xff0c;RLHF 文章目录 GPT实战系列-GPT训练的Pretraining&#xff0c;SFT&#xff0c;Reward Modeling&#xff0c;RLHFPretraining 预训练阶段Supervised FineTuning &#xff08;SFT&#x…

Vue 3 面试经验分享

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

docker容器运维操作命令

docker exec &#xff1a;在运行的容器中执行命令 docker exec [OPTIONS] CONTAINER COMMAND [ARG...] OPTIONS说明&#xff1a; -d :分离模式: 在后台运行 -i :即使没有附加也保持STDIN 打开 -t :分配一个伪终端docker ps : 列出容器 docker ps [OPTIONS] OPTIONS说明&#…

【EI会议投稿】第四届物联网与智慧城市国际学术会议(IoTSC 2024)

第四届物联网与智慧城市国际学术会议 2024 4th International Conference on Internet of Things and Smart City 继IoTSC前三届的成功举办&#xff0c;第四届物联网与智慧城市国际学术会议&#xff08;IoTSC 2024&#xff09;将于2024年3月22-24日在河南洛阳举办。 智慧城市的…

<HarmonyOS第一课>应用程序框架 【课后考核】

【习题】应用程序框架 判断题 一个应用只能有一个UIAbility。错误(False)创建的Empty Ability模板工程&#xff0c;初始会生成一个UIAbility文件。正确(True)每调用一次router.pushUrl()方法&#xff0c;页面路由栈数量均会加1。错误(False) 单选题 API9及以上&#xff0c;r…

Oracle ORA12514 监听程序当前无法识别连接描述符中请求的服务

最简单的有可能是你的服务还没有开启&#xff0c;需要启动服务&#xff01;&#xff01;&#xff01;&#xff01; 在连接数据库的时候&#xff0c;有时会遇到一个“ORA12514&#xff1a;监听程序当前无法识别连接描述符中请求的服务”的错误&#xff0c;这个错误其实就是数据…

二十章多线程

概念 有很多工作是可以同时完成的&#xff0c;这种思想放在Java中被称为并发&#xff0c;并发完成每一件事被称为线程。 程序员可以在程序中执行多个线程&#xff0c;每一个线程完成一个功能//与其他线程并发执行&#xff0c;这种机制被称为多线程&#xff0c;并不算所有编程…

Echarts大屏可视化_02 球体模块制作

继续跟着b站大佬pink老师学大屏可视化 球体模块制作 1.球体模块布局 HTML <div class"column"><div class"no"><div class"no-hd"><ul><li>125811</li><li>104563</li></ul></div&g…

Mysql解决随机选取问题

常规的随机选取效率差的原因&#xff1a; 两种解决方法&#xff1a; 总结&#xff1a;