深入浅出Docker
1. Docker引擎
Docker引擎是用来运行和管理容器的核心软件。通常人们会简单的将其指代为Docker或Docker平台。
基于开放容器计划(OCI)相关的标准要求,Docker引擎采用了模块化
的设计原则,其组件是可替换的。
Docker引擎由如下主要的组件构成:Docker客户端(Docker Client)、Docker守护进程(Docker daemon)、containerd以及runc。
Docker引擎的架构示意图,如下
1.1 runc
runc
是OCI容器运行时
规范的参考实现。去粗取精,会发现runc实质上是一个轻量级的、针对Libcontainer
进行了包装的命令行交互工具(Libcontainer取代了早期Docker架构中的LXC
,LXC提供了对诸如命令空间namespace和控制组CGroup等基础工具的操作能力)
runc生来只有一个作用 — 创建容器,它是一个CLI包装器,实质上就是一个独立的容器运行时工具。因此直接下载它或者基于源码编译二进制文件,即可拥有一个全功能的runc。但它只是一个基础工具,并不提供类似Docker引擎所拥有的丰富功能。
1.2 containerd
在对Docker daemon
的功能拆解后,所有的容器执行逻辑被重构到一个新的名为containerd
的工具中。它的主要任务是容器的生命周期管理 — start|stop|pause|rm...
在Docker引擎技术栈中,containerd位于daemon和runc所在的OCI层之间。Kubernetes
也可以通过cri-containerd
使用containerd。
1.3 启动一个新的容器(流程)
现在我们对Docker引擎已经有了一个总体认识,也了解了一些历史,下面介绍一下创建新容器的过程。
常用的启动容器的方法就是使用Docker命令行工具。下面的docker container run命令会基于alpine:latest
镜像启动一个新容器。
docker container run --name ctr1 -it alpine:latest sh
当使用Docker命令行工具执行如上命令时,Docker客户端会将其转换
为合适的API格式,并发送到正确的API端点。
API是在daemon
中实现的。这套功能丰富、基于版本的REST API已经成为Docker的标志,并且被行业接受成为事实上的容器API。
一旦daemon接收到创建新容器的命令,它就会向containerd
发出调用。daemon已经不再包含任何创建容器的代码了!
daemon使用一种CRUD风格的API,通过gRPC与containerd进行通信。
虽然名叫containerd,但是它并不负责创建容器,而是指挥runc
去做。containerd将Docker镜像转换为OCI bundle
,并让runc基于此创建一个新的容器。
然后,runc与操作系统内核接口进行通信,基于所有必要的工具(Namespace
、CGroup
等)来创建容器。容器进程作为runc的子进程
启动,启动完毕后,runc将会退出。
现在,容器启动完毕了。整个过程如下图。
1.4 shim
shim是实现无daemon的容器不可或缺的工具。
前面提到,containerd指挥runc来创建新容器。事实上,每次创建容器时它都会fork
一个新的runc实例。不过,一旦容器创建完毕,对应的runc进程就会退出。
一旦容器进程的父进程runc退出
,相关联的containerd-shim
进程就会成为容器的父进程
。
作为容器的父进程,shim的部分职责
如下。
- 保持所有STDIN和STDOUT流是开启窗台,从而当daemon重启的时候,容器不回因为管道(pipe)的关闭而终止。
- 将容器的退出状态反馈给daemon。
1.5 daemon的作用
当所有的执行逻辑和运行时代码都从daemon中剥离出来之后,daemon的主要功能包括镜像管理、镜像构建、REST API、身份验证、安全、核心网络以及编排
。
2. Docker镜像
Docker镜像就是停止运行的容器。如果读者是一名研发人员,可以将镜像理解为类Class。
读者需要先从镜像仓库
服务中拉取镜像。常见的镜像仓库服务是Docker Hub,但是也存在其他镜像仓库服务。
镜像由多个层租场,每层叠加之后,从外部看起来就如一个独立的对象。镜像内部是一个精简的操作系统(OS),同时还包含应用运行所必须的文件和依赖包。
镜像中不包含内核
,容器都是共享所在Docker主机的内核。
3. Docker容器
容器是镜像的运行时实例。虚拟机和容器最大的区别是容器更快并且更轻量级,与虚拟机运行在完整的操作系统之上相比,容器会共享其所在主机的操作系统/内核
。
3.1 容器 vs 虚拟机
从更高层面上讲,Hypervisor是硬件虚拟化
,Hypervisor将硬件物理资源划分为虚拟资源;容器是操作系统虚拟化
,容器将系统资源划分为虚拟资源。
虚拟机模型
在虚拟机模型中,首先要开启物理机并启动Hypervisor
引导程序,一旦Hypervisor启动,就会占有机器上的全部物理资源,如CPU、RAM、存储以及NIC。Hypervisor接下来就会将这些物理资源
划分为虚拟资源
,并且看起来与真实物理资源完全一致。
然后Hypervisor会将这些资源打包进一个叫做虚拟机(VM)的软件结构
当中。这样用户就可以使用这些虚拟机,并在其中安装操作系统和应用。
容器模型
与操作系统模型相同的是,OS也占用了全部硬件资源。
在OS层之上,需要安装容器引擎(如Docker)
。容器引擎可以获取系统资源
,如进程树、文件系统以及网络栈,接着将资源分割为安全的相互隔离的资源结构,称之为容器
。每个容器看起来就像一个真实的操作系统,在其内部可以运行应用。
虚拟机的额外开销
虚拟机模型
通过Hypervisor将底层硬件资源划分为虚拟机当中。每个虚拟机都是包含了虚拟CPU、虚拟RAM、虚拟磁盘等资源的一种软件结构。因此,每个虚拟机都需要有自己的操作系统来声明、初始化并管理这些虚拟资源。但不幸的是,操作系统本身是有额外开销的。
容器模型
具有宿主机操作系统中运行的单个内核。这意味着只有一个操作系统消耗CPU、RAM和存储资源。简而言之,就是只有一份OS损耗!
4. 应用容器化
容器是为应用而生!具体来说,容器能够简化应用的构建、部署和运行过程。
完整的应用容器化过程主要分为以下几个步骤。
(1)编写应用代码。
(2)创建一个Dockerfile,其中包括当前应用的描述、依赖以及该如何运行这个应用。
(3)对该Dockerfile执行docker image build命令。
(4)等待Docker将应用程序构建到Docker镜像中。
5. 容器网络
Docker对于容器之间、容器与外部网络和VLAN之间的连接均有相应的解决方案。
Docker网络架构源自一种叫做容器网络模型(CNM)
的方案,该方案是开源的并且支持插接式
连接。Libnetwork
是Docker对CNM的一种实现,提供了Docker核心网络架构的全部功能。不同的驱动
可以通过插拔的方式接入Libnetwork来提供定制化的网络拓扑。
为了实现开箱即用的效果,Docker封装了一系列本地驱动,覆盖了大部分常见的网络需求。其中包括单机桥接网络(Single-Host Bridge Network)、多机覆盖网络(Multi-Host Overlay),并且支持接入现有VLAN。
最后要说的是,Libnetwork提供了本地服务发现和基础的容器负载均衡解决方案。
基础理论
在顶层设计中,Docker网络架构由3个主要部分
构成:CNM、Libnetwork、驱动。
CNM是设计标准。Libnetwork是CNM的具体实现。驱动通过实现特定网络拓扑的方式来扩展该模型的能力。
5.1 CNM
Docker网络架构的设计规范是CNM。CNM中规定了Docker网络的基础组成要素。
CNM定义了3个基本要素:沙盒
(Sandbox)、终端
(Endpoint)和网络
(Network)。
-
沙盒
是一个独立的网络栈。其中包括以太网接口、端口、路由表以及DNS配置。 -
终端
就是虚拟网络接口。在CNM中,终端负责将沙盒连接到网络。 -
网络
是802.1d网桥
(类似于大家熟知的交换机)的软件实现。因此,网络就是需要交换的终端的集合,并且终端之间相互独立。
Docker环境中最小的调度单位就是容器,图11.3展示了CNM组件是如何与容器进行关联的 — 沙盒被放置在容器内部
,为容器提供网络连接。
容器A只有一个网络接口(终端)并连接到了网络A。容器B有两个接口(终端)并且分别接入了网络A和网络B。容器A和容器B之间是可以相互通信的,因为都接入了网络A。但是,如果没有三层路由器
的支持,容器B的两个终端之间是不能通信的。
5.2 Libnetwork
CNM是设计规范文档,Libnetwork
是标准的实现。
Docker将网络部分从daemon中拆分,并重构为一个叫作Libnetwork的外部类库。Libnetwork实现了CNM中定义的全部3个组件。此外它还实现了本地服务发现(Service Discovery)、基于ingress的容器负载均衡,以及网络控制层和管理层功能。
5.3 驱动
如果说Libnetwork实现了控制层和管理层功能,那么驱动
就负责实现数据层
。
Docker封装了若干内置驱动
,通常被称为原生驱动或者本地驱动。在Linux上包括Bridge、Overlay以及Macvlan。第三方也可以编写Docker网络驱动,这些驱动叫作远程驱动,例如Calico、Contiv、Kuryr以及Weave。
每个驱动都负责其上所有网络资源的创建和管理。
6. Docker覆盖网络Overlay
容器间通信的可靠性和安全性相当重要,即使容器分属于不同网络中的不同主机。这也是覆盖网络大展拳脚的地方,它允许读者创建扁平、安全的二层网络
来连接多个主机,容器可以连接到覆盖网络并直接通信。
创建overlay网络命令
docker network create -d overlay uber-net
6.1 工作原理VXLAN
首先必须知道,Docker使用VXLAN隧道技术创建了虚拟二层覆盖网络
。
在VXLAN的设计中,允许用户基于已经存在的三层网络结构创建虚拟二层网络。VXLAN的美妙之处在于它是一种封装
技术,能使现存的路由器和网络架构看起来就像普通的IP/UDP包
一样,并且处理起来毫无问题。
为了创建二层覆盖网络,VXLAN基于现有的三层IP网络创建了隧道
,VXLAN隧道终端(VXLAN Tunnel Endpoint, VTEP
)。VTEP完成了封装和解压的步骤,以及一些功能实现所必须的操作。
6.2 网络联通举例
假设当前有2个网络(172.31.1.0/24,192.168.1.0/24),每个网络下有一台主机。通过IP网络将两台主机连接起来。每个主机运行了一个容器,之后又为容器连接创建一个VXLAN覆盖网络
。
为了实现上述场景,在每台主机上都新建了一个Sandbox
(网络命名空间)。Sandbox就像一个容器,但其中运行的不是应用,而是当前主机上独立的网络栈
。
在Sandbox内部创建了一个名为Br0
的虚拟交换机
(又称虚拟网桥
)。同时Sandbox内部还创建了一个VTEP,其中一端接入到名为Br0的虚拟交换机当中,另一端接入主机网络栈(VTEP
)。在主机网络栈中的终端从主机所连接的基础网络中获取到IP地址,并以UDP Socket的方式绑定到4789端口。不同主机上的两个VTEP通过VXLAN隧道创建了一个覆盖网络,如下图所示。
这是VXLAN上层网络创建和使用所必需的。
接下来每个容器都会有自己的虚拟以太网(veth)适配器
,并接入本地Br0虚拟交换机。目前拓扑结果如图12.7
所示,虽然是在主机所属网络互相独立的情况下,但这样能更容器看出两个分别位于不同主机上的容器之间是如何通过VXLAN上层网络进行通信的。
6.3 通信示例
在本例中,将node1
上的容器称为C1
,node2
上的容器称为C2
,如图12.8
所示。假设C1
希望ping
通C2
。
C1
发送ping请求,目标IP为C2的地址10.0.0.4
。该请求的流量通过连接到Br0虚拟交换机
的veth接口
发出。虚拟交换机并不知道将包发送在哪里,因为在虚拟交换机的MAC地址映射表(ARP映射表)
中并没有与当前目的IP对应的MAC地址
。所以虚拟交换机会将该包发送到其上的全部端口。连接到Br0的VTEP接口
知道如何转发这个数据帧,所以会将自己的MAC地址返回。这就是一个代理ARP响应
,并且虚拟交换机Br0根据返回结果学会了如何转发该包。接下来虚拟交换机会更新自己的ARP映射表
,叫10.0.0.4映射到本地VTEP
的MAC地址
上。
现在Br0交换机
已经学会如何转发目标C2
的流量,接下来所有发送到C2的包都会被直接转发到VTEP接口。VTEP接口知道C2,是因为所有新启动的容器都会将自己的网络详情采用网络内置Gossip协议
发送给相同Swarm集群内的其他节点。
交换机会将包转发到VTEP接口,VTEP完成数据帧的封装
,这样就能在底层网络传输。具体来说,封装操作就是把VXLAN Header
信息添加到以太帧当中。
VXLAN Header
信息包含了VXLAN网络ID(VNID
),其作用是记录VLAN到VXLAN的映射关系。每个VLAN
都对应一个VNID,以便可以在解析后被转发到正确的VLAN。封装的时候会将数据帧放到UDP包中,并设置UDP的目的IP字段为node2
节点的VTEP
的IP地址
,同时设置UDP Socket端口为4789。这种封装方式保证了底层网络即使不知道任何关于VXLAN的信息,也可以完成数据传输。
当包达到node2
之后,内核发现目的端口为UDP端口4789,同时还知道存在VTEP接口绑定到该Socket。所以内核
将包发给VTEP,由VTEP读取VNID,解压包信息,并根据VNID发送到本地名为Br0
的连接到VLAN的交换机上。在该交换机上,包被发送给容器C2
。
以上大体介绍了Docker覆盖网络是如何利用VXLAN技术的。
相关文章:

