西部数码的超g型虚拟主机怎么样怎么样,他们的虚拟主机有如何

在“开源与容器技术”分论坛上,来自知乎的计算平台负责人张阜兴发表了题为“知乎容器平台演进及与融合实践”的精彩演讲。

本文将按照如下三个部分展开讨论:

? 知乎容器平台的演进历程
? 容器平台维护踩过的坑
? 容器与大数据的融合实践

知乎容器平台的演进历程

知乎容器平台的演进历程大致可以分成三个阶段:

? 2015 年 9 月,我们的容器平台正式在生产环境中上线应用。

? 到了 2016 年 5 月,我们已经将 90% 的业务迁移到了容器平台之上。

? 如今,除了业务容器之外,包括 HBase、Kafka 等多个基础组件都已迁至容器平台。

总的节点数达到了 2 千多个,而容器数则达到了 3 万多个。可以说知乎基本已经 All in 容器平台之上。

在容器平台整体演进的过程中,我们总结了五个要点:

? 从单集群到多集群混合云的架构调整。

? 从滚动部署到部署与发布相分离的使用优化。

? 在容器使用上,从无状态到有状态,引入持久化的存储。

早在 2015 年,我们就已经开始在生产环境中使用容器平台了。由于那时 Kubernetes 刚被发布,且不成熟,因此我们当时选用的是 Mesos 技术方案。

? 单集群所能容纳的容器规模较大(官方称:单个集群可容纳 5000 个节点)。

Mesos 的劣势:由于是单独开发一套 Framework,因此开发的成本较高。我们最开始采用的就是自研 Framework。

? 有强大的社区支持。

? 由于功能完善,接入使用成本较低。

Kubernetes 的劣势:由于它将所有的状态都放入 Etcd 中进行存储,因此单集群的规模没有 Mesos 那么大。官方称:在将 Etcd 升级到 V3 版本之后,才能达到 5000 个节点。

在运行之初,我们使用的是一些简单的无状态容器。后来随着 Proxy、Kafka 等基础组件的引入,针对每一套组件都需要开发一套 Framework 的接入成本太高。

因此在后续的实践过程中,我们直接采用了 Kubernetes,通过资源调度层,统一进行资源的调度和管理。

在生产环境中,我们有着如下实际需求:

? 对于 Mesos 或 Kubernetes 的任意参数变更,都需要在灰度集群上去先进行验证。只有验证通过之后,才能大规模地部署到生产环境之中。

因此,我们需要有一个线上与线下相似的环境,它们的区别仅在于测试的集群规模略小于实际运行的集群。

? 对于 Kubernetes 的单个集群来说,容量是有限的,所以需要通过实施多集群方案来对容量进行水平扩展。

? 可容忍单集群级别的故障。

? 需要采用混合云的架构。由于公有云的集群池比较大,它既能够大幅提升弹性资源池的容量,又能够抵御突发的扩容需求。

计费模式较为灵活,可按需计费,并“廉价”地实现一些临时性的活动所带来的计算资源的消耗。

在混合云架构的实现过程中,我们曾调研过 Kubernetes 的 Federation 方案,但是发现它存在如下两点不足:

? 由于尚不成熟,目前官方并不推荐运行在生产环境之中。

? 组件过多,在部署和管理上较为繁琐。

因此我们采用了自行研发的管理方案,其特点是:

? 每一组业务容器都会同时在多个集群上创建 Deployment。

? 这些 Deployment 的配置,包括:容器版本、CPU / 内存资源的配额,都是完全相同的,唯一不同的只是容器的数量,它们会根据不同的集群大小做出相应的调整。

从滚动部署到部署发布分离

我们优化了部署与发布的流程,从原先的滚动部署模式转换成了部署与发布相分离的模式。

在此,我们来区分一下部署与发布这两个概念:

? 部署,是分发代码的配置,启动诸如 Web Service 进程之类的服务实例。

? 发布,是指把一组服务实例注册到、或者其他流量分发系统上,使其能够对外接收流量。

如上图下方的流程所示,上线的基本流程为:内网流量测试→金丝雀流量测试→生产环境全量。

那么在每一个阶段,我们都需要去观察线上业务的指标,一旦出现异常,我们就需要及时地进行回滚操作。

我们来深入分析一下滚动部署方式的优缺点。

? 每次先升级一部分的容器实例,然后再迭代运行。

? 能够保证在升级过程中服务的不中断,而瞬时产生的最大资源消耗是受限制的。

? 在滚动部署的过程中,我们无法做到:先部署 10%→停下来→再部署 20%→再停下来→接着部署 50%,因此无法灵活地控制进度,也不能对应到前面所提到的各个发布阶段。

? 如果每个发布的阶段都采用独立的滚动部署方式,那么整体部署速度将会比较缓慢。

? 在滚动部署过程中,旧的容器实例会被立刻销毁。一旦此时线上指标出现问题,而我们的观察却有所滞后,那么所涉及到的“销毁新实例和启动旧实例”,回滚速度会比较缓慢。

针对上述问题,我们在设计上采用了“部署与发布相分离”的模式。

例如:我们在上线时,先在后台启动一组新的业务容器实例,当容器实例达到并满足了内网发布的数量要求时,我们就把它注册到内网之中,然后将旧的实例从内网流量分发的系统中“反注册掉”。

如此,新的实例就能够在内网中被发布与验证。在后台继续启动新的容器实例的同时,也避免了用户能感知到容器启动实例的时间。

