极客时间已完结课程限时免费阅读

59 | 数据中心操作系统:上市敲钟

59 | 数据中心操作系统:上市敲钟-极客时间

59 | 数据中心操作系统:上市敲钟

讲述:刘超

时长16:02大小14.68M

在这门课程里面,我们说了,内核态有很多的模块,可以帮助我们管理硬件设备,最重要的四种硬件资源是 CPU、内存、存储和网络。
最初使用汇编语言的前辈,在程序中需要指定使用的硬件资源,例如,指定使用哪个寄存器、放在内存的哪个位置、写入或者读取哪个串口等等。对于这些资源的使用,需要程序员自己心里非常地清楚,要不然一旦 jump 错了位置,程序就无法运行。
为了将程序员从对硬件的直接操作中解放出来,提升程序设计的效率,于是,我们有了操作系统这一层,用来实现对于硬件资源的统一管理。某个程序应该使用哪个 CPU、哪部分内存、哪部分硬盘,只需要调用 API 就可以了,这些都由操作系统自行分配和管理。
其实操作系统最重要的事情,就是调度。因此,在内核态就产生了这些模块:进程管理子系统、内存管理子系统、文件子系统、设备子系统和网络子系统。
这些模块通过统一的 API,也就是系统调用,对上提供服务。基于这些 API,用户态有很多的工具可以帮我们使用好 Linux 操作系统,比如用户管理、软件安装、软件运行、周期性进程、文件管理、网络管理和存储管理。
但是到目前为止,我们能管理的还是少数几台机器。当我们面临数据中心成千上万台机器的时候,仍然非常“痛苦”。如果我们运维数据中心依然像运维一台台物理机的前辈一样,天天关心哪个程序放在了哪台机器上,使用多少内存、多少硬盘,每台机器总共有多少内存、多少硬盘,还剩多少内存和硬盘,那头就大了。
因而对应到数据中心,我们也需要一个调度器,将运维人员从指定物理机或者虚拟机的痛苦中解放出来,实现对于物理资源的统一管理,这就是 Kubernetes。
Kubernetes 究竟有哪些功能,可以解放运维人员呢?为什么它能做数据中心的操作系统呢?
我列了两个表格,将操作系统的功能和模块与 Kubernetes 的功能和模块做了一个对比,你可以看看。
Kubernetes 作为数据中心的操作系统还是主要管理数据中心里面的四种硬件资源:CPU、内存、存储、网络。
对于 CPU 和内存这两种计算资源的管理,我们可以通过 Docker 技术完成。它可以将 CPU 和内存资源,通过 namespace 和 cgroup,从大的资源池里面隔离出来,并通过镜像技术,实现计算资源在数据中心里面的自由漂移。
就像我们上面说的一样,没有操作系统的时候,汇编程序员需要指定程序运行的 CPU 和内存物理地址。同理,数据中心的管理员,原来还需要指定程序运行的服务器及使用的 CPU 和内存。现在,Kubernetes 里面有一个调度器 Scheduler,你只需要告诉它,你想运行 10 个 4 核 8G 的 Java 程序,它会自动帮你选择空闲的、有足够资源的服务器,去运行这些程序。
对于操作系统上的进程来讲,有主线程做主要的工作,还有其它线程做辅助的工作。对于数据中心里面的运行的程序来讲,也会有一个主要提供服务的程序,例如上面的 Java 程序,也会有一些提供辅助功能的程序;例如监控、环境预设值等。Kubernetes 将多个 Docker 组装成一个 Pod 的概念。在一个 Pod 里面,往往有一个 Docker 为主,多个 Docker 为辅。
操作系统上的进程会在 CPU 上切换来切换去,它使用的内存也会换入换出。在数据中心里面,这些运行中的程序能不能在机器之间迁移呢?能不能在一台服务器故障的时候,选择其它的服务器运行呢?反正我关心的是运行 10 个 4 核 8G 的 Java 程序,又不在乎它在哪台上运行。
Kubernetes 里面有 Controller 的概念,可以控制 Pod 们的运行状态以及占用的资源。如果 10 个变 9 个了,就选一台机器添加一个;如果 10 个变 11 个了,就随机删除一个。
操作系统上的进程有时候有亲和性的要求,比如它可能希望在某一个 CPU 上运行,不切换 CPU,从而提高运行效率。或者,两个线程要求在一个 CPU 上,从而可以使用 Per CPU 变量不加锁,交互和协作比较方便。有的时候,一个线程想避开另一个线程,不要共用 CPU,以防相互干扰。Kubernetes 的 Scheduler 也是有亲和性功能的,你可以选择两个 Pod 永远运行在一台物理机上,这样本地通信就非常方便了;你也可以选择两个 Pod 永远不要运行在同一台物理机上,这样一个挂了不影响另一个。
你可能会问,Docker 可以将 CPU 内存资源进行抽象,在服务器之间迁移,那数据应该怎么办呢?如果数据放在每一台服务器上,其实就像散落在汪洋大海里面,用的时候根本找不到,所以必须要有统一的存储。正像一台操作系统上多个进程之间,要通过文件系统保存持久化的数据并且实现共享,在数据中心里面也需要一个这样的基础设施。
统一的存储常常有三种形式,我们分别来看。
第一种方式是对象存储
顾名思义,这种方式是将文件作为一个完整对象的方式来保存。每一个文件对我们来说,都应该有一个唯一标识这个对象的 key,而文件的内容就是 value。对象可以分门别类地保存在一个叫作存储空间(Bucket)的地方,有点儿像文件夹。
对于任何一个文件对象,我们都可以通过 HTTP RESTful API 来远程获取对象。由于是简单的 key-value 模式,当需要保存大容量数据的时候,我们就比较容易根据唯一的 key 进行横向扩展,所以对象存储能够容纳的数据量往往非常大。在数据中心里面保存文档、视频等是很好的方式,当然缺点就是,你没办法像操作文件一样操作它,而是要将 value 当成整个的来对待。
第二种方式是分布式文件系统
这种是最容易习惯的,因为使用它和使用本地的文件系统几乎没有什么区别,只不过是通过网络的方式访问远程的文件系统。多个容器能看到统一的文件系统,一个容器写入文件系统,另一个容器能够看到,可以实现共享。缺点是分布式文件系统的性能和规模是个矛盾,规模一大性能就难以保证,性能好则规模不会很大,所以不像对象存储一样能够保持海量的数据。
第三种方式是分布式块存储
这就相当于云硬盘,也即存储虚拟化的方式,只不过将盘挂载给容器而不是虚拟机。块存储没有分布式文件系统这一层,一旦挂载到某一个容器,可以有本地的文件系统,这样做的缺点是,一般情况下,不同容器挂载的块存储都是不共享的,好处是在同样规模的情况下,性能相对分布式文件系统要好。如果为了解决一个容器从一台服务器迁移到另一台服务器,如何保持数据存储的问题,块存储是一个很好的选择。它不用解决多个容器共享数据的问题。
这三种形式,对象存储使用 HTTP 进行访问,当然任何容器都能访问到,不需要 Kubernetes 去管理它。而分布式文件系统和分布式块存储,就需要对接到 Kubernetes,让 Kubernetes 可以管理它们。如何对接呢?Kubernetes 提供 Container Storage Interface(CSI)接口,这是一个标准接口,不同的存储可以实现这个接口来对接 Kubernetes。是不是特别像设备驱动程序呀?操作系统只要定义统一的接口,不同的存储设备的驱动实现这些接口,就能被操作系统使用了。
存储的问题解决了,接下来是网络。因为不同的服务器上的 Docker 还是需要互相通信的。
Kubernetes 有自己的网络模型,里面是这样规定的。
1.IP-per-Pod,每个 Pod 都拥有一个独立 IP 地址,Pod 内所有容器共享一个网络命名空间。
2. 集群内所有 Pod 都在一个直接连通的扁平网络中,可通过 IP 直接访问。
所有容器之间无需 NAT 就可以直接互相访问。
所有 Node 和所有容器之间无需 NAT 就可以直接互相访问。
容器自己看到的 IP 跟其它容器看到的一样。
这其实是说,里面的每一个 Docker 访问另一个 Docker 的时候,都是感觉在一个扁平的网络里面。
要实现这样的网络模型,有很多种方式,例如 Kubernetes 自己提供 Calico、Flannel。当然,也可以对接 Openvswitch 这样的虚拟交换机,也可以使用 brctl 这种传统的桥接模式,也可以对接硬件交换机。
看,这又是一种类似驱动的模式,和操作系统面临的问题是一样的。Kubernetes 同样是提供统一的接口 Container Network Interface(CNI,容器网络接口)。无论你用哪种方式实现网络模型,只要对接这个统一的接口,Kubernetes 就可以管理容器的网络。
至此,Kubernetes 作为数据中心的操作系统,内核的问题解决了。
接下来是用户态的工作模式问题了。我们能不能像操作一台服务器那样操作数据中心呢?
使用操作系统,需要安装一些软件,于是,我们需要 yum 之类的包管理系统,使得软件的使用者和软件的编译者分隔开来,软件的编译者需要知道这个软件需要安装哪些包,包之间的依赖关系是什么,软件安装到什么地方,而软件的使用者仅仅需要 yum install 就可以了。Kubernetes 就有这样一套包管理软件 Helm,你可以用它来很方便地安装、升级、扩容一些数据中心里面的常用软件,例如数据库、缓存、消息队列。
使用操作系统,运行一个进程是最常见的需求。第一种进程是交互式命令行,运行起来就是执行一个任务,结束了马上返回结果。在 Kubernetes 里面有对应的概念叫作 Job,Job 负责批量处理短暂的一次性任务 (Short Lived One-off Tasks),即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束。
第二种进程是 nohup(长期运行)的进程。在 Kubernetes 里对应的概念是 Deployment,使用 Deployment 来创建 ReplicaSet。ReplicaSet 在后台创建 Pod。也即,Doployment 里面会声明我希望某个进程以 N 的 Pod 副本的形式运行,并且长期运行,一旦副本变少就会自动添加。
第三种进程是系统服务。在 Kubernetes 里面对应的概念是 DaemonSet,它保证在每个节点上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。
第四种进程是周期性进程,也即 Crontab,常常用来设置一些周期性的任务。在 Kubernetes 里面对应的概念是 CronJob(定时任务),就类似于 Linux 系统的 Crontab,在指定的时间周期运行指定的任务。
使用操作系统,我们还需使用文件系统,或者使用网络发送数据。虽然在 Kubernetes 里面有 CSI 和 CNI 来对接存储和网络,但是在用户态,不能让用户意识到后面具体设备,而是应该有抽象的概念。
对于存储来讲,Kubernetes 有 Volume 的概念。Kubernetes Volume 的生命周期与 Pod 绑定在一起,容器挂掉后,Kubelet 再次重启容器时,Volume 的数据依然还在,而 Pod 删除时,Volume 才会真的被清理。数据是否丢失取决于具体的 Volume 类型。Volume 的概念是对具体存储设备的抽象,就像当我们使用 ext4 文件系统时,不用管它是基于什么硬盘一样。
对于网络来讲,Kubernetes 有自己的 DNS,有 Service 的概念。Kubernetes Service 是一个 Pod 的逻辑分组,这一组 Pod 能够被 Service 访问。每一个 Service 都一个名字,Kubernetes 会将 Service 的名字作为域名解析成为一个虚拟的 Cluster IP,然后通过负载均衡,转发到后端的 Pod。虽然 Pod 可能漂移,IP 会变,但是 Service 会一直不变。
对应到 Linux 操作系统的 iptables,Kubernetes 在有个概念叫 Network Policy,Network Policy 提供了基于策略的网络控制,用于隔离应用并减少攻击面。它使用标签选择器模拟传统的分段网络,并通过策略控制它们之间的流量以及来自外部的流量。
看,是不是很神奇?有了 Kubernetes,我们就能像管理一台 Linux 服务器那样,去管理数据中心了。
如果想深入了解 Kubernetes 这个数据中心的操作系统,你可以订阅极客时间的专栏“深入剖析 Kubernetes”。

