干货分享 | PaaS云平台在企业落地的 8 大关键点

5月26日,时速云企业级容器 PaaS 技术沙龙第9期在深圳成功举办,时速云联合创始人兼技术总监杨乐就 PaaS 平台落地实施所关注的一些问题、Kubernetes 核心组件、Kubernetes 资源对象以及 Devops 体系、微服务治理等方面做出了深入的探讨和分享。

以下是本次分享的实录:

杨乐:非常感谢大家,在这个天气炎热的周六来到这里。在这里给大家带来的是关于 PaaS 云平台在企业中落地的经验分享,其中包括了生产环境中关注的问题,Kubernetes 的架构和资源对象的利用,以及我们在实际实施过程中遇到的一些问题。另外 PaaS 平台体系构建完成,是如何在容器云上进行的应用实践的,以及我们基于 Docker、Kubernetes 所构建 DevOps 体系持续集成,测试环境和生产环境是如何应用 Kubernetes 去构建运行使用的,我们还会介绍微服务治理相关的架构,以及我们部署架构的知识。

基于Docker和K8S的平台建设
1、PaaS 容器云平台落地实施关注的问题

在 PaaS 云平台落地的时候,会有一些关注点,我们在企业落地实施的过程中,首先关注架构运行的方式,也就是说我们最初架构的选型,以及它的核心组件,比如说我们的日志如何去收集,监控和报警组件是如何运行的。在 PaaS 平台上运行的应用,相关的应用服务是如何发布出去的,是以何种方式代理出去的。以及我们在落地实施的时候,平台自身的组件以及 Kubernetes 本身的组件如何实现它的高可用,真正实现生产运行体系。

为了运行有状态应用,需要分布式存储进行支持。如何构建集群的网络类型,如何将容器服务进行集群内的网络打通。持续集成体系是我们基于 Kubernetes 相关的资源对象去构建的开发测试运维一体化的子产品。而最终要去注重用户应用的发布、运行,同时需要以容器的方式在部署到 PaaS 平台,如何将应用容器进行互联。

我们会关注真正落地实施之后,从它的架构运营、高可用性,到最终成体系的构建、应用的部署。而这几个关键点,会在后面每一个对应到 Kubernetes 架构体系上,一一介绍。

在场的各位对 Docker 和 Kubernetes 有没有一些了解,Docker  是单机容器的运行引擎。而 Kubernetes 是将容器以及 Docker 做集群架构的体系,它的架构方式是 Master、Slave 的方式。也就是说 Master 作为中控调动中心,去控制我的 Slave 结点。而 Slave 节点上面,所有的这些结点去运行相关的容器。应用服务都会用容器的方式运行在 Slave 节点之上。而它的发布是通过 Service 以及外部代理的方式向外发布。而每一个容器可以通过设置后端存储的方式进行持久的存储。

在 Kubernetes 组件里,需要关注日志组件。当容器运行在 Kubernetes 架构体系的时候,我需要关心应用本身产生的日志有没有问题。测试和开发人员需要获取一些调试的信息,然后去判断它的问题在哪里。而运维人员也需要查看发生问题的应用,它的日志在哪里。

当容器的 CPU 或者是内存发生了一些变动,超出负载的阈值时,需要做及时的报警。在内网进行服务发现的时,需要一个 DNS 的配置,以此各个应用间可进行探测和调用。

我们后面会有一些存储和网络,网络需要支持我们整个集群之内所有的结点,容器之间需要网络的打通,可以让容器在内网之间做一个互联,做一个架构的连接。

2、Kubernetes核心组件

Kubernetes 核心组件包括日志、监控、kube-dns。从日志来说,Kubernetes 这些日志组件是从 ElsaticSearch 构建的。它会从节点里面收集相关的容器日志信息。会把这些信息发送到中控的 ElsaticSearch 组件里面去。当这些信息收集完了之后,会通过外部的 UI、开发的UI的组件或者是用 Kibana 展示组件去进行合理的展示。

运维人员和开发人员可以通过可视化的展示组件去检索对应的日志。对于日志来说,Docker logs 是默认的日志输出的位置。但是通过一些特定的设置,不单单可以收集 Docker logs 本身产生的日志,还能够指定应用所能够达到日志的位置,指定相关的目录,并能够随意收集容器内部日志的信息。

在监控体系方面,第一种方式,Kubernetes 本身是使用 Kubelet 以及 Heapster、Influxdb 构建的。Influxdb 会把相关监控信息存储起来,监控数据从kubelet中通过heapster远程获取的。通过 Grafana 去展示相关的监控信息。用户通过一个集中化监控展示平台,可以查看到指定的容器服务所用的 CPU、内存相关的监控信息。

第二种监控体系是使用 Prometheus 组件,这两种体系是分别独立的。它的方式也是通过收集每一个节点相关的 CPU、内存等等监控信息,存储到一个中心化存储体系里面去,然后再把相应的监控信息展示出来。

