Kubernetes 中的远程 EJB

Posted

技术标签:

【中文标题】Kubernetes 中的远程 EJB【英文标题】:Remote EJB in Kubernetes 【发布时间】:2020-11-05 15:14:18 【问题描述】:

我正在尝试在部署在 k8s 中的 2 个 WebSphere Liberty 服务器之间设置远程 EJB 调用。 是的,我知道 EJB 不是在 k8s 中部署时想要使用的东西,但我现在必须处理它。

我遇到的问题是如何在 k8s 中公开远程 ORB IP:port。据我了解,只有在客户端和远程“侦听”同一个 IP 时,它才能使其工作。我不是网络专家,而且我对 k8s 很陌生,所以我可能在这里遗漏了一些东西,这就是我需要帮助的原因。

我让它工作的唯一方法是当我将远程服务器上的主机显式设置为它自己的 IP 地址,然后从同一个 IP 上的客户端访问它。此测试是在具有 macvlan0 网络的 Docker 主机上完成的(每个容器都有自己的 IP 地址)。

这是远程 server.xml 配置的 ORB 设置:

<iiopEndpoint id="defaultIiopEndpoint" host="172.30.106.227" iiopPort="2809" />

<orb id="defaultOrb" iiopEndpointRef="defaultIiopEndpoint">
    <serverPolicy.csiv2>
        <layers>
            <!-- don't care about security at this point -->
            <authenticationLayer establishTrustInClient="Never"/>
            <transportLayer sslEnabled="false"/>
        </layers>
    </serverPolicy.csiv2>
</orb>

及客户端server.xml配置:

    <orb id="defaultOrb">
    <clientPolicy.csiv2>
        <layers>
            <!-- really, I don't care about security -->
            <authenticationLayer establishTrustInClient="Never"/>
            <transportLayer sslEnabled="false"/>
        </layers>
    </clientPolicy.csiv2>
</orb>

来自客户端,这是我尝试访问的 JNDI 名称:

corbaname::172.30.106.227:2809#ejb/global/some-app/ejb/BeanName!org\.example\.com\.BeanRemote

这行得通。

由于在暴露 ORB 端口时不想设置固定 IP,我必须找到一种基于主机 IP 动态暴露它的方法。 在 0.0.0.0 上公开不起作用。本地主机也是如此。在这两种情况下,客户端都拒绝连接并出现这种错误:

Error connecting to host=0.0.0.0, port=2809: Connection refused (Connection refused)

在 k8s 中,我通过 LoadBalancer 服务为远程 pod 公开了端口 2809,并尝试从客户端 pod 访问远程服务器,我在 corbaname 定义中设置了远程的服务 IP 地址。 这当然行不通。我可以通过 telnet 访问远程 ip:port,所以这不是网络问题。

我已经尝试了远程服务器上的所有设置组合。在 host="0.0.0.0" 上导出结果与上述相同的异常(连接被拒绝)。

我不确定在内部 IP 地址上导出是否可以,但即使可以,我也不知道在 k8s 中部署 pod 之前的内部 IP。或者有没有办法知道?没有环境。变量,我已经检查过了。

在服务 IP 地址上公开(使用 host="$REMOTE_APP_SERVICE_HOST")失败并出现此错误:

The server socket could not be opened on 2,809. The exception message is Cannot assign requested address (Bind failed).

再一次,我知道用 Rest 替换 EJB 是可行的方法,但现在不是一个选择(不要问为什么)。

请帮忙!


编辑:

我已经取得了一些进展。实际上,我相信我已经成功调用了远程 EJB。 我所做的是在 pod 定义中添加 hostAliases,它为我的主机添加了别名,如下所示:

hostAliases:
- ip: 0.0.0.0
  hostnames:
  - my.host.name

然后我将此主机名添加到远程 server.xml:

<iiopEndpoint id="defaultIiopEndpoint" host="my.host.name" iiopPort="2809" />

我还为我的客户端 pod 添加了主机别名:

hostAliases:
- ip: remote.server.service.ip.here
  hostnames:
  - my.host.name

最后,我将 JNDI 名称更改为:

corbaname::my.host.name:2809#ejb/global/some-app/ejb/BeanName!org\.example\.com\.BeanRemote

通过此设置,远程服务器被成功调用!

但是,现在我遇到了另一个在 Docker 主机上测试时没有遇到的问题。查找已完成,但我得到的不是我所期望的。

查找代码与您所期望的差不多:

Object obj = new InitialContext().lookup(jndi);
BeanRemote remote = (BeanRemote) PortableRemoteObject.narrow(obj, BeanRemote.class);

不幸的是,这个狭窄的调用失败了ClassCastException

Caused by: java.lang.ClassCastException: org.example.com.BeanRemote
    at com.ibm.ws.transport.iiop.internal.WSPortableRemoteObjectImpl.narrow(WSPortableRemoteObjectImpl.java:50)
    at [internal classes]
    at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:62)

我收到的对象是org.omg.stub.java.rmi._Remote_Stub。有什么想法吗?

【问题讨论】:

如果你不能像你写的那样做 REST,那么我会把这两个应用程序放在一个容器中,并使用 localhost,以避免所有带有端口的 mambo jumbo。或者至少单个部署/pod 在 pod 中有两个容器。然后它们在同一主机上,您可以使用 localhost。还尝试将host="*" 放入您的iiopEndpoint。 RMI/IIOP 不是容器友好的协议。 @Gas 谢谢你的回复。单独的 pod 正是我想要完成的 - 在两个应用程序层之间分离。同一个 pod 中的两个应用程序是我开始的地方。另外,我尝试过host="*",但它不起作用,ORB 因为这个错误而拒绝启动:Caused by: java.net.UnknownHostException: *: *: unknown error 您是否尝试过这里的解决方案:github.com/WASdev/ci.docker#optional-enterprise-functionality 如果您将ARG IIOP_ENDPOINT=true 添加到您的 dockerfile,您将能够通过env.IIOP_ENDPOINT_HOST 设置主机名。虽然我仍然建议在同一个 pod 中运行它们 ;-) 并在您重写为 REST 时分开。 @Gas 再次感谢。我想我设法调用它,但现在我有另一个问题。我已经编辑了原始帖子。 【参考方案1】:

解决了!

所以,第一个问题是解决主机映射问题,正如上面编辑中提到的那样,通过添加主机别名 id pod 定义来解决:

远程吊舱:

hostAliases:
- ip: 0.0.0.0
  hostnames:
  - my.host.name

客户端:

hostAliases:
- ip: remote.server.service.ip.here
  hostnames:
  - my.host.name

然后远程服务器必须在 iiop 主机定义中使用该主机名:

<iiopEndpoint id="defaultIiopEndpoint" host="my.host.name" iiopPort="2809" />

此外,客户端必须通过 JNDI 查找引用该主机名:

corbaname::my.host.name:2809#ejb/global/some-app/ejb/BeanName!org\.example\.com\.BeanRemote

此设置可解析远程 EJB 调用。

ClassCastException 的另一个问题非常不寻常。我设法在 Docker 主机上重现了该错误,然后一次更改一件事,直到问题得到解决。事实证明,问题出在ldapRegistry-3.0 功能(!?)。将此功能添加到客户的功能列表中解决了我的问题:

<feature>ldapRegistry-3.0</feature>

添加此功能后,远程 EJB 调用成功。

【讨论】:

以上是关于Kubernetes 中的远程 EJB的主要内容,如果未能解决你的问题,请参考以下文章

在windows电脑上配置kubectl远程操作kubernetes

远程访问 EC2 上的 Kubernetes 仪表板

使用 grafana 访问远程 kubernetes 集群

基于Goland和dlv远程调试Kubernetes组件

基于Goland和dlv远程调试Kubernetes组件

如何远程访问本地 kubernetes minikube 仪表板