写点什么

云原生:详解|容器核心技术解析

作者:息之
  • 2021 年 12 月 01 日
  • 本文字数:6734 字

    阅读完需:约 22 分钟

云世

原创 谭一笑,左太冲 云世  2021-10-17 21:05

收录于话题

#云原生 210 个内容

#Docker 容器 42 个内容


先认识架构应用趋势


业界不断有架构方面的探索,从最开始的我们所熟知的这种单体架构,后来大概在 10 年前左右,大家又推崇面向服务的架构叫 SOA server service oriented architecture。 SOA 就是把业务解绑,把一个大的系统分到不同的子模块,子模块和子模块之间,通过 API 调用去交互的模式。

SOA 架构衍生到最后出现了一个一个模块叫做系统服务总线,系统服务总线作为一个统一的 API,让所有微服务之间互相调用,但是最后随着业务的复杂性提升,这个业务总线又变得巨复杂了。


然后 SOA 再往前演进,衍生到了我们所熟知的微服务架构。微服务架构,可以把它理解为 SOA 架构的一种最佳实践。没有强制性要求微服务和微服务之间一定要根据企业总线去通信,鼓励点对点通信,也可以说是开放一个统一的 API 网关,然后微服务和微服务之间互相去通信。

一个应用,一个大的系统一个大的平台,它可能会被切分成几百上千个微服务。一个业务流有可能一个用户点击了某个页面上的某个按钮,从背后来看,从真正实现来看,可能是微服务调微服务,再调微服务,有可能一个业务流后面你前端点了一个按钮,后端可能是有几百个应用在互相调用,这带给大家就是在业务架构上面带来一个什么样的挑战?

就是 A 服务掉 B 服务的时候,服务发现怎么做?


调用这个服务的地址是什么?一般都是一个 IP 地址加一个端口。

起一个任何的应用,都是一个 IP 地址加一个端口。作为一个服务提供商,发布一个服务的时候,就是要把服务发布到某一个机器机器上面,无论它是一个物理机还是虚拟机。要有一个独立的 IP,一个独立端口,有一个固定访问的 URL。这样服务发布出去,别人就可以来调用了。

传统的做法有两种方式,一种是物理机,可以把很多应用放上去,一台机器有一个 IP。 IP 可以有很多端口,把很多的服务按以不同的端口发布在这台机器上面,这样就可以发布多个服务了。带来挑战是什么?如果想发布多个 web 服务,他们 IP 一样的话,就得换端口,比如很可能 80 端口被别人用了,其他应用就用不了 80 端口了,所以早期基于物理机的进程部署,就会有这样的挑战。


随着时间发展就出了虚拟化技术,一个物理机,把它切成不同的虚拟机,每个虚拟机是一个独立的操作系统,每一个虚拟机都有自己独立的 IP。在第一个虚拟机里面装一个 web 应用,在第二个虚拟机里面装一个 web 应用,它们的 IP 不一样,完全是不同的操作系统,这样两个 web 应用都可以占用 80 端口了。


所以通过这种方式,把资源做了切分,服务可以提供在默认端口上面,但是有不同的 IP。


虚拟化带来什么问题?


虚拟化引入的复杂性,使我们的运维成本,应用的性能都会有所下降。


那么有没有更轻量级的方法来实现同样的目的?


以更简单的技术来实现异军突起的容器技术。Docker 是如何工作的?和虚拟机有哪些区别?Docker 所依赖的这些技术的细节是什么?


简要介绍,docker 是基于 Linux 内核的已存在的技术,比如说 C group,namespace, unionFS. 


虚拟机架构:


一个完整的虚拟机的技术栈


  • 最下面是服务器,在这个服务器基础上,要装一个 host os,然后再 host os 上面要装一个 hypervisor。这个是在物理逻辑上所预装的软件。


  • 要在这上面起一个虚拟机,hypervisor 要启动了一个 guest os,然后它会模拟一个完整的操作系统,包括驱动。


  • 要在这个基础之上要部署应用,需要部署中间件,依赖,然后再部署应用。


