Vm -> Docker -> K8s
前言
在实际的软件开发过程中,我们需要多的环境:如开发环境、测试环境、沙箱环境、自动化环境、预发环境、生产环境……这么多的环境要如何维护呢?是一台机器部署一个应用,还是一台机器部署多个应用?多个应用之前又要怎么隔离呢?这时候就需要使用到虚拟化技术了。
VM(虚拟机)
所谓虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的完整计算机系统 。这个听起来有些绕口,其实就是通过软件的隔离,让你的电脑能够同步安装多个完整的计算机系统,这里说的软件比较有名的就是VMWare和OpenStack,通过VMWare或OpenStack,我们在原来的电脑中模拟出一台甚至多台“子电脑”出来。这些子电脑可以是Mac、windows、linux中的任意系统、任意版本,只你软件支持且你能找到镜像。在“子电脑”里,你可以和正常电脑一样运行程序,例如打开word。各个子电脑之间的软件硬件都是相互隔离的,互不影响的。
虚拟化有哪些优势?
优点:
虚拟机能够让一台机器像多台机器一样运行,这意味着您需要的服务器更少,并且还可以最大限度地利用您拥有的服务器。这种效率的提高能够节省硬件、冷却和维护成本。借助虚拟化,我们可以在同一台机器上运行多种类型的应用、桌面和操作系统。
缺点:
虚拟机虽然可以隔离出很多「子电脑」,但占用空间更大,启动更慢。虚拟机软件可能还要花钱,例如 VMWare
运行空间,虚拟机一般要几 GB 到 几十 GB 的空间
Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了
Linux 基金会,遵从了 Apache 2.0协议, 项目代码在 GitHub 上进行维护。Docker
自开源后受到广泛的关注和讨论,以至于 dotCloud 公司后来都改名为 Docker Inc。Redhat 已经在其 RHEL6.5
中集中支持 Docker;Google 也在其 PaaS 产品中广泛应用
Docker 的基础是 Linux 容( LXC)等技术。在 LXC 的基础上 Docker 进行了进一步的封装, 让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。
Docker的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么我就不需要专门运送水果的船和专门运送化学品的船了。只要这些货物在集装箱里封装的好好的,那我就可以用一艘大船把他们都运走。Docker就是类似的理念。
现在都流行云计算了,云计算就好比大货轮,Docker就是集装箱。
Docker 技术的三大核心概念,分别是:
1、镜像 Image
2、容器 Container
3、仓库 Repository
核心思想:
Build,Ship and Run(搭建、运输、运行)。
Build once,Run anywhere(一次搭建,处处运行)。
Docker 轻量级的原因是什么?相信你也会有这样的疑惑:为什么 Docker 启动快?如何做到和宿主机共享内核?
当我们请求 Docker 运行容器时,Docker 会在计算机上设置一个资源隔离的环境。
然后将打包的应用程序和关联的文件复制到 Namespace 内的文件系统中,此时环境的配置就完成了。之后 Docker 会执行我们预先指定的命令,运行应用程序。
镜像不包含任何动态数据,其内容在构建之后也不会被改变。
由于 Namespace 和 Cgroups 功能仅在 Linux 上可用,因此容器无法在其他操作系统上运行。那么 Docker 如何在 macOS 或 Windows 上运行?Docker 实际上使用了一个技巧,并在非 Linux 操作系统上安装 Linux 虚拟机,然后在虚拟机内运行容器。
镜像是一个可执行包,其包含运行应用程序所需的代码、运行时、库、环境变量和配置文件,容器是镜像的运行时实例。
为了更好的理解 Docker 是什么,我们来举个例子
我需要盖一个房子,于是我搬石头、砍木头、画图纸、盖房子。一顿操作,终于把这个房子盖好了。
结果,住了一段时间,心血来潮想搬到海边去。这时候按以往的办法,我只能去海边,再次搬石头、砍木头、画图纸、盖房子。
烦恼之际,跑来一个魔法师教会我一种魔法。这种魔法可以把我盖好的房子复制一份,做成「镜像」,放在我的背包里。
等我到了海边,就用这个「镜像」,复制一套房子,拎包入住。
是不是很神奇?对应到我们的项目中来,房子就是项目本身,镜像就是项目的复制,背包就是镜像仓库。
如果要动态扩容,从仓库中取出项目镜像,随便复制就可以了。Build once,Run anywhere!
不用再关注版本、兼容、部署等问题,彻底解决了「上线即崩,无休止构建」的尴尬。
容器:将操作系统层虚拟化,是一个标准的软件单元
其特点如下:
*• 随处运行:容器可以将代码与配置文件和相关依赖库进行打包,从而确保在任何环境下的运行都是一致的。
• 高资源利用率:容器提供进程级的隔离,因此可以更加精细地设置 CPU 和内存的使用率,进而更好地利用服务器的计算资源。
• 快速扩展:每个容器都可作为单独的进程予以运行,并且可以共享底层操作系统的系统资源,这样一来可以加快容器的启动和停止效率。*
K8S
Docker容器技术被炒得热火朝天之时,大家发现,如果想要将Docker应用于具体的业务实现,是存在困难的——编排、管理和调度等各个方面,都不容易。于是,人们迫切需要一套管理系统,对Docker及容器进行更高级更灵活的管理。于是K8S出现了
K8S就是基于容器的集群管理平台,它的全称,是kubernetes。
1、k8s 架构:
概括来说 K8s 架构就是一个 Master 对应一群 Node 节点。下面我们来逐一介绍 K8s 架构图中的 Master 和 Node。
Master 节点结构如下:
• apiserver 即 K8s 网关,所有的指令请求都必须要经过 apiserver。
• Scheduler 调度器,使用调度算法,把请求资源调度到某一个 Node 节点。
• Controller 控制器,维护 K8s 资源对象。
• etcd 存储资源对象。
Node 节点结构如下:
• Kubelet 在每一个 Node 节点都存在一份,在 Node 节点上的资源操作指令由 Kubelet 来执行。
• Kube-proxy 代理服务,处理服务间负载均衡。
• Pod 是 K8s 管理的基本单元(最小单元),Pod 内部是容器,K8s 不直接管理容器,而是管理 Pod。
• Docker 运行容器的基础环境,容器引擎。
• Fluentd 日志收集服务。
2、K8s核心组件
①K8s 组件
K8s 是用来管理容器,但是不直接操作容器,最小操作单元是 Pod (间接管理容器):
• 一个 Master 有一群 Node 节点与之对应。
• Master 节点不存储容器,只负责调度、网管、控制器、资源对象存储。
• 容器的存储在 Node 节点,容器是存储在 Pod 内部的)。
• Pod 内部可以有一个容器,或者多个容器。
• Kubelet 负责本地 Pod 的维护。
• Kube-proxy 负责负载均衡,在多个 Pod 之间来做负载均衡。
②Pod 是什么?
解释如下:
• Pod 也是一个容器,这个容器中装的是 Docker 创建的容器,Pod 用来封装容器的一个容器,Pod 是一个虚拟化分组。
• Pod 相当于独立主机,可以封装一个或者多个容器。
Pod 有自己的 IP 地址、主机名,相当于一台独立沙箱环境。
③Pod 到底用来干什么?
通常情况下,在服务部署时候,使用 Pod 来管理一组相关的服务。一个 Pod 中要么部署一个服务,要么部署一组有关系的服务。
一组相关的服务是指:在链式调用的调用连路上的服务。
④Web 服务集群如何实现?
实现服务集群:只需要复制多方 Pod 的副本即可,这也是 K8s 管理的先进之处,K8s 如果继续扩容,只需要控制 Pod 的数量即可,缩容道理类似。
⑤Pod 底层网络,数据存储是如何进行的?
具体如下:
• Pod 内部容器创建之前,必须先创建 Pause 容器。
• 服务容器之间访问 localhost ,相当于访问本地服务一样,性能非常高。
⑥ReplicaSet 副本控制器
控制 Pod 副本「服务集群」的数量,永远与预期设定的数量保持一致即可。
当有 Pod 服务宕机时候,副本控制器将会立马重新创建一个新的 Pod,永远保证副本为设置数量。
副本控制器:标签选择器-选择维护一组相关的服务(它自己的服务)
• ReplicationController 副本控制器:单选。
• ReplicaSet 副本控制器:单选,复合选择。
不过在新版中,建议使用 ReplicaSet 作为副本控制器,ReplicationController 不再使用了。
⑦Deployment 部署对象
Deployment 部署对象如下:
• 服务部署结构模型
• 滚动更新
ReplicaSet 副本控制器控制 Pod 副本的数量。但是,项目的需求在不断迭代、不断的更新,项目版本将会不停的的发版。版本的变化,如何做到服务更新?
部署模型:
• ReplicaSet 不支持滚动更新,Deployment 对象支持滚动更新,通常和 ReplicaSet 一起使用。
• Deployment 管理 ReplicaSet,RS 重新建立新的 RS,创建新的 Pod。
⑧MySQL 使用容器化部署,存在什么样的问题?
问题如下:
• 容器是生命周期的,一旦宕机,数据丢失
• Pod 部署,Pod 有生命周期,数据丢失
对于 K8s 来说,不能使用 Deployment 部署有状态服务。
通常情况下,Deployment 被用来部署无状态服务,那么对于有状态服务的部署,使用 StatefulSet 进行有状态服务的部署。
什么是有状态服务?
• 有实时的数据需要存储。
• 有状态服务集群中,把某一个服务抽离出去,一段时间后再加入机器网络,如果集群网络无法使用。
什么是无状态服务?
• 没有实时的数据需要存储。
• 无状态服务集群中,把某一个服务抽离出去,一段时间后再加入机器网络,对集群服务没有任何影响。
⑨StatefulSet
为了解决有状态服务使用容器化部署的一个问题:
• 部署模型
• 有状态服务
StatefulSet 保证 Pod 重新建立后,Hostname 不会发生变化,Pod 就可以通过 Hostname 来关联数据。
3、K8s 的服务注册与发现
①Pod 的结构是怎样的?
结构如下:
Pod 相当于一个容器,Pod 有独立 IP 地址,也有自己的 Hostname,利用 Namespace 进行资源隔离,独立沙箱环境。
Pod 内部封装的是容器,可以封装一个,或者多个容器(通常是一组相关的容器)。
②Pod 网络
具体如下:
Pod 有自己独立的 IP 地址。
Pod 内部容器之间访问采用 Localhost 访问。
Pod 内部容器访问是 Localhost,Pod 之间的通信属于远程访问。
③Pod 是如何对外提供服务访问的?
Pod 是虚拟的资源对象(进程),没有对应实体(物理机,物理网卡)与之对应,无法直接对外提供服务访问。
那么该如何解决这个问题呢?Pod 如果想要对外提供服务,必须绑定物理机端口。
也就是说在物理机上开启端口,让这个端口和 Pod 的端口进行映射,这样就可以通过物理机进行数据包的转发。
概括来说:先通过物理机 IP+Port 进行访问,再进行数据包转发。
④一组相关的 Pod 副本,如何实现访问负载均衡?
我们先明确一个概念,Pod 是一个进程,是有生命周期的。宕机、版本更新,都会创建新的 Pod。
这时候 IP 地址会发生变化,Hostname 会发生变化,使用 Nginx 做负载均衡就不太合适了。
所以我们需要依赖 Service 的能力。
⑤Service 如何实现负载均衡?
简单来说,Service 资源对象包括如下三部分:
Pod IP:Pod 的 IP 地址。
Node IP:物理机 IP 地址。
Cluster IP:虚拟 IP ,是由 K8s 抽象出的 Service 对象,这个 Service 对象就是一个 VIP 的资源对象。
⑥Service VIP 更深入原理探讨
具体如下:
Service 和 Pod 都是一个进程,Service 也不能对外网提供服务。
Service 和 Pod 之间可以直接进行通信,它们的通信属于局域网通信。
把请求交给 Service 后,Service 使用 iptable,ipvs 做数据包的分发。
⑦Service 对象是如何和 Pod 进行关联的?
具体如下:
不同的业务有不同的 Service。
Service 和 Pod 通过标签选择器进行关联。
selector:
app=x 选择一组订单的服务 pod ,创建一个 service;
通过 endpoints 存放一组 pod ip;
Service 通过标签选择器选择一组相关的副本,然后创建一个 Service。
⑧Pod 宕机、发布新的版本的时候,Service 如何发现 Pod 已经发生了变化?
每个 Pod 中都有 Kube-Proxy,监听所有 Pod。如果发现 Pod 有变化,就动态更新(etcd 中存储)对应的 IP 映射关系。
总结,这里简单介绍了Vm -> Docker -> K8s的演变过程,以及不同载体之间优缺点,具体在软件架构设计中采用哪种,还是要结合实际项目情况。
例如,虚拟机出现之前,我有钱有能力,我可以买套别墅
虚拟机出现后,实体机成本太高,我可以买个商品房
Docker出现,为了节约成本,胶囊公寓也不错
还没有评论,来说两句吧...