Kubernetes,旧貌新颜?

| June 12, 2018

从单体到微服务,论企业级应用服务器到微服务基础设施架构设计演进

本文原文发布在InfoQ中国微信公众号上。 链接

一,架构问题:

作为一名软件工程师或者系统架构师,当我们在构造大型应用系统时,常常需要画出一个体系架构图,来表现要开发的应用系统的软件架构。 我想很多软件开发人员都有这样的疑问:这几年业界都在谈微服务,容器化,这样的技术变化的原因是什么?新的或者原有的软件系统到底该用什么样的技术架构体系?如果需要改造,应该怎么做? 希望通过阅读本文给您一些启发。

二,技术背景:

应用服务器是近十几年来应用开发的主流部署环境。以Java语言社区为例,Java EE 应用服务器是软件中间件开发领域的主要产品,包括以Weblogic, Websphere商业产品, JBoss AS(Wildfly), Glassfish开源产品,还有Tomcat, Jetty等Servlet容器服务器,Spring Framework应用框架等,这些共同组成商业业务软件最重要的部分。

容器Docker,容器编排Kubernetes等带来了容器化微服务软件技术浪潮,互联网公司作为先行者,并在国内外引领软件设计的方法变革,Cloud Native已经成为当前软件设计中必须考虑的要素。

那么,“传统”的应用服务器和Kubernetes之间是否有技术关联性?如果有,它们的内在联系是什么?

三,相似之处:

我在专业技术网站找到了两幅图片,分别是完整的JavaEE实现Wildfly应用服务器域模式和kubernetes架构体系图。

Wildfly应用服务器域模式

图片来源于 https://kb.novaordis.com/index.php/WildFly_Domain_Mode_Concepts

kubernetes架构体系图

图片来源于 https://x-team.com/blog/introduction-kubernetes-architecture/

以上两幅图,并不是这两个产品所有技术架构细节最全面的图形,但已经能够充分表现它们的架构特点和组件之间的关系。

我们发现,两者的架构有很多一致的地方:

  1. 都有一个主控节点,Kubernetes称为Master Node,Wildfly中是含有domain controller的host1,也是作为主控节点。
  2. 通过主控节点管理多个工作节点,Kubernetes有两个Worker Node,Wildfly图中也有两个工作节点host2和host3。
  3. 管理员通过管理接口(Rest API)来对整个系统进行管理,Kubernetes是通过kubectl访问API server,Wildfly是通过jboss-cli工具访问管理接口,服务器处理组件是domain controller。当然,它们也都提供图形管理工具。
  4. 工作节点上都有控制进程,Kubernetes是kubelet和kube-proxy,Wildfly为host controller和process controller,其中kubelet和host controller作用类似,都是起到工作节点和主控节点通信和管理节点工作进程的作用。
  5. 每个工作节点上都有多个工作进程,只不过Kubernetes是由容器管理Pod,而Wildfly是JVM进程管理工作线程。

另外图示中没有表示出来,或者在逻辑上概念相似的还有:

  1. Kubenetes中的controller-manager包括各类功能的控制器模块,Wildlfy中有类似的功能组件,也在domain controller中,它们都具备可扩展能力。
  2. Rest API对外接口采用简单易懂的Json格式,各个节点间为了高效率,通信方式为二进制数据流,都可以配置加密方法。
  3. 尽管工作进程中,Pod和线程有所不同,但逻辑上也有相似之处:都是独立的工作主体,都有完整的生命周期;Pod间共享网络,存储等信息,线程间可以传递上下文。我个人更愿意把Pod看作是隔离性更好的“工作线程池”。
  4. 不同的节点或者进程中的服务工作单元,可以动态的组成服务群组。Wildfly中有Server Group概念,一个应用可以被同时部署到Server Group的所有工作单元;Kubernetes的Pod可以通过定义的Label来Selector,即可以筛选出具有某些标记的Pod,而作为服务群组对外提供服务。
  5. Kubernetes有Service来提供服务,这样对于服务消费者,后面Pod服务提供者的信息都是透明的。而且还有Ingress对外部应用进一步暴露服务能力。Wildfly提供了Wildfly-cluster作为服务组件的反向代理。虽然做不到像Service那样直接通过iptables底层机制去映射网络访问端口,但同样也有强大的根据负载能力调节转发请求量的特性,更多的是Ingress的作用。
  6. Kubernetes对有状态的组件支持,是通过StatefulSet,挂接Persistent Volumes,重新构建相同状态的工作容器。而Wildfly中对状态的管理,包含Stateful SessionBean, Servlet session等,都是通过Infinispan的分布式机制,复制状态到多个节点,而且还有一种远程Infinispan的配置方式,就和Kubernates对状态的管理逻辑上完全一致了。
  7. 对于Master主控节点的安全性管理,两者都有完备RBAC用户管理认证授权机制,以及完备的加密方式,密钥配置管理等功能。