这里面其实有两层操作系统。


针对虚拟化技术,最大的挑战是什么?

  • 第一、任何问题的分析变得很复杂。

    比如要查一个网络问题,有可能出现在上面这一层,有可能出现在下面这一层,还有内存问题也可能是有可能是上面有可能是下面。所以它的调试就变得很复杂,性能也不会很好。因为任何的数据包进来,比如任何数据包进来,它要从主机的 host os 走一遍,然后 guest os 又走一遍,所以性能不会很好。

  • 第二、上面的 OS 是一个完整的操作系统,是平台需要的, server 需要保留一些资源去支撑这个操作系统,那么它的资源利用率就有所降低。因为需要拿一部分资源来支撑这些操作系统。


对于容器技术,就变得简单多了,就是一个物理服务器。



  • 第一、操作系统简单,性能利用率高

    服务器上面有个 host os,装了一个操作系统,然后上面就是一个轻量级的 Docker 引擎,再上面就是应用了。只有一层操作系统。


    这样的话,在做任何问题排查,整个操作系统的资源基本上都是给应用的。Docker 本身是不吃资源的,所以所有的资源利用性能高。


  • 第二,有更快速的启动时间

    任何 Docker 或者容器里面运行的应用,它只是在主机上面的一个普通进程,所以应用启动的时间,就是这个主机启动进程的时间,而不需要去额外的起一个新的 os,所以它的启动时间非常快。


  • 第三、然后 Docker 通过镜像的存储结构,实现和保证了一致的运行环境

    这个怎么做到的?其实是打通了持续交付和持续部署的工具链。在容器技术之前,我们都在谈持续交付持续部署,但是工具链是打不通的,因为应用程序的部署是一个非常复杂的话题。一个应用在 dev 环境里面,已经布好了,到生产环境部署的时候,很可能缺这个依赖,缺那个依赖。


Docker run

告诉 docker 的服务,要运行一个容器的实例,要运行的这个实例的镜像是谁?是 center os。

这条命令在背后会去看本地是不是有这个镜像,如果有,会直接运行这个镜像的实例,如果没有,就会去镜像仓库拉取一个镜像。


镜像仓库是哪呢?默认情况下,相当于先运行了 docker pull 的命令,然后把这个镜像拉取下来,拉取下来以后它就去 replay,相当于回放了这个镜像,然后把这个镜像的实例起来了。


一个容器它可以起也可以停,通过 Docker stop 把它停掉,通过 docler star 把它起起来。

通过 Docker ps 来看当前这个机器上所运营正在运行的容器进程。


Docker file

就是我们构建 docker 镜像的一个原文件。

可以把这个 Docker file 理解成为我有一个什么样的基础镜像,镜像启动以后要执行哪些东西。

Docker 主要特性

第一个是隔离性,第二个是可配额,第三个是便携性,第四个是安全性。


怎么理解?在微服架构下面,作为一个服务提供者,要提供一个服务的话,需要提供什么?需要提供你的应用要绑定在某个网络地址上面。I P+端口。


Docker 是一种用轻量级的技术手段来实现类似于虚拟机的业务目标的机制。


隔离性,应用程序要跑,一定要有一个运行程序的沙箱,要有一个运行环境。


这个运行环境要跟其他人隔离,这个隔离有什么作用?

第一,应用程序要运行的时候,往往都需要一些依赖,来支撑你的业务,所以需要一个封闭的运行环境。


这个封闭的运行环境跟其他隔离有几个好处:

第一,跟其他不会互相有影响,你的应用就跑在你的这个框框里,别人的应用在别人的控制下,就是有隔离性。

