近两年,很多金融企业已经开始部署或计划部署容器云。我们先分析一下容器云如何帮助金融客户构建敏态IT以及适合容器云的应用是什么。
我们知道,在敏态IT建设过程中,DevOps的建设是其中最重要的一个环节。笔者这里通过对云计算开源产业联盟发布的《中国DevOps现状调查报告》 进行解读,分析国内企业敏态IT建设趋势。
阅读报告,可以得出如下21条结论。
1)国内企业普遍接受了DevOps的观念,并已经开始实践敏捷开发。
2)敏捷管理实践排名采用度依次为:发布计划、看板、每日站会、Spring迭代。Sprint迭代是DevOps的基础。举例来说,红帽OpenShift采用Sprint迭代模式开发,而Ansible采用看板模式开发。
3)最受欢迎的四个工程实践:持续集成、自动构建、单元测试、持续部署。
4)项目管理使用最多的工具是JIRA。
5)多数企业将代码、配置管理、自动化脚本被纳入版本控制系统。
6)代码主干集成比例提升。
7)自动化测试比例大幅提升,但模糊测试、混沌测试、全链路测试仍需要提升。
8)测试左移比例提升,但仍不高。
9)大多数客户在使用虚拟机和容器。
10)告警平台的智能化与自动化决策有待提升。
11)运维全生命周期数据智能化分析有待提升。
12)变更管理可视化能力有待提升。
13)智能化配置管理和关联分析能力弱。
14)全链路容量管理能力有待提升。
15)自动化和智能化高可用管理能力有待提升。
16)企业应用RTO有待提升。
17)Spring Boot和Spring Cloud被大量使用。
18)两成企业微服务拆分简单粗暴。
19)半数以上企业尝试DevSecOps。
20)选择混合云的企业比重增加,选择公有云的企业比重下降。
21)超过20%的企业无法判断DevOps实践是否成功。
通过以上21条结论,我们来分析企业今后在敏态IT方面的8个建设重点。
1)混沌工程平台的建设会成为继容器云、DevOps建设后,企业IT建设这两年的重点。
2)企业短时间很难实现所有应用上容器,虚拟机+容器模式将会长期存在,因此DevOps建设应该考虑虚拟机+容器的混合环境。
3)智能告警、运维、变更、自动化等平台建设是企业在DevOps建设后,提升运维能力的重点建设方向。
4)企业应用RTO有待提升,企业会重视基于容器云实现业务的双活建设,保证在单数据中心出现故障时,服务不降级。
5)DevSecOps被普遍接受,将容器云的安全工具纳入DevSecOps工具成为企业IT建设的主要方向。
6)Spring Boot和Spring Cloud仍然受欢迎,因此Istio大规模商用的基础目前尚不存在。
7)20%的企业单体应用拆分简单粗暴,因此使用专业的方法论(如DDD)拆分单体应用,并进行微服务落地是建设重点。
8)选择混合云的企业比重增加,因此基于混合云实现DevOps、多云管理是企业建设的重点。
在物理机中部署应用,我们需要先安装操作系统(如Linux),然后安装应用服务器(如WebLogic、Tomcat),再部署应用包(如war包)。在虚拟化环境中,可以将部署了应用服务器的虚拟机做成模板,如果需要部署新的应用服务器,可先进行模板部署,再将应用包部署到应用服务器上。
虚拟化环境下应用部署的便捷性有了很大的提升,但在应用弹性扩容方面,效果还是不理想。在业务突然繁忙的时候,如银行的纪念币销售、保险公司的开门红业务造成大量的突发访问请求,紧急通过模板部署虚拟机、部署并启动应用,显然耗时太长。但是,如果提前准备虚拟化环境,一来增加工作量,浪费资源,二来临时准备的虚拟机,也未必能够承载突增的业务访问请求。所以,构建容器云是金融科技敏态业务的基础。金融科技敏态IT的构建分为5个步骤,如图2-1所示。
图2-1 金融科技敏态IT构建路径
接下来,我们针对图2-1中的5个步骤进行说明。
在介绍了金融科技通过容器云构建敏态IT的路径后,接下来我们介绍适合于容器云承载的应用。
容器云在发展之初,主要是承载无状态的、轻量级的应用。比较常见的企业级应用有运行在Tomcat中的War包,或者以Spring Boot方式打包并运行在OpenJDK中的Fat Jar。可以看到,这类应用都是重要性相对较低的Web应用。如果容器云平台只是Web类、网站前端类的应用,显然容器云平台的重要性也不会太高。在Kubernetes层面,我们可以通过Statefulset支撑有状态应用,而大量无状态应用和少量有状态应用则在容器云运行,如图2-2所示。
图2-2 容器云承载应用种类
随着Operator项目的兴起并被CNCF采纳,有状态应用集群也可以很方便地在容器云上部署和管理。目前OperatorHub已经有超过3000种有状态应用,并且仍在迅速增长,如etcd、ElasticSearch、TiDB等。
如果我们想让容器云承载更为复杂的业务,那势必需要借助一些类似中间件的架构,才能使容器化应用体系化。Spring Cloud作为一种微服务治理框架,本身具备一定中间件功能。例如在OpenShift上基于Spring Cloud开发一套电商平台,其UI界面如图2-3所示。
图2-3 电商平台UI界面示意图
本质上讲,Spring Cloud不是一个产品化的方案。Spring Cloud包括大量组件,可以根据客户的不同需求定制出一个可落地的完整方案,但这个定制过程涉及较多的架构相关的工作,以及业务代码的实现。
由于Spring Cloud主要靠定制计划开发,因此对应用开发人员或独立软件开发商(Independent Software Vendor,ISV)要求很高,而且一旦某个微服务模块的业务逻辑发生变化,都需要重新定制开发和编译。此外,这种代码实现的业务逻辑缺乏IT厂商的支持。因此,不少企业客户还是希望使用产品化的中间件。
我们仍然以上文提到的电商业务为例,其技术架构如图2-4所示。
在图2-4所示的微服务架构中,Pricing Service是定价服务。我们可以通过代码的方式实现定价逻辑,但工作量较大,且变更不方便。在Pricing Service中,如果使用JBoss BRMS产品实现定价业务规则,则会灵活得多。因为开发者可以只关注业务代码开发,而无须将过多精力放在架构开发上。
图2-4 电商业务技术架构示意图
近两年,中间件厂商针对容器云发布了更为轻量级的容器化中间件,主要也是这个目的。如IBM推出了WAS Liberty,红帽推出了很多云原生相关的开源方案,如Quarkus(云原生开发框架)、Camel-K(云原分布式集成)、Kogito(云原生业务流程自动化)、Debezium(云原生的CDC)、AMQ-Streams(容器化Kafka)、JBoss Data Grid(云原生分布式缓存)。具体技术细节,可以参考《云原生应用构建:基于OpenShift》这本书。
Spring Cloud的本质和首要目的,是实现微服务治理。但我们知道Spring Cloud的治理框架是代码侵入式的,不是针对Kubernetes原生的微服务治理框架,所以代码开发人员需要站在七层协议的角度,同时关注微服务之间的调度关系。2017年由谷歌和IBM主导,正式开源了Service Mesh架构:Istio。Istio的目的是将微服务的治理框架交由底层Istio和Kubernetes来实现。但Istio并不负责具体微服务的业务逻辑,比如上文举的Pricing Service微服务的例子,其定价规则可以由代码实现,也可以由容器化中间件实现。
随着Kubernetes的发展,现在有一个新的技术趋势:在容器云中以Pod的方式运行虚拟机,这样容器云平台就能够提供普通容器无法实现的功能。例如OpenShift上的OpenShift Virtualization技术,对应开源社区的KubeVirt技术。OpenShift Virtualization能够承载的应用包括WebSphere Application Server、Oracle DB、MSFT SQL Server(non-clustered)、IBM DB2 LUW、MySQL等。相信通过类似的技术,越来越多的应用会向容器云迁移。
整体而言,应用上容器云的准入条件包含如下几个方面(包含但不限于)。
如果应用明显不符合上述条件,则其暂时不适合运行在容器上。
在应用上容器云时,除了需要遵循以上准入条件,还需要尽量符合以下最佳实践。
针对已有传统应用系统的改造迁移,通常需要经过如图2-5所示的流程。
图2-5 应用容器化迁移流程图
从图2-5中,我们可以看到应用容器化迁移大致需要经历6个步骤。
可以看到,在这6个步骤中,最关键的是制定应用迁移方案和应用容器化。应用迁移方案没有一个通用的形式,它会因应用系统的不同而差异很大,所以企业需要根据应用系统的特点制定。后文将着重介绍应用容器化的方法。
应用容器化的第一步就是选择基础镜像,具体遵循如下选择标准。
镜像应从官方途径获得,避免使用来自社区构建和维护的镜像。应用镜像应在PaaS平台中构建,所选择的基础镜像应来自可信的镜像源,包括:
在容器云中,我们更推荐使用第二类镜像。红帽提供的镜像经过了严格的安全扫描,其镜像扫描遵循如下规则。
根据扫描结果确定镜像的健康级别,只有A、B级别可运行在OpenShift平台上,避免使用C及以下级别的镜像,如图2-6所示。
图2-6 镜像安全等级
红帽的很多基础镜像,是可以直接从互联网拉取(无须额外的认证)的,如RHEL7的基础容器镜像,如图2-7所示。
图2-7 RHEL7的基础容器镜像
查看镜像的健康等级,如图2-8所示。
图2-8 查看镜像的健康等级
使用Docker或者Podman都可以拉取镜像,如图2-9所示。
图2-9 成功拉取容器镜像
除了RHEL容器镜像之外,红帽还提供了通用基础镜像(Universal Base Image,UBI),该镜像可以运行在任何OCI兼容的Linux上。这意味着我们可以在UBI上构建容器化的应用程序,将其推送到镜像仓库,然后分享给别人。UBI的架构如图2-10所示。
图2-10 UBI的架构
什么时候使用UBI?可以参照以下几种情况。
UBI 7支持8类容器镜像,供我们自行选择,如图2-11所示。
图2-11 UBI 7提供的8类容器镜像
我们可以在任意安装了Podman或Docker的Linux服务器上获取UBI的镜像,如图2-12所示。
图2-12 获取UBI的镜像
目前,红帽UBI已经发布到Docker Hub中,也就是说即使没有OpenShift的订阅,也可以使用这个基础镜像,如图2-13所示。
图2-13 ubi8-minimal镜像
截至目前,笔者所接触的容器云上运行的应用,大多基于Java语言,少量基于Python、Go语言。由于Java是解释型语言,使用OpenJDK或Tomcat的基础容器镜像实现应用容器化即可,这里不再赘述。而C语言是本地编译的,这可能会和编译环境的操作系统产生关联。在本节中,我们将具体介绍C语言应用上容器云的方法。
C语言应用上云需要考虑的第一点是基础镜像。如果容器云使用的基础镜像与容器云宿主机的操作系统不一致,是否会有问题?举例而言,如果开发环境是SUSE Linux,那应用上OpenShift的时候,使用红帽基于RHEL的容器镜像,是否能够正常运行?
不能,但这个问题解决起来并不难。在C语言应用上容器云时,我们可以使用比红帽提供的基础容器镜像更为底层的镜像:Alpine Linux。这样我们就可以将C语言的编译和运行环境做到容器镜像里,从而规避了跨Linux操作系统的问题。Alpine Linux是一个由社区开发的基于MUSL和BusyBox的Linux操作系统,它以安全为理念,面向x86路由器、防火墙、虚拟专用网、IP电话盒及服务器而设计。
Alpine Linux的基础层只有6MB。它使用BusyBox提供外壳程序,根据MUSL C库而不是glibc构建。MUSL是一个符合POSIX的最小C标准库。Alpine Linux镜像中可以正常使用诸如cp和wget之类的命令。BusyBox有自己的方式来执行系统设置任务,例如添加用户和组。
下面我们来查看Alpine Linux的版本和Linux内核的版本。我们在写Dockerfile的时候,需要选对应内核版本的Alpine Linux,如图2-14所示。后文的验证使用Alpine Linux 3.12。
图2-14 Alpine Linux的版本
需要注意的是,Alpine Linux的核心应用程序都与MUSL连接,而不是glibc,并且Alpine Linux默认不包含其他C库。对于在Linux开发中已经习惯glibc扩展的人来说,使用MUSL会遇到一些问题。这里简单举几个例子。首先,MUSL中没有与glibc qsort_r()函数等效的函数,该函数用于对任意数据结构进行排序。其次,MUSL在实现某些功能时存在一些无法解释的问题。例如,用于格式化时间数据的strftime()函数缺少glibc实现所具有的说明符。
如果需要对微服务的HTTP通信进行加密,则需要决定是在OpenShift集群中还是仅在外部通过HTTP访问OpenShift上的应用时进行加密。对到集群的所有流量加密其实很简单,因为我们可以配置OpenShift路由进行边缘终止。如果在OpenShift集群中也要对流量进行加密,则需要为微服务提供自己的传输层安全性(TLS)支持。libmicrohttpd库支持TLS,但是该支持需要使用许多GNU TLS库的开发版本来构建。当然,这些库也必须在运行时可用于容器。
此外,需要提供服务器证书,并为客户的管理员提供一种获取该证书的方法。你可以在OpenShift Secret或ConfigMap中提供证书,然后将其作为文件挂载到Pod的文件系统中。这种技术相对普遍,基于C语言或基于其他任何语言编写在原理上没有什么不同。
接下来,我们通过一个基于C语言的微服务测试代码验证上容器的方式。在这个展示中,我们使用solunar_ws,它是基于REST的Web服务,可在指定日期提供特定城市的日出和日落时间并设置信息。solunar_ws是用C语言实现的基于REST的Web服务的demo,容器的总大小约为10MB,包括操作系统层、应用程序二进制文件和相关性,以及(在此特定情况下)完整的世界时区数据库。solunar_ws组件只有两个重要的依赖项:libmicrohttpd和tzdata(全局时区数据库)。libmicrohttpd是GUN下开源的一个小型HTTP库,能够方便地嵌入系统中。它支持HTTP 1.1可以同时监听多个端口,具有select、poll、pthread、thread poo等多种模式。tzdata软件包(全称为Time Zone and Daylight-Saving Time Data)可供各个Linux系统安装,以读取时区数据库中的数据。
查看如下Dockerfile,我们将C语言应用编译和容器化:
FROM alpine:3.12 RUN apk add git build-base tzdata zlib-dev && \ wget https://ftp.gnu.org/gnu/libmicrohttpd/libmicrohttpd-latest.tar.gz && \ tar xfvz libmicrohttpd-latest.tar.gz && \ (cd libmi*; ./configure; make install) && \ git clone https://github.com/kevinboone/solunar_ws.git && \ make -C solunar_ws # Binary solunar_ws ends up in / directory FROM alpine:3.12 RUN apk add tzdata COPY --from=0 /solunar_ws/solunar_ws / COPY --from=0 /usr/local/lib/libmicrohttpd.so.12 /usr/local/lib USER 1000 CMD ["/solunar_ws"]
以上Dockerfile的整体构建包含两个阶段。
第一阶段: 基于Alpine Linux 3.12基础镜像下载libmicrohttpd的源代码并进行构建,然后对solunar_ws进行相同操作。这些源代码来自不同的地方,但是它们都是以相同的方式编译。在此示例中,请注意,在构建Web服务之前,我们必须先构建libmicrohttpd的原因是Web服务依赖它。
本阶段镜像构建完以后,镜像大小约为210MB。
第二阶段: 从相同的Alpine Linux 3.12基础层开始,仅安装运行时所需的软件包,即tzdata。然后,从先前的版本中复制容器在运行时所需的两个文件:二进制solunar_ws和库libmicrohttpd.so.12。
查看镜像构建过程:
[root@helper c]# docker build -t davidwei/capp:1.0 . Sending build context to Docker daemon 2.56kB Step 1/8 : FROM alpine:3.12 3.12: Pulling from library/alpine Digest: sha256:36553b10a4947067b9fbb7d532951066293a68eae893beba1d9235f7d11a20ad Status: Downloaded newer image for alpine:3.12 ---> 13621d1b12d4 Step 2/8 : RUN apk add git build-base tzdata zlib-dev && wget https://ftp.gnu. org/gnu/libmicrohttpd/libmicrohttpd-latest.tar.gz && tar xfvz libmicrohttpd- latest.tar.gz && (cd libmi*; ./configure; make install) && git clone https://github.com/kevinboone/solunar_ws.git && make -C solunar_ws ---> Using cache ---> 1d295e9520a1 Step 3/8 : FROM alpine:3.12 ---> 13621d1b12d4 Step 4/8 : RUN apk add tzdata ---> Using cache ---> bb67735c5825 Step 5/8 : COPY --from=0 /solunar_ws/solunar_ws / ---> 7eff173bd44c Step 6/8 : COPY --from=0 /usr/local/lib/libmicrohttpd.so.12 /usr/local/lib ---> d64545f7695e Step 7/8 : USER 1000 ---> Running in 34c744835d6f Removing intermediate container 34c744835d6f ---> 6c8ba9f65b94 Step 8/8 : CMD ["/solunar_ws"] ---> Running in ce84fd4cfb84 Removing intermediate container ce84fd4cfb84 ---> fb0ab1acd1b0 Successfully built fb0ab1acd1b0 Successfully tagged davidwei/capp:1.0
镜像构建成功后,如图2-15所示。
图2-15 查看构建好的镜像
我们可以在本地运行容器镜像:
#docker run -d -p 8080:8080 davidwei/capp:1.0
然后通过浏览器访问应用,代码如下,访问结果如图2-16所示。
http://localhost/day/london/jun%2020
图2-16 访问C语言应用
在OpenShift中,我们可以使用以下三种方式部署应用。
下面展示第三种部署方法,yaml文件如下所示:
kind: DeploymentConfig apiVersion: apps.openshift.io/v1 metadata: name: solunar-ws spec: replicas: 1 strategy: type: Rolling selector: name: solunar-ws template: metadata: name: solunar-ws labels: name: solunar-ws spec: containers: - env: - name: SOLUNAR_WS_LOG_LEVEL value: "1" name: solunar-ws image: quay.io/davidwei/capp:1.0 imagePullPolicy: Always ports: - containerPort: 8080 protocol: TCP livenessProbe: failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 tcpSocket: port: 8080 timeoutSeconds: 1 readinessProbe: failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 tcpSocket: port: 8080 timeoutSeconds: 1 resources: limits: memory: 128Mi securityContext: privileged: false --- kind: Service apiVersion: v1 metadata: name: solunar-ws spec: ports: - name: solunar-ws port: 8080 protocol: TCP targetPort: 8080 selector: name: solunar-ws
从之前的步骤可以看出,在OpenShift上运行C语言应用是完全没问题的。但是,由于C语言无法像Java语言那样实现外部构建(mvn),因此我们不建议让C语言应用参与到OpenShift的CI/CD中。我们在书写Dockerfile的时候,需要以Alpine Linux为基础镜像,把C语言应用编译和运行所依赖的环境都做到容器镜像中。如果应用的源码发生变化,则在OpenShift上以Dockerfile的方式重新部署应用即可。
在OpenShift上选择以Dockerfile方式部署应用,输入Dockerfile所在的git地址,选择自动生成Route和Deployment,如图2-17所示。
图2-17 在OpenShift上部署C语言应用
在介绍了C语言应用上容器云后,接下来我们介绍如何将应用迁移到轻量级应用服务器。
混沌工程是在分布式系统上进行实验的学科,目的是建立系统抵御生产环境中失控条件的能力以及信心。测试混沌工程本身是一种生产演练,即通过周期化和自动化的生产演练,发现未知的故障场景,处理未知场景下的问题,从而提升系统的可用性。
接下来,我们简单介绍混沌工程的发展。混沌工程是2010年由Netflix提出的,到2014年,混沌思想成为Netflix的一种企业文化(内部设置混沌工程师岗位)。2015年Netflix提出混沌工程原则。2016年,第一个混沌工程商业化的产品出现:Gremlin。国内对混沌工程探索比较多的公司是阿里巴巴。它开源了ChaosBlade混沌工程工具。
想到混沌工程,我们就会想到混沌测试,也会想到传统的压力测试。混沌测试和压力测试的主要区别如下所示。
混沌工程的五个原则如下。
目前混沌测试的工具较多,除了有阿里开源的ChaosBlade Box,还有其他开源工具,如Powerfulseal、Litmus、Kraken、Chaos Mesh。目前国内企业使用ChaosBlade Box较多。如果客户对构建混沌工程平台无太多要求,可以直接使用ChaosBlade Box。企业使用混沌工程应该是来构建一个平台,而不仅仅是对开源工具的验证。因此我们在构建混沌工程平台时,可能需要多种开源工具进行集成。
混沌工程平台需要具备的功能可以从工具视角和流程视角两方面来看。
从流程视角来看,混沌工程需要具备以下四种功能。
1)实验计划管理功能:模板管理、流水线编排、演练方案设计、审批流程(技术方案评审)管理。
2)自动化执行功能:执行控制与风险管控,故障注入,应急恢复,自动化操作脚本、代理。
3)故障观察功能:评价系统健康的KPI指标,故障感知涉及的主动拨测、被动监控、数据可视化等功能,应急处置协同连接功能。
4)事后环境恢复功能:环境恢复的自动化、环境恢复的数据分析、总结报告、跟进闭环。
从流程视角来看,混沌工程需要在以下方面实现如下功能。
1)决策层面,接受复杂与不确定性,认同故障常态化,并推动有效应对故障的架构设计与应急管理。
2)执行层面,加强故障注入、故障观察、故障恢复的管控能力,控制好故障影响范围,在对生产保持敬畏之心的基础上践行混沌工程,并建立持续优化的闭环协同机制。我们使用混沌工程最终是为了解决问题。
3)场景层面,生产环境注入故障实验,实际协同应急环境执行应急管理。
4)工具层面,加强故障注入的风险管控、操作留痕,并与实际工作场景涉及的工具连接。
我们以为某客户设计的混沌工程平台的建设步骤为例,如表2-1所示。
表2-1 混沌工程平台建设步骤
混沌工程平台的目标架构如图2-18所示。
图2-18 混沌工程平台的目标架构
为了帮助读者对开源混沌测试工具有所了解,接下来我们介绍Kraken工具的验证效果。需要指出的是,Kraken比较适合简单的Kubernetes/OpenShift故障注入场景,本节列出该工具的验证效果只是为了帮助读者理解容器云的故障注入实现,并非推荐读者使用Kraken。
Kraken工具是红帽主导的开源项目,以故意注入故障并在Kubernetes/OpenShift环境中造成混乱的方式进行测试。构建Kraken的目标是确认在故障注入期间和之后,处于混乱状态的Kubernetes/OpenShift组件不仅能够恢复,而且在性能和规模方面不会降低。
通过Kraken,我们可以简单的方式在Kubernetes/OpenShift集群中注入混乱。用户可以持续引起混乱,并从长远角度观察集群如何响应各种故障。另外,可以验证集群能否从一组故障注入引发的混乱中完全恢复到其正常的健康状态。Kraken的工作示意图如图2-19所示。
图2-19 Kraken工作示意图
Kraken底层调用PowerfulSeal(一种测试Kubernetes的开源工具)。该工具将故障注入Kubernetes集群中,以尽早发现问题。红帽在PowerfulSeal中打开了许多增强功能,以改善该工具的覆盖范围。
Kraken支持以下几个混乱场景。
Pod的健康状态不仅关系到Pod是否已启动并正在运行,还关系到其能否接收和响应请求以及能否从混乱注入中恢复的能力。通过调整配置文件,用户可以杀死任何命名空间中的Pod。Kraken当前具有在以下命名空间中杀死Pod并得到预期结果的方案。
Kraken支持以下几种节点混乱方案。
目前,Kraken支持以停止、重新引导和终止等适用于AWS云类型的任何节点实例(后面一定会适应到私有云场景)的混乱情况。
Kraken提供了一个混乱场景,可以关闭所有节点(包括控制平面),并在指定的持续停止时间后重新启动它们,以查看集群是否从混乱注入中恢复、稳定并能够满足请求。
Kraken可以作为Kubernetes部署在集群内部运行。但是,建议从集群外部运行Kraken,以确保混沌注入不会意外杀死Kraken所运行的Pod。我们将Kraken安装在一台独立的虚拟机上,对Kubernetes/OpenShift发起测试。由于篇幅有限,这里不展示Kraken安装的步骤,具体步骤见https://github.com/cloud-bulldozer/kraken/blob/master/docs/installation.md。
我们查看Kraken工具的配置文件的核心部分,文件路径为#cat /home/david/kraken/config/config.yaml。
kraken: distribution: openshift # 确定发行版是Kubernetes还是Openshift kubeconfig_path: /home/david/1/kubeconfig # kubeconfig的路径 exit_on_failure: False # 当一个后动作方案失败时退出 litmus_version: v1.10.0 # 要安装的Litmus版本 litmus_uninstall: False # 如果失败,卸载Litmus chaos_scenarios: # 要加载的policies/chaos列表 - pod_scenarios: # 要加载的pod故障场景 - - scenarios/etcd.yml - - scenarios/regex_openshift_pod_kill.yml - scenarios/post_action_regex.py - node_scenarios: # 要加载的节点故障场景 - scenarios/node_scenarios_example.yml - pod_scenarios: - - scenarios/openshift-apiserver.yml - - scenarios/openshift-kube-apiserver.yml - time_scenarios: # 要加载的时间错乱故障场景 - scenarios/time_scenarios_example.yml - litmus_scenarios: # 要加载的Litmus场景 - - https://hub.litmuschaos.io/api/chaos/1.10.0?file=charts/generic/ node-cpu-hog/rbac.yaml - scenarios/node_hog_engine.yaml - cluster_shut_down_scenarios: - - scenarios/cluster_shut_down_scenario.yml - scenarios/post_action_shut_down.py
在上面的配置文件中,最关键的是设置distribution和kubeconfig_path。配置文件其余部分是测试场景对应的yaml配置文件和Python脚本。如果我们想修改某个测试项,修改对应的yaml文件即可,例如修改节点测试场景的yaml文件。如果我们不想测试某些项目,将yaml文件中对应的行注释掉或删除即可。yaml文件路径为[david@helper kraken]$ cat scenarios/node_scenarios_example.yml.
node_scenarios: - actions: - node_stop_start_scenario - stop_start_kubelet_scenario - node_crash_scenario node_name: label_selector: node-role.kubernetes.io/worker with matching label_selector is selected for node chaos scenario injection instance_kill_count: 1 timeout: 120 - actions: - node_reboot_scenario node_name: label_selector: node-role.kubernetes.io/worker instance_kill_count: 1 timeout: 120
在上面的配置文件中,我们对集群关闭场景进行了混沌测试。接下来,我们对主要混沌测试过程进行分析。
启动混沌测试后,Kraken会通过kubeconfig_path指定的文件获取OpenShift集群信息,如图2-20所示。
图2-20 Kraken获取OpenShift集群信息
查看Kill Pod的测试场景,测试通过,如图2-21所示。
图2-21 Kill Pod的测试场
查看Kill API Server场景,如图2-22所示。
图2-22 Kill API Server场景
Crash节点场景如图2-23所示。
图2-23 Crash节点场景
查看API Server Pod,有一个Pod被删除后自动重建,如图2-24所示。
图2-24 API Server Pod被删除后自动重建
结合使用Kraken与Cerberus,除了可以完成全面的集群运行状况检查外,还可以在合理的时间内仔细检查目标分组是否从混乱注入中恢复。
目前主流的微服务治理框架主要是Spring Cloud。而Istio作为新一代微服务框架,越来越受到关注。在本节中,我们分享如何选择这两种微服务框架。
Istio被引入的主要原因是传统微服务存在以下问题。
那么,是不是说企业一定需要使用Istio?不是。表2-2是对Spring Cloud与Istio的简单对比。
表2-2 Spring Cloud与Istio的对比与选择
也就是说,如果企业的开源语言主要是Java、更新升级不频繁、无过多高级治理功能需求、业务规模不是非常大,使用Spring Cloud是比较合适的。
如果企业要引入Istio,引入成本有多高?具体分三种情况,如表2-3所示。
表2-3 企业引入Istio的成本
接下来,我们对在OpenShift上通过Spring Cloud和Istio实现的企业微服务治理进行对比,如表2-4所示。
表2-4 Spring Cloud与Istio的实现对比
从开放性以及先进性角度来说,建议将服务网格Istio作为首选微服务应用框架。接下来我们介绍Istio在实践中的使用建议。
Istio运维方面的建议包括版本选择、备用环境、评估范围、配置生效、功能健壮性参考、入口流量选择。当然,这些建议只是基于目前我们在测试过程中得到的数据总结的。随着Istio使用越来越广泛,相信最佳实践将会越来越丰富。
Istio是一个迭代很快的开源项目。截止到2021年5月,社区最新的Istio版本为1.9。
频繁的版本迭代会给企业带来一些困扰:是坚持使用目前已经测试过的版本,还是使用社区的最新版本?在前文中我们已经提到,红帽针对Istio有自己的企业版,通过Operator进行部署和管理。出于安全性和稳定性的考虑,红帽Istio往往比社区要晚两个小版本左右。因此建议使用红帽Istio的最新版本。目前看,社区的最新版本的Istio的稳定性往往不尽如人意。
针对相同的应用,在OpenShift环境中部署一套不被Istio管理的环境。比如文中的三层微服务,独立启动一套不被Istio管理的应用,使用OpenShift原本的访问方式即可。这样做的好处是,每当进行Istio升级或者部分参数调整时都可以提前进行主从切换,让流量切换到没有被Istio管理的环境中,将Istio升级调整验证完毕后再将流量切换回来。
由于Istio对微服务的管理是非代码侵入式的。因此通常情况下,业务服务需要进行微服务治理,需要被Istio纳管。而对于没有微服务治理要求的非业务容器,不必强行纳管在Istio中。当非业务容器需要承载业务时,被Istio纳管也不需要修改源代码,重新在OpenShift上注入Sidecar部署即可。
如果系统中已经有相关对象的配置,我们需要使用oc replace -f指定配置文件来替换之前配置的对象。Istio中有的配置策略能够较快生效,有的配置需要一段时间才能生效,如限流、熔断等。新创建策略(oc create -f)的生效速度要高于替换性策略(oc replace -f)。因此在不影响业务的前提下,可以在应用新策略之前,先删除旧策略。
此外,Istio的配置生效,大多是针对微服务所在的项目,但也有一些配置是针对Istio系统。因此,在配置应用时,要注意指定对应的项目。
在OpenShift中,Virtual Service和Destination Rules都是针对项目生效,因此配置应用时需要指定项目。
从笔者大量的测试效果看,健壮性较强的功能有基于目标端的蓝绿、灰度发布,基于源端的蓝绿、灰度发布,灰度上线,服务推广,延迟和重试,错误注入,mTLS,黑白名单。
健壮性有待提升的功能有限流和熔断。
所以,从整体上看,Istio的功能虽日趋完善,但仍有待提升。
在创建Ingress网关的时候,会自动在OpenShift的Router上创建相应的路由。Ingress网关能够暴露的端口要多于Router。所以,我们可以根据需要选择通过哪条路径来访问应用。在Istio体系中的应用不使用Router也可以正常访问微服务。但是PaaS上运行的应用未必都是Istio体系下的,其他非微服务或者非Istio体系下的服务还是要通过Router访问。此外,Istio本身的监控系统和Kiali的界面都是通过Router访问的。
相比Spring Cloud,Istio较好地实现了微服务的路由管理。但在实际生产中,仅有微服务的路由管理是不够的,还需要诸如不同微服务之间的业务系统集成管理、微服务的API管理、微服务中的规则流程管理等。
前面我们提到,容器云主要适合承载无状态的应用。那么,容器云常用的中间件和数据服务都有哪些?企业客户应该如何选择呢?本节将详细介绍。
对于消息中间件,我们针对常见的3种消息中间件进行对比,如表2-5所示。
表2-5 常见消息中间件对比
我们可以得出如下结论:
在容器云中,我们通常可以使用RocketMQ、ActiveMQ Artemis和Kafka这三种消息中间件中的任意一种。如果不需要实现BASE事务,使用ActiveMQ Artemis即可。在海量数据场景中,建议使用Kafka。
对于关系型数据库,我们对以下3种常见关系型数据库进行对比,如表2-6所示。
表2-6 关系型数据库的对比
我们可以得出如下结论:
对于分布式关系型数据库,我们对以下5种常见分布式关系型数据库进行对比,如表2-7所示。
表2-7 分布式关系型数据库对比
我们可以得出如下结论:
从开源的角度看,我们建议在容器云上使用TiDB分布式关系型数据库。
对于分布式缓存,我们对以下4种缓存进行对比,如表2-8所示。
表2-8 分布式缓存对比
从表2-8可以看出,Redis是成熟度最高、使用度最广泛的商业开源键–值(Key-value)型数据库。在容器云上,我们使用Redis作为分布式缓存。
对于文档存储型NoSQL产品,我们对比如下4种方案,如表2-9所示。
表2-9 NoSQL方案对比
从表2-9中可以得出结论:MongoDB是成熟度最高、使用度最广泛和可扩展性最好的文档型数据库。我们在容器云上选择使用MongoDB文档型数据库。
对于流程及规则引擎产品,我们对比如下4种方案,如表2-10所示。
表2-10 流程及规则引擎方案对比
结合表2-10的对比,在容器云上,我们推荐使用jBPM。
综上所述,在容器云中,我们推荐的开源中间件和数据服务如表2-11所示。
表2-11 推荐使用的开源中间件和数据服务