百度微服务架构师随手笔记:教你如何手写Docker

模拟Docker实现一个简单的容器,不到 200行代码(包括空行、注释、异常处理),这并不是吹牛B。容器技术几乎是Linux kernel内置的模块,我们简单调用一下API就能搞定很多事情。当然你要考虑各种商业因素、政治因素那就会成长为Docker这种量级的代码量了。

盗用一下朋友圈里的段子:小公司与大公司的区别就是,以杀猪为例,小公司是找到猪直接乱刀砍死。大公司要先做一套笼具抓猪,再做一套流程磨刀,再发明一套刀法(工程师通常会就刀法争论很久)杀猪。抓猪的笼具除了能抓猪还能抓跳骚,磨刀的工具除了能磨柴刀,还能磨指甲刀。杀猪的流程除了能杀猪,也能杀鸡。做完了之后你只敲一个杀猪的命令就行。你不知道猪在哪里,因为这是另一个人负责的,代码放在你不知道的某个目录下;你也不知道刀在哪里,因为目录不可见,格式不可读。刀法是啥你也不知道。这套系统理论上威力无比,一群人费了老大劲做出来,除了用柴刀杀猪没干过别的,杀鸡从来没测试过,杀跳骚代码都不完整。但是公司里的所有人都觉得,杀猪就应该这样。所以大家每天忙忙碌碌,猪快活的过了一年又一年。

所以这系列文章我主要介绍如何找到猪、怎么持刀不伤到自己,如何发力能够更凶狠;然后现场表演一下把一头活蹦乱跳的猪捅死。

涉及到的技术

写一个容器只需要两个技术——Namespace和CGroup,而这两个东西都是Linux kernel提供的,我们要做的就是——调用一下。无耻的盗用一下Brendan Gregg大神的图。

这张图中蕴含了一个经常被忽视的细节——容器是共享内核的,它们属于多个进程同时运行在一个内核上,只不过是利用Namespace把它们隔离开,用CGroup限制可用资源。而虚拟机是共享“硬件”的,每个虚拟机都有自己独立的操作系统。所以,虚拟机是可引导的、绝对安全的隔离技术;而容器是非常脆弱的,不安全的隔离技术。

Namespace是Linux内核提供的一种隔离技术,它提供了六种隔离空间:

看的一脸懵逼对不对?没关系,简单的解释一下。

学过操作系统原理的同学都知道(没学过?你还敢在这个行业混?),在一个内核所有进程都共享操作系统定义的资源——主机名、域名、ARP表、路由表、NAT表;文件系统、用户和组、进程编号。以主机名为例,它是由操作系统定义在一块内存空间中的,所以进程A能看到,进程B也能看到(如果有权限甚至可以修改)。Namespace提供了一种隔离技术,可以让每个进程都定义“自己的主机名”。你可以理解为内核为每个进程都提供了一份当前主机名的备份,进程当然可以修改这份数据,但是这个修改只能作用于自己,其他进程感知不到——因为它不再是“全局”的。

经常有人问是不是所有应用都可以做容器化?理解Namespace就很容易回答这个问题。容器技术本质上还是共享内核,所以任何需要修改内核的应用都不可以被容器化。比如LVS、OpenvSwtich这些需要加载内核模块的应用都没有办法做成容器。

Hello world

调用Namespace非常简单,只需要一个API(没错,一个,只要一个)——clone。

它会创建一个新的线程(内核不会太区分线程和进程),第一个参数指定了线程的代码入口,第二个参数是线程栈,第三个参数是标志位,第四个参数是代码入口的参数指针。

我们上面所罗列的Namespace参数就是通过第三个参数——标志位传递的。

我们先测试一下UTS(主机名)是否能正常工作,因为子进程不涉及到递归调用所以定义1024字节的stack大小应该足够了。main方法里的os.waitpid(pid, 0)是必须的,否则子进程会因为父进程终止而提前退出。

child_func是子进程的入口,这段代码里我们调用sethostname修改主机然后再执行hostname验证修改是否生效了。

libc是我封装好的系统调用,非常简单。

小试牛刀一下:

首先在父进程中输出自己的进程编号和子进程的编号,然后在子进程中输出自己的进程编号和父进程的编号。在子进程中我们调用sethostname修改了主机名并且通过hostname验证了调用结果。但是这个修改并没有波及到内核,最后我们在shell中调用hostname验证了这一结果。

要有Shell

上面只是执行一次修改hostname的动作,动作有点小,不够过瘾。我们希望能够在独立的Namespace中拿到一个shell。

只需要更改两行代码。父进程里面增加NEW_PID、NEW_IPC的标志位,子进程里调用execle执行bash,通过最后一个参数指定了环境变量PS1,这个表示提示符。

再次执行,我们发现shell已经变化了。通过hostname验证我们已经“在容器里面”了。键入exit,退出容器。

是不是已经无法掩盖自己内心的兴奋了。别急,还有更兴奋的,我们进行第三步——分离文件系统。

彻底分离

如果你在上一部的shell中输入一些top、ps、ls命令会发现几乎和“Host”环境中一摸一样。这是因为我们还没有做最重要的一部——分离文件系统。

Docker提供的有Ubuntu、CentOS的镜像,其实这些并不是严格意义上的镜像,它们准确的叫法应该是——根文件系统(root filesystem)。

容器是共享内核的,所以无论是Ubuntu、CentOS它们里面都使用Host的内核,如果你在Docker中通过uname查看会发现无论什么镜像它们的内核版本都和Host一摸一样。所以,不同“操作系统”Docker镜像其实就是不同的根文件系统。

很多人用BusyBox的rootfs做演示,作为一个风骚的男人怎么怎么可能如此俗套。所以我用CentOS 7作为演示。

真正的原因切换容器中的根目录,后续的代码执行会使用新的根文件系统,而后续的代码是依赖Python运行环境的。所以我们需要一个带Python的rootfs,CentOS 7刚好满足这个。如果我们用C或者Golang就不会有这个限制了。

你可以通过CentOS提供的Dockerfile找到相关的rootfs的下载,比如:https://github.com/CentOS/sig- ... ocker

把下载到的文件解压到/tmp目录下。

分离文件系统分为三个步骤,首先我们建立容器里面的/proc文件系统,很多Linux命令都是读取这个文件系统下的内容(比如top中显示的进程列表);其次我们要把现在的用户和容器里面的用户做映射,否则会提示权限不足;最后我们要通过pivot_root 函数把“切换”根文件系统。

不要忘记修改main方法,为标志位增加三个参数,映射用户。

再次执行。

和CentOS 7一摸一样,你甚至可以用yum命令,当然由于我们现在还没有实现网络功能所以yum会告诉你无法访问网络。

再多执行几个添加文件、删除文件看看?你会发现无论做什么动作最终的数据都会被牢牢地固定在/tmp/rootfs下,也就是说——在容器里面我们是没有办法访问host的文件的。

完整代码:https://github.com/fireflyc/mini-docker。

推荐一个交流学习群:685167672 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多:

原文地址:https://www.cnblogs.com/jdx6/p/8686812.html

时间: 2024-10-08 19:00:35

百度微服务架构师随手笔记:教你如何手写Docker的相关文章

《微服务设计》读书笔记大纲

cha1:微服务的概念--<微服务设计>读书笔记 cha2:微服务架构师的职责--<微服务设计读书笔记> cha3:建模:确定服务的边界--<微服务设计>读书笔记 cha4:微服务集成--<微服务设计>读书笔记 服务的协作:服务间的消息传递--<微服务设计>读书笔记 cha5:拆分:分解单块系统--<微服务设计>读书笔记 cha6:部署:持续集成(CI)与持续交付(CD)--<微服务设计>读书笔记 cha7:测试--<

微服务架构与实践及云原生等相关概念

微服务架构与实践 笔记:<微服务架构与实践> 王磊 著 一 单块架构 1 定义:对于这种功能集中.代码和数据中心化.一个发布包.部署后运行在同一进程的应用程序,我们通常称之为单块架构应用,并非物理上的分层. 2 单层架构:数据 逻辑 页面 混合 3 三层架构: 1)表示层:数据显示和用户交互 2)业务逻辑层:业务逻辑处理 3)数据访问层:数据存储访问 4 优势: 比较适合小项目 易于开发:开发简单直接,集中式管理,基本不会重复开发,集成工具适合 易于测试:单进程 易于部署:单项目包,功能都在本