深入浅出Docker
1. Docker引擎 Docker引擎是用来运行和管理容器的核心软件。通常人们会简单的将其指代为Docker或Docker平台。 基于开放容器计划(OCI)相关的标准要求,Docker引擎采用了模块化的设计原则,其组件是可替换的。 Docker引擎由如下主…...

Flink 与 Kubernetes (K8s)、YARN 和 Mesos集成对比
Flink 与 Kubernetes (K8s)、YARN 和 Mesos 的紧密集成,是 Flink 能够在不同分布式环境中高效运行的关键特性。 Flink 提供了与这些资源管理系统的深度集成,以便在多种集群管理环境下提交、运行和管理 Flink 作业。Flink 与 K8s、YARN 和 Mesos 集成的详…...
Python 集合的魔法:解锁高效数据处理的秘密
引言 集合作为 Python 的一种内置数据类型,其本质是一个无序且不重复的元素序列。虽然表面上看它似乎只是列表或元组的一种变体,但实际上,集合背后有着更为高效的查找机制。通过学习和掌握集合的高级操作,我们不仅能更好地理解 P…...
Go必知必会:构建复杂数据模型的基石
Go语言以其清晰的语法和强大的内置类型系统,为构建高效且易于维护的软件程序提供了坚实的基础。在Go的数据类型体系中,结构体(struct)扮演着至关重要的角色,它是实现复杂数据模型的关键工具。结构体允许开发者将多个不…...

