【Docker#2】容器化虚拟化

🌈 个人主页:Zfox_

🔥 系列专栏:Docker

目录

  • [一:🔥 虚拟化 & 容器化](#一:🔥 虚拟化 & 容器化)
    • [🦋 什么是虚拟化、容器化](#🦋 什么是虚拟化、容器化)
    • [🦋 为什么要虚拟化、容器化?](#🦋 为什么要虚拟化、容器化?)
    • [🦋 虚拟化常见类别](#🦋 虚拟化常见类别)
  • [二:🔥 常见虚拟化实现方式](#二:🔥 常见虚拟化实现方式)
    • [🦋 主机虚拟化(虚拟机)实现](#🦋 主机虚拟化(虚拟机)实现)
    • [🦋 容器虚拟化实现](#🦋 容器虚拟化实现)
  • [三:🔥 容器虚拟化基础之 LXC](#三:🔥 容器虚拟化基础之 LXC)
    • [🦋 LXC 是什么?](#🦋 LXC 是什么?)
    • [🦋 LXC 容器操作](#🦋 LXC 容器操作)
  • [四:🔥 共勉](#四:🔥 共勉)

一:🔥 虚拟化 & 容器化

🦋 什么是虚拟化、容器化

物理机:实际的服务器或者计算机。

  • 相对于虚拟机而言的对实体计算机的称呼。
  • 物理机提供给虚拟机以硬件环境,有时也称为"寄主"或"宿主"。

虚拟化:是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。

  • 在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。

容器化:容器化是一种虚拟化技术,又称操作系统层虚拟化(Operating system levelvirtualization),这种技术将操作系统内核虚拟化,可以允许用户空间软件实例(instances)被分割成几个独立的单元,在内核中运行,而不是只有一个单一实例运行。

  • 这个软件实例,也被称为是一个容器(containers)。对每个实例的拥有者与用户来说,他们使用的服务器程序,看起来就像是自己专用的。
  • 容器技术是虚拟化的一种,而 docker是现今容器技术的事实标准

类比理解

  1. 物理机就像一个庄园,独立占用了一块土地,花园都是自己的,其他人无法共享使用。
  2. 虚拟机相当于开发商的一个楼盘,一栋楼一套房子一户人家,共享一块宅基地,共享小区的花园,共享小区的游乐设施
  3. 容器相当于几个人一起合租一套房,共享这套房子的卫生间、共享厨房、共享 WiFì,只有衣服、电脑等私人物品是你自己的。

🦋 为什么要虚拟化、容器化?

我们从上面的历史发展来看,虚拟化和容器化的最主要目的就是资源隔离,随着资源隔离的实现逐渐也带来了更大的收益。

  1. 资源利用率高 :将利用率较低的服务器资源进行整合,用更少硬件资源运行更多业务,降低 IT 支出和运维管理成本。
    • 比如上图中我们的土地直接复用,使用这块土地的人多了,但是成本还是庄园那块地
  2. 环境标准化 :一次构建,随处执行。实现执行环境的标准化发布,部署和运维。
    • 开发过程中一个常见的问题是 环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些bug 并未在开发过程中被发现。
    • 而 Docker 的镜像提供了除内核外完整的运行时环境确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
  3. 资源弹性收缩 :根据业务情况,动态调整计算、存储、网络等硬件及软件资源。
    • 比如遇到双 11 了,把服务扩容 100 个,双 11 过去了, 把扩容的 100 个收回去。
  4. 差异化环境提供 :同时提供多套差异化的执行环境,限制环境使用资源。
    • 比如我的服务一个以来 Ubuntu 操作系统,一个服务依赖 CentOS 操作系统,但是没有预算购买两个物理机,这个时候容器化就能很好的提供多种不同的环境。
  5. 沙箱安全 :为避免不安全或不稳定软件对系统安全性、稳定性造成影响,可使用虚拟化技术构建虚拟执行环境。
    • 比如我在容器里面执行 rm -f/* 不会把整个服务器搞死,也不影响其他人部署的程序使用。
  6. 容器对比虚拟机更轻量,启动更快 :传统的虚拟机技术启动应用服务往往需要数分钟,而 Docker 容器应用,由于直接运行于宿主内核,无需启动完整的操作系统,因此可以做到秒级、甚至毫秒级的启动时间。
    • 大大的节约了开发、测试、部署的时间。docker不需要虚拟内核,所以启动可以更快,相当于 windows 的开机时间省去了。
  7. 维护和扩展容易 :Docker 使用的分层存储以及镜像的技术,使得应用重复部分的复用更为容易,也使得应用的维护更新更加简单,基于基础镜像进一步扩展镜像也变得非常简单。
    • 此外,Docker 团队同各个开源项目团队一起维护了一大批高质量的 官方镜像,既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
    • 比如 docker hub 提供了很多镜像,各个系统的一个命令就可以拿到了,研发也可以自己定制镜像分享给各个产品。

🦋 虚拟化常见类别

虚拟机 :存在于硬件层和操作系统层间的虚拟化技术。

  • 虚拟机通过"伪造"一个硬件抽象接口将一个操作系统以及操作系统层以上的层嫁接到硬件上,实现和真实物理机几乎一样的功能。
  • 比如我们在一台 Windows 系统的电脑上使用 Android 虚拟机,就能够用这台电脑打开 Android 系统上的应用。

容器 :存在于操作系统层和函数库层之间的虚拟化技术。

  1. 容器通过"伪造"操作系统的接口将函数库层以上的功能置于操作系统上。以 Docker 为例,其就是一个基于 Linux 操作系统的 Namespace 和 Cgroup 功能实现的隔离容器,可以模拟操作系统的功能。
  2. 简单来说,如果虚拟机是把整个操作系统封装隔离,从而实现跨平台应用的话,那么容器则是把一个个应用单独封装隔离,从而实现跨平台应用。
  3. 所以 容器体积比虚拟机小很多,理论上占用资源更少M。
  4. 容器化就是应用程序级别的虚拟化技术。
  5. 容器提供了将应用程序的代码、运行时、系统工具、系统库和配置打包到一个实例中的标准方法。容器共享一个内核(操作系统),它安装在硬件上。

JVM 之类的虚拟机 :存在于函数库层和应用程序之间的虚拟化技术。

  • Java 虚拟机同样具有跨平台特性,所谓跨平台特性实际上也就是虚拟化的功劳。
  • 因为 Java 语言是 调用操作系统函数库 的,JVM 就是在应用层与函数库层之间建立一个 抽象层,对下通过不同的版本适应不同的操作系统函数库,对上提供统一的运行环境交给程序和开发者,使开发者能够调用不同操作系统的函数库。

补充:应用程序执行环境分层

  1. 硬件层:提供硬件抽象,包括指令集架构、硬件设备及硬件访问接口
  2. 操作系统层:提供系统调用接口,管理硬件资源
  3. 程序库层:提供数据结构定义及函数调用接口

二:🔥 常见虚拟化实现方式

🦋 主机虚拟化(虚拟机)实现

主机虚拟化的原理是通过在物理服务器上安装一个 虚拟化层 来实现。这个虚拟化层可以在物理服务器和客户操作系统之间建立虚拟机,使得它们可以独立运行。

从软件框架的角度上,根据虚拟化层是直接位于硬件之上还是在一个宿主操作系统之上,将虚拟化划分为 Type1Type2

  • Type1 类的 Hypervisor:是一种系统软件,它充当计算机硬件和虚拟机之间的中介,负责有效地分配和利用由各个虚拟机使用的硬件资源,这些虚拟机在物理主机上单独工作,因此,Hypervisor 也称为 虚拟机管理器
    • 特点 :直接运行在硬件之上,没有宿主机操作系统,Hypervisor 直接控制硬件资源和客户机
    • 典型框架为Xen、VmwareESX
  • Type2 类的 Hypervisor:运行在一个宿主机操作系统之上(Vmware Workstation) 或者 系统里面,Hypervisor 作为宿主机操作系统中的一个应用程序,客户机就是在宿主机操作系统上的一个进程。

🦋 容器虚拟化实现

容器虚拟化,有别于主机虚拟化,是操作系统层的虚拟化。

基本原理 :通过 namespace 进行各程序的隔离,加上 cgroups 进行资源的控制,以此来进行虚拟化。

🎀 Namespace(命名空间)

  • 定义:namespace 是 Linux 内核用来隔离内核资源的方式。

  • 作用:实现进程、文件系统、用户等资源的隔离。

  • 具体实现:通过将一个或多个进程指定在同一个namespace中,使得这些进程只能看到与自己相关的资源。

注意:Linux namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个 namespace 中的系统资源只会影响当前namespace 里的进程,对其他 namespace 中的进程没有影响。

Namespace 系统调用参数 隔离的全局系统资源 内核版本
UTS CLONE_NEWUTS 主机名和域名 2.6.19
IPC CLONE_NEWIPC 信号量、消息队列和共享内存 -- 进程间通信 2.6.19
PID CLONE_NEWPID 进程编号 2.6.24
Network CLONE_NEWNET 网络设备、网络栈、端口等 2.6.29
Mount CLONE_NEWNS 文件系统挂载点 2.4.19
User CLONE_NEWUSER 用户和用户组 3.8

以上命名空间在容器环境下的隔离效果如下:

  1. UTS:每个容器能看到自己的 hostname,拥有独立的主机名和域名。
  2. IPC:同一个 IPC namespace 的进程之间能互相通讯,不同的IPC namespace 之间不能通信。
  3. PID:每个 PID namespace 中的进程可以有其独立的 PID,每个容器可以有其 PID 为进程。1 的 root
  4. Network:每个容器用有其独立的网络设备,IP地址,IP路由表,/proc/net目录,端口号。
  5. Mount:每个容器能看到不同的文件系统层次结构。
  6. User:每个 container 可以有不同的 user 和 group id.

想想以下如果我们要隔离两个进程需要怎么办?

  1. 首先容器进程与进程之间需要隔离,所以需要 PID 隔离
  2. 首先 容器 A 进程 不能读取 容器 B进程 通讯内容需要、隔离信号量等,所以需要 IPC 隔离
  3. 首先 **容器 A 进程 **不能读取 容器 B进程 的文件,所以需要 Mount 隔离
  4. 首先 **容器 A 进程 **不能读取 容器 B进程 的 socket,所以需要 网络隔离、主机隔离
  5. Docker 允许用户在主机和容器间共享文件夹,同时不需要限制容器的访问权限这就容易让容器突破资源限制。需要借助用户空间来完成用户之间的隔离。
命令详解
命令 功能 用途
dd 复制文件并转换数据 创建镜像、测试性能、备份磁盘
mkfs 创建文件系统 格式化新分区
df 查看磁盘空间 查看挂载点使用情况
mount 挂载文件系统 挂载 ISO、U盘、设备等
unshare 创建隔离命名空间 容器底层调试、实验性隔离环境

① dd 命令:用于读取、转换并输出数据,可以从标准输入或文件中读取数据,根据指定的格式转换数据,再输出到文件、设备或标准输出

语法dd OPTION ,参数如下:

参数 描述
if=文件名 输入文件名,默认为标准输入。即指定源文件。
of=文件名 输出文件名,默认为标准输出。即指定目的文件。
bs=bytes 同时设置读入/输出的块大小为 bytes 个字节,如果是ibs设置单次读入块大小, obs 设置单次输出块大小, cbs 设置转换块大小
skip/seek=blocks 输入 /输出 文件开头跳过 blocks 个块后再开始复制
count=blocks 仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数。

conv=<关键字>,关键字有如下类型:

  1. conversion:用指定的参数转换文件
  2. ascii:转换 ebcdicascii
  3. ebcdic:转换 ascciiebcdic
  4. ibm:转换 asciialternate ebcdic
  5. block/unblock:把每一行转换为长度为 cbs,不足部分用空格
  6. lcase/ucase:交换输入的每对字节
  7. noerror:出错时不停止
  8. notrunc:不截断输出文件
  9. sync:将每个输入块填充到 ibs 个字节,不足部分用空(NULL)字符补齐

案例

bash 复制代码
# 生成镜像文件
dd if=/dev/zero of=test.txt bs=8k count=1014
# 大写转小写
dd if=in.txt of=out.txt conv=ucase
# 测试磁盘写入速度
dd if=/dev/zero of=testfile bs=1G count=1 oflag=direct

② mkfs 命令 :在设备上创建指定类型的文件系统,即 "格式化"

语法mkfs [-V] [-t fstype] [fs-options] filesys [blocks] ,参数如下:

参数 描述
-t fstype 指定要建立何种文件系统;如 ext3,ext4。
filesys 指定要创建的文件系统对应的设备文件名。
blocks 指定文件系统的磁盘块数。
-V 详细显示模式。
fs-options 传递给具体文件系统的参数。

案例

bash 复制代码
# 格式化分区为 ext4 文件系统
mkfs -t ext4 test.txt

mke2fs 1.46.5 (30-Dec-2021)
Discarding device blocks: done                            
Creating filesystem with 20480 4k blocks and 20480 inodes

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done

③ df 命令:用于显示目前在 Linux 系统上的文件系统磁盘使用情况统计。

语法dd OPTION ,参数如下:

参数 描述
-a, --all 包含所有的具有 0 Blocks 的文件系统。
-h, --human-readable 使用人类可读的格式。
-H, --si 很像 -h,但是用 1000 为单位而不是用 1024。
-t, --type=TYPE 限制列出文件系统的类型。
-T, --print-type 显示文件系统的形式。

案例

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           340M 1020K  339M   1% /run
/dev/vda2        69G   22G   45G  33% /
tmpfs           1.7G   24K  1.7G   1% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           340M  4.0K  340M   1% /run/user/1002
tmpfs           340M  4.0K  340M   1% /run/user/1001

④ mount 命令:用于加载文件系统到指定的加载点

语法

bash 复制代码
mount [-l] 
mount [-t vfstype] [-o options] device dir

常见参数如下

参数 描述
-l 显示已加载的文件系统列表。
-t vfstype 指定加载文件系统类型,支持常见的 ext3, ext4, iso9660, tmpfs, xfs 等。
-o options 主要用来描述设备或档案的挂接方式。
loop 用来把一个文件当成硬盘分区挂接上系统。
ro 采用只读方式挂接设备。
rw 采用读写方式挂接设备。
device 要挂接(mount)的设备。
dir 挂载点的目录。

案例

bash 复制代码
lighthouse@VM-8-10-ubuntu:test$ sudo mkdir /mymount
lighthouse@VM-8-10-ubuntu:test$ sudo mount test.txt /mymount
lighthouse@VM-8-10-ubuntu:test$ ll /mymount/
total 24
drwxr-xr-x  3 root root  4096 Jul  9 20:51 ./
drwxr-xr-x 21 root root  4096 Jul  9 20:51 ../
drwx------  2 root root 16384 Jul  9 20:47 lost+found/
lighthouse@VM-8-10-ubuntu:test$ df -t ext4
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/vda2       72127952 22751700  46319384  33% /
/dev/loop4         72652       24     66896   1% /mymount

# 取消挂载
lighthouse@VM-8-10-ubuntu:test$ sudo umount /mymount
lighthouse@VM-8-10-ubuntu:test$ df -t ext4
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/vda2       72127952 22751804  46319280  33% /

⑤ unshare 命令:

语法dd OPTION ,参数如下:

参数 描述
-i, --ipc 不共享 IPC 空间。
-m, --mount 不共享 Mount 空间。
-n, --net 不共享 Net 空间。
-p, --pid 不共享 PID 空间。
-u, --uts 不共享 UTS 空间。
-U, --user 不共享用户。
-V, --version 版本查看。
--fork 执行 unshare 的进程 fork 一个新的子进程,在子进程中执行 unshare 传入的参数。
--mount-proc 执行子进程前,将 proc 优先挂载过去。

案例

bash 复制代码
lighthouse@VM-8-10-ubuntu:test$ sudo unshare -u /bin/bash
root@VM-8-10-ubuntu:/home/lighthouse/code/test# hostname test1
root@VM-8-10-ubuntu:/home/lighthouse/code/test# hostname
test1
# 查看进程
root@VM-8-10-ubuntu:/home/lighthouse/code/test# ps -ajx | grep bash
1877172 1877180 1877180 1877180 pts/2    1886346 Ss    1001   0:00 -bash
1877180 1886346 1886346 1877180 pts/2    1886346 S+       0   0:00 sudo unshare -u /bin/bash
1886346 1886347 1886347 1886347 pts/1    1886575 Ss       0   0:00 sudo unshare -u /bin/bash
1886347 1886348 1886348 1886347 pts/1    1886575 S        0   0:00 /bin/bash
1886348 1886576 1886575 1886347 pts/1    1886575 S+       0   0:00 grep --color=auto bash

# exit 退出进程, 发现之前的没有持久设置
root@VM-8-10-ubuntu:/home/lighthouse/code/test# exit
exit
lighthouse@VM-8-10-ubuntu:test$ hostname
VM-8-10-ubuntu

⚠️ 注意:unshare 是一个运行时命令,执行后会启动一个新的 shell 进程,该进程处于独立的命名空间中,但不会持久化 ,退出即失效。

空间隔离实战

① 进程隔离unshare命令专门提供了一个参数--mount-proc,在新的namespace挂载一个独立的/proc目录,方便进行进程的监控。

bash 复制代码
lighthouse@VM-8-10-ubuntu:test$ sudo unshare --fork --pid --mount-proc /bin/bash
root@VM-8-10-ubuntu:/home/lighthouse/code/test# ps -aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1   7636  4272 pts/1    S    21:00   0:00 /bin/bash
root           7  0.0  0.1  10336  3752 pts/1    R+   21:00   0:00 ps -aux
  • 可以看到,创建了新的 namespace后,ps -aux只能查到两个进程,一个是bash,一个是grep。这就将namespace内部的进程与宿主机的进程隔离开了。

② 文件隔离

🎀 CGroup

  • 定义cgroups(Control Groups) 是 linux 内核提供的一种机制,这种机制可以根据需求把系列系统任务及其子任务整合(或分隔)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。
  • 作用:限制CPU、内存、网络等所使用的物理资源。
  • 具体实现:本质上来说,cgroups 是内核附加在程序上的一系列钩子(hook),通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。

用途如下

  1. Resource limitation:限制资源使用,例:内存使用上限/cpu 的使用限制
  2. Prioritization:优先级控制,例:CPU 利用/磁盘 IO 吞吐
  3. Accounting:一些审计或一些统计
  4. Control:挂起进程/恢复执行进程
相关命令

① pidstat:用于检测一个进程的 CPU、内存、IO、线程等资源的占用情况。

bash 复制代码
sudo apt install sysstat # 安装
pidstat [option] [时间间隔] [次数] # 语法

选项

  • -u:检测 CPU 使用情况(默认)
  • -r:检测内存使用情况
  • -d:检测 IO 使用情况
  • -p:指定进程 PID,如果指定 ALL 则监视所有进程
  • -C:检测通过指定命令启动的进程

示例

  • 默认输出pidstat 会输出所有进程的 CPU 占用情况。
  • 指定进程pidstat -p 1234 检测 PID 为 1234 的进程。
  • 指定命令pidstat -C bash 检测通过 bash 命令启动的进程。
  • 检测内存pidstat -r 检测内存占用情况。
  • 指定检测次数与频率pidstat 1 3 每隔一秒检测一次,共检测三次。

简单测试

bash 复制代码
lighthouse@VM-8-10-ubuntu:test$ pidstat -C bash
Linux 5.15.0-126-generic (VM-8-10-ubuntu) 	07/09/2025 	_x86_64_	(2 CPU)

09:19:13 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
09:19:13 PM  1001   1877180    0.00    0.00    0.00    0.00    0.00     0  bash
lighthouse@VM-8-10-ubuntu:test$ pidstat -r
Linux 5.15.0-126-generic (VM-8-10-ubuntu) 	07/09/2025 	_x86_64_	(2 CPU)

09:19:20 PM   UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
09:19:20 PM     0         1      0.09      0.00  184012   10948   0.31  systemd
09:19:20 PM     0       366      0.00      0.83  179024   81516   2.34  systemd-journal
09:19:20 PM     0       410      0.00      0.00  289312   27096   0.78  multipathd
09:19:20 PM     0       412      0.00      0.00   12120    5012   0.14  systemd-udevd
09:19:20 PM   101       828      0.00      0.00   16128    1608   0.05  systemd-network
09:19:20 PM     0       843      0.00      0.00    2816    1104   0.03  acpid
09:19:20 PM   103       848      0.00      0.00    8876    4008   0.12  dbus-daemon
09:19:20 PM     0       864      0.00      0.00  234504    4472   0.13  polkitd

② stress:一个压力测试工具,可以对 CPU、内存、IO 等进行压力测试。

bash 复制代码
sudo apt install stress # 安装
stress [option]		# 语法 

参数

  • -c --cpu N:产生 N 个进程,每个进程都循环调用 sqrt 函数产生 CPU 压力。
  • -m --vm N:产生 N 个进程,每个进程都循环调用 mallocfree 函数,产生内存压力。

示例stress -c 1 创建一个进程进行 CPU 压力测试。

  • 左侧使用stress创建了一个进程进行CPU压力输出
  • 右侧检测stress产生的压力
  • 结果一个进程占满了100%的CPU资源
资源控制实战

① 信息查看

  1. cgroups 版本查看

    bash 复制代码
    lighthouse@VM-8-10-ubuntu:~$ cat /etc/*release*	# 查看当前系统版本
    DISTRIB_ID=Ubuntu
    DISTRIB_RELEASE=22.04
    DISTRIB_CODENAME=jammy
    DISTRIB_DESCRIPTION="Ubuntu 22.04 LTS"
    PRETTY_NAME="Ubuntu 22.04 LTS"
    NAME="Ubuntu"
    VERSION_ID="22.04"
    VERSION="22.04 (Jammy Jellyfish)"
    VERSION_CODENAME=jammy
    ID=ubuntu
    ID_LIKE=debian
    HOME_URL="https://www.ubuntu.com/"
    SUPPORT_URL="https://help.ubuntu.com/"
    BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
    PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
    UBUNTU_CODENAME=jammy
    
    lighthouse@VM-8-10-ubuntu:~$ cat /proc/filesystems |grep cg
    nodev	cgroup
    nodev	cgroup2	# 可以支持两个版本 cgroup
  2. cgroups 子系统查看

    bash 复制代码
    lighthouse@VM-8-10-ubuntu:test$ cat /proc/cgroups
    #subsys_name	hierarchy	num_cgroups	enabled
    cpuset	0	109	1
    cpu	0	109	1
    cpuacct	0	109	1
    blkio	0	109	1
    memory	0	109	1
    devices	0	109	1
    freezer	0	109	1
    net_cls	0	109	1
    perf_event	0	109	1
    net_prio	0	109	1
    hugetlb	0	109	1
    pids	0	109	1
    rdma	0	109	1
    misc	0	109	1
  3. 查看挂载信息 :这里是每一个资源的控制目录,比如在 /sys/fs/cgroup/cpu 目录下,就是控制CPU资源的配置文件

    bash 复制代码
    lighthouse@VM-8-10-ubuntu:~$ mount | grep cgroup
    cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
  4. 查看一个进程上的 cgroup 限制

    bash 复制代码
    lighthouse@VM-8-10-ubuntu:~$ cat /proc/$$/cgroup
    0::/user.slice/user-1001.slice/session-83590.scope	# 层级编号:挂载的子系统:路径

② 内存控制

  1. 创建内存控制组

    bash 复制代码
    cd /sys/fs/cgroup/memory
    mkdir test_memory
  2. 设置最大内存

    bash 复制代码
    echo "20971520" > test_memory/memory.limit_in_bytes
  3. 将进程加入控制组

    bash 复制代码
    stress -m 1 --vm-bytes 50m	# 每个进程占用 50M
    pidstat -r
    echo "15070" > test_memory/tasks

③ CPU 控制

  1. 创建 CPU 控制组

    bash 复制代码
    cd /sys/fs/cgroup/cpu
    mkdir test_cpu
  2. 设置 CPU 占用率

    bash 复制代码
    echo "5000" > test_cpu/cpu.cfs_period_us
    echo "2000" > test_cpu/cpu.cfs_quota_us
  3. 将进程加入控制组

    bash 复制代码
    stress -c 1
    pidstat -u
    echo "60769" > test_cpu/tasks

三:🔥 容器虚拟化基础之 LXC

🦋 LXC 是什么?

LXC(LinuX Containers)是一种操作系统层虚拟化技术,为 Linux 内核容器功能的一个用户空间接口。

  • 它将应用软件系统打包成一个软件容器(Container),内含应用软件本身的代码,以及所需要的操作系统核心和库。
  • 透过统一的名字空间和共享 API 来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得 Linux 用户可以容易地创建和管理系统或应用容器。

尽管 LXC 极大地简化了容器技术的使用,但比起直接通过内核调用来使用容器技术,其复杂程度其实并没有多大降低,因为我们必须要学会 LXC 的一组命令工具,且由于内核的创建都是通过命令来实现的,通过批量命令实现数据迁移并不容易。

其隔离性也没有虚拟机那么强大。后来就出现了 Docker,所以从一定程度上来说,Docker 就是 LXC 的增强版。

🦋 LXC 容器操作

Ubuntu 上安装 LXC,如下:

  1. 检查及卸载(如需)

    cpp 复制代码
    systemctl status lxc
    lxc-stop -n xxx # 停止所有运行的容器
    lxc-destroy -n xxx # 删除所有容器
    apt-get purge --auto-remove lxc lxc-templates
    systemctl status lxc # 确保服务已卸载
  2. 安装 LXC

    bash 复制代码
    sudo apt install lxc lxc-templates bridge-utils -y
    
    systemctl status lxc # 检查服务是否正常

LXC的常用命令说明如下:

检查系统支持性lxc-checkconfig

创建指定模板容器lxc-create -n NAME -t TEMPLATE_NAME [--template-options]

启动容器lxc-start -n NAME -d

列出容器lxc-ls -f(-f 参数显示容器得详细信息)

查看容器信息lxc-info -n NAME

进入容器lxc-attach --name=NAME [--COMMAND]

停止容器lxc-stop -n NAME

删除容器lxc-destroy -n NAME

实战如下

bash 复制代码
# 1. 检查运行状态
root@VM-8-10-ubuntu:~$ systemctl status lxc
● lxc.service - LXC Container Initialization and Autoboot Code
     Loaded: loaded (/lib/systemd/system/lxc.service; enabled; vendor preset: enabled)
     Active: active (exited) since Fri 2025-07-11 15:28:38 CST; 3min 34s ago
       Docs: man:lxc-autostart
             man:lxc
    Process: 2423230 ExecStartPre=/usr/lib/x86_64-linux-gnu/lxc/lxc-apparmor-load (code=exited, status=0/SUCCESS)
    Process: 2423235 ExecStart=/usr/lib/x86_64-linux-gnu/lxc/lxc-containers start (code=exited, status=0/SUCCESS)
   Main PID: 2423235 (code=exited, status=0/SUCCESS)
        CPU: 24ms

# 2. 查看可用模板
root@VM-8-10-ubuntu:/home/lighthouse# ls /usr/share/lxc/templates/
lxc-alpine     lxc-centos    lxc-fedora         lxc-oci           lxc-plamo      lxc-sparclinux    lxc-voidlinux
lxc-altlinux   lxc-cirros    lxc-fedora-legacy  lxc-openmandriva  lxc-pld        lxc-sshd
lxc-archlinux  lxc-debian    lxc-gentoo         lxc-opensuse      lxc-sabayon    lxc-ubuntu
lxc-busybox    lxc-download  lxc-local          lxc-oracle        lxc-slackware  lxc-ubuntu-cloud

# 3. 创建容器 -n 容器的名称 -t 模版    -r release版本 -a cpu架构
lxc-create -n lxchost1 -t ubuntu -- -r xenial -a amd64 # Ubuntu上创建Ubuntu容器
lxc-create -n centos7 --template=download -- --dist=centos --release=7 --arch=amd64 # Ubuntu上创建CentOS容器

# 4. 查看创建结果
root@VM-8-10-ubuntu:/home/lighthouse# lxc-ls -f
NAME     STATE   AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED 
lxchost1 STOPPED 0         -      -    -    false      

# 5. 启动容器
root@VM-8-10-ubuntu:/home/lighthouse# lxc-start -n lxchost1 -d
root@VM-8-10-ubuntu:/home/lighthouse# lxc-info -n lxchost1
Name:           lxchost1
State:          RUNNING
PID:            2455869
Link:           vethNx0mnE
 TX bytes:      726 bytes
 RX bytes:      1.41 KiB
 Total bytes:   2.12 KiB

# 6. 使用 ssh 进入容器
root@VM-8-10-ubuntu:/home/lighthouse# ssh ubuntu@ip
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
ubuntu@1.12.51.69's password: # 密码是当前 系统密码

# 7. 在容器中执行常用命令
ip addr # 查看网络信息
df -h # 查看磁盘挂载情况
ps -ef # 查看进程信息
ubuntu@VM-8-10-ubuntu:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           340M  1.1M  339M   1% /run
/dev/vda2        69G   23G   44G  35% /
tmpfs           1.7G   24K  1.7G   1% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           340M  4.0K  340M   1% /run/user/1002
tmpfs           340M  4.0K  340M   1% /run/user/1001
tmpfs           1.7G     0  1.7G   0% /run/qemu
tmpfs           340M  4.0K  340M   1% /run/user/1000

# 8. 从宿主机向容器中发送命令
root@VM-8-10-ubuntu:/home/lighthouse# lxc-attach -n lxchost1 --clear-env -- echo "Hello LXC"
Hello LXC

# 9. 停止 & 删除容器
root@VM-8-10-ubuntu:/home/lighthouse# lxc-stop -n lxchost1  
root@VM-8-10-ubuntu:/home/lighthouse# lxc-destroy -n lxchost1
  • 通过LXC学习容器的创建与管理,体会容器化技术的基本原理。
  • 了解Docker不是唯一的容器实现方式,Docker在0.9版本起引入了自家的 libcontainer,而如今大部分Docker使用的都是libcontainer而非LXC。

四:🔥 共勉

😋 以上就是我对 【Docker#2】容器化虚拟化 的理解, 觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~ 😉

相关推荐
fanruitian2 小时前
k8s 设置副本数
linux·容器·kubernetes
小北方城市网2 小时前
Spring Cloud Gateway实战:路由、限流、熔断与鉴权全解析
java·spring boot·后端·spring·mybatis
xiaozenbin2 小时前
宝塔8.5在nginx中部署动态php页面出现找不到页面处理
运维·nginx·php
晨非辰2 小时前
Linux权限实战速成:用户切换/文件控制/安全配置15分钟掌握,解锁核心操作与权限模型内核逻辑
linux·运维·服务器·c++·人工智能·后端
草莓熊Lotso2 小时前
Linux 进程创建与终止全解析:fork 原理 + 退出机制实战
linux·运维·服务器·开发语言·汇编·c++·人工智能
信创新态势4 小时前
财经媒体研判:内存疯涨多米诺效应推倒,服务器涨价箭在弦上
运维·服务器·媒体
Physicist in Geophy.4 小时前
本地调用服务器数据
运维·服务器
爱莉希雅&&&10 小时前
LVS+Keepalived+DNS+Web+NFS 高可用集群项目完整部署流程
运维·nginx·dns·lvs·keepalived·nfs·ipvsadm
Loo国昌10 小时前
【LangChain1.0】第五阶段:RAG高级篇(高级检索与优化)
人工智能·后端·语言模型·架构