对于报警体系,可以通过 Prometheus 本身的一些规则的设置,可以设置达到我 CPU 预值20% 的时候会触发报警事件。它可以调用外部相关操作的动作,比如说调用我们的平台,调用我们平台 API 里面所集成的短信或者邮件 API。就可实现从我们平台发生的监控,比如说超过了预值的 CPU,自动发出报警给我们的管理员,管理员就可以在及时检测到CPU、容器以及节点它的问题所在。

Kubernetes 一个核心组件就是 kube-DNS,它是为 Kubernetes 内部应用之间做服务发现。什么是服务发现,当我们把我们的应用去运行到 Kubernetes 体系里面去的时候,每一个应用中需要有一定的机制发现对方。我需要知道我周围的这些应用运行的名字是什么,它的运行位置在哪里,它的 IP 是多少。我需要这样一套发现机制,而 Kubernetes 本身提供的一方面把每一个应用和容器的信息记录到 Master 里面去。同时用 Kubernetes DNS 的方式展现给其它的应用工具。

当用户创建应用后,会在内网 kube-dns 里面记录一个域名。 每一个域名对应我一个应用,当其它的应用容器想要连接指定的应用的时候,只需要通过 DNS 域名就可以连接到。DNS 的 Kubedns 组件,不停的跟 Master Apiserver 进行交互,实时获取所创建或者是删除的这些应用的状态,获取IP地址、名称,并记录在 DNS 存储空间里,形成一条条 DNS 记录。而 DNS 会把相应的记录信息整合成DNS的服务出口。这样其它的应用服务可以通过DNS的53端口,进行查询,和DNS记录检索。这样就实现在整个联网范围之内,通过DNS去查询到指定的应用服务的功能。

Kube-DNS 是可以应用到 Kubernetes 本身的编排体系里面去。也就是说当我们运行应用到Kubernetes 架构体系里面之后,它不单是一个应用,而是多应用需要编排在一起。编排在一起就需要每一个应用互相之间进行一个发现和连接,而连接就需要用IP地址或者是域名,这里面就是用域名的方式。

所以我在编排的时候,通过一个编排文件,把编排文件每一个应用之间,它是用域名的方式设计到里面去。通过编排文件它可以统一的创建所有的应用,让它同时去启动或者是顺序启动,进行一个架构的建设。

高可用性,高可用对于系统平台来说,包括 Kubernetes 本身的高可用,还有我们提供自身产品的高可用,还有各种其它组件和存储的高可用。Kubernetes 本身高可用提供的这种方式,首先 Master高可用,Master 高可用通过多个 Master 的方式让它多活,然后通过统一的 Keepalived 的方式跟 Service 进行一个互联。

而相应的服务对外发布出口的时候,需要有一个对外的出口。底层存储的方式是通过多活的方式进行高可用的设置。平台本身每一个涉及到单点故障问题的组件都设置了高可用性,这个也是在生产环境中必要考虑的。

3、Kubernetes的资源对象
Kubernetes 的一些资源对象, Kubernetes 的 Pod 的概念,对容器本身来说,一个 Pod 里面可以包含多个容器,而多个容器在同一个 Pod 里面是可以共享网络和存储的。这就实现了在多个容器进行编排的时候,每一个容器都可以进行非常紧密的连接。Deployment 可以对 Pod 进行副本的管理,或者是进行滚动升级的识别。

而 Service 这个概念就是一个抽象的服务出口,这就是为了将我的 Pod 或者是我的容器运行在 Kubernetes 之后,如何将它发布出去,如何让用户从外部进行一个访问,让 Service  做这件事情,它实际上是在我们的节点上做了一个负载均衡器。一个基于 IOS 一个负载均衡器。它会把用户外部访问的流量分发到内部多个 Pod 或者是容器上面进行一个负载均衡。

Labels 实际上是指在我 Kubernetes 本身资源对象里面作为一个标签,以及标签选择的方式。

ConfigMap 实际上是对数据的管理,我可以通过把我的一些外部配置信息放在 Kubernetes  存储里面的一种方式。然后去解决我在构建完我的容器进项之后,我希望把我的这些进项放在不同的环境里面,而不同的环境外部配置信息反而不一样。而我又不希望更改我容器里面的这些内容。那就用外部的方式,将外置的配置信息加载到容器里面。

而这个 ConfigMap 就起外部配置信息加载到容器里面的作用的。Secret 本身是解决密码以及 token 相关的问题。Job 是任务以及定时任务,我可以设置一个应用程序或者是一个进程让它运行一次,或者我可以设置定时进行。这些可以把它思考成一个 cronjob,也就是说一些定时任务会去做。

