前言php
容器技术目前的市场现状是一家独大、百花齐放。 关于容器技术,看看青云QingCloud 王渊命(老王)是如何看待它的,本文来自他在青云QingCloud 深圳站实践课堂的演讲。全文 2780 字,阅读时长约为 11 分钟。node
容器是什么nginx
容器的概念外延比较广,讨论的时候容易产生分歧,虽然你们都在说容器,但各自的角度不一样,表达的具体内容也彻底不同。总结来看容器有两个视角,一是资源,二是应用。编程
一是从资源隔离的角度。容器技术常常被拿来跟虚拟化技术做对比,从技术角度来讲,容器是一种跟 VM 相似的资源隔离技术,它比 VM 的资源损耗小,但隔离性和安全性不如 VM ,等等。安全
二是从应用封装的角度。Docker 之因此兴起,缘由在于其重点关注应用的标准化,而不是资源的隔离。Docker 的镜像机制提供了一种更高级的通用的应用制品包,也就是你们说的集装箱能力。原来各类操做系统或编程语言都有各本身的制品机制,各自的依赖管理,制品库都不相同。应用从源码打包,分发到制品库,再部署到服务器,很难抽象出一种通用的流程和机制。服务器
而有了 Docker 的镜像以及镜像仓库标准以后,这个流程终于能够标准化了。同时 Docker 将进程的管理,好比启动中止也标准化了。相似杯子、筐、集装箱都是容器,它们的共同特色是能把杂物打包,标准化,方便运输和订价。在此之上,容器能够作更高级的逻辑分装和调度。网络
容器生态圈现状架构
容器技术目前的市场现状是一家独大、百花齐放。容器的解决方案很是多,以 Docker 为首占据了大部分的市场,此外还有各类解决方案如 Rocket、Mesos Universal container、LXC、Hyper Container 等。负载均衡
容器主流的调度系统 Kubernetes、Mesos 和 Docker Swarm 是三足鼎立的状态,他们各有优点。Kubernetes 偏重于应用的抽象和规范的定义,Mesos关注可扩展性及资源混合部署,Swarm 关注于开发环境和线上环境的一体化,更方便使用。编程语言
能够看出,容器市场的竞争现已上升到调度层,这也是为何 Docker 把 Swarm 嵌在内部,使得 Docker 再也不是一个单机容器,而变成了调度系统的解决方案。
青云QingCloud 容器解决方案
从资源视角和应用视角分析一下青云QingCloud 提供的容器解决方案。
就资源视角来讲,用户但愿 VM 能像 Docker 同样,可对标准进程进行封装,使得 VM 也是一个完整的操做系统。为延续用户对VM 的操做体验,青云QingCloud 在统一的 IaaS平台上同时支持 VM(Virtual Machine 虚拟主机)与 CM(Container Machine 容器主机),使得用户对虚拟化的部署习惯得以沿袭,同时还可享受容器资源轻量隔离的特色。
就应用视角来讲,青云QingCloud 支持容器编排系统,体如今两方面:一是AppCenter 应用支持 Docker 镜像,二是容器编排系统能够做为一个应用放在AppCenter 上。容器能够在 VM 之上部署集群,Mesos、Kubernetes、Swarm 也能够做为云应用放在 AppCenter 之上,让用户能够自主选择。
Kuberneteson QingCloud AppCenter
咱们第一步作的是在 AppCenter 上部署 Kubernetes。为何选择 Kubernetes 呢?主要是由于 Kubernetes 部署比较复杂,若是最为复杂的 Kubernetes 可以在青云QingCloud AppCenter 上运行,其余集群也同样能够部署到 AppCenter 上。
QingCloud支持用户一键部署 Kubernetes 集群,不只解决了用户很大的痛点,同时也验证了 AppCenter 支持应用的普遍性。
为此,咱们解决了四大难题:容器调度系统的网络、数据本地存储的读取、容器平台与负载均衡器集成以及实现 Kubernetes 应用的弹性伸缩能力。
接下来总体介绍一下 Kubernetes。
Kubernetes 概览
Kubernetes 集群包含两种角色,一是 master, 二是 node,至关于 worker 或者 slave。
Master 有三个主要的组件:
一是 API Server(APIs),其底层是分布式存储(etcd),存储集群全部的数据;
二是 Controller Manager,承担了 master 的主要职能,管控全部的节点以及 Kubernetes 之上的 pod,service 等;
三是调度器 Scheduler,能够根据调度规则来分配节点最适合部署的位置。
如图有两个 Node,其上的 Kubelet 是节点的守护进程,用以管理 Node 上的全部 Pod。
Kubernetes 的 Pod 和 Docker Container 有点区别,这里特殊说明下,Pod 里包含多个 Container。Kubernetes 这样设计主要有两方面缘由:
1. 为了和 Docker 解耦。Docker 启动时会先初始化网络,而后再启动容器进程,由于不少应用启动后若是没有网络就会报错。但 Kubernetes 想用本身的网络方案,就必须是先启动容器,再建立网络。
因而 Kubernetes 会先启动一个空进程(pause进程,启动后就一直 sleep),占据容器的一个命名空间,在网络、存储建立出来后挂载到这个空容器上,而后才启动用户定义的容器,而这个容器直接复用 pause 容器的网络和存储。
2. 经过 Pod 打包多个 Container,使之共享同一个生命周期。这样的解决方案也很是有利于多个容器有强依赖关系的场景,好比 nginx 和 php-fpm 进程,好比 Kubernetes 的内置 dns 的多个组件,kube-dns 负责监听 Kubernetes 的 service 变动,而后转换成 dns 记录,写入到 dnsmasq 中。这种场景下,任何一个组件独立存活都是没有意义的。
Kubernetes 抽象概念
Kubernetes 的目标在于制定一个标准和规范,可让你来描述集群的架构,定义服务的最终状态,它来帮助你的系统达到和维持在这个状态。这个其实和 Puppet/Ansible 等配置管理工具的目的是一致的,只是配置管理工具只能作达到某个状态,无法实现维持到这个状态(由于没有动态的伸缩以及故障迁移等调度能力)。因此 Kubernetes 提出了许多抽象的概念,用来实现这种描述能力。如 Service、Job、ReplicaSet、Deployment等。
Kubernetes 网络设计
Kubernetes 对于网络有三点要求:一是容器之间能够直接互通,不须要 NAT;二是节点能够和容器直接互通,不需 NAT;三是容器看到本身的 IP 应该和其余容器看到的是一致的,即中间不能作IP转换,避免复杂的分布式架构应用节点之间的链接复杂问题。
Kubernetes 网络之 Cluster IP
Kubernetes 的 Service 概念大概是,一组服务有多个容器,经过同样的端口运行,暴露出来的 IP 都是同样的。经过一个松耦合的选择器把后面的容器或者 Pod 所有概括在这个 Service 之下。
Cluster IP 是一个虚IP,能够自动分配,也能够指定。当用户向这个 IP 的service port (好比例子中是 80) 发送数据的时候,iptables 会拦截这个数据包,而后把数据包随机分发至其中一个 Pod。这至关因而内部的一种负载均衡器,但它是自动的,即定义Service 的时候,会自动建立一个轻量的负载均衡器。
同时,Kubernetes 内置了 dns 服务,每一个 service 都会有一个和 service name 同样的 dns 记录,解析到 service 的 Cluster IP 上。这样一来,就实现了服务之间依赖的解耦。当请求一个服务的时候,不须要知道服务后面 Pod 的真实 IP 是多少,只须要请求 Cluster IP 或者 DNS。
Kubernetes 之 Flannel
先想象一下,若是咱们要自行实现一个容器的网络,每一个主机上有一个 Docker 容器,并自行分配一个 DockerBridge 的 IP。这样一来,若是在多个主机上启动Docker 就会发现:
第一,它会产生 IP 冲突,怎么解决这个 IP 冲突呢?首先得有一个机制协调,协调每一个主机分别用什么 IP。
第二,从某个主机里的容器发出来的数据包,它须要有一种转发机制,肯定这个包应该如何转发到另一个容器所在的主机上。
为了解决 IP 冲突,它首先须要 IP 分配策略,经过共享的 etcd 存储。也就是说,Flannel 会给每一个主机分配一个 IP 段,把它捆到 etcd 里,使得每个主机都知道另外主机的 IP 段是多少。这样就能确保 IP 不会冲突,使某个容器发出的数据可以准确传给对应主机的目标容器上,而且是经过 Kubernetes 分配 IP 的规则。
怎么去转发数据包呢?一种方法是经过 etcd 隧道,建立一个连接直接转发数据包;还有一种方法是经过云服务提供的路由规则,修改路由表便可。
Kubernetes 网络之 QingCloud
Kubernetes 的网络是如何发挥青云QingCloud IaaS 层网络的优点以及 SDN Passthrough(网络直通)的特性呢?
首先,一个主机可挂多个网卡,将一个网卡给这个主机,其余的网卡直接绑到容器里,使得在 VPC 环境中每一个容器的 IP 和对应主机的 IP 是对等的。这样一来,主机之间、主机和容器之间、容器之间能够实现互通,同时省去了 Flannel 解决方案的损耗。
其次,青云QingCloud 的负载均衡器能感知到容器网络,而传统的方案在内部还须要再作一层虚拟网络,IaaS 层的负载均衡器没法感知容器网络。
Kubernetes 存储
容器的存储解决方案是影射一个本地硬盘到容器中,本地硬盘的生命周期和容器是脱离的,容器删了以后数据还在。可是当咱们用调度系统的时候会发现,若是把容器从这个节点迁移到这个节点的时候,若是直接把本地硬盘路径挂上去以后,数据就没了,说明它的数据是迁移不过来的。
为此,Kubernetes 采用了分布式的存储,好比 nfs、ceph、glusterfs,PersistentVolume plugin。
此外,Kubernetes 还提供了存储插件,支持谷歌、AWS,以及青云QingCloud(QingCloudStore) 。有了这些插件,用户能够在主机上挂载一个硬盘,再将硬盘映射到容器。当容器从一个节点迁到另一个节点的时候,这个硬盘也跟着迁过来,使得容器的数据实现迁移。
Kubernetes 存储之 QingCloudStore
Kubernetes 有一个抽象的配置文件,配置文件标明 QingCloudStore,它能够关联一个 volumeID。这种方式的缺点在于配置文件和资源是绑定的、强关联的,配置文件用一次以后就不能用了,使得测试环境和现场环境不同。因此,为解决这个问题,须要在 Kubernetes 中声明须要多大的空间、是否读写、什么权限、提供方是谁,再加上 StorageClass 的配置。
有了这样的声明以后有什么好处呢?使得环境和具体的资源不绑定了,当集群发现该声明尚未知足的状况下,它会自动建立一个盘,关联到你的 Pod 上。当 Pod 删除的时候,它会回收资源。这样,实现了解耦。
Kubernetes 负载均衡器
Kubernetes 自己的负载均衡器提供了一种插件,让云服务商实现插件和 IaaS 层整合。由于最终用户暴露的时候须要一个公网 IP,这个实现和各云厂商的服务是息息相关的,而 Kubernetes 本身比较难直接提供这样的服务,因此它就提供插件让云服务商去实现。
可是云厂商的负载均衡器只能感知到节点主机这一层,对主机里面的容器是无感的,因此大多数状况下只能把 Kubernetes 集群下全部的节点都挂载到 LoadBalancer以后。前面讲到 Service 时说到,Kubernetes 为每个 Service 都在全部主机上监听一个随机的端口,也就是 NodePort,这个请求会转发到主机的随机端口上,由随机端口转发到 ClusterIP 上,再由 ClusterIP 转发到后面的容器,能够看出,这样就多了几层转发。
若是负载均衡器能感知到容器的网络,就能够直接透传请求到容器中。咱们的负载均衡器后面直接挂在的是容器网卡,这样就省去了几层转发。同时咱们的支持公网和私网两种 Load Balancer。由于通常不可能把全部的服务迁到 Kubernetes,有一部分迁进去了,有一部分服务可能在外面。这种状况下外部服务访问不了Kubernetes Service 的 Cluster IP 和 DNS ,这个时候须要私网的 Load Balancer 去转发这种请求。
Kubernetes 自动伸缩
Kubernetes 提供了自己一种机制,经过相应命令可自动增长 Pod 的节点数。但光有这一层伸缩是不够的,部署 Kubernetes 集群的时候,节点数是提早规划好的。当自动伸缩使 Kubernetes 容量达到上限的时候,就没法伸缩了。这个时候集群自己须要有自动伸缩的功能,当前只有谷歌云实现了集群的伸缩能力。
当 Kubernetes 集群的资源不够了,它会触发一个事件,IaaS 层监听这个事件,收到事件请求以后增长集群的节点。这样就实现了业务应用层的自动伸缩以及 Kubernetes 资源池的伸缩。
扫描下方二维码,带你领略最酷的云计算知识