1.Docker究竟是什么,解决什么问题
1.1.Docker出现的背景
Docker是一种轻量级、可移植、自包含的软件打包的容器技术,使应用程序可以在几乎任何地方以相同的方式运行。
Docker解决的是应用难以移植的问题,它使得开发人员能在自己笔记本上创建并测试好的容器,无须任何修改就能够在生产系统的虚拟机、物理服务器或公有云主机上运行。
假设我们目前存在多种服务,这些服务有自己所依赖的库和软件包;另一方面存在多种部署环境,服务在运行时可能需要动态迁移到不同的环境中。这就产生了一个问题:如何让每种服务能够在所有的部署环境中顺利运行?开发人员在编写代码时需要考虑不同的运行环境,运维人员则需要为不同的服务和平台配置环境。
Docker将集装箱思想运用到软件打包上,为代码提供了一个基于容器的标准化运输系统。Docker可以将任何应用及其依赖打包成一个轻量级、可移植、自包含的容器。容器可以运行在几乎所有的操作系统上,这就解决了容器的移植问题。
1.2.容器与虚拟机的区别
容器与虚拟机两者都是为应用提供封装和隔离,但是两者的实现原理却不尽相同,容器又被称为“轻量级的虚拟机”。
容器由应用程序本身及所需依赖组成,程序指的是容器所打包的指令,依赖指的是程序所需要的库、软件或操作系统支持,对于Docker来说,开发人员只需要定义指令部分,而依赖均来自宿主机提供,并且借助cgroup及namespace技术,实现对宿主机的资源隔离及命名隔离。在Docker容器中的资源(进程、内存、CPU)等与宿主机隔离,但是所有资源都从宿主机共享。
正因为这样,每个虚拟机实质上包含了整个操作系统引擎,而容器不包含操作系统引擎,所以容器的大小比虚拟机小很多,并且底层的能力可以借助操作系统镜像来进行动态拓展。
1.3.Docker架构核心组成
Docker的核心组件包括:
- Docker客户端:Client,负责向服务器发送请求及Docker命令,通常Client部署在用户环境或服务端中。
- Docker服务器:Docker daemon,负责处理Docker客户端的请求,是镜像及容器的载体,对镜像及容器进行监控和构建。
- Docker镜像:Image,是容器运行的模板,可以从0到1构建程序镜像,也可以在先有镜像中通过dockerfile构建。
- Docker仓库:Registry,提供远程集中式的镜像管理服务,方便对镜像进行版本控制及存储。
- Docker容器:Container,容器是镜像的运行实例,可以将镜像理解为软件的构建和打包阶段,而容器则是启动和运行阶段。
1.4.Docker镜像及容器原理
镜像是Docker容器的基石,容器是镜像的运行实例,有了镜像才能启动容器。
Docker镜像的构建哲学是,所有的镜像都从底层到高层进行构建,高层镜像依赖于底层镜像的内容,底层镜像依赖于base镜像。
base镜像有两层含义:
- 不依赖其他镜像,从scratch构建
- 其他镜像可以以之为基础进行扩展。
所以,能称作base镜像的通常都是各种Linux发行版的Docker镜像,比如Ubuntu、Debian、CentOS等。
对于base镜像来说,底层直接用宿主机的kernel,自己只需要提供rootfs就行了,在启动容器运行过程中,base镜像只提供相关的指令和操作,底层使用宿主机的kernel来运行。
新镜像是从 base 镜像一层一层叠加生成的。每安装一个软件,就在现有镜像的基础上增加一层。
镜像分层最大的一个好处就是共享资源。
比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如 /etc 下的文件,这时其他容器的 /etc 是不会被修改的,修改只会被限制在单个容器内。这就是容器 Copy-on-Write 特性。
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。比如需要读取容器中的/etc/host文件,实质上是从底层所依赖的操作系统镜像中读取/etc/host文件内容,当需要/etc/host文件时,会在容器层面copy一个/etc/host并进行修改,那么在读取时就会先容器层面读取,而不对镜像层面进行读取了。
2.Kubernetes究竟是什么,解决什么问题
2.1.Kubernetes出现的背景
当前,Docker这门容器化技术已经被很多公司采用,从单机走向集群已成为必然,所以对于大规模容器的管理,如果只是依赖于人工手动运维,那么会出现难以管理、管理混乱的问题。对于典型的微服务架构来说,一个巨大的单体应用被拆分为多个相互调用的微服务,并且每个微服务都由多个副本支撑,服务间调用、负载均衡、流量控制等问题也日益出现,随着服务量级的增大,不可能由人工来管理数千乃至数万个容器,而Kuberentes就是为了解决大量容器的管理和运维问题。
Kubernetes是谷歌严格保密十几年的秘密武器——Borg的一个开源版本。Borg是谷歌的一个久负盛名的内部使用的大规模集群管理系统,它基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。
Kubernetes是一个开放的开发平台。与J2EE不同,它不局限于任何一种语言,没有限定任何编程接口,所以不论是用Java、Go、C++还是用Python编写的服务,都可以被映射为Kubernetes的Service(服务),并通过标准的TCP通信协议进行交互。此外,Kubernetes平台对现有的编程语言、编程框架、中间件没有任何侵入性,因此现有的系统也很容易改造升级并迁移到Kubernetes平台上。
基于Kubernetes可以轻松做到:
- 服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。 - 存储编排
Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。 - 自动部署和回滚
你可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态 更改为期望状态。例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。 - 自动完成装箱计算
Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来管理容器的资源。 - 自我修复
Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的 运行状况检查的容器,并且在准备好服务之前不将其通告给客户端。 - 密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。
2.2.Kubernetes架构核心组成
Kubernetes里的Master指的是集群控制节点,在每个Kubernetes集群里都需要有一个Master来负责整个集群的管理和控制,基本上Kubernetes的所有控制命令都发给它,它负责具体的执行过程。Master通常会占据一个独立的服务器(高可用部署建议用3台服务器),主要原因是它太重要了,是整个集群的“首脑”,如果它宕机或者不可用,那么对集群内容器应用的管理都将失效。
除了Master,Kubernetes集群中的其他机器被称为Node,在较早的版本中也被称为Minion。与Master一样,Node可以是一台物理主机,也可以是一台虚拟机。Node是Kubernetes集群中的工作负载节点,每个Node都会被Master分配一些工作负载(Docker容器),当某个Node宕机时,其上的工作负载会被Master自动转移到其他节点上。
在Master节点中存在以下关键进程:
- Kubernetes API Server(kube-apiserver):提供了HTTP Rest接口的关键服务进程,是Kubernetes里所有资源的增、删、改、查等操作的唯一入口,也是集群控制的入口进程
- Kubernetes Controller Manager(kube-controller-manager):Kubernetes里所有资源对象的自动化控制中心,可以将其理解为资源对象的“大总管”。
- Kubernetes Scheduler(kube-scheduler):负责资源调度(Pod调度)的进程,相当于公交公司的“调度室”。
- Kubernetes Etcd:etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。
在Node节点中存在以下关键进程:
- kubelet:负责Pod对应的容器的创建、启停等任务,同时与Master密切协作,实现集群管理的基本功能。
- kube-proxy:实现Kubernetes Service的通信与负载均衡机制的重要组件。
- Docker Engine(docker):Docker引擎,负责本机的容器创建和管理工作。