大数据Flink(一百一十七):Flink SQL的窗口操作
文章目录 Flink SQL的窗口操作 一、窗口的概述 二、Group Windows 1、滚动窗口(TUMBLE) 2、滑动窗口(HOP) 3、Session 窗口(SESSION&am…...

【西电电装实习】6. 手装无人机的蓝牙断连debug
文章目录 前言零、闪灯状态零零、翻滚角,俯仰角,偏航角一、问题描述二、现象解释三、解决方案参考文献 前言 在 西电无人机电装实习 时遇到的问题使用蓝牙芯片 CH582F。沁恒的蓝牙芯片CH582F是一款集成了BLE(Bluetooth Low Energy࿰…...

AIGC实战之如何构建出更好的大模型RAG系统
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…...

【数据结构-差分】力扣1589. 所有排列中的最大和
有一个整数数组 nums ,和一个查询数组 requests ,其中 requests[i] [starti, endi] 。第 i 个查询求 nums[starti] nums[starti 1] … nums[endi - 1] nums[endi] 的结果 ,starti 和 endi 数组索引都是 从 0 开始 的。 你可以任意排列…...

Spark部署文档
Spark Local环境部署 下载地址 https://dlcdn.apache.org/spark/spark-3.2.0/spark-3.2.0-bin-hadoop3.2.tgz 条件 PYTHON 推荐3.8JDK 1.8 Anaconda On Linux 安装 本次课程的Python环境需要安装到Linux(虚拟机)和Windows(本机)上 参见最下方, 附: Anaconda On Linux 安…...

Broadcast:Android中实现组件及进程间通信
目录 一,Broadcast和BroadcastReceiver 1,简介 2,广播使用 二,静态注册和动态注册 三,无序广播和有序广播 1,有序广播的使用 2,有序广播的截断 3,有序广播的信息传递 四&am…...
5分钟熟练上手ES的具体使用
5分钟上手ES的具体使用 相信有很多同学想要去学习elk时会使用docker等一些方式去下载相关程序,但提到真正去使用es的一系列操作时又会知之甚少。于是这一篇博客应运而生。 本文就以下载好elk/efk系统后应该如何去使用为例,介绍es的具体操作。 es关键字…...

lambda 自调用递归
从前序与中序遍历序列构造二叉树 官方解析实在是记不住,翻别人的题解发现了一个有意思的写法 class Solution { public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {auto dfs [](auto&& dfs, auto&&…...

mac中git操作账号的删除
命令行玩的很溜的可以跳过 找到钥匙串访问 搜github、gitee就行了...

AI Agent的20个趋势洞察
结论整理自【QuestMobile2024 AI智能体应用洞察半年报】: AI原生应用(APP)一路高歌;豆包用户突破3000万;TOP10 APP以综合类应用为主。无论何种类型的AIGC APP都以智能体为“抓手”,专注于解决各种细分场景中的问题&am…...
Spring Boot-定时任务问题
Spring Boot 定时任务问题及其解决方案 1. 引言 在企业级应用中,定时任务是一项常见需求,通常用于自动化执行某些操作,如数据备份、日志清理、系统监控等。Spring Boot 提供了简洁易用的定时任务机制,允许开发者通过简单的配置来…...

从混乱到清晰!借助Kimi掌握螺旋型论文结构的秘诀!
AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 写学术论文有时会让人感到头疼,特别是在组织结构和理清思路时,往往觉得无从下手。 其实,找到合适的结构不仅能帮你清晰地表达研究成果,还能让你的论文更有说…...
中国电子学会202306青少年软件编程(Python)等级考试试卷(二级)真题
一、单选题(共25题,每题2分,共50分) 1、运行以下程序,如果通过键盘先后输入的数是1和3,输出的结果是?( ) a = int(input()) b = int(input()) if a < b:a = b print(a)A. 3 1 B. 1 3 C. 1 D. 3 2、运行以下程序,输出的结果是?( ) n = 10 s = 0 m = 1 while…...

样本册3D翻页电子版和印刷版同时拥有是一种什么体验
在数字化时代,样本册3D翻页电子版的兴起,让传统印刷版样本册面临着前所未有的挑战。与此同时,许多企业也开始尝试将两者相结合,以满足更多元化的市场需求。那么,拥有一份既具备数字化优势,又保留传统印刷…...

8586 括号匹配检验
### 思路 1. **初始化栈**:创建一个空栈用于存储左括号。 2. **遍历字符串**:逐个字符检查: - 如果是左括号(( 或 [),则入栈。 - 如果是右括号() 或 ]),则检查栈是…...

案例精选 | 聚铭助力河北省某市公安局筑牢网络安全防护屏障
近年来,各级公安机关积极响应信息化发展趋势,致力于提升公安工作的效能与核心战斗力。河北省某市公安局作为主管全市公安工作的市政府部门,承担着打击违法犯罪、维护社会稳定的重任。随着信息化建设的推进,局内系统数量、种类及数…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...