【微服务架构】实用建议:使用Kubernetes在Java中构建微服务应用程序时的关键决策
作为Java开发人员或解决方案架构师,您的领导团队可能会问您以下问题:
- 我们是否利用云的优势(例如,集中管理,计算效率,可扩展性,安全性,易维护性)?
- 为了鼓励重用和开发效率,我们是否推广微服务方法?
- 我们是否使用基于Docker的容器技术来简化我们的部署和可扩展性策略?
如果我是你,答案将是:“当然!我们正在做这件事。”
最近,我的解决方案工程师团队将这些问题作为开发样本店面应用程序的一部分,作为微服务Garage方法参考架构的一部分。这个应用程序,内部称为BlueCompute,是按照微服务原则设计的(如果感兴趣,您可以阅读其设计的更多细节,并在项目ibm-cloud-architecture / refarch-cloudnative中仔细阅读GitHub上的实现)。
除了遵循微服务原则,我们还决定使用Kubernetes作为我们的容器编排平台。在此过程中,我们制定了关键设计和架构决策,我想以问题/答案的形式分享:
-
Should I use Kubernetes virtual IP or DNS based service lookup?
-
How do I expose the services for external consumption? LoadBalancer or Ingress or NodePort?
-
Which tool should I use for continuous integration and deployment (CI/CD) in Kubernetes cluster?
我们相信,在IBM Bluemix平台上使用Kuberenetes服务构建系统时,在项目早期考虑这些设计决策将会非常有用。
Q1:作为Java开发人员,我应该使用哪个框架作为构建微服务风格应用程序的基础?
Sprint Boot是Java开发人员的热门选择之一。其独立的应用程序方法非常适合微服务模块化原理。作为单个进程运行允许Sprint Boot应用程序轻松打包并作为Docker容器分发。 MicroProfile是另一个新兴的框架,尤其受到企业Java开发人员的青睐。
Q2:我应该在哪里运行Kubernetes平台?
Kubernetes可以在您自己的数据中心或云提供商的开发笔记本电脑,VM或裸机服务器上运行。显然,这个决定必须与您组织的整体云和托管策略保持一致。如果您正在寻找托管的Kubernetes环境(或Kubernetes即服务),那么IBM Bluemix容器服务是一个不错的选择。如果您出于安全性和合规性原因希望在自己的数据中心托管托管Kubernetes服务,则可以选择IBM Spectrum Conductor for Containers或OpenShift。当然,您可以通过在数据中心或基于云的基础架构中作为服务安装和配置Kubernetes环境来自行推出。
根据您的具体情况,您最终可能会采用不同的方法。例如,使用托管Kubernetes服务在公共云上运行开发/测试环境,并将生产工作负载部署到内部部署的Kubernetes平台。这种混合方法利用了Docker容器和Kubernetes的可移植性功能。就个人而言,我尽可能地利用托管的Kubernetes服务,从我的盘子中删除另外一项任务。
问题3:如何处理应用程序服务注册表和发现?
为了从您在分布式弹性云环境中创建的许多微服务中受益,正确的服务注册和发现策略对于允许它们彼此通信或被消费至关重要。作为云原生微服务实现的先驱,Netflix已经构建并发布了一组名为Netflix OSS的自定义库,如Eureka,Zuul,Ribbon等。它们与Spring框架很好地集成在一起。通常,服务注册到Eureka,Ribbon / Zuul处理服务发现和基本负载平衡。然而,我所描述的是近5年前。
今天,Kubernetes本身支持服务注册,发现和负载平衡。您不再需要Netflix OSS来完成这些任务。相反,您将系统设计为Kubernetes方式。您可以利用Kubernetes的服务类型来公开您的微服务,然后通过虚拟IP或DNS方法自动注册到Kubernetes系统(我将在下一个问题/答案中详细说明这个决定)。该发现将通过熟悉的DNS查找样式进行。对于基于服务的集群,Kubernetes提供了一个内置的负载均衡器,用于在Pod(容器)之间分配工作负载。
问题4:我应该使用Kubernetes虚拟IP还是基于DNS的服务查找?
如前面的问题/答案中所述,我们决定服务注册表和查找应该以Kubernetes方式完成。您有两种选择:环境变量或DNS。环境变量由Kubernetes引物开箱即用。在封面下,Kubernetes公开集群中的服务虚拟IP,以便其他Pod / Services可以通过此环境变量条目调用目标服务。这种方法的缺点是服务在依赖Kubernetes服务事务中的创建顺序。一般而言,依赖IP地址并不是一个好主意。
更好的解决方案是基于DNS的方法。假设我有一个“Order”微服务,我将它命名为order-service,作为服务yaml定义中名称的一部分。前端Web服务可以通过REST端点http:// order-service / id简单地调用Order服务。这将从底层基础架构中抽象出应用程序。要使用DNS方法,如果要构建自己的Kubernetes基础结构,则需要安装Kubernetes DNS加载项。但是,如果您使用Kubernetes作为服务,例如使用IBM Bluemix Container服务,则会在群集中自动启用DNS服务。
问题5:Kubernetes处理应用程序弹性,但是如何优雅地处理依赖服务的故障?
Kubernetes通过其内置的自我恢复机制确保应用程序弹性或容错。作为ReplicaSet实现,Kubernetes确保您的应用程序Pod(容器)始终尝试满足所需的状态。例如,在任何给定时间,我的群集中总是有3个订单服务Pod在运行。
这很酷,并由Kubernetes提供服务。但是你仍然需要设计你的微服务以应对依赖性失败。例如,如果下游服务已关闭,或者存在数据库或存储中断。如果发生这种情况,您不希望此服务问题通过阻止资源或降低整个用户体验来影响整个应用程序。您希望优雅地降级或失败保护此服务。对于基于Java的实现,我建议使用Netflix Hystix库来提供命令来实现故障处理模式,如Circuit Breaker或Bulkhead,以及用于查看系统整体运行状况的仪表板。它与基于Spring Boot的容器应用程序集成良好; Hystrix仪表板本身可以轻松打包和部署为容器,并由Kubernetes管理。
问题6:如何公开服务以供外部消费? LoadBalancer或Ingress或NodePort?
您需要确定客户端应用程序(Web 2.0或移动应用程序)如何访问Kubernetes集群上托管的微服务。很可能,您不希望将您的核心业务逻辑或数据微服务直接暴露给Internet,而应该构建一个BFF(前端后端)或一个API网关,后者又决定将哪个后端服务消耗。在此设计下,通常只能通过Kubernetes内部网络访问后端数据微服务。前端层(BFF或API网关)成为面向Internet的组件。
然后问题就变成了如何公开这个前端服务层以供外部消费。您在Kubernetes中有两个选择:LoadBalancer或Ingress(还有第三个选项 - NodePort - 但我不推荐它用于生产用途)。
具有LoadBalancer的服务提供外部可访问的IP地址,可将流量发送到群集节点上的正确端口。 LoadBalancer易于启用,并允许您的客户端应用程序通过服务定义的HTTP路径访问REST API。 LoadBalancer的缺点是为您的应用程序消耗更多的IP(可计费资源),依赖于云供应商实现,以及缺乏处理TLS终止等常见任务的中心入口点。
另一种方法是Ingress。 Ingress不是为您希望向公众公开的每个服务创建LoadBalancer服务,而是提供一种独特的公共路由,允许您根据各自的路径将公共请求转发到群集内的服务。此方法允许您应用程序的中央入口点。因此,您可以轻松地在多个Kubernetes区域中添加DNS路由和全局负载平衡。这是一个很有前景的解决方但在早期阶段 - Ingress控制器仍然不够灵活,无法处理复杂的应用程序/服务路由路径,终止TLS,过滤传入请求等。
在我们的实现中,我们最终部署了另一个具有Ingress服务类型的NGINX服务。在NGINX内部,我应用上述处理。当Ingress成熟时,这可能是一个临时解决方案。
问题7:我应该在Kubernetes集群中使用哪种工具进行持续集成和部署(CI / CD)?
现在您已准备好编码,但请等待!还有一个决定。您不想进行自动持续集成和部署(CI / CD)吗?如果是这样,最好在开始之前制定策略。
CI / CD是一个通用术语;当它引用Kubernetes集群中的微服务应用程序时,它包括自动Spring Boot应用程序构建,构建Docker映像,将映像推送到Docker注册表,以及部署Kubernetes服务或Pod。当开发人员向源控制系统(例如git)提交代码更改或修复问题时,流程通常会启动。
这是最容易做出的决定之一 - 我们只是使用Jenkins作为工具。我们最终确定了一个名为Jenkins-kubernetes-plugin的开源工具(GitHub上的jenkinsci / kubernetes-plugin)。这种方法的主要好处是我们可以轻松地将Jenkins构建主节点和从节点作为Kubernetes组件运行。这使我们免于安装和维护单独的Jenkins环境。同样,对我们来说,少一项任务是好的。
使用此工具,CI / CD流程如下:
- 开发人员在GitHub中提交代码更改
- Git webhook通过插件触发部署在Kubernetes集群中的Jenkins master的构建
- 主服务器在您的Kubernetes集群中部署Jenkins slave Pod
- Jenkins slave Pod开始构建阶段 - 构建Sprint Boot应用程序,构建Docker镜像,推送到Docker注册表。
- 完成构建阶段后,Jenkins master部署了另一个Jenkins slave Pod,它将启动部署阶段。
- 部署阶段(在Jenkins文件中定义)将您的Microservices部署为Kubernetes服务。
所有这些步骤都是自动化的。
结论
要了解我们如何将这些决策付诸实践,请尝试构建在IBM Bluemix Container服务之上的参考实现应用程序。我们的样本店面应用程序是使用Microservices方法构建的,它实现了本文中描述的所有设计原则。 GitHub上的ibm-cloud-architecture / refarch-cloudnative项目的自述文件包括下载代码并在您自己的Bluemix环境中安装代码的体系结构和说明的概述。
本文:
讨论:请加入知识星球或者小红圈【首席架构师圈】
- 34 次浏览