水平伸缩也就是说 HPA,在 Kubernetes 里面,它可以做到应用容器的一些自动伸缩。可以根据我们的 CPU 或者是内存、网络或者是磁盘 AIO,它的参数,进行一个实例的伸缩。如果我们设置了一个预值,如果 CPU 超过了 50%,那么我的容器自动扩展到 10 个或者是 20 个。当 CPU 低于百分之多少的时候,我可以让他自动回缩到指定的数量。这就是在负载变化的情况下,对实例伸缩的功能。

而下面的 Stateful、Volumes 以及 Ingress,Stateful 是为了解决有状态服务,以及可以做集群模式对象。Volumes 是为了解决相关磁盘存储,还有 Ingress 是 Kubernetes 本身指定的负载均衡代理。

对于 Kubernetes 资源对象 Stateful 首先是为了解决有状态存储的一些应用。如果需要手动设置多个 Pod 之间的存储配置,就会出现一个问题,Pod 重启之后就消失了。所以如果我们手动配置的话,就很难做到他们之间主从的配置

而 Stateful 是为了解决这个问题,Stateful 第一个特点是可以挂载相应的动态存储。第二他可以将起来的这些 Pod 进行有序的标号,也就是说普通的 Pod 的话,它的标号是随机的。但是这种 Stateful 是有序的,从 0 开始一直到 N 为止。也就是说这几个 Pod 之间是可以用有序的名字互相发现。这就带来一个可能,我在运行 Stateful 的时候,我可以设置一些参数或者是脚本,让他们按照这个名字互相发现。这样你通过互相发现的方式,再进行主从之间一些动态设置。这就可以实现我起了多个容器,通过 Stateful 进行一些动态设置。他们可以完成主从,进行集群的配置。也就是说 Stateful 可以实现各个需要进行主从配置应用软件的集群设置。

Ingress 我们之前提到作为一个服务出口,当我们的应用运行在 Kubernetes 的时候,我们需要把它进行对外的发布,发布的方式可以通过代理的方式,也可以通过 Ingress 的方式。

实际上 Ingress 对应的就是我们所关注的服务出口的问题,而 Ingress 是解决出口的方式之一,实际上还有其它很多种方式,也可以自研去做这个事情。

Volumes 是解决整个 PaaS 平台它的存储问题,我们应用容器在运行的时候,如果我们用过 Kubernetes,如果 Pod 起来以后,如果不进行持久化存储的话,重启以后很多内容丢失。为了防止关键信息丢失,我们需要挂在分部式的存储。

一种方式就是我们通过 PVC 的方式,挂在一些文件体系上面。这样 Pod 在进行迁移的时候,其中一个 Pod 在机器上挂掉以后。它的存储会跟随我们的 Pod 从另外一个可用的机器上起来。这样的话,它原来的内容可以在新的 Pod 里面读取到,这样就达到存储可用性的效果。

Kubernetes 网络类型也有很多种方式,现在我们常用或者是我们现在支持的方式就是包括让 Calico、Flannel、Weave 的方式。实际上一种是隧道的方式,或者是用路由的方式去实现。

4、Kubernetes生产环境的实施

从上图我们可以看到生产环境实施的整个架构模式图,首先对于 Kubernetes 来说,整个集群各个组件模块是需要多副本的,整个控制台对 API 调用的控制端需要多个节点,以及镜像仓库、文件存储,以及相关的 Slave 都是需要多节点的。

而在集群内部,需要一组服务出口。在应用的时候,持续集成所需要运行一组集群,这些都需要高可用去做。每一个功能组件,可以通过一种方式进行合理的分组。每种类型的组件或者应用,可以运行到指定的服务器节点上去。

容器云平台在企业中的应用场景
1、容器云平台功能体系
下面给大家介绍一下容器云平台在企业中应用场景,首先可以看一下整个容器云平台功能体系,首先是最基本的应用管理。可以通过 Kubernetes 去创建应用,去管理应用。可以通过 Kubernetes job 去实现持续集成的体系,包括代码仓库、镜像构建以及持续部署这些功能。微服务体系包括服务发现、负载均衡等,应用之间可以进行服务监控。可以通过Stateful 资源对象一键创建一套集群体系。包括我们分布式的存储,相应队列,大数据的一些组件等等。

 而 Kubernetes 本身部署起来,可以是虚拟机,也可以是物理机,也就是说它的底层架构可以是偶合的。

2、Devops体系

通过 Kubernetes job 的方式来进行持续集成,也就是说持续集成构建的框架。通过这个框架,我们启动我们的持续集成的时候,我们会调动 API。通过 job 的方式,启动多个构建服务,每一个 job 对应一个任务去完成它指定的工作。当它完成以后,会通过代码的构建以及镜像的生成。结束以后,它会把相应的镜像放在指定的镜像仓库里面去。。