第二,一个封闭的系统,那么你所有需要的依赖必须在这个封闭环境里面存在,在其他外面的地方存在的,比如说一个依赖装在别处你是用不到的,你的依赖必须在你的隔离环境里面,这样我们会实现一个目标,就是在不同的环境里面运行这个容器镜像,它其实都是把整个容器镜像的整个环境 replay 出来,任何需要的依赖都需要在都会在,所以就不会出现你在 dev 环境测过了,到生产环境又不通的这种情况。


第二,对资源的管控。一个应用需要两个 CPU,4G 的内存,那么怎么保证一定能有这么多资源?怎么保证应用进程出现在这个资源环境?

如果写不对,吃了更多的资源,会影响别人,所以需要一个配额的控制。


还有封装性,它是便携的,可以在不同的环境下 replay,不同的应用之间是安全隔离的。


容器的几个核心技术

Namespace

技术是 Linux kernel 提供,一种隔离资源的方案。


namespace 的目的是什么?是资源的独立分配进程,一次隔离,希望的是你把放在不同 namespace 的进程,互相不干扰。


所谓的 namespace,当系统起了一个新进程的时候,开辟了一些新的 namespace,可以把用户进程隔离开,可以让容器里面运行的程序看不到外面的世界,让它有一个独立的网络 IP 地址,让它有独立的文件系统,让它有独立的用户管理,让它有独立的主机名。


通过这种方式,相当于只是在本机起了一个进程,但是把它模拟成了一个操作系统。

什么是 namespace 技术

它是一种隔离的技术,就是把用户的进程放在了不同的 namespace。在这些不同的 namespace 里面,可以创建新的网络配置,有新的进程,管理有新的文件系统,有新的用户和域名。

作为微服务平台,一个服务提供商,你需要提供一个服务,要定义这个服务是什么服务,就要有独立的主机、域名、IP 地址、端口号。

那么把这个进程塞到 namespace 就达到目的了。


容器技术它只是进程,它并没有操作完整的操作系统,相当于就是在主机上 开辟了一个子进程。在主机上能看到它的 PID。


ns enter,日常调试容器里面进程应用的一个法宝:有些时候要做一些 debug,缺一些工具,就可以登到主机上面,进到容器的 namespace 去看它的配置。

Docker 如何通过 Cgroup 控制资源

我们起了很多进程,这些进程虽然放在了不同的 namespace,它们互相隔离了,互相不可见了,但事实上它们都是这个主机上 fork 出来的。运行在同一个操作系统里面的进程。

如果不加以管控,一定会出现一些问题。

第一种,比如总会有人写了一个应用,可能有个地方出现了死循环,可能要吃掉很多 CPU,主机可能就会变慢了,其他的应用就会受影响了。

第二种,可能应用有内存泄露,比如 200G 内存,因为把这 200G 内存都吃掉了,这样主机整个就不能访问了。

所以还要做一个事情是什么?是资源管控。主要的资源就是 CPU、内存,这些是最直观的我们能够理解的计算资源。

Cgroup 是怎么组织的呢?

首先 Cgroup 有不同的子系统,CPU 是个子系统,要管控 CPU,用 CPU 的子系统管的,要管控进程的内存,用 memory 的子系统管的。 CGroup 是怎么管的?它是以树状结构管理的,其实是一个目录文件。


通过 C group 的文件系统来管理整个 Cgroup 的架构,相当于建一个根目录,这个根目录里面筛了 100 个进程,然后根目录里有 222 个子目录,这个子目录里面每个子目录里面又放多少个进程,在每一个层级都可以通过 CPU 部分去控制资源。

  • 第一,不同文件目录里面会有不同的进程,每一个进程每一个子目录里面都会有一个自己的 CPU share,这个 cpu share 约定一个相对值,说明 Cgroup 能用的 CPU 是几比几。

  • 第二,控制 CPU 一个进程可以使用的 CPU 的绝对值。通过 C group 把 CPU 使用资源控制住,虽然你的程序里面是一个两个死循环去吃 200%的 CPU,但可以通过 Cgroup 给它控制到 10%,这样相当于控制住每一个进程所消耗的资源。

