深入剖析docker核心技术(namespace、cgroups、union fs、网络)(二)

简介: 深入剖析docker核心技术(namespace、cgroups、union fs、网络)(二)

深入剖析docker核心技术(namespace、cgroups、union fs、网络)(一):https://developer.aliyun.com/article/1417842

OverlayFS

大白话:就是把不同的目录结构,merge到一个目录去,并且把这个目录挂载到这个容器里面,这样每一个容器看到的都是自己独立的一个文件系统。

OverlayFS 是一种与 AUFS 类似的联合文件系统,同样属于文件级的存储驱动,包含了最初的 Overlay 和 更新更稳定的 overlay2。

Overlay 只有两层:upper 层和 lower 层,Lower 层代表镜像层,upper 层代表容器可写层。

upper和lower会一起合并成一个合并层,就是mount指定两个层级,最后会被合并成一个目录。

  • 如果一个目录在下层,那么在合并层是可见的(文件1)
  • 如果一个目录在上层,那么在合并层也是可见的(文件4)
  • 如果一个文件在上下层都存在,那么在合并层中用的是上层文件(文件2)

那么这就给容器机会了, 在dockerfile中的每一条指令,都是原来层的上一层,每一层都往上叠一次,那么最终容器加载看到的文件项目就是文件Mount。

OverlayFS 文件系统例子操作

[root@node2 /]# mkdir upper lower merged work
[root@node2 /]# echo "from lower" > lower/in_lower.txt
[root@node2 /]# echo "from upper" > upper/in_upper.txt
[root@node2 /]# echo "from lower" > lower/in_both.txt
[root@node2 /]# echo "from upper" > upper/in_both.txt
[root@node2 /]# sudo mount -t overlay overlay -o lowerdir=`pwd`/lower,upperdir=`pwd`/upper,workdir=`pwd`/work `pwd`/merged
[root@node2 /]# cd merged/
[root@node2 merged]# ls
in_both.txt  in_lower.txt  in_upper.txt
# 当有同名文件的时候以上层为主
[root@node2 merged]# cat in_both.txt 
from upper

查看docker容器是怎么用的

可以看到GraphDriver这里就定义了文件系统,可以看到lowerdir有很多不同的部分,事实上,dockerfile中的每一层都做了一次monut,中间的指令都是一次次mount出来的。

[root@node2 /]# docker run -it --name centos -P centos /bin/bash
[root@26cb16ab2fc0 /]# exit
exit
[root@node2 /]# docker inspect 26cb16ab2fc0
"GraphDriver": {
            "Name": "overlay2",
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/bd7b9b6577911e31ba997a11022b8241cebd8d6b435aa8d8b109f18f41d9b7f0-init/diff:/var/lib/docker/overlay2/7da4ae3d97674a0cdfe8af9f9b341f75c3a436cf8538325b9e2263fbc043a990/diff",
                "MergedDir": "/var/lib/docker/overlay2/bd7b9b6577911e31ba997a11022b8241cebd8d6b435aa8d8b109f18f41d9b7f0/merged",
                "UpperDir": "/var/lib/docker/overlay2/bd7b9b6577911e31ba997a11022b8241cebd8d6b435aa8d8b109f18f41d9b7f0/diff",
                "WorkDir": "/var/lib/docker/overlay2/bd7b9b6577911e31ba997a11022b8241cebd8d6b435aa8d8b109f18f41d9b7f0/work"
            }
        }

OCI 容器标准

Open Container Initiative

  1. OCI 组织于 2015 年创建,是一个致力于定义容器镜像标准和运行时标准的开放式组织。
  2. OCI 定义了运行时标准(Runtime Specification)、镜像标准(Image Specification)和分发标准(Distribution Specification)
  • 运行时标准定义如何解压应用包并运行
  • 镜像标准定义应用如何打包
  • 分发标准定义如何分发容器镜像

Docker 引擎架构

