Docker容器基础入门认知-Namespce
在使用 docker 之前我一般都认为容器的技术应该和虚拟机应该差不多,和虚拟机的技术类似,但是事实上容器和虚拟机根本不是一回事。
虚拟机是将虚拟硬件、内核(即操作系统)以及用户空间打包在新虚拟机当中,虚拟机能够利用“虚拟机管理程序”运行在物理设备之上。虚拟机依赖于 hypervisor,其通常被安装在“裸金属”系统硬件之上,这导致hypervisor在某些方面被认为是一种操作系统。一旦 hypervisor 安装完成, 就可以从系统可用计算资源当中分配虚拟机实例了,每台虚拟机都能够获得唯一的操作系统和负载(应用程序)。简言之,虚拟机先需要虚拟一个物理环境,然后构建一个完整的操作系统,再搭建一层Runtime,然后供应用程序运行。
容器其实就是在系统中,利用 namespace 和 cgroup 原本的 linux 特性,将进程隔离在一个封闭的环境中,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”,再通过 veth 让进程的网络环境相隔离,利用 docker 的网桥来进行容器进程之间的相互通信。
这里要说的是容器并没有使用什么很高深的技术,而是将上面所说的 linux 相关的技术进行融合形成容器技术,所以有句话非常正确:
容器本身没有价值,有价值的是“容器编排”。
接下来会从三个方向说一下容器底层所使用到的技术:隔离,限制还有互通。
隔离-Namespace机制
首先先创建一个简单的容器:
$ docker run -it busybox /bin/sh
/ #
这里是简单起了一个 busybox 的容器,用 -it 交互的方式来进行 shell
此时在容器内 ps
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh
10 root 0:00 ps
可以看到,我们在 Docker 里最开始执行的 /bin/sh,就是这个容器内部的第 1 号进程(PID=1),而这个容器里一共只有两个进程在运行。这就意味着,前面执行的 /bin/sh,以及我们刚刚执行的 ps,已经被 Docker 隔离在了一个跟宿主机完全不同的世界当中。
这里的 pid=1 只是 namespace 机制中的映射,实际在宿主机器中
$ ps -ef | grep docker
root 7067 2417 0 16:02 pts/0 00:00:00 docker run -it busybox /bin/sh
这里的 pid=7067
这种技术,就是 Linux 里面的 Namespace 机制。而 Namespace 的使用方式也非常有意思:它其实只是 Linux 创建新进程的一个可选参数。我们知道,在 Linux 系统中创建进程的系统调用是 clone(),比如:
int pid = clone(main_function, stack_size, SIGCHLD, NULL);
这个系统调用就会为我们创建一个新的进程,并且返回它的进程号 pid。而当我们用 clone() 系统调用创建一个新进程时,就可以在参数中指定 CLONE_NEWPID 参数,比如:
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
这时,新创建的这个进程将会“看到”一个全新的进程空间,在这个进程空间里,它的 PID 是 1。
之所以说“看到”,是因为这只是一个“障眼法”,在宿主机真实的进程空间里,这个进程的 PID 还是真实的数值,比如 100。当然,我们还可以多次执行上面的 clone() 调用,这样就会创建多个 PID Namespace,而每个 Namespace 里的应用进程,都会认为自己是当前容器里的第 1 号进程,它们既看不到宿主机里真正的进程空间,也看不到其他 PID Namespace 里的具体情况。而除了我们刚刚用到的 PID Namespace,Linux 操作系统还提供了 Mount、UTS、IPC、Network 和 User 这些 Namespace,用来对各种不同的进程上下文进行“障眼法”操作。比如,Mount Namespace,用于让被隔离进程只看到当前 Namespace 里的挂载点信息;Network Namespace,用于让被隔离进程看到当前 Namespace 里的网络设备和配置。这,就是 Linux 容器最基本的实现原理了。
userns-remap
在这里还想说一下关于 docker 中使用 userns-remap 做用户命名空间
下面的步骤我是参考 https://blog.csdn.net/zyy247796143/article/details/114386484
使用普通用户运行docker容器,在docker中,在容器内创建的文件在从主机检查时往往具有不可预测的所有权。默认情况下,卷上文件的所有者是root(uid 0),但只要非root用户帐户涉及容器并写入文件系统,所有者就会从主机角度变得或多或少随机 。需要使用调用docker命令的同一用户帐户从主机访问卷数据时,这是一个问题.
典型的解决方法是:
- 在Dockerfiles中创建时强制用户uID(非可移植)
- 将主机用户的UID作为环境变量传递给docker run命令,然后在入口点脚本中的卷上运行一些chown 命令
用户命名空间( user namespace)是这个问题的最终解决方案.
通过 user namespace 技术,把宿主机中的一个普通用户(只有普通权限的用户)映射到容器中的 root 用户。在容器中,该用户在自己的 user namespace 中认为自己就是 root,也具有 root 的各种权限,但是对于宿主机上的资源,它只有很有限的访问权限(普通用户)。
Kernel 内核启用 namespace
grubby --args="namespace.unpriv_enable=1 user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
echo "user.max_user_namespaces=15076" >> /etc/sysctl.conf
重启系统
reboot
创建用户
useradd -u 5000 dku
groupadd -g 500000 dku-root
useradd -u 500000 -g dku-root dku-root
在/etc/subuid 和 /etc/subgid 文件中修改自动生成的从属ID范围:
dku:500000:65536
修改 /etc/docker/daemon.json,新增 "userns-remap"
[root@izm5e37rlunev9ij58ixy9z ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"],
"userns-remap": "dku"
}
访问数据卷文件
假如,在容器里面创建一个 UID 为1000 的 test 用户,他能读取挂载在容器里面的什么权限的文件呢?
测试文件权限:在系统的 /data/test 目录上,创建几个不同的测试文件
1. 一个属主和属组都为 501000 的文件,权限为600,文件名为:501000.txt 。
3. 一个属主和属组都为 dku-root (UID为500000)的文件,权限为600,文件名为:dku-root.txt 。
4. 一个在系统上权限为 root (UID为0)的文件,权限为600,文件名为:root.txt 。
5. 一个在系统上权限为 root (UID为0)的文件,权限为666,文件名为:test.txt 。
6.启动一个centos 7.9 的容器,并在里面创建一个 UID 为 1000 的test 用户,进入挂载的 /test 目录。
查看权限如下:
结果是只有 501000.txt 和 test.txt 这两个文件可以看到里面内容。剩下两个均没有权限。其中501000.txt 有权限,是因为在系统上这个文件的属主和属组都是 501000,其映射在容器里面的属主和属组就是1000,所以UID 为 1000 的 test 用户可以查看里面的内容。
test.txt 能查看,因为文件的权限是666,other 位的权限是 rw,所以其他用户都有权限查看。
这里的实验步骤要复现的话,还需要考虑linux的内核版本,如果低版本的运行 docker 的用户空间会出现这种问题:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:319: getting the final child's pid from pipe caused \"EOF\"": unknown.
我用 centos7.6 的是肯定会出现的,貌似这个 error 在 github 上有很多 issues
https://github.com/moby/moby/issues/40835
Docker容器基础入门认知-Namespce的更多相关文章
- Docker容器基础入门认知-网络篇
这篇文章中,会从 docker 中的单机中的 netns 到 veth,再到单机多个容器之间的 bridge 网络交互,最后到跨主机容器之间的 nat 和 vxlan 通信过程,让大家对 docker ...
- docker容器基础
一.docker容器基础6种名称空间:UTS.MOunt.IPC.PID.User.Net (1) Linux Namespaces:namespace 系统调用参数 隔离内容 内核版本 UTS ...
- Docker容器基础认知
## 一. [docker](http://www.itxdm.me/archives/tag/docker/)概念 [Docker](http://www.itxdm.me/wp-content/p ...
- Docker容器使用 (入门到精通)
Docker容器 CentOS安装Docker Docker 分为 CE 和 EE 两大版本.CE 即社区版(免费,支持周期 7 个月),EE 即企业版,强调安全,付费使用,支持周期 24 个月. D ...
- Docker容器基础知识学习
Docker作为操作系统层面的轻量级的虚拟化技术,凭借简易的使用.快速的部署以及灵活敏捷的集成等优势,迅速发展目前最为火热的技术. 1.云计算服务是一种资源管理的资源服务,该模式可以实现随时随地.便捷 ...
- Kubernetes 普及系列:容器基础入门
随着云原生时代的来临,云以及分布式计算已经是时下最受欢迎的技术之一了.其中 Docker 作为最知名的容器平台,到底有着怎样的魅力来让其无人不知无人不晓?废话不多说,让我们开始逐层掀开容器技术的神秘面 ...
- Docker容器技术入门
独立容器分开的条件: 1.Namespace命名空间 1.主机名和域名,UTS 2.文件系统,mount 3.进程间通信,IPC 4.独立的进程树PID 5.独立的用户User 6.独立的IP地址tc ...
- Docker容器入门到精通
Docker 容器 快速入门 第一章:Docker容器 第二章:Dockerfile指令与Docker-compose容器编排-搭建docker私有仓库 h1 { color: rgba(0, 60, ...
- 1.Docker容器学习之新生入门必备基础知识
0x00 Docker 快速入门 1.基础介绍 描述:Docker [ˈdɑ:kə(r)] 是一个基于Go语言开发实现的遵循Apache 2.0协议开源项目,目标是实现轻量级的操作系统虚拟化解决方案: ...
- docker容器技术基础入门
目录 docker容器技术基础入门 容器(Container) 传统虚拟化与容器的区别 Linux容器技术 Linux Namespaces CGroups LXC docker基本概念 docker ...
随机推荐
- 【“互联网+”大赛华为云赛道】GaussDB命题攻略:支持三种开发语言,轻松完成数据库缓冲池
摘要:七届中国国际"互联网+"大学生创新创业大赛火热报名中,为了帮助参赛者更好了解赛题设计思路和命题方向,华为云产业命题赛道举行了线上直播解读,华为云数据库资深架构师苏斌在直播间详 ...
- PPT 模仿力,看到好的设计随意为我所用
PPT 模仿力,看到好的设计随意为我所用 网上搜索一些作品 Q1: 这一页的设计亮点在哪? Q2: 我能不能用在PPT里面? Q3: 我能不能用PPT模仿出来? 举例 思源黑体
- 错误: -source 1.7 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式)
Modules 把 Language level 调成 8
- gunicorn 高性能wsgi服务器
参考: https://zhuanlan.zhihu.com/p/102716258 Gunicorn是什么 Gunicorn Green Unicorn 是一个 UNIX 下的 WSGI HTTP ...
- ME2N增强
一.ME2N增加字段 二.结构中添加扩展字段 附加结构中添加同名这些字段时会报错,原因是MEREP_OUTTAB_DOWNPAY等结构已存在该字段,导致冲突 三.添加逻辑代码 包含文件LMEREPI0 ...
- 同步时间,为什么我选 Chrony 而不是 NTP ?
初识 chrony chrony 是网络时间协议(Network Time Protocol )的通用实现 它不但可以提供保持系统时间与 NTP 时钟服务器同步的服务,还能作为 NTP 服务器对其他服 ...
- IntelliJ IDEA项目导入时报错:The import javax.servlet.http.HttpServletRequest cannot be resolved
IntelliJ IDEA项目导入时报错: The import javax.servlet.http.HttpServletRequest cannot be resolved 翻译一下错误信息是说 ...
- linux ntp时间服务器搭建
工作中经验遇到搭建时间服务器的任务,如何搭建网上找的例子总是有些许问题,如下自己动手操作一遍总结一下,方便自己和后来人直接上手使用. 准备工作:192.168.0.1 服务端: ntp服务器192 ...
- 这才是你应该了解的Redis数据结构!
深入了解Redis数据结构 Redis,作为一种高性能的内存数据库,支持多种数据结构,从简单的字符串到复杂的哈希表.在这篇博文中,我们将深入探讨Redis的一些主要数据结构,并通过详细的例子展示它们的 ...
- linux chown 与 chmod 命令的使用
本文为博主原创,未经允许不得转载: 最近在做 linux 系统安全管理检查操作,频繁的用到了 chown 与 chmod 两个命令,觉得有必要对着两个命令总结一下. 一. chown 命令: 1. 设 ...