聊聊微服务架构与应用

>>微服务架构 随着敏捷开发.持续交付以及基于Docker的应用部署的发展,微服务结构开始慢慢流行起来. >>应用架构演进 (1)垂直应用架构 传统的LAMP架构和Spring+Struts+iBatis/Hibernate的架构都是典型的垂直应用架构,垂直应用架构学习成本低,开发产出快,测试.部署和运维比较简单,在过去的十几年中一直比较流行.但是随着业务的发展,垂直应用架构逐渐暴露出一些缺陷,以Spring MVC架构为例,可能的表现:1.复杂应用的开发维护成本越来越高,测试变得

SpringCloud与Docker微服务架构实战pdf

下载地址:网盘下载 作为一部帮助大家实现微服务架构落地的作品,<Spring Cloud与Docker微服务架构实战>覆盖了微服务理论.微服务开发框架(Spring Cloud)以及运行平台(Docker)三大主题.全书可分为三部分,第1章对微服务架构进行了系统的介绍:第2-11章使用Spring Cloud开发框架编写了一个"电影售票系统":第12-14章则讲解了如何将微服务应用运行在Docker之上.全书Demo驱动学习,以连贯的场景.具体的代码示例来引导读者学习相关知

百度“百老汇”架构师深刻透视微服务架构

首先解释这个"百老汇"=百度老年架构师活动中心.......什么是微服务首先微服务并没有一个官方的定义,想要直接描述微服务比较困难,我们可以通过对比传统WEB应用,来理解什么是微服务.传统的WEB应用核心分为业务逻辑.适配器以及API或通过UI访问的WEB界面.业务逻辑定义业务流程.业务规则以及领域实体.适配器包括数据库访问组件.消息组件以及访问接口等.一个打车软件的架构图如下: 尽管也是遵循模块化开发,但最终它们会打包并部署为单体式应用.例如Java应用程序会被打包成WAR,部署在T

你真的了解微服务架构吗?听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构

微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业界已经有一些很有影响力的开源微服务架构框架提供了微服务的关键思路,例如Dubbo和Spring Cloud.各大互联网公司也有自研的微服务框架,但其模式都于这二者相差不大. 微服务主要的优势如下: 1.降低复杂度 将原来偶合在一起的复杂业务拆分为单个服务,规避了原本复杂度无止境的积累.每一个微服务专

听听八年阿里架构师怎样讲述Dubbo和Spring Cloud微服务架构

转自:https://baijiahao.baidu.com/s?id=1600174787011483381&wfr=spider&for=pc 微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然微服务架构没有公认的技术标准和规范或者草案,但业界已经有一些很有影响力的开源微服务架构框架提供了微服务的关键思路,例如Dubbo和Spring Cloud.各大互联网公司也有自研的微服务框架,但

个推首席架构师Qcon分享 |微服务架构的那些事儿

微服务架构需要注意哪些问题? 微服务架构,首先考虑客户端与服务端之间的通信问题.有两种解决办法,一是客户端与多个服务端直接进行通信,但存在对外暴露接口细节.众多接口协议无法统一.客户端的代码复杂.服务端升级相对困难等问题.二是客户端访问统一的API网关,由API网关调用众多服务接口,易实现统一通信协议,降低客户端和服务端代码耦合,也可以达到统一的鉴权和流控,然而此方式存在延时增加的风险,可能使API网关成为系统发展的瓶颈. 微服务架构是分布式服务架构,如何进行服务的注册和发现也是需要解决的问题.

阿里P8高级架构师带你领略阿里巴巴微服务架构——最后有惊喜哦

Dubbo微服务框架的核心功能 启动时检查 ?Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true" 集群容错 failover 失败自动切换,当出现失败重试其它服务器.通常用于读操作,重试带来更长延迟. failfast快速失败,只发起一次调用,失败立即报错.通常用于非幂等性写操作,如新增记录. failsafe失败安全,出现异常时,直接忽略.通常用于写入审计日志等操作. fai