在docker初期,docker daemon是主进程, 任何的container进程都是daemon fork出来的,这样就有一个问题,如果docker重启或者升级,那么docker daemon这个父进程是要销毁的,那么这些子进程怎么办。这是docker早期的问题。

 后面containerd出来了,他做了一个docker shim或者叫container shim,就是说containerd是一个单纯的daemon,所有fork出来的子进程的父进程不再说daemon,他为每一个容器进程构建了一个shim,作为他的父进程,那么 shim的父进程是谁呢,是systemd,这样的话containerd重启的话所有的容器是不受影响的。

容器里面的1号进程,是entrypoint指定的那个进程

网络

概述

  • Null(–net=None)
把容器放入独立的网络空间但不做任何网络配置;
用户需要通过运行 docker network 命令来完成网络配置。
  • Host
使用主机网络名空间,复用主机网络。
  • Container
重用其他容器的网络。
  • Bridge(–net=bridge)
使用 Linux 网桥和 iptables 提供容器互联,
Docker 在每台主机上创建一个名叫 docker0的网桥,
通过 veth pair 来连接该主机的每一个 EndPoint。

跨主机网络方式,下面两种

  • Overlay(libnetwork, libkv)
通过网络封包实现。
  • Remote(work with remote drivers)
Underlay:
• 使用现有底层网络,为每一个容器配置可路由的网络 IP。
Overlay:
• 通过网络封包实现。

默认模式–Bridge和NAT

在主机启动容器:

[root@node2 /]# docker run -it -p 8888:80 nginx

Docker 会以标准模式配置网络:

  • 创建 veth pair;
  • 将 veth pair的一端连接到 docker0 网桥;
  • veth pair 的另外一端设置为容器名空间的 eth0;
  • 为容器名空间的 eth0 分配 ip;
  • 主机上的 Iptables 规则:-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8888 -j DNAT --to-destination 172.17.0.2:80

linux中是由bridge网桥设备的,图中的docker0就是网桥,docker驱动CNM会自动给容器分配ip(bridge模式下),任何会构建一个veth pair,是一个虚拟的网络设备,可以理解为是一个网线,有A,B两端,双向的。只需要创建一个veth pair,一端插在docker0网桥上面,一端查到容器里面,作为容器的虚拟网口,并且把ip地址配置在上面,这样从主机到容器的网络就联通了。

下面来查看这些信息

# 运行一个容器
# -p 8888:80的意思就是将主机的8888端口映射到容器的80端口
[root@node2 /]# docker run -it -p 8888:80 nginx
...
# 可以看到docker0这个网桥
[root@node2 /]# brctl show 
bridge name bridge id   STP enabled interfaces
docker0   8000.0242463a9968 no    veth5cecfe5
# 查看容器进程号
[root@node2 /]# docker inspect 6ef7f2dd7253|grep -i pid
            "Pid": 99551,
            "PidMode": "",
            "PidsLimit": 0,
# 查看该pid的net namespace下的网络
[root@node2 /]# nsenter -t 99551 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link 
       valid_lft forever preferred_lft forever
[root@node2 /]# nsenter -t 99551 -n ip r
default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2

 可以看到这个容器有自己的interface和自己的路由表,那么在主机上就能访问到这个ip地址,网络是通的。这一切都是容器驱动帮我们做的,下面介绍Null的时候将介绍自己创建网络

[root@node2 /]# iptables-save
...
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8888 -j DNAT --to-destination 172.17.0.2:80
...


iptable是linux内核里面处理数据包的时候,做包过滤和包修改的工具,可以定义一些规则,linux在处理这些数据包的时候来读这些规则,按照规则去修改数据包的包头。

Nul网络。

Null 模式是一个空实现,即容器没有配置任何网络。可以通过 Null 模式启动容器并在宿主机上通过命令为容器配置网络。

# 创建net namespace 的目录
[root@node2 /]# mkdir -p /var/run/netns
[root@node2 /]# find -L /var/run/netns -type l -delete
# 以Null网络模式启动nginx docker
[root@node2 /]# docker run --network=none  -d nginx
9ebdcd509ea7c11f454dc981808799183e847b03d6c0f519fd7316ea1f7f1818
# 找到容器对应的pid
[root@node2 /]# docker inspect 9ebdcd509|grep -i pid
            "Pid": 127513,
            "PidMode": "",
            "PidsLimit": 0,
