你有没有想过为什么我们要用容器来部署多平台应用?这只是“跟风”吗?在这篇文章中,我将提出一些具有挑战性的问题来支持我的观点,这就是为什么说Kubernetes是新的应用服务器。您可能已经注意到,大多数语言都是“解释型”的,并使用“运行时”来执行源代码。理论上,大多数Node.js、Python和Ruby代码都可以轻松地从一种平台(Windows、Mac、Linux)转换到另一种平台。Java应用程序更进一步,将已编译的Java类转换为可以在任何地方使用JVM(Java虚拟机)运行的字节码。Java生态系统提供了一种标准格式,用于在同一应用程序中分发所有Java类。我们可以将这些类打包为JAR(JavaArchive)、WAR(WebArchive)和EAR(EnterpriseArchive),其中包含这几种格式的前端、后端和嵌入式库。所以我要问:为什么要使用容器来分发Java应用程序?它不是已经支持在不同环境之间轻松迁移吗?如果站在开发者的角度来回答这个问题,答案可能就不是那么明显了。但是,让我们考虑一下您的开发环境,以及由于开发环境和生产环境之间的差异可能出现的问题:您使用的是Mac、Windows还是Linux?您是否遇到过与路径分隔符相关的\和/问题?您使用的是什么版本的JDK?您是否使用Java10进行开发并使用JRE8进行生产?您遇到过由JVM差异引入的错误吗?您使用的是什么版本的应用程序服务器?您是否在生产中使用相同的配置?、安全补丁和相同版本的库?在生产部署的时候,你有没有遇到过驱动或者数据库服务器版本不同导致的JDBC驱动问题,而这些问题在开发环境中可能不存在?您是否请求应用服务器管理员为您创建了数据源或JMS队列,但在创建过程中出现了错别字?所有这些问题都是由应用程序之外的因素引起的。容器的最大好处之一是它可以构建的容器部署一切(例如Linux发行版、JVM、应用程序服务器、库、配置,最后是您的应用程序)。此外,将所有内容都放在一个容器中可以更轻松地将您的代码转移到生产环境中,并在代码不工作时分析差异。因为它很容易执行,所以也很容易将同一个容器镜像扩展为多个副本。强化应用在容器流行之前,应用服务器提供了一些非功能性需求(NFR,non-functionalrequirements),比如安全、隔离、容错、配置管理等。打个比方,应用服务器和应用程序之间的关系就像CD播放器和CD之间的关系。作为开发人员,您应该遵循预定义的标准并以特定格式分发您的应用程序,应用程序服务器将“执行”您的应用程序并带来一些附加功能,这些功能因服务器的“品牌”而异。类似于CD播放器类比,随着容器变得越来越流行,容器映像成为新的CD格式。实际上,容器镜像只是一种分发容器的格式。当您需要为您的应用程序添加企业级功能时,容器的真正好处就会显现出来。为容器化应用程序提供这些功能的最佳方式是使用Kubernetes作为它们的平台。此外,Kubernetes平台还为包括RedHatOpenShift、Istio和ApacheOpenWhisk在内的其他项目提供了出色的基础设施,基于这些项目可以更轻松地构建和部署健壮的、具有生产质量的应用程序。接下来,我们探索九个这样的功能:1.服务发现服务发现是指确定如何连接到服务的过程。为了获得容器和云原生应用程序的许多好处,我们需要从容器镜像中删除配置,以便我们可以将相同的容器镜像应用于所有环境。在应用程序外部提取配置是12因素应用程序的核心原则之一。服务发现是一种从运行时环境中获取配置信息而无需将其硬编码到应用程序中的方法。Kubernetes带有内置的服务发现功能。Kubernetes还提供了ConfigMaps和[Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)来从应用程序容器中删除配置。在运行时环境中,如果我们要连接数据库等服务,我们会存储凭证信息,而Secrets解决了这方面面临的一些挑战。使用Kubernetes,我们不需要使用外部服务器或框架。2、基础调用容器中的应用可以通过Ingress访问,也就是从外界路由到你暴露的服务。OpenShift提供基于HAProxy的路由对象,具有各种功能和负载均衡策略。您可以使用路由功能进行轮询部署。这可能是一些非常复杂的CI/CD策略的基础。请参阅下面的“6.构建和部署管道”。如果你想运行一个一次性的任务,比如一个批处理或者只是使用集群来计算一个结果(比如计算Pi的位数)怎么办?针对这种场景,Kubernetes提供了作业对象。还有一个管理基于时间的任务的cron作业。3.Elasticity在Kubernetes中,弹性(elasticity)是通过ReplicaSets(过去被称为ReplicationControllers)来解决的。与Kubernetes的大多数配置一样,ReplicaSet是一种协调所需状态的方法:您告诉Kubernetes系统应该处于什么状态,而Kubernetes知道如何到达那里。ReplicaSet可以随时控制应用程序的副本数量或实例的确切数量。但是如果你构建的服务的流行度超过了预先计划,计算资源耗尽了怎么办?您可以使用KubernetesHorizo??ntalPodAutoscaler,它将定义指标并应用提供的指标)来扩展Pod的数量。4.日志因为Kubernetes集群可以运行容器化应用程序的多个副本,所以聚合这些日志很重要,这样它们就可以在一个地方查看。同时,为了利用自动缩放(以及云原生应用程序的其他功能)的优势,容器应该是不可变的。因此,我们应该将日志存储在容器之外,以便它们在运行时持久化。OpenShift允许我们部署EFK堆栈来聚合来自主机和应用程序的日志,甚至来自多个容器甚至已删除的pod。EFK技术栈的组成如下:Elasticsearch(ES),用于存储日志内容的对象存储;Fluentd,从节点收集日志并将它们发送到ElasticsearchKibana,Elasticsearch的WebUI。5.监控日志记录和监控虽然看起来解决的是同一个问题,但它们是不同的。监控是观察、检查,通常是警报和日志记录,而日志记录只是日志记录。Prometheus是一个包含时间序列数据库的开源监控系统。它可用于存储和查询指标、警报以及可视化系统的内部健康状况。Prometheus可能是监控Kubernetes集群最流行的选择。6.构建和部署管道CI/CD(持续集成/持续交付)不是您的应用程序的“必须具备”要求。然而,CI/CD通常被认为是成功的软件开发和DevOps实践的支柱。软件不应该在没有经过CI/CD管道的情况下发布到生产环境。JezHumble和DavidFarley的《持续交付:发布可靠软件的系统方法》是这样描述CD的:“持续交付使得能够向生产环境发布各种类型的变更,包括新特性、配置变更、错误修复和实验功能,或者说是安全和以可持续的方式迅速将这些变化交到用户手中”。7.适应性Kubernetes为集群本身提供了弹性解决方案,同时也提供了PersistentVolumes来支持卷拷贝,帮助应用实现适应性。Kubernetes的ReplicationControllers/部署可确保指定数量的pod副本始终在集群中正常运行,并自动处理可能出现的任何节点故障。结合适应性,容错可以有效解决用户对可靠性和可用性的担忧。运行在Kubernetes上的应用程序也可以通过Istio的重试规则、断路器和池弹出(poolejection,移除失败的容器-注解)来实现容错。8.认证在Kubernetes中,认证可以通过Istio的双向TLS认证来实现,目的是在不改变服务代码的情况下,增强微服务及其通信的安全性。它将负责:为每个服务提供代表其角色的强大身份,使其能够跨集群和云进行互操作;保护服务到服务和最终用户到服务的通信;提供一个密钥管理系统,可以自动生成、分发、轮换和吊销密钥和证书。此外,值得一提的是,我们还可以在Kubernetes/OpenShift集群中运行Keycloak来提供身份验证和授权。Keycloak是RedHatSingleSign-on的上游产品。9.跟踪基于Istio的应用程序可以配置为使用Zipkin或Jaeger收集跟踪的跨度。无论用于构建应用程序的语言、框架或平台如何,Istio都支持分布式跟踪。应用服务器会消亡吗?有了这些特性,您可以意识到Kubernetes+OpenShift+Istio可以真正增强您的应用程序并提供一些以前由应用程序服务器或框架(如NetflixOSS)处理的功能。这是否意味着应用服务器正在消亡?在这个新的容器世界中,应用服务器越来越像框架。软件开发的发展自然导致了应用服务器的发展。这种演变的一个例子是EclipseMicroProfile规范和WildFlySwarm应用服务器,它为开发人员提供了各种特性,例如容错、配置、跟踪、REST(客户端和服务器)等等。WildFlySwarm和MicroProfile规范的设计非常轻量级,WildFlySwarm不包含一个完整的Java企业应用服务器的各个组件。相反,它专注于微服务,只留下构建和运行作为简单可执行“.jar”文件的应用程序的能力。在此博客中,您可以阅读有关MicroProfile的更多信息。此外,Java应用程序还包括Servlet引擎、数据库池、依赖注入、事务和消息等特性。当然,框架可能会提供这些功能,但应用服务器必须具备在任何环境中构建、运行、部署和管理企业应用程序所需的所有功能,无论它是否在容器中运行。应用服务器实际上可以在任何地方执行,例如,在裸机上,在像RedHatVirtualization这样的虚拟化平台上,在像RedHatOpenStackPlatform这样的私有云环境中,在像MicrosoftAzure或AmazonWebServices这样的服务器上的公共云环境中。一个好的应用服务器保证了它提供的API和具体实现的一致性。开发人员可以确信,如果他的业务逻辑需要特定功能,他部署的逻辑将起作用,因为应用程序服务器开发人员(和预定义的标准)可以保证它们一起工作并共同发展。此外,一个好的应用服务器还负责最大化吞吐量和可扩展性,因为它处理来自用户的所有请求;减少延迟并提高负载能力,这有助于提高应用程序的可处置性;轻量资源占用,最小化硬件资源和成本;最后,它必须足够安全以防止所有安全漏洞。对于Java开发人员,红帽提供了红帽JBoss企业应用平台,它可以满足现代模块化应用服务器的所有需求。结论容器镜像已经成为分发云原生应用的标准打包格式。虽然容器本身并没有为应用程序提供任何真正的业务优势,但Kubernetes和相关项目(如OpenShift和Istio)提供了非功能性需求,这些需求曾经是应用程序服务器功能的一部分。开发人员过去使用的大多数非功能性需求来自应用服务器或库,如NetflixOSS,并且这些需求与特定语言相关联,例如Java。但是,如果开发人员选择使用Kubernetes+OpenShift+Istio来满足这些需求,则它们不受任何特定语言的束缚,因此鼓励开发人员为每个用例选择最佳技术/语言。最后,在软件开发领域,应用服务器仍然占有一席之地。然而,它们变得更像是特定于语言的框架,这在开发应用程序时很容易,因为它们包含许多已经编写和测试的功能。迁移到容器、Kubernetes和微服务架构的最大好处之一就是不必为您的应用程序选择单一的应用程序服务器、框架、架构风格,甚至编程语言。您可以使用运行现有JavaEE应用程序的JBossEAP轻松部署容器,其他容器可能包含用WildflySwarm编写的微服务或用EclipseVert.x编写的反应程序。这些容器都可以通过Kubernetes进行管理。要了解这些概念在实践中的工作原理,请参阅RedHatOpenShift应用程序运行时。你可以说Kubernetes/OpenShift是新的Linux,甚至“Kubernetes是新的应用服务器”。但事实上,应用服务器/运行时+OpenShift/Kubernetes+Istio已经成为云原生平台的事实标准。关于作者RafaelBenevides是RedHat的开发人员体验总监。凭借在IT行业各个领域的多年经验,帮助全球的开发者和公司提高软件开发效率。Rafael将自己视为问题解决者并且乐于分享。他是Duke的选择奖获奖项目ApacheDeltaSpikePMC的成员,他在JavaOne、Devoxx、TDC、DevNexus等技术会议上发表演讲。
