作为一名软件工程师或者系统架构师,当我们在构造大型应用系统时,常常需要画出一个体系架构图,来表现要开发的应用系统的软件架构。
我想很多软件开发人员都有这样的疑问:这几年业界都在谈微服务,容器化,这样的技术变化的原因是什么?新的或者原有的软件系统到底该用什么样的技术架构体系?如果需要改造,应该怎么做?
希望通过阅读本文给您一些启发。
技术背景应用服务器是近十几年来应用开发的主流部署环境。以 Java 语言社区为例,Java EE 应用服务器是软件中间件开发领域的主要产品,包括以 Weblogic, Websphere 商业产品, JBoss AS(Wildfly), Glassfish 开源产品,还有 Tomcat, Jetty 等 Servlet 容器服务器,Spring Framework 应用框架等,这些共同组成商业业务软件最重要的部分。
容器 Docker,容器编排 Kubernetes 等带来了容器化微服务软件技术浪潮,互联网公司作为先行者,并在国内外引领软件设计的方法变革,Cloud Native 已经成为当前软件设计中必须考虑的要素。
那么,“传统”的应用服务器和 Kubernetes 之间是否有技术关联性?如果有,它们的内在联系是什么?
相似之处我在专业技术网站找到了两幅图片,分别是完整的 JavaEE 实现 Wildfly 应用服务器域模式和 kubernetes 架构体系图。
图片出处:
https://kb.novaordis.com/index.php/Wildfly_Domain_Mode_Concepts
图片出处:
https://x-team.com/blog/introduction-kubernetes-architecture/
以上两幅图,并不能表现这两个产品所有技术架构细节,但已经能够充分表现它们的架构特点和组件之间的关系。
我们发现,两者的架构有很多一致的地方:
-
都有一个主控节点。Kubernetes 称为 Master Node,Wildfly 中含有 domain controller 的 host1,也是作为主控节点。
-
通过主控节点管理多个工作节点。Kubernetes 有两个 Worker Node,Wildfly 图中也有两个工作节点 host2 和 host3。
-
管理员通过管理接口 (Rest API) 来对整个系统进行管理,Kubernetes 是通过 kubectl 访问 API server,Wildfly 是通过 jboss-cli 工具访问管理接口,服务器处理组件是 domain controller。当然,它们也都提供图形管理工具。
-
工作节点上都有控制进程,Kubernetes 是 kubelet 和 kube-proxy,Wildfly 为 host controller 和 process controller,其中 kubelet 和 host controller 作用类似,都是起到工作节点和主控节点通信和管理节点工作进程的作用。
-
每个工作节点上都有多个工作进程,只不过 Kubernetes 是由容器管理 Pod,而 Wildfly 是 JVM 进程管理工作线程。
另外在图示中没有表示出来,在逻辑上概念相似的还有:
-
Kubenetes 中的 controller-manager 包括各类功能的控制器模块。Wildlfy 中有类似的功能模块,也在 domain controller 中,它们都具备可扩展能力。
-
Rest API 对外接口采用简单易懂的 Json 格式。而各个节点间为了高效率,通信方式为二进制数据流,可以配置加密方式。
-
尽管在工作进程中,Pod 和线程是不同的。但它们逻辑上也有相似之处:都是独立的工作主体;都有完整的生命周期;Pod 间共享网络,存储等信息,线程间可以传递上下文。我个人更愿意把 Pod 看作是高一个或者半个维度的,隔离性更好的“工作线程池”。
-
不同的节点或者进程中的服务工作单元,可以动态组成服务群组。Wildfly 中有 Server Group 概念,一个应用可以被同时部署到 Server Group 的所有工作单元;Kubernetes 的 Pod 可以通过定义的 Label 来 Selector,即可以筛选出具有某些标记的 Pod,而作为服务群组对外提供服务。
-
Kubernetes 有 Service 来提供服务,对于服务消费者,后面的 Pod 服务提供者的信息都是透明的,而且还有 Ingress 对外部应用进一步暴露服务能力。Wildfly 提供了 Wildfly-cluster 作为服务组件的反向代理,虽然做不到像 Service 那样直接通过 iptables 底层机制去映射网络访问端口,但同样也有强大的根据负载能力调节转发请求量的特性,更多起到 Ingress 的作用。
-
Kubernetes 对有状态的组件支持,是通过 StatefulSet,挂接 Persistent Volumes,启动时重新构建相同状态的工作容器。而 Wildfly 中对状态的管理,包含 Stateful SessionBean, Servlet session 等等,都是通过 Infinispan 的分布式机制,复制状态到多个节点。而且还有一种远程 Infinispan 的配置方法,和 Kubernates 对状态的管理在逻辑上完全一致了。
-
对于 Master 主控节点的安全性管理,两者都有完备 RBAC 用户管理认证授权机制,以及完备的加密方式,密钥配置管理等功能。
Java EE 技术一直是一个完整的开发生态,同样,Kubernetes 也快速形成了更加庞大的生态体系,我们从其中一些对开发很重要的方面进行分析。
-
JavaEE 有一套标准的打包方式,如构建 jar,组合成应用 war,进而打包成企业完整应用 ear。Kubernetes 是利用容器镜像,即 docker 的打包机制来管理容器。在 docker 之上,Kubernetes 提出 Pod 概念。对于整体的应用部署,目前 Kubernetes 社区提供了 helm 工具和 chart 包格式。当然也类似 yum 工具管理的 rpm 格式。
-
Kubernetes 动态扩容,即 ReplicaSets 定义的创建特定数目的实例,可以说是 Kubernetes 最重要的特性之一。JavaEE 定义的 Stateless SessionBean,在应用服务器实现中,会创建一个池来实例化多个,虽然实例个数控制粒度没有那么细,但也是可以通过控制台来定义其实例数量的,实例池由容器来保证其可用实例数目。
-
Kubernetes 用 ConfigMap 来定义配置信息,用 Secrets 来定义安全方面的配置信息。JavaEE 也有类似的定义,比如 Resource 和 Securtiy 方面的 annotation。在应用服务器扩展方面,Wildfly 可以自行定义 xml schema,提供友好可读的 xml 配置信息,以及 Security Domain/Realm 来定义安全方面的配置信息。
-
原 Coreos(后被红帽收购)定义的 Operator Framework(运维框架),基于 Kubernetes CRD(Custom Resource Definitions),定义了完整的一套打包,部署,管理应用的方法,有了这样的工具,第三方软件产品,可以用一种相对“标准”的方式提供容器化的产品。Custom Resource Definitions 是 Kubernetes 的扩展机制,可以预见 Kubernetes 三方扩展将会如雨后春笋般出现。对应的,Wildfly 有子系统(subsystem 扩展机制),可以在 Wildfly 服务器内核之上,开发子系统来扩展功能,Wildfly 所有的 Java EE 都是通过子系统方式实现的。它们都是通过扩展 Controller 的功能,把管理命令挂接到 API server 之上,设计思路惊人的一致!
-
Wildfly 工作节点的管理,可以通过暴露信息发给主控节点,也可以利用 JMX,Java agent,Interceper 等方式来发送数据到分布式数据中心上(比如可以加载 jolokia),再用独立的或者统一的控制台来管理。同样的,Istio 项目,也是利用 sidecar 模式,在 pod 工作进程上,挂接一个 envoy 模块,由其完成流量分配,安全管理,policy 设置等功能,再由控制台统一管理。
-
Kubernetes 被成为容器编排产品,所谓编排 (orchestration),就是把不同的应用运行组件,按照实现定义好的规则,根据其依赖性能够启动运行,并保证其运行健壮的能力。Java EE 各个规范间也有依赖性,比如 Webservice 依赖于 Servlet,Wildfly 有一个组件成为 DeploymentFramework,也是处理组件之间的依赖关系的,服务器会按照应用定义好的最终状态声明,按照自己的依赖性原则,逐个启动各个服务,保证应用最后可用。
毕竟 Kubernetes 是演进后技术,具有大量新的特性:
-
存储方面的特性,Kubernetes 可以挂载各种存储,包括普通的文件系统,NFS,云端的 S3,开源存储方案 Ceph 等应有尽有。Wildfly 还是使用标准的操作系统的文件和目录。利用容器,Kubernetes 能更方便的对文件限额,资源使用量等进行定义和限制操作。
-
网络方面的特性,Wildfly 定义了网络接口配置属性,可以对网络 IP,端口,偏移值等进行设置。但这些和 Kubernetes 相比就是九牛一毛,Kubernetes 在 Service 层,就利用 iptables 等方法做网络请求的路由映射,而且商业 Kubernetes 产品都会加入 SDN(软件定义网络)的方案,网络管理成为应用体系重要的一部分。
-
Kubernetes 中非常重要的组件是 scheduler 调度器,这个在 Wildfly 中没有功能完全一致的组件,因为企业应用的集群部署是按组整体部署的。Wildfly 提供了控制台工具来部署到不同的节点上,尽管这个过程可以自动化,甚至可以引入一些智能的成分来“调度”,但还是和 Kubernetes 提供的调度能力相差甚远。
-
对工作节点的管理的规模不同。企业应用服务器集群一般在数十台左右,和互联网动则成千上万的服务器差了几个数量级。对事务的一致性要求也是不同的,它们对于状态信息的分布式分发复制方式存在差别。
-
企业级应用服务器,应用上下文信息包含了事务,安全等信息,在线程间进行传递。而应用分布化后,微服务之间也要传递安全,事务等信息,就要用 OIDC/Jwt,TCC/Saga 等分布式方案。业务目标是一致的,但实现方法有很大差异,也对软件架构设计提出了非常高的要求。
毫无疑问 Kubernetes 已经赢得了容器之战,甚至取代 docker 成为容器技术中最重要的开源产品。开发工程师和架构师也需要适应微服务化技术的变化,部署应用到云端上,这个趋势已经开始了。同时,Kubernetes 和其生态,对于应用开发和运维也提出更高的要求。企业在开发软件应用时,也要多方位考虑,包括应用复杂度,访问量,事务的要求,运维能力等。再选择技术方案和中间件产品 / 云计算平台。软件设计从来都没有银弹,最适合的才是最好的。