# 检查容器的网络配置
[root@node2 /]# nsenter -t 127513 -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
# 链接网络名称空间
[root@node2 /]# export pid=127513
[root@node2 /]# ln -s /proc/$pid/ns/net /var/run/netns/$pid
[root@node2 /]# ip netns list
127513
# 创建veth pair
[root@node2 /]# ip link add A type veth peer name B
# 往docker0这个网桥上插A口
[root@node2 /]# brctl addif docker0 A
# 启动A口
[root@node2 /]# ip link set A up
[root@node2 /]# SETIP=172.17.0.10
[root@node2 /]# SETMASK=16
[root@node2 /]# GATEWAY=172.17.0.1
# 将B口放到pid的namespace里面去
[root@node2 /]# ip link set B netns $pid
# 可以看到B口已经在这个namespace里面了
[root@node2 /]# nsenter -t $pid -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
20: B@if21: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 9a:39:63:07:3c:a2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
# 将B口改名为eth0
[root@node2 /]# ip netns exec $pid ip link set dev B name eth0
# 启动eth0口
[root@node2 /]# ip netns exec $pid ip link set eth0 up
# 配置ip、mark
[root@node2 /]# ip netns exec $pid ip addr add $SETIP/$SETMASK dev eth0
# 配置路由
[root@node2 /]# ip netns exec $pid ip route add default via $GATEWAY
# 查看
[root@node2 /]# nsenter -t $pid -n ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state 
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 9a:39:63:07:3c:a2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.10/16 scope global eth0
# 成功使用容器提供的服务
[root@node2 /]# curl 172.17.0.10
<!DOCTYPE html>
...
</html>

上面的命令其实就是默认的网桥模式做的事情

Underlay

上面介绍的都是解决了容器和主机的网络联通,那么如果想跨主机联通如何实现呢。第一种方法是,物理网络认识一个网络段,能不能预留一个网络段分配给容器呢,那么这样通过ip分配的机制把ip分配给容器,那么这样跨主机的网络就互通了,因为这个ip段是物理网络认识的,物理机知道路由怎么走。相当于容器的网络依托于物理的网络。这种模式就是Underlay。

  • 采用 Linux 网桥设备(sbrctl),通过物理网络连通容器;
  • 创建新的网桥设备 mydr0;
  • 将主机网卡加入网桥;
  • 把主机网卡的地址配置到网桥,并把默认路由规则转移到网桥 mydr0;
  • 启动容器;
  • 创建 veth 队,并且把一个 peer 添加到网桥 mydr0;
  • 配置容器把 veth 的另一个 peer 分配给容器网卡;

Overlay

  • Docker overlay 网络驱动原生支持多主机网络;
  • Libnetwork 是一个内置的基于 VXLAN 的网络驱动

VXLAN

overlay就是隧道模式,容器A和容器B是不互通的,但是主机上的底层网络是互通的,overlay就是主机上的包发出去的时候,从主机A容器访问主机B容器,本身是不互通的。

 overlay就是在每一个主机上面有一个设备,这个设备会处理每一个数据包,如果是容器网络的数据包,他会在容器网络的原始数据包上面加一层,在linux里面看到的任何的数据包,看到的是skb,skb会看到每一层header,ipheader,tcpheader,他可以在不破坏原来的header基础之上,在上面再加一层header,那么加上的这一层的原始地址就是主机A的地址,目标地址就是主机B的地址,这样数据包就可以传到对端了。

 传到对端后,主机B的虚拟设备再把外层的header剥掉,剩下的数据包就是原来的数据包了,这样的话在主机上处理原始数据包的时候,看到目标地址,就知道是主机B的容器,就知道走哪个口了。所以所谓的overlay就是封包解包的过程。

Flannel

  比较出名的flannel就是走overlay的,默认的主机上装的就是overlay的模式。flannel在每个主机上就会有flannel这样一个设备,任何数据包出去的时候,会被flannel封一层,这样数据包就能到达对端。