做的这件事的目的是什么?是用来确保你作为一个服务提供商,你告诉系统要多少资源,就确保这些资源给你,但是你程序有 bug,想多吃资源,是吃不到的。因为要确保,主机是大家共用的,不能你写一个坏的程序就把其他人给弄坏了,影响到其他人。

Cgroup 要控制的资源分两大类:


  • 一类叫做可压缩资源,就是 CPU。那么什么是可压缩资源?就是本身程序是需要两个 CPU 的,但是给你压到 0.1 你也能跑,就是这就叫可压制资源。


  • 但对服务提供商来说,会受到什么样的影响?就是应用程序慢了,因为你本来可能需要两个 CPU 来跑,但是你只拿到了 0.1 个 CPU。

    操作系统本身是没有容器或者 Docker 概念的,当切到某个 namespace 去看它的时候,事实上它看到的是主机的。要看 CPU 的话怎么看?通过 Cgroup 的里面的 CPU account 的这个子系统去看,这里面会告诉你说真正的 CPU 值是多少。


  • 还有一种资源是不可压缩资源,什么是不可压缩资源?内存就是不可压缩资源。怎么理解?一个应用程序需要 2G 的内存,如果已经把内存限死了,没有资源给他了,所以这种情况这种资源就是不可压缩资源。


  • 对于不可压缩资源,操作系统所处理的行为就不一样了, memory 已经分不出来的话,进程怎么办?操作系统这个时候会有一个默认的 OEM control。它的行为是可以自定义的,同时它有个默认行为,如果你的应用进程所消耗的内存已经超出了它的 Cgroup 限制,那么操作系统就会通过 ormq 把它 Q 掉,让这个进程重新启动,这就是 memory 子系统所操作的一个方式。

    在操作系统,lock 和 memory set 是两个行为。lock 的时候只分虚拟地址,但是这些内存没有被使用,没有被赋值的话,事实上物理内存是不分配的。

    通过 memory sat 把它复制以后,真正去消耗物理内存。

    要启动一个轻量级的容器技术去起真正的服务,还需要什么?还需要一个文件系统。


要运行的文件要存在的,这个运行文件从哪来?UnionFS,直白的理解就是把多个目录做成一个目录,相当于把两个不同的目录挂载到同一个目录下面,然后通过读写权限的设置,使得我们呈现一个最终的文件目录,容器。

union fs 是一层层叠加的。Docker file,首先 from 谁,一个 based 是谁,然后接下来要执行的每一条命令都需要写的到里面,这里面的命令就会形成一层一层的形式,就是 Docker file,它在 build 的时候可以看到有一个一个层级,会按照这个 Docker file 一层一层往下构建。


比如会去 docker hub 上面把镜像拉下来,然后会设置环境变量。每一条 env 命令都加一层,然后打 label, label 也是一层。基本上每一条 Docker file 里面的指令,在做镜像构建的时候会把指令作为一个文件层保存下来。

容器就可以去读取这些文件。


写操作,要修改一个已经存在的文件,这个文件又在底层,怎么办?copy on write,不会直接去修改下面的层,是把这个文件复制出来,然后你做的任何更改它都会保存在上面的层。这就是 Docker 的文件系统提供的一个机制。Docker inspect

看一个容器所运行的现实状况。

可以看到它的 network、 namespace 是什么,网络配置是什么,它的工作目录在主机上是什么样子。

Docker 的网络配置

要发布一个服务,需要解决哪些问题?

  • 第一,容器里面的网络怎么配

  • 第二,容器网络和主机网络怎么互通

  • 第三,容器网络怎么跟外面的世界互通


这是不同维度的问题。


