Linux namespace隔离容器的运行环境

概念
  • 通过将某个特定的全局系统资源通过抽象方法使得namespace中的进程看起来拥有它们自己的隔离的全局系统资源实例、
  • 当Docker创建一个容器时,它会创建6种namespce的实例,然后把容器中的所有进程放到这些namespace中,使得Docker中的进程只能看到隔离的系统资源
  • 如下是Linux内核中的6种namespace
namespace被隔离的全局系统资源在容器语境下的隔离效果
mount namespace                                                              文件系统挂载点每个容器能看到不同的文件系统层次结构
UTS namespacenodename and domainname每个容器都可以有自己的hostname和domainname
IPC namespace特定进程间通信资源,包括System V IPC 和 POSIX message queues每个容器有自己的System V IPC 和 POSIX 消息队列文件系统,因此,只有在同一个IPC namespace的进程间才能互相通信
PID namespace进程ID数字空间process ID numberspace每个PID namespace 中的进程可以有其独立的PID;每个容器可以有其PID为1的root进程;也可以使得容器可以在不同的host之间迁移,因为namespace的进程ID和host无关了。这也使得容器中的每个进程有两个PID:容器的PID和host上的PID
Network namespace网络相关的系统资源每个容器用有其独立的网络设备,IP 地址,IP 路由表,/proc/net 目录,端口号等等。这也使得一个 host 上多个容器内的同一个应用都绑定到各自容器的 80 端口上
User namespace用户和组 ID 空间在 user namespace 中的进程的用户和组 ID 可以和在 host 上不同; 每个 container 可以有不同的 user 和 group id;一个 host 上的非特权用户可以成为 user namespace 中的特权用户
PID namespace

我们能够看到,在容器内外的PID时不同的:

  • 在容器内PID=1,PPID=0
  • 在容器外PID=xxx,PPID=xxxx,即docker-containerd-shim进程
  • 关于containerd, containerd-shim & container的关系,如下图
    Docker
  • Docker 引擎管理着镜像,然后一脚给containerd运行,containerd再使用runC运行容器
  • Containerd是一个简单的守护进程,它可以使用runC管理容器,使用gRPC暴露容器的其他功能。它管理容器的开始,停止,暂停和销毁。
  • 由于容器运行时是孤立的引擎,引擎最终能够启动和升级而无需重新启动容器
  • runC是要给轻量级的工具,它就是用来运行容器的,是一个小命令行工具,可以不用通过Docker引擎,直接操作容器
user namespace
  • Linux通过clone()系统调用中使用的CLONE_NUWUSER标志,一个单独的user namespace就会被创建出来
  • 新的user namespace中,有一个虚拟机用户和用户组的集合。这些用户/用户组可以映射到namespace之外的非root用户

在容器内部启动sleep进程
容器进程

在主机上查看该进程
主机进程
权限受限

可见容器内外都是root用户,且容器外的进程用户权限是受限的。但很明显,不能信任,其中可能存在漏洞。面对同样的进程,在容器内享有root权限,映射到主机上应该对应一个普通用户。

一般情况下,docker会帮我们创建好dockermap用户,没有的话就自己创建一个
创建dockermap用户
edit_daemon.json

重启docker后,再容器内创建sleep进程可见:
容器内sleep
映射到主机进程

检查Linux是否开启namespace

检查是否开启namespace

// 查看namespace关键字
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
network namespace

默认情况下,当docker实例被创建出来后,使用ip netns命令无法看到network namespace,因为ip netns命令是从/var/run/netns文件夹中读取内容的

  • 找到容器的主进程ID
ps -ef |grep [containerID]
  • 创建/var/run/netns目录以及符号链接
ln -s /proc/[container PID]/ns/net /var/run/netns/[containerID]
  • 此时可以使用ip netns
ip netns 
ip netns exec [containerID] ip addr

本文参考自 https://www.cnblogs.com/sammyliu/p/5878973.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值