虚拟化与容器化

本文详细介绍了虚拟化和容器化的基本概念,重点讲解了Namespaces(特别是MountNamespace和PIDNamespace)的作用,以及它们在容器技术中的运用。文章还提到容器与虚拟机的区别,以及如何通过unshare命令创建和管理不同的Namespace来实现进程和资源隔离。
摘要由CSDN通过智能技术生成

目录

什么是虚拟化、容器化

关于容器技术(容器虚拟化)

Namespce技术

Mount Namespace

PID Namespace

User/UTS/IPC/Network/... Namespace


什么是虚拟化、容器化

        虚拟化技术最初起源于20世纪60年代末,主要是将计算机硬件(物理机)虚拟分区成一个或多个虚拟机,并提供多用户对大型计算机的交互访问。

容器具有极其轻量、秒级部署、易于移植、敏捷弹性伸缩等多种优势。

容器化和虚拟化是互补的。虚拟化是用来进行硬件资源划分的完美解决方案,通过hypervisor层来实现对资源的彻底隔离;而容器化是对OS级别的虚拟化,利用内核cgroup namespace特性,仅仅是进程本身的隔离。

因虚拟化是OS系统级隔离,而容器则是进程级隔离,相对于硬件虚拟化来说,容器的安全性更弱一些,因此需要一些额外的安全技术或安全容器方案来弥补。

关于容器技术(容器虚拟化)

容器技术的诞生,其主要目的是为解决PaaS层的技术实现,就像OpenStack、Cloudstack等技术为解决IaaS层的问题而诞生一样。是一种操作系统虚拟化,属于轻量级虚拟化技术。

容器技术之所以受欢迎,一是因为即使没有虚拟化的技术背景,也可以单独来学习容器虚拟化。二是因为它已经集成到了Linux内核中,已经被当做Linux内核原生提供的特性。

然而对于容器本身,并没有一个严格的定义,一般来说,它必须是一个相对独立的运行环境,这点上类似虚拟机的概念,但是又没有虚拟机那样彻底。另外,在一个容器环境内,应该最小化对外界(宿主)的影响,比如资源控制等等

一般来说容器技术主要包括Namespace 和 Cgroup两个内核特性

  • Namespace:

    • 主要做访问隔离。针对一类资源进行抽象,并将其封装在一个独立的容器内,彼此不可见

  • Cgroup

    • 主要做资源控制。

Namespce技术
Mount Namespace

        Mount Namespace 是 Namespace 的一种类型,它允许不同的进程看到不同的文件系统视图。这意味着在一个 Mount Namespace 中进行的挂载和卸载操作仅在该 Namespace 中可见,对其他 Namespace 无影响。

以下实验:

  • 如何使用unshare 创建mnt ns

  • 如何进入某个mnt ns

  • 验证mnt ns之间是隔离的

  • 如何清理mnt ns

    • mnt ns是和某个进程绑定的,也就是该PID不存在了,所在mnt也会被清理掉

# 1. 登陆Linux,本测试使用CentOS7.5
# 2. 查看当前系统所有的mnt ns
> lsns -t mnt
        NS TYPE NPROCS   PID USER   COMMAND
4026531840 mnt      87     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531856 mnt       1    18 root   kdevtmpfs
4026532121 mnt       1   406 root   /usr/lib/systemd/systemd-udevd
4026532122 mnt       1   503 chrony /usr/sbin/chronyd

# 3. 查看当前所在mnt ns ---->   4026531840 ---> PID=1 系统默认mnt ns
# $$ --> 表示当前执行命令的PID,即ls -l 这条命令本身 --> PID=30775
> ls -l /proc/$$/ns/mnt
/proc/30775/ns/mnt -> mnt:[4026531840]

# 4. 打开另一个shell-B,同样查看mnt ns
# 5. 使用unshare创建一个mnt ns
#    unshare 是一个 Linux 命令,用于在创建新的进程时从父进程分离出(或"unshare")一些特定的资源,例如命名空间(namespaces)
#    --fork 表示创建创建一个ns之后立刻执行某个命令
#    默认会继承父进程所有的资源情况,包括mnt,当新的子命令是在新的隔离空间执行的
> unshare --mount --fork /bin/bash

# 6. 查看当前所有的mnt ns. 发现多了新的mnt ns 其ID --> 4026532493
> lsns -t mnt
        NS TYPE NPROCS   PID USER   COMMAND
4026531840 mnt      92     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531856 mnt       1    18 root   kdevtmpfs
4026532121 mnt       1   406 root   /usr/lib/systemd/systemd-udevd
4026532122 mnt       1   503 chrony /usr/sbin/chronyd
4026532493 mnt       3  5179 root   unshare --mount --fork /bin/bash

# 6.1 在另一个Terminal上也查看一次

# 7. 查看当前所在mnt ns ---->   4026532493 ---> PID=5179 在新创建的mnt ns下
#    $$ --> 表示当前执行命令的PID,即ls -l 这条命令本身 --> PID=5180
#    即,上述的unshare命令,默认创建一个新的mnt ns,并且进入到该mnt ns下。
#    也可以显示的进入某个mnt ns下 -- 执行把PID替换成目标mnt ns下的任何一个PID
#    nsenter --mount=/proc/${PID}/ns/mnt -- findmnt 
> ls -l /proc/$$/ns/mnt
/proc/5180/ns/mnt -> mnt:[4026532493]

# 8. 查看当前mnt ns中 mount的情况, 因为继承了PID=1的mount情况
> df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/nvme0n1p1   20G  4.6G   16G   23% /
devtmpfs        1.9G     0  1.9G    0% /dev
tmpfs           1.9G     0  1.9G    0% /dev/shm
tmpfs           1.9G     0  1.9G    0% /sys/fs/cgroup
tmpfs           1.9G  193M  1.7G   11% /run
tmpfs           374M     0  374M    0% /run/user/1001