我们先来了解一下,今天花一点时间了解一下 1 和 2。在容器技术下,容器怎么获得一个独立的网络配置,应该配什么才能跟外面互通的。


  • 第一种模式就是 non,起 Docker 的时候告诉它,刚刚 net 等于 non。这种模式下不配任何网络。这种模式相当于每个主机上会有一个 docker 里面的 bridge,就是不要给我配任何网络,但是开一个新的网络空间。


  • 这种模式一般做什么用?

    相当于你自己有网络插件,你要自己完成配置的时候就用这种模式。


  • 第二种方式叫 host,host 就是告诉 doctor 要复用主机网络。容器起的进程,没有独立的网络,会用复用主机的网络,主机的 IP 是啥它就是啥,主机用的端口它都能看到。


  • 这样的话,多个容器不能跑在同样的端口。因为大家都是主机网络,就会有端口冲突。你可以重用其他网络容器的网络,可以用 bridge 网络。


  • 第三种,一些跨主题网络怎么做,今天不重点去强调,后面章节详谈。


Docker 技术优势

  • 首先它不需要启动内核,所以它速度快

  • 其次它不模拟操作系统,所以它资源利用率很高

  • 它可以通过 Cgroup 来调整资源

  • Docker 本身通过 Docker 镜像的 tag 来完成版本管理

  • 不同的 namespace 互相隔离,所以不同应用版本可以存在一台机器上,而不会产生端口冲突

  • Union FS 可以支持镜像基于层的镜像复用。

    比如:如果你有多个镜像,都依赖于 centerOS,那么它只需要维护一份 centerOS 镜像的副本就可以了。因为分层的架构结构,它的推送是增量的,下面的所有中间件操作系统没有发生过变更,它不需要重新挖取了,只需要通过增量的方式把你那个文件重新分发一次就好了,所以对网络带宽,对文件分发来说是非常方便的。


往期推荐

关注 云世 微信公众号。

最全云厂商及云方案能力报告【建议收藏】

最新Serverless服务研究报告【收藏参考】

云原生:一文读懂K8s架构

云原生:一文读懂Docker核心技术

云原生:一文读懂K8s架构原则和对象设计》

云原生:一文读懂DevOps工具链


如果你觉得这个系列有价值,也欢迎转发给有需要的朋友。


云世 专注职场人的硬实力|软技能提升。为企业应用上云和云原生前沿技术及落地实践布道,分享微服务、容器、K8s、Service Mesh、面向企业的 ToB 服务能力的体系化建设等方案、最佳实践、免费课程资料;持续发布职场做事方法论、管理提效等软技能。350 篇原创内容

公众号



喜欢就|关注|转发|点赞|订阅专题吧

公号专题

【职场硬实力】:「云原生」「微服务」「Service Mesh」「K8s」「Docker

【职场软实力】:「职场养分」「职场软实力」「认知跨越


---END---

资料+视频课+课程下载⚡ 云世公众号后台:

回复:DDD,领取 DDD 实践全系列课程;

回复:DDD 源码,领取 DDD 系列 Git 源码;

回复:K8s,领取 K8s 架构实践全系列课程;

回复:微服务,领取微服务实践课程;

回复:Docker,领取 Docker 容器全系列学习课程;

回复:servicemesh,领取全系列课程;

回复:go,领取 Go 全系列学习课程;

回复:职场软技能,领取软技能系列课程;

回复:管理实践,领取管理实践+课程;

回复:面试技能,领取面试技能经验+课程;

回复:麦肯锡工作法,领取完整麦肯锡工作法;

回复:技术视频 3,领取 Servicemesh、Serverless 视频课(全套视频课更新);

回复:serverless,领取全系列课程+实践;


发布于: 4 小时前阅读数: 5
用户头像

息之

关注

微信公众号【云世】,云厂商产品从业者 2021.08.06 加入

【云世】专注职场人的硬实力和软技能提升。为产品上云,微服务和云原生前沿技术和落地实践布道。

评论

发布
暂无评论
云原生:详解|容器核心技术解析