docker底层技术概览

简介:

docker解决了云计算环境难于分发并且管理复杂,而用KVM、Xen等虚拟化又浪费系统资源的问题。Docker最初是基于lxc构建了容器引擎,为了提供跨平台支持,后又专门开发了libcontainer来抽象容器引擎。但无论是libcontainer还是lxc,其底层所依赖的内核特性都是相同的。我们来看看docker都使用了技术来实现容器引擎的。

命名空间

Docker使用了pid、network、ipc、美mnt、uts等命名空间来隔离网络、文件系统、进程等资源。注意,由于Linux并不是namespace了所有东西(如cgroups、/sys、SELinux、/dev/sd*、内核模块等),仅靠这几个namespace是无法实现像KVM那样的完全资源隔离的。

  • pid namespace:实现进程隔离,容器只能看到自己的进程,并且每个容器都有一个pid为1的父进程,kill掉该进程容器内的所有进程都会停止;
  • net namespace:实现网络隔离,每个容器都可以设置自己的interface、routers、iptables等;docker默认采用veth的方式将container中的虚拟网卡同host上的一个docker bridge: docker0连接在一起;
  • ipc namespace:container中进程交互还是采用linux常见的进程间交互方法(interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不同的是,container 的进程间交互实际上还是host上具有相同pid namespace中的进程间交互,因此需要在IPC资源申请时加入namespace信息 - 每个IPC资源有一个唯一的 32 位 ID;
  • mnt namespace:类似chroot,将一个进程放到一个特定的目录执行。mnt namespace允许不同namespace的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同chroot不同,每个namespace中的container在/proc/mounts的信息只包含所在namespace的mount point;
  • uts namspace:允许每个container拥有独立的hostname和domain name, 使其在网络上可以被视作一个独立的节点而非Host上的一个进程;
  • user namespace:每个container可以有不同的 user 和 group id, 也就是说可以在container内部用container内部的用户执行程序而非Host上的用户。

对于容器所依赖的内核文件系统(这些都是non-namespaced),为了保证安全性,docker将其限制为只读的:

. /sys
. /proc/sys
. /proc/sysrq-trigger
. /proc/irq
. /proc/bus

cgroups机制

cgroups 实现了对资源的配额和度量。 cgroups 的使用非常简单,提供类似文件的接口,在 /cgroup目录下新建一个文件夹即可新建一个group,在此文件夹中新建task文件,并将pid写入该文件,即可实现对该进程的资源控制。groups可以限制blkio、cpu、cpuacct、cpuset、devices、freezer、memory、net_cls、ns九大子系统的资源,以下是每个子系统的详细说明:

  • blkio 这个子系统设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。
  • cpu 这个子系统使用调度程序为cgroup任务提供cpu的访问。
  • cpuacct 产生cgroup任务的cpu资源报告。
  • cpuset 如果是多核心的cpu,这个子系统会为cgroup任务分配单独的cpu和内存。
  • devices 允许或拒绝cgroup任务对设备的访问。
  • freezer 暂停和恢复cgroup任务。
  • memory 设置每个cgroup的内存限制以及产生内存资源报告。
  • net_cls 标记每个网络包以供cgroup方便使用。
  • ns 名称空间子系统。

对于centos7来说,通过systemd-cgls来查看系统cgroups tree:

...
  ├─docker-b1f965f8e682e9d2ff9ed3039fca63c008810efd9c5e6d796344b0270d329a98.scope
  │ ├─18853 /usr/lib/systemd/systemd
  │ └─system.slice
  │   ├─keepalived.service
  │   │ ├─19307 /usr/sbin/keepalived -D -d -S 7
  │   │ └─19309 /usr/sbin/keepalived -D -d -S 7
  │   ├─haproxy.service
  │   │ ├─25195 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
  │   │ ├─25210 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
  │   │ └─25211 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
  │   ├─rsyslog.service
  │   │ └─23648 /usr/sbin/rsyslogd -n
  │   └─systemd-journald.service
  │     └─18990 /usr/lib/systemd/systemd-journald
...

特权模式下的容器:

└─system.slice
  ├─NetworkManager-dispatcher.service
  │ └─2580 /usr/libexec/nm-dispatcher.action
  ├─var-lib-docker-devicemapper-mnt-a80a5f851d00842414d5fb03866c19424df1f2afb47a04f41dd056b54c4df7ac.mount
  ├─docker-a80a5f851d00842414d5fb03866c19424df1f2afb47a04f41dd056b54c4df7ac.scope
  │ ├─2558 /usr/sbin/init
  │ └─system.slice
  │   ├─systemd-journald.service
  │   │ └─2605 /usr/lib/systemd/systemd-journald
  │   ├─dbus.socket
  │   ├─dbus.service
  │   ├─system-getty.slice
  │   ├─rc-local.service
  │   ├─systemd-user-sessions.service
  │   ├─dev-dm\x2d0.swap
  │   ├─etc-yum.repos.d.mount
  │   ├─etc-hosts.mount
  │   ├─etc-hostname.mount
  │   ├─etc-resolv.conf.mount
  │   └─-.mount

cgroups配置方法:

(1) cpu相对权重:docker run -it --rm -c 512,如果未设置,默认为1024

# cat /sys/fs/cgroup/cpu/system.slice/docker-a80a5f851d00842414d5fb03866c19424df1f2afb47a04f41dd056b54c4df7ac.scope/cpu.shares
1024

如果在容器开启的时候没有设置cpu权重,可以在容器启动后修改,如

[root@fei ~]# systemctl set-property --runtime docker-a80a5f851d00842414d5fb03866c19424df1f2afb47a04f41dd056b54c4df7ac.scope CPUShares=128
[root@fei ~]# cat /sys/fs/cgroup/cpu/system.slice/docker-a80a5f851d00842414d5fb03866c19424df1f2afb47a04f41dd056b54c4df7ac.scope/cpu.shares
128

(2) 设置cpu pin:docker run -it --rm --cpuset=0,1

# cat /sys/fs/cgroup/cpuset/system.slice/docker-b0848aa49a03b8541bb698c1544b6c411c584dce5e86831f84803228e93e61d4.scope/cpuset.cpus
0-1

(3) 内存限制: docker run -it --rm -m 128m,默认swap为mem的两倍

[root@fei ~]# cat /sys/fs/cgroup/memory/system.slice/docker-c9fed54afc8986be888b231b984be9c1a2a533c739f7a5458a56882fb13b4b93.scope/memory.limit_in_bytes
134217728
[root@fei ~]# cat /sys/fs/cgroup/memory/system.slice/docker-c9fed54afc8986be888b231b984be9c1a2a533c739f7a5458a56882fb13b4b93.scope/memory.memsw.limit_in_bytes
268435456

如果不设置-m 128m,则默认容器内存是不设限的

[root@fei ~]# cat /sys/fs/cgroup/memory/system.slice/docker-641cdebd22b55f2656a560cd250e661ab181dcf2f5c5b78dc306df7ce62231f2.scope/memory.limit_in_bytes
9223372036854775807

(4) 磁盘IO限制,docker本身默认没有做磁盘io的限制,不过我们可以通过直接操作cgroups来实现

# 磁盘写
[root@fei ~]# cid=641cdebd22b5
[root@fei ~]# nsenter --target $(docker inspect -f '{{ .State.Pid }}' $cid) --mount --uts --ipc --net --pid mount | head -1
/dev/mapper/docker-253:1-138011042-641cdebd22b55f2656a560cd250e661ab181dcf2f5c5b78dc306df7ce62231f2 on / type ext4 (rw,relatime,discard,stripe=16,data=ordered)
[root@fei ~]# systemctl set-property --runtime docker-641cdebd22b55f2656a560cd250e661ab181dcf2f5c5b78dc306df7ce62231f2.scope "BlockIOWriteBandwidth=/dev/mapper/docker-253:1-138011042-641cdebd22b55f2656a560cd250e661ab181dcf2f5c5b78dc306df7ce62231f2 1M"
# 磁盘读
[root@fei ~]# systemctl set-property --runtime docker-641cdebd22b55f2656a560cd250e661ab181dcf2f5c5b78dc306df7ce62231f2.scope "BlockIOReadBandwidth =/dev/mapper/docker-253:1-138011042-641cdebd22b55f2656a560cd250e661ab181dcf2f5c5b78dc306df7ce62231f2 1M"

(5) 磁盘大小,docker容器默认都会分配10GB的空间,如果想改变这个值,需要修改docker服务启动参数,并重启docker服务:docker -d --storage-opt dm.basesize=5G。其他磁盘相关的配置可以参考https://github.com/docker/docker/tree/master/daemon/graphdriver/devmapper

Capability机制

Linux把原来和超级用户相关的高级权限划分成为不同的单元,称为Capability,这样就可以独立对特定的Capability进行使能或禁止。通常来讲,不合理的禁止Capability,会导致应用崩溃。

Docker默认为容器删除了以下capability:

CAP_SETPCAP Modify process capabilities
CAP_SYS_MODULE  Insert/Remove kernel modules
CAP_SYS_RAWIO   Modify Kernel Memory
CAP_SYS_PACCT   Configure process accounting
CAP_SYS_NICE    Modify Priority of processes
CAP_SYS_RESOURCE    Override Resource Limits
CAP_SYS_TIME    Modify the system clock
CAP_SYS_TTY_CONFIG  Configure tty devices
CAP_AUDIT_WRITE Write the audit log
CAP_AUDIT_CONTROL   Configure Audit Subsystem
CAP_MAC_OVERRIDE    Ignore Kernel MAC Policy
CAP_MAC_ADMIN   Configure MAC Configuration
CAP_SYSLOG  Modify Kernel printk behavior
CAP_NET_ADMIN   Configure the network
CAP_SYS_ADMIN   Catch all

如果确实需要这些capability,可以通过--cap-add or --cap-drop添加或删除,如docker run --cap-add all --cap-drop sys-admin -ti rhel7 /bin/sh

SELinux

SELinux是一个标签系统,进程有标签,每个文件、目录、系统对象都有标签。SELinux通过撰写标签进程和标签对象之间访问规则来进行安全保护。

Union FS

对于这种叠加的文件系统,有一个很好的实现是AUFS,在Ubuntu比较新的发行版里都是自带的,这个可以做到以文件为粒度的copy-on-write,为海量的container的瞬间启动,提供了技术支持,也会持续部署提供了帮助(注意,centos7系统是基于devicemapper来实现类似的功能的)。

AUFS支持为每一个成员目录(类似Git Branch)设定readonly、readwrite 和 whiteout-able 权限, 同时 AUFS 里有一个类似分层的概念, 对 readonly 权限的 branch 可以逻辑上进行修改(增量地, 不影响 readonly 部分的)。通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个disk挂到同一个目录下, 另一个更常用的就是将一个 readonly 的 branch 和一个 writeable 的 branch 联合在一起,Live CD正是基于此方法可以允许在 OS image 不变的基础上允许用户在其上进行一些写操作。Docker 在 AUFS 上构建的 container image 也正是如此。

IPTABLES

主要用来做端口映射以及NAT转换,端口映射已经集成到Docker命令中,但NAT转换需要手动执行iptables命令。


本文转自feisky博客园博客,原文链接:http://www.cnblogs.com/feisky/p/4105739.html,如需转载请自行联系原作者

相关文章
|
3月前
|
Kubernetes Docker Python
Docker 与 Kubernetes 容器化部署核心技术及企业级应用实践全方案解析
本文详解Docker与Kubernetes容器化技术,涵盖概念原理、环境搭建、镜像构建、应用部署及监控扩展,助你掌握企业级容器化方案,提升应用开发与运维效率。
710 108
|
1月前
|
Java Linux 虚拟化
【Docker】(1)Docker的概述与架构,手把手带你安装Docker,云原生路上不可缺少的一门技术!
1. Docker简介 1.1 Docker是什么 为什么docker会出现? 假定您在开发一款平台项目,您的开发环境具有特定的配置。其他开发人员身处的环境配置也各有不同。 您正在开发的应用依赖于您当前的配置且还要依赖于某些配置文件。 您的企业还拥有标准化的测试和生产环境,且具有自身的配置和一系列支持文件。 **要求:**希望尽可能多在本地模拟这些环境而不产生重新创建服务器环境的开销 问题: 要如何确保应用能够在这些环境中运行和通过质量检测? 在部署过程中不出现令人头疼的版本、配置问题 无需重新编写代码和进行故障修复
295 2
|
3月前
|
Kubernetes Cloud Native 持续交付
Docker:轻量级容器化技术解析
Docker:轻量级容器化技术解析
|
3月前
|
运维 测试技术 Docker
Docker:轻量级容器化技术革命
Docker:轻量级容器化技术革命
|
8月前
|
存储 虚拟化 Docker
|
8月前
|
安全 API 算法框架/工具
大模型文件Docker镜像化部署技术详解
大模型文件Docker镜像化部署技术详解
1095 2
|
8月前
|
开发工具 虚拟化 git
自学软硬件第755 docker容器虚拟化技术youtube视频下载工具
docker容器虚拟化技术有什么用?怎么使用?TubeTube 项目使用youtube视频下载工具
|
9月前
|
消息中间件 Linux 数据中心
Docker核心技术:Docker原理之Namespace
通过以上内容,您可以深入了解Docker中的Namespace机制及其在资源隔离中的应用,从而更好地理解和应用Docker技术。
318 25
|
8月前
|
安全 开发者 Docker
Docker技术背景与应用:解决现代开发中的关键问题
Docker作为一种革命性的容器化技术,极大地改变了现代软件开发的方式。通过解决环境一致性、依赖管理、部署复杂性和资源利用率等问题,Docker为开发者提供了高效、灵活的开发和部署环境。尽管面临着一些挑战,但随着技术的发展和完善,Docker将继续在现代软件开发中发挥重要作用。作为全栈工程师,掌握并善用Docker技术,将为我们的开发工作带来更多便利和可能性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
11月前
|
Unix Linux Docker
CentOS停更沉寂,RHEL巨变限制源代:Docker容器化技术的兴起助力操作系统新格局
操作系统是计算机系统的核心软件,管理和控制硬件与软件资源,为用户和应用程序提供高效、安全的运行环境。Linux作为开源、跨平台的操作系统,具有高度可定制性、稳定性和安全性,广泛应用于服务器、云计算、物联网等领域。其发展得益于庞大的社区支持,多种发行版如Ubuntu、Debian、Fedora等满足不同需求。
333 5