目录
相关文章
|
7天前
|
SQL 安全 算法
网络安全与信息安全:攻防之间的技术博弈
【4月更文挑战第20天】在数字化时代,网络安全与信息安全已成为维护国家安全、企业利益和个人隐私的重要屏障。本文深入探讨了网络安全漏洞的成因、加密技术的进展以及提升安全意识的必要性,旨在为读者提供全面的网络安全知识框架,同时分享最新的防御策略和技术手段。通过对网络攻防技术的分析,本文揭示了安全防御的复杂性,并强调了持续教育和技术创新在网络安全领域的重要性。
16 6
|
24天前
|
SQL 安全 算法
网络安全与信息安全:防御前线的关键技术与意识
【4月更文挑战第3天】在数字化时代,网络安全与信息安全已成为维护信息完整性、确保数据私密性和保障系统可用性的基石。本文深入探讨了网络安全漏洞的概念、加密技术的应用以及提升安全意识的重要性,旨在为读者提供全面的网络安全知识框架,以应对日益复杂的网络威胁。
|
17天前
|
数据采集 大数据 数据安全/隐私保护
掌握网络抓取技术:利用RobotRules库的Perl下载器一览小红书的世界
本文探讨了使用Perl和RobotRules库在遵循robots.txt规则下抓取小红书数据的方法。通过分析小红书的robots.txt文件,配合亿牛云爬虫代理隐藏真实IP,以及实现多线程抓取,提高了数据采集效率。示例代码展示了如何创建一个尊重网站规则的数据下载器,并强调了代理IP稳定性和抓取频率控制的重要性。
掌握网络抓取技术:利用RobotRules库的Perl下载器一览小红书的世界
|
1天前
|
存储 缓存 开发框架
Flutter的网络请求:使用Dart进行HTTP请求的技术详解
【4月更文挑战第26天】了解Flutter网络请求,本文详述使用Dart进行HTTP请求
|
2天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:防护之道在技术与意识的双重保障
【4月更文挑战第25天】随着信息技术的飞速发展,网络已经成为我们生活和工作中不可或缺的一部分。然而,伴随着网络技术的普及,网络安全问题也日益凸显。本文将从网络安全漏洞、加密技术、安全意识等方面进行探讨,旨在分享如何通过技术和意识的双重保障来维护网络的安全。
|
3天前
|
SQL 监控 安全
网络安全与信息安全:防御前线的关键技术与策略
【4月更文挑战第24天】在数字化时代,数据成为了新的货币,而网络安全则是保护这些宝贵资产不受威胁的保险箱。本文深入探讨了网络安全漏洞的本质、加密技术的进展以及提升个人和企业安全意识的重要性。通过分析当前网络环境中的安全挑战,我们提出了一系列创新的防御机制和实践方法,以期为读者提供一套全面的信息保护方案。
|
3天前
|
存储 监控 安全
网络安全与信息安全:防御前线的技术与意识
【4月更文挑战第24天】在数字化时代,网络和信息安全已成为维护社会稳定、保护个人隐私和企业资产的关键。本文深入探讨了网络安全漏洞的概念、加密技术的进展以及提升安全意识的重要性。通过分析当前网络威胁的多样性,我们强调了持续监控、定期更新系统、使用复杂密码和多因素认证的必要性。同时,文章还介绍了非对称加密、量子加密等先进加密技术的原理和应用。最后,我们讨论了培养全民网络安全意识的策略,包括教育培训、模拟演练和社会工程防护。
|
3天前
|
弹性计算 测试技术 持续交付
Docker技术这些应用场景,你知道吗?
Docker技术这些应用场景,你知道吗?
|
6天前
|
运维 前端开发 Devops
云效产品使用报错问题之流水线打包docker镜像时报网络代理有问题如何解决
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
6天前
|
安全 物联网 网络安全
网络安全与信息安全:防御前线的关键技术与策略
【4月更文挑战第21天】在数字化时代,数据成为了新的货币,而网络安全则是保护这些资产不受威胁的盾牌。本文深入探讨了网络安全漏洞的本质、加密技术的进展以及提升个人和企业安全意识的方法。通过分析当前网络攻击的模式和动机,我们提出了一系列切实可行的防御措施,旨在帮助读者构建更加安全的网络环境。