我们实现了内部用户在验证完毕的时刻,下一个阶段的部署就在数秒内直接升级完毕了。

另外,由于我们旧的容器实例并非立刻被销毁掉,而是要等到在生产环境发布完成的一段安全时期之后,再按照类似于金丝雀的策略将旧的一组容器完全销毁掉。

因此,在金丝雀发布的过程中,如果线上出现任何问题,我们就能够立刻把旧的实例重新注册回来,以实现秒级回滚。

在容器的使用模式上,我们最初部署的是一些无状态的业务 Web 容器。但是随着其他基础组件被迁移到了该容器平台之上,我们引入了持久化存储,以提供服务支持。

因此在生产环境中,我们用到了如下典型的持久化存储方式:

? HostPath。主要是配合 DaemonSet 进行使用。因为 HostPath 本身就能够保证在每一个 Node 上只启动一个 Pod 实例,因此不出现多个 Pod 同时使用同一个 HostPath,进而导致产生路径冲突的问题。

例如,我们让 Consul Agent 采用 DaemonSet 部署,那么由于 Consul Service 在注册的时候需要持久化到本地存储目录之中,因此就很适合于用这种方式去实现。

? Local。最新版的 Kubernetes 已经能够支持 Local Volume 了。优势在于:因为使用的是本地的磁盘,它相对于网络存储有着较高的 IOPS,且延时较低。

所以对于诸如 MySQL 和 Kafka 之类的有着高 IOPS、低延时的存储类应用来说,是非常合适的。

? NFS。我们通过将分布式文件系统的 Fuse 接口映射到容器之中,以保证业务能够从分布式文件系统上去读取各种数据文件。

在容器网络的模式上,我们最早采用的是 iptable 所实现的 NAT 模式。该模式实现起来较为方便,不需要对现有网络予以调整。

但是它存在一定的性能损耗问题,这对于我们早期的那些业务容器来说尚可接受。

到了后期,需要将一些大流量的高速网络应用,如 Ngix、Haproxy 放到容器里时,我们对这种性能开销就无法容忍了。

因此我们结合自身机房的网络实际,在 Kubernetes 方案上选用了 Underlay IP,这种简单互联的网络模式,以保证容器的 IP 与所在物理机的 IP 是完全对等的。

由于不存在 Overlay 的封包 / 解包处理,因此性能几乎没有损耗。通过实测,我们觉得性能非常好,所以将各种大流量的分发应用都放在了此容器里。

另外,由于 IP 模式具有良好的业务对应关系,因此我们可以方便地去定位网络连接的来源和故障。

例如:倘若在 MySQL 侧发现有大量的连接产生,你将如何定位这些连接的来源呢?

按照原有的端口映射方式,你可能只能定位到是来自于某台机器,但是往往一台机器上会被部署了多个业务应用,因此也就没法精确地定位到是由哪个业务方所导致的。

如今,采用了 IP 方式之后,你就可以很方便地根据 IP 地址来判定对应的是哪个业务容器了。

同时,在具体的实践过程中,我们还给每一台机器分配了一个固定的网段(如一个 C 类网段),然后通过 Kubelet 的 CNI 插件,即 APAM,来负责每台机器 IP 地址的创建、分配和释放。

由于我们在生产环境中大规模地使用了容器平台,可见容器平台已经成为了我们基础组件中的基础组件。

那么它一旦出现问题,将会对我们的生产环境造成重大的故障。下面给大家分享一些我们曾经在生产环境中踩过的坑。

一次半夜三更,我们的 API Server 突然全部无法访问了。通过调查,我们发现原因就在于 K8S Events。

众所周知,K8S Events 就像 Log 一样记录着 K8S 集群里发生的任何变更事件。

如果你没有进行额外配置的话,它会根据默认模式将这些变化全部记录到线上的同一个 Etcd 里。

同时,K8S 为这些 Events 配置了相应的过期策略 TTL,以保证在经过一段时间后,该 Events 会被自动回收掉,从而释放 Etcd 的存储空间。

该设计看似合理,但是在 Etcd 实现 TTL 时,却采用的是遍历的方式,因此实现效率比较低下。

随着集群规模的逐渐变大,集群上会出现频繁的发布、部署与变更,这就会导致 Etcd 的负载逐渐增大,直至最终造成 Etcd 无法再选举出一个 Leader,而整个 K8S 集群就此崩溃。

针对上述事故,其实 K8S 也意识到了,它为我们提供了一项可以将 Events 记录到某个单独 Etcd 集群中的配置。

不过,针对该单独的 Etcd 集群,我们是不需要进行高可用存储的,因此我们就直接使用了单节点的 Etcd,而并没有采用 Raft 方式去组建具有更好性能的集群。

另一方面,我们意识到 K8S 所给定的诸如“每隔三个小时就回收掉 Events”的 TTL 机制过于精确。

因此我们自行实现了一种过期清理策略,即:固定在每天晚低峰的时候,再将整个 Events 的 Etcd 集群清空。

除了上面提到的“由于 API Server不响应,所导致的整个 K8S 集群失控”故障,我们也碰到过“所有生产环境中的 Pods 全部给直接删掉”的坑。

在所有 API Server 都“挂掉”的极端情况下,如果你没有及时去处理,并超过了一段时间(如五分钟),那么在 K8S
特别注意:本站所有转载文章言论不代表本站观点!
本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。

我要回帖

更多关于 西部数码的超g型虚拟主机怎么样 的文章

 

随机推荐