Java EE技术一直是一个完整的开发生态,同样的,Kubernetes也快速的形成了庞大得多的生态体系,我们从其中一些对开发很重要的方面进行分析。

  1. JavaEE有一套标准的打包方式,如构建jar,组合成应用war,进而打包成企业完整应用ear。Kubernetes是利用容器镜像,即docker的打包机制来管理容器。在docker之上,Kubernetes提出Pod概念,对于整体的应用部署,目前Kubernetes社区提供了helm工具和chart包格式。当然也类似yum工具管理的rpm格式等。
  2. Kubernetes动态扩容,即ReplicaSets定义的创建特定数目的实例,可以说是Kubernetes最重要的特性之一。JavaEE定义的Stateless SessionBean,在应用服务器实现中,会创建一个池来实例化多个,虽然实例个数控制粒度没有那么细,但也是可以通过控制台来定义其实例数量的,实例池由容器来保证其可用实例数目。
  3. Kubernetes用ConfigMap来定义配置信息,用Secrets来定义安全方面的配置信息。JavaEE也有类似的定义,比如Resource和Securtiy方面的annotation。在应用服务器扩展方面,Wildfly可以自行定义xml schema,提供友好可读的xml配置信息,以及Security Domain/Realm来定义安全方面的配置信息。
  4. 原Coreos(后被红帽收购)定义的Operator Framework(运维框架),基于Kubernetes CRD(Custom Resource Definitions),定义了完整的一套打包,部署,管理应用的方法,有了这样的工具,第三方软件产品,可以用一种相对“标准”的方式提供容器化的产品。Custom Resource Definitions是Kubernetes的扩展机制,可以预见Kubernetes三方扩展将会如雨后春笋般的出现。对应的,Wildfly有子系统(subsystem扩展机制),可以在Wildfly服务器内核之上,开发子系统来扩展功能,Wildfly所有的Java EE都是通过子系统方式实现的。它们都是通过扩展Controller的功能,把管理命令挂接到API server之上,设计思路惊人的一致!
  5. Wildfly工作节点的管理,可以通过暴露信息发给主控节点,也可以利用JMX,Java agent,Interceper等方式来发送数据到分布式数据中心上(比如可以加载jolokia),再用独立的或者统一的控制台来管理。同样的,Istio项目,也是利用sidecar模式,在pod工作进程上,挂接一个envoy模块,由其完成流量分配,安全管理,policy设置等功能,再由控制台统一管理。
  6. Kubernetes被成为容器编排产品,所谓编排(orchestration),就是把不同的应用运行组件,按照实现定义好的规则,根据其依赖性能够启动运行,并保证其运行健壮的能力。Java EE各个规范间也有依赖性,比如Webservice依赖于Servlet,Wildfly有一个组件成为DeploymentFramework,也是处理组件之间的依赖关系的,服务器会按照应用定义好的最终状态声明,按照自己的依赖性原则,逐个启动各个服务,保证应用最后可用。

四,异同之处:

毕竟Kubernetes是演进后技术,具有大量新的特性:

  1. 存储方面的特性,Kubernetes可以挂载各种存储,包括普通的文件系统,NFS,云端的S3,开源存储方案Ceph等应有尽有。Wildfly还是使用标准的操作系统的文件和目录。利用容器,Kubernetes能更方便的对文件限额,资源使用量等进行定义和限制操作。
  2. 网络方面的特性,Wildfly定义了网络接口配置属性,可以对网络IP,端口,偏移值等进行设置。但这些比起Kubernetes来说就是九牛一毛,Kubernetes在Service层,就利用iptables等方法做网络请求的路由映射,而且商业Kubernetes产品都会加入SDN(软件定义网络)的方案,网络管理成为应用体系重要的一部分。
  3. Kubernetes中非常重要的组件是scheduler调度器,这个在Wildfly中没有功能完全一致的组件,因为企业应用的集群部署是按组整体部署的,Wildfly提供了控制台工具来部署到不同的节点上。尽管这个过程可以自动化,甚至可以引入一些智能的成分来“调度”,但还是和kubernetes提供的调度能力相差甚远。
  4. 对工作节点的管理的规模不同。企业应用服务器集群一般在数十台左右,和互联网动则成千上万的服务器差了几个数量级。对事务的一致性要求也是不同的,它们对于状态信息的分布式分发复制方式存在差别。
  5. 企业级应用服务器,应用上下文信息包含了事务,安全等信息,在线程间进行传递。而应用分布后,微服务之间也要传递安全,事务等信息,就要用OIDC/Jwt,TCC/Saga等分布式方案,业务目标是一致,但实现方法变化很大,也对软件架构设计提出了很高的要求。

五,总结和展望:

毫无疑问Kubernetes已经赢得了容器之战,甚至取代docker成为容器技术中最重要的开源产品。开发工程师和架构师也需要适应微服务化技术的演变,部署应用到云端,这个趋势已经开始。

同样的,Kubernetes和生态,对于应用开发和运维也提出更高的要求。企业在开发软件应用时,也要多方位考虑,包括应用复杂度,访问量,事务的要求,运维能力等。选择最适合技术和中间件产品/云计算平台。软件设计没有银弹,最适合的才是最好的。