总结时刻

下面,你可以对照着这个图,来总结一下这个数据中心操作系统的功能。

课堂练习

Kubernetes 有一个简单的版本,你可以按照官方文档,用一台虚拟机安装一个,试验一下。
欢迎留言和我分享你的疑惑和见解,也欢迎收藏本节内容,反复研读。你也可以把今天的内容分享给你的朋友,和他一起学习和进步。
分享给需要的人,Ta购买本课程,你将得20
生成海报并分享

赞 12

提建议

上一篇
58 | cgroup技术:内部创业公司应该独立核算成本
下一篇
60 | 搭建操作系统实验环境(上):授人以鱼不如授人以渔
 写留言

精选留言(18)

  • Boyang
    2019-08-13
    我之前的留言,提到的是不是问题,如果不对哪怕探讨一下呢。。。

    作者回复: 没有,我是写专栏占用太多时间了,所以没来得及回

    7
  • 静✨
    2021-06-14
    这节真是太棒了!!!
    5
  • fy
    2019-08-12
    能坚持下来就是对老师对最大的恩赐

    作者回复: 赞,加油

    5
  • 饭粒
    2019-08-17
    有趣的对比👍
    4
  • D
    2019-08-12
    老师,能否讲讲最近比较火的微内核,加个餐?

    作者回复: 不少问微内核的了,我研究一下

    2
  • 许童童
    2019-08-12
    老师讲得好啊,深入浅出,跟着老师一起精进。

    作者回复: 加油

    2
  • 安排
    2019-08-12
    通俗易懂
    2
  • songyy
    2021-07-04
    这一节的确很棒。从高处着眼,把Kubernetes的概念讲清楚了。 (相比之下……上一节 cgroup我觉得就没从高处着眼,太细节了。。)
    共 1 条评论
    1
  • 一省吾身
    2023-01-20 来自湖北
    醍醐灌顶,对于操作系统和k8s的概念理解清晰了很多,赞!
  • Geek_278a2c
    2022-06-01
    老师,你讲的linux内核是基于哪个版本啊?
  • Run
    2022-01-17
    的确,k8s这么对比过来,和操作系统也没啥区别,都是基于资源的调度
  • 朱熙
    2021-08-20
    二刷到这里了~再过一遍总结去
  • 紫气迷城2
    2021-02-06
    感谢分享
  • Frame
    2020-06-14
    梦幻联动
  • 莫名
    2019-10-23
    不错的对比形式。
  • 尚墨
    2019-09-24
    老师对于 Mesos 怎么看呢?Mesos 在最初的设想也是一个数据中心操作系统内核。我在博客园看见您的 Mesos 源码阅读分享。
  • 潇是潇洒的洒
    2019-09-07
    如果 10 个变 9 个就选一台机器添加一个,10 个变 11个 就删除一个,这里是不是写反了
    共 1 条评论
  • leslie
    2019-08-13
    现在完全在用刘老师介绍的学习方法在学习:希望在数遍之后能收获到想要的东西。

    作者回复: 多看几遍,总会有收获