# 9. 查看当前mnt ns 多一个了mount点  tmpfs -> /tmp/xxx_tmpfs
> mkdir /tmp/xxx_tmpfs
> mount -t tmpfs -o size=20m tmpfs /tmp/xxx_tmpfs
> df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/nvme0n1p1   20G  4.6G   16G   23% /
devtmpfs        1.9G     0  1.9G    0% /dev
tmpfs           1.9G     0  1.9G    0% /dev/shm
tmpfs           1.9G     0  1.9G    0% /sys/fs/cgroup
tmpfs           1.9G  193M  1.7G   11% /run
tmpfs           374M     0  374M    0% /run/user/1001
tmpfs            20M     0   20M    0% /tmp/xxx_tmpfs
# 4.1 登陆Linux,本测试使用CentOS7.5
# 4.2 查看当前系统所有的mnt ns
> lsns -t mnt
        NS TYPE NPROCS   PID USER   COMMAND
4026531840 mnt      87     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531856 mnt       1    18 root   kdevtmpfs
4026532121 mnt       1   406 root   /usr/lib/systemd/systemd-udevd
4026532122 mnt       1   503 chrony /usr/sbin/chronyd

# 4.3 查看当前所在mnt ns ---->   4026531840 ---> PID=1 系统默认mnt ns
# $$ --> 表示当前执行命令的PID,即ls -l 这条命令本身 --> PID=4594
> ls -l /proc/$$/ns/mnt
/proc/4594/ns/mnt -> mnt:[4026531840]

# 6.1 查看当前所有的mnt ns. 发现多了新的mnt ns 其ID --> 4026532493
> lsns -t mnt
        NS TYPE NPROCS   PID USER   COMMAND
4026531840 mnt      93     1 root   /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026531856 mnt       1    18 root   kdevtmpfs
4026532121 mnt       1   406 root   /usr/lib/systemd/systemd-udevd
4026532122 mnt       1   503 chrony /usr/sbin/chronyd
4026532493 mnt       2  5179 root   unshare --mount --fork /bin/bash

# 7.1  进入新创建的mnt ns下,
> nsenter --mount=/proc/5179/ns/mnt

# 7.2  查看当前的mnt ns 是否为新创建的mnt ns
> ls -l /proc/$$/ns/mnt
/proc/5873/ns/mnt -> mnt:[4026532493]

# 7.3  进入PID=1mnt ns下, ---> 4026531840
> nsenter --mount=/proc/1/ns/mnt

# 8.1 查看当前PID=1中 mount的情况, 和 4026532493 是一样的。
> df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/nvme0n1p1   20G  4.6G   16G   23% /
devtmpfs        1.9G     0  1.9G    0% /dev
tmpfs           1.9G     0  1.9G    0% /dev/shm
tmpfs           1.9G     0  1.9G    0% /sys/fs/cgroup
tmpfs           1.9G  193M  1.7G   11% /run
tmpfs           374M     0  374M    0% /run/user/1001

# 9.1 查看PID=1中的mount情况,并不能看到 4026532493 这个mnt ns中的新增的mount点
#     可以得出,不同mnt ns之间是隔离的。
> df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/nvme0n1p1   20G  4.6G   16G   23% /
devtmpfs        1.9G     0  1.9G    0% /dev
tmpfs           1.9G     0  1.9G    0% /dev/shm
tmpfs           1.9G     0  1.9G    0% /sys/fs/cgroup
tmpfs           1.9G  193M  1.7G   11% /run
tmpfs           374M     0  374M    0% /run/user/1001

# 10. PID=5179 是 /bin/bash那个命令
> kill -9 5179
PID Namespace

        Linux宿主机上运行着成千上万的进程,默认情况下,容器内无法看到宿主机的进程表,因此,你的应用在容器启动时,pid为1。

#1. 查看当前所有pid ns
> lsns -t pid
        NS TYPE NPROCS   PID USER COMMAND
4026531836 pid      96     1 root /usr/lib/systemd/systemd --switched-root --system 
--deserialize 21

#2. 创建新的pid空间 ---> 可以看到新的pid空间的,pid=1,
>unshare --pid --mount-proc --fork /bin/bash
>echo $$
1
>ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0 115576  2048 pts/1    S    05:40   0:00 /bin/bash
root        10  0.0  0.0 155364  1864 pts/1    R+   05:40   0:00 ps aux
#1.1 查看当前所有pid ns
> lsns -t pid
        NS TYPE NPROCS   PID USER COMMAND
4026531836 pid      96     1 root /usr/lib/systemd/systemd --switched-root --system 
--deserialize 21

#2.1 再次查看当前所有pid ns   ---> 多了一个 4026532494 其PID=9751
> lsns -t pid
        NS TYPE NPROCS   PID USER COMMAND
4026531836 pid      97     1 root /usr/lib/systemd/systemd --switched-root --system --deserialize 21
4026532494 pid       1  9751 root /bin/bash

#2.2 查看PID=9751 的进程树
>ps -ef |grep 9751
root      9751  9750  0 05:40 pts/1    00:00:00 /bin/bash

>ps -ef |grep 9750
root      9750  9014  0 05:40 pts/1    00:00:00 unshare --pid --mount-proc --fork /bin/bash
root      9751  9750  0 05:40 pts/1    00:00:00 /bin/bash

#2.3 即在新的pid ns中,虽然PID=1,但实际在宿主机器上PID=9751。在新的pid ns是看不到其他pid空间的进程的,实现了进程隔离
 User/UTS/IPC/Network/... Namespace

        用unshare命令,类似构建独立的ns,相互是隔离。大家可以自己试试

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值