Docker简介
什么是虚拟化、容器化
物理机:实际的服务器或者计算机。相对于虚拟机而言的对实体计算机的称呼。物理机提供给虚拟机以硬件环境,有时也称为 “寄主” 或 “宿主”。物主机,也就是实际的主机,以主机为单位的形式存在。
虚拟化:是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机,每个逻辑计算机可运行不同的操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。比如在华为云购买服务器,服务器将虚拟出来一核2G的主机给我们使用。
容器化:容器化是一种虚拟化技术(针对操作系统的虚拟),又称操作系统层虚拟化(Operating system level virtualization),这种技术将操作系统内核虚拟化,可以允许用户空间软件实例(instances)被分割成几个独立的单元,在内核中运行,而不是只有一个单一实例运行。这个软件实例,也被称为是一个容器(containers)。对每个实例的拥有者与用户来说,他们使用的服务器程序,看起来就像是自己专用的。容器技术是虚拟化的一种。
为什么要虚拟化、容器化
当我们进行虚拟化,容器化之后,就可以对资源进行合理的利用,并且可以进行差异化控制,限制环境利用资源。
可以根据业务的需要进行调整对应的系统环境,做到合理使用。虚拟机启动更加快速,就像启动进程一样。
容器虚拟化实现
原理
容器虚拟化,有别于主机虚拟化,是操作系统层的虚拟化。通过 namespace 进行各程序的隔离,加上 cgroups 进行资源的控制,以此来进行虚拟化。当我们进行启动容器的时候,就给容器规定了只能看见某些文件,其他文件没有权限看不了,就类似于形成了箱子,但是他们是共用操作系统内核的,Docker 通过 Linux 内核提供的Namespace和cgroups等技术来实现容器之间的隔离。软件层面上被实现欺骗了。
namespace
Namespace 机制可以对不同的资源进行隔离,使得不同容器中的进程、网络、文件系统等资源看起来像是独立存在的,互不干扰,只能看到自己相关的一部分资源,A进程看到A进程的资源,B进程只能看到B进程的资源,就好比java中的package,不同的包下面可以有类名重复的类。
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 |
dd命令
dd if=/dev/zero of=test.img bs=8k count=1024
dd
:是 Linux 下一个强大的命令,用于复制文件(可通过指定参数实现特殊的数据转换、生成等操作 ),常用来创建特定大小的文件、备份磁盘分区等。if=/dev/zero
:if
是input file
(输入文件)的缩写,/dev/zero
是 Linux 系统中的一个特殊设备文件,它会不断输出 0(空字节),作为dd
命令的输入源,用于填充要创建的文件。of=test.img
:of
是output file
(输出文件)的缩写,这里指定创建的文件名为test.img
,你也可以改成其他自己想要的文件名及路径 。bs=8k
:bs
是block size
(块大小)的缩写,即每次读写数据的块大小为 8KB(1KB = 1024 字节,8k 就是 8×1024 = 8192 字节 )。count=1024
:表示要读写的块数量,这里是 1024 块 。结合bs=8k
,最终创建文件的大小就是8k×1024 = 8192KB = 8MB
(因为 1024KB = 1MB,8192÷1024 = 8 )。
conv=ucase
:conv
(conversion)表示数据转换规则,ucase
意为将输入内容全部转换为大写字母后输出
dd if=in.txt of=out.txt conv=ucase
代表将输入的文件全部转化成大写,并且输出到out.txt文件中。
mkfs命令
mkfs实际上的功能就是格式化,比如使用u盘也要格式化才能使用,也就是在Linux上面创建文件系统。
mkfs [-V] [-t fstype] [fs-options] filesys [blocks]
-t fstype
:指定要建立的文件系统类型(如 ext3、ext4 等)filesys
:指定要创建文件系统的设备文件名blocks
:指定文件系统的磁盘块数-V
:启用详细显示模式,输出更多操作信息fs-options
:传递给具体文件系统的参数(不同文件系统支持的参数不同)
mkfs -t ext4 ./test.img
类似于这样的形式,就代表在test.img文件下创建一个ext4文件系统,也就是对他进行格式化。
df(disk free)命令
该命令用于显示目前在Linux系统上的文件资源磁盘使用情况,df
命令查看的 “磁盘空间”,本质是 系统中已挂载的 “文件系统” 对应的存储设备空间。
df [option]....[File]
- -a, --all 包含所有的具有 0 Blocks 的文件系统
- -h, --human-readable 使用人类可读的格式 (预设值是不加这个选项的...)
- -H, --si 很像 -h, 但是用 1000 为单位而不是用 1024
- -t, --type=TYPE 限制列出文件系统的 TYPE
- -T, --print-type 显示文件系统的形式
mount命令
mount就是加载文件系统到指定的加载点,比如我们插入U盘,然后在此电脑界面就会弹出一个E盘的界面,这时候其实就是将我的U盘挂载到本地的E盘目录下面。在windows下面可以自动挂载,但是在Linux下面只能通过mount命令进行挂载。挂载的目的就是添加一个入口。
常见命令
mount [-l]
mount [-t vfstype] [-o options] device dir
- 常见参数
- -l: 显示已加载的文件系统列表;
- -t: 加载文件系统类型支持常见系统类型的 ext3,ext4,iso9660,tmpfs,xfs 等,大部分情况可以不指定,mount 可以自己识别
- -o options 主要用来描述设备或档案的挂接方式。
loop: 用来把一个文件当成硬盘分区挂接至系统
ro: 采用只读方式挂接设备
rw: 采用读写方式挂接设备 - device: 要挂接 (mount) 的设备。
- dir: 挂载点的目录
像这里我就通过创建了一个新的目录,通过mount我前面通过mkfs创建的文件系统挂载到data/column下面,这个column下面我们也可以正常对其进行读写。
unshare命令
unshare实际上主要能力是使用与父程序不共享的namespace运行程序。
unshare [options] program [arguments]
-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 优先挂载过去 |
unshare -u /bin/bash
通过该命令就可以不共享主机名字和域名了,此时就可以看到hostname为syx,但是如果我们使用另外一个xshell看到的主机名是👇。说明发生了不共享数据。
PID隔离(进程隔离)
unshare -p --fork /bin/bash
unshare
:Linux 命令,用于创建新的命名空间(namespace)并在其中运行程序,实现资源隔离-p
或--pid
:表示创建一个新的进程命名空间(PID namespace)--fork
:在新命名空间中 fork 一个新进程/bin/bash
:指定在新命名空间中运行的程序,这里是启动 bash shell
实际上上面并不会看到创建的子进程的ID,如果想要进行子进程的观察就要基于下面的命令。
unshare -p --fork --mount-proc /bin/bash
简单说,--mount-proc
是为了让新的进程命名空间拥有独立的 /proc
视图,避免看到宿主机的进程信息,是实现完整进程隔离的必要步骤(类似容器中的进程视图隔离)。
mount-proc 是因为 Linux 下的每个进程都有一个对应的 /proc/PID 目录,该目录包含
了大量的有关当前进程的信息。对一个 PID namespace 而言,/proc 目录只包含当前
namespace 和它所有子孙后代 namespace 里的进程的信息。创建一个新的 PID
namespace 后,如果想让子进程中的 top、ps 等依赖 /proc 文件系统的命令工作,还
需要挂载 /proc 文件系统。而文件系统隔离是 mount namespace 管理的,所以 linux
特意提供了一个选项 --mount-proc 来解决这个问题。如果不带这个我们看到的进程还
是系统的进程信息。
Mount隔离
unshare --mount --fork /bin/bash
首先需要对该文件进行格式化,格式化后将其挂载到新的目录下面。
此时我们再进行df -h查看挂载点,就可以看到已经挂载到对应的点上面去了。
在进行mount隔离之后创建的挂载点,在外面看这个点的文件是都看不到的。
cgroups
cgroups的概念:cgroups (Control Groups) 是 linux 内核提供的一种机制,这种机制可以根据需求把一系列系统任务及其子任务整合 (或分隔) 到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。简单说,cgroups 可以限制、记录任务组所使用的物理资源。本质上来说,cgroups 是内核附加在程序上的一系列钩子 (hook),通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。(简称做到对CPU的,内存等资源的分配和控制,资源控制技术)。
blkio | 对块设备的 IO 进行限制 |
cpu | 限制 CPU 时间片的分配 |
cpuacct | 生成 cgroup 中的任务占用 CPU 资源的报告,与 cpu 挂载在同一目录 |
cpuset | 给 cgroup 中的任务分配独立的 CPU(多处理器系统)和内存节点 |
devices | 限制设备文件的创建,和对设备文件的读写 |
freezer | 暂停 / 恢复 cgroup 中的任务 |
memory | 对 cgroup 中的任务的可用内存进行限制,并自动生成资源占用报告 |
perf_event | 允许 perf 观测 cgroup 中的 task |
net_cls | cgroup 中的任务创建的数据报文的类别标识符,这让 Linux 流量控制(tc 等工具)可基于该标识区分、调度不同 cgroup 产生的网络流量 |
pidstat
pidstat是sysstat的一个命令,能够监控cpu,内存,线程等情况。
命令格式:pidstat [ 选项 ] [ <时间间隔> ] [ <次数> ]
选项 | 说明 |
---|---|
-u | 默认参数,显示各进程的 CPU 使用统计 |
-r | 显示各进程的内存使用统计 |
-d | 显示各进程的 IO 使用情况 |
-p | 指定进程号,ALL 表示所有进程 |
-C | 指定命令 |
-l | 显示命令名和所有参数 |
Shell
# 卸载
apt remove sysstat -y
# 安装
apt install sysstat -y
当我们安装好sysstat之后,再输入pidstat就可以看到当前系统的所有进程信息。这里 也可以指定时间间隔和次数,也就在在多少时间间隔就弹出详细内容。
stress
stress是一个Linux的压力测试工具可以对cpu,memory,io,磁盘进行压力测试。
Shell
stress [OPTION [ARG]]
- -c, --cpu N: 产生 N 个进程,每个进程都循环调用 sqrt 函数产生 CPU 压力。
- -i, --io N: 产生 N 个进程,每个进程循环调用 sync 将内存缓冲区内容写到磁盘上,产生 IO 压力。通过系统调用 sync 刷新内存缓冲区数据到磁盘中,以确保同步。如果缓冲区内数据较少,写到磁盘中的数据也较少,不会产生 IO 压力。在 SSD 磁盘环境中尤为明显,很可能 iowait 总是 0,却因为大量调用系统调用 sync,导致系统 CPU 使用率 sys 升高。
- -m, --vm N: 产生 N 个进程,每个进程循环调用 malloc/free 函数分配和释放内存。
- --vm-bytes B: 指定分配内存的大小
- --vm-keep: 一直占用内存,区别于不断的释放和重新分配 (默认是不断释放并重新分配内存)
- -d, --hdd N: 产生 N 个不断执行 write 和 unlink 函数的进程 (创建文件,写入内容,删除文件)
- --hdd-bytes B: 指定文件大小
- -t, --timeout N: 在 N 秒后结束程序
这里我们引入了内核态cpu和用户态cpu,内核态就是应用程序内部频繁进行网络传输以及文件IO等操作可能会导致升高,用户态就是应用程序内部运行频繁占用系统资源导致用户态cpu升高。
什么是LXC
LXC(Linux Containers)Linux 容器,一种操作系统层虚拟化技术,为 Linux 内核容器功能的一个用户空间接口。它将应用软件系统打包成一个软件容器(Container),内含应用软件本身的代码,以及所需要的操作系统核心和库。透过统一的名字空间和共享 API 来分配不同软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得 Linux 用户可以容易的创建和管理系统或应用容器。后面就出现docker也就是LXC的增强版。
lxc - checkconfig
- 作用:用于检查系统是否满足运行 LXC(Linux Containers)容器的要求,会列出内核是否支持 LXC 所需的各项特性,如命名空间(namespaces)、控制组(cgroups)等相关功能的支持情况,帮助用户确认系统是否具备运行 LXC 容器的环境基础。
lxc - create
格式: lxc-create -n NAME -t TEMPLATE_NAME [-- template-options]
- 作用:创建一个 LXC 容器。可以指定容器的模板(如基于 Debian、Ubuntu 等系统模板),还能通过参数配置容器的各种属性,比如网络、存储等,执行后会在系统中生成一个新的容器实例,但此时容器还未启动。
lxc - start
- 作用:启动一个已经创建好的 LXC 容器,使容器进入运行状态,容器内的系统和应用程序开始执行。
lxc - ls
- 作用:列出系统中所有的 LXC 容器,包括正在运行的和已停止的容器,方便用户查看当前系统中容器的存在情况。
lxc - info
- 作用:显示指定 LXC 容器的详细信息,比如容器的状态(运行中、已停止等)、PID(进程 ID)、资源使用情况等,帮助用户了解容器的运行状态和资源占用等情况。
lxc - attach
- 作用:进入一个正在运行的 LXC 容器的命名空间,在容器内部执行命令或获取交互 shell,就像登录到容器内部系统一样,便于对运行中的容器进行调试、管理等操作。进入容器后执行相关的命令。
lxc - stop
- 作用:停止一个正在运行的 LXC 容器,使容器从运行状态转为停止状态,容器内的进程会被终止或暂停。
lxc - destroy
- 作用:销毁一个 LXC 容器,会删除容器相关的所有资源,包括文件系统、配置等,执行后该容器将不复存在,使用时需谨慎,避免误删重要容器。
Ubuntu安装LXC
Shell
一、检查是否安装、清理资源
systemctl status lxc
lxc-stop -n xxx # lxc-ls -f 遍历所有容器,停止运行的容器
lxc-destroy -n xxx # 删除对应的容器
二、卸载软件
apt-get purge --auto-remove lxc lxc-templates
三、检查服务已经没有该服务了
systemctl status lxc
Shell
# 一、安装
#1xc 主程序包
#1xc-templates lxc 的配置模板
#bridge-utils 网桥管理工具
apt install lxc lxc-templates bridge-utils -y
# 二、检查服务是否正常运行
systemctl status lxc
此时就可以观察大服务已经正确运行起来了。 此时可以通过lxc-checkconfig来查看lxc的相关配置。
lxc-create -t ubuntu --name lxchost1 -- -r xenial -a amd64
通过该命令用于基于 Ubuntu 模板创建一个 LXC 容器,通过
ll /usr/share/lxc/templates/
可以查看该目录下面的模板,有很多模板,这些模板都可以被创建。
创建后的账号密码默认都是是ubuntu。
首先我们启动LXC,通过lxc-ls -f查看有哪些LXC容器,