通过对镜像仓库以及 API 的设置,它可以自动从镜像仓库里再次部署到 Kubernetes 的环境里面。

开发人员可以通过代码提交的方式去触发持续集成。同时进行单元测试。测试结束之后做一些审计,然后把这些结果发送。扫描结束之后会对它进行一个编辑,编译的结果会传到下一步里面,进行一个代码构建,代码构建会生成相应的镜像,它会推送到我的镜像中心,然后会接受一些安全扫描。扫描镜像里面是否存在一些安全风险,它有没有一些漏洞。在漏洞扫描结束之后,会经过部门的审批流程。如果部门审批流程通过,它就可以进行下一个镜像发布或者是发布到我们的平台,或者是让它上传到我们的应用商店里面。

这样当镜像进行一个发布之后,会运行到测试环境,可以交给测试团队进行一个部署的测试。当测试团队发现问题之后,会交给开发人员进行再一次迭代。这样就会形成从研发体系到代码提交到研发开发测试,到最终的部署运行以及再次回环的迭代,整个回环体系就构建起来了。

3、测试生产运行体系

这是测试环境以及生产环境的运行体系,在给客户部署实施的时候,一般情况下,很多用户都是按不同的部门或者是按不同的网络环境的多个集群。在这个图上可以看到左边是测试环境集群,也就是说这是一套独立的 Kubernetes 集群体系,右边是生产环境的一些集群。这里面是所有生产环境的应用都在运行。

从构建体系来说,持续集成体系可以在这里面跑。也就是说从代码的生成到持续集成部署到镜像生成,自动把业务应用上去,开发测试人员通过测试环境对它进行一个测试。最终当测试完毕之后,这些镜像可以通过定版的方式同步到生产环境的镜像中心里面。

然后再通过运维或者是项目经理的管理,进行一个生产环境的部署。这样的话它就形成整套从生产环境到测试环境整体的运维体系。当我们在真正生产运维的时候,可以通过生产环境中的日志管理、监控管理、审计系统,通过这些组件进行生产环境的运维。

4、微服务治理

微服务治理是基于 Kubernetes 的特性基础上,将 SpringCloud 架构结合在一起。集成了  SpringCloud 的服务发现、负载均衡、配置管理等组件,可以用容器的方式运行到  Kubernetes 平台里面。用户可以把基于 springboot 开发的应用运行到平台里面,运行上去之后,应用将注册到服务注册中心,并可使用 SpringCloud 的相关组件。

生产环境落地实施后,最终要实现的是用户的应用要上云,真正的部署上去。部署的环节需要首先把应用程序进行容器化。需要构建应用的生产环境,将应用程序进行打包,然后将应用的镜像部署到我们的 Kubernetes 里,让 Kubernetes 对应用程序进行生命周期的管理,当整个架构体系和服务体系上云以后,可以进行多个组件之间的编排,组件直接进行互联,并且通过配置管理进行相同应用多个环境的部署。

当涉及到数据库的存储时,需要使用 Stateful 对象进行管理。当应用架构部署完成以后,对外发布的时候,需要进行负载均衡出口的管理。最终以如图这种方式,通过负载均衡访问到 APP,以及数据存储通过存储块进行有状态保持,在运维的过程中,对其进行配置管理,以及监控、日志的查看、操作,这样一整套运维体系就可以构建起来。

Q&A

Q:用户隔离怎么做?

A:用户隔离是基于用户命名空间的体系做的网络隔离。Calico本身是负责网络隔离的,再就是一些用户体系的资源隔离,都可以通过kubernetes 的命名空间进行隔离。

Q:我刚才看有大数据相关的组件,我不知道你这边大数据有没有用到ES等性能要求比较高的应用。在这种情况下,你们的性能表现是什么样的。第二个问题是在Kubernetes有三种service模式,你这边是哪一种模式?

A:大数据相关的组件实际上如果你要运行的话,跟性能相关的,还是基于底层硬件体系。也就是说 Kubernetes 本身是需要架设在 IaaS 或者是物理基上的。如果说底层性能不够优的话,你构建那些 SDN 网络,它的性能也会受到连累。因为本身它访问的性能以及存储的性能,都是涉及到我用 ios 这种软件定义网络的方式去做的。最终是要打到物理环境里的。

第一建议网络做的比较优,再就是要用高性能,高 IO 的存储组件。

第二个问题是 Service,通过 Service nodeport 对外发布的时候,但是对于企业管理来说,你可能涉及到要发布到哪一个节点上,以及这些节点上的关口如何去管理。如果你这一套系统自用的话,这个方式是没有问题的。但是如果是一个企业或者是公有云,就会涉及到这些端口对于管理人员来说,管理起来是比较困难的。

所以最好集中的方式用这种指定节点,并且让它只是在几个节点上开端口的方式,或者是用 externalIP 这种方式做比较好。

K8S中文社区微信公众号