内容简介:关于容器,你真的需要听听老王怎么说
前言
容器技术目前的市场现状是一家独大、百花齐放。 关于容器技术,看看青云QingCloud 王渊命(老王)是如何看待它的,本文来自他在青云QingCloud 深圳站实践课堂的演讲。全文 2780 字,阅读时长约为 11 分钟。
容器是什么
容器的概念外延比较广,讨论的时候容易产生分歧,虽然大家都在说容器,但各自的角度不同,表达的具体内容也完全不一样。总结来看容器有两个视角,一是资源,二是应用。
一是从资源隔离的角度。容器技术经常被拿来跟虚拟化技术作对比,从技术角度来说,容器是一种跟 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 资源池的伸缩。
扫描下方二维码,带你领略最酷的云计算知识
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 假如 Go 能说话,听听 GMP 的心声
- 哪些书是技术人必看的?听听网友怎么说
- 微表情识别到底靠不靠谱?来听听陈通怎么说
- 何为SCA?听听一枚产品汪妹子的纯干货分享
- 云计算基础之什么是Ceph?听听Ceph创始人怎么说
- 容器技术之容器镜像篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。