【问题标题】:How to connect to IBM MQ deployed to OpenShift?如何连接到部署到 OpenShift 的 IBM MQ?
【发布时间】:2021-08-27 19:02:25
【问题描述】:

我有一个带有 IBM MQ(Docker 映像 ibmcom/mq/9.2.2.0-r1)的容器,暴露了两个端口(9443 - 管理员,1414 - 应用程序)。

OpenShift 中所有必需的设置都已完成(Pod、Service、Routes)。

有两条路线,每个港口一条。

相应地指向端口(外部端口默认为 http=80、https=443)。

可以通过第一条路径访问管理控制台,因此 MQ 已启动并运行。

我尝试使用标准方法作为客户端(JMS 2.0,com.ibm.mq.allclient:9.2.2.0)进行连接:

  var fctFactory = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
  var conFactory = fctFactory.createConnectionFactory();

  // ... other props

  conFactory.setObjectProperty(WMQConstants.WMQ_HOST_NAME, "route-app.my.domain");
  conFactory.setObjectProperty(WMQConstants.WMQ_PORT, 443);

连接失败。还尝试将路由重新定义为 HTTP 并使用端口 80,但再次失败。

如果有帮助,我们假设我们使用最新版本的 MQ Explorer 作为客户端。

每次出现同样的连接错误:

...
Caused by: com.ibm.mq.MQException: JMSCMQ0001: 
           IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
... 
Caused by: com.ibm.mq.jmqi.JmqiException: 
           CC=2;RC=2009;AMQ9204: Connection to host 'route-app.my.domain(443)' rejected.
           [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2009;AMQ9208: 
            Error on receive from host 'route-app.my.domain/10.227.248.2:443 (route-app.my.domain)'.
           [1=-1,2=ffffffff,3=route-app.my.domain/10.227.248.2:443 (route-app.my.domain),4=TCP]],
            3=route-app.my.domain(443),5=RemoteConnection.receiveTSH]
...
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009;AMQ9208: 
           Error on receive from host 'route-app.my.domain/10.227.248.2:443

也许,这个article 可以提供一些关于错误代码 2009 的提示,但仍然不确定究竟是什么影响了 OpenShift 端的连接错误。

以前,我总是通过显式指定端口值连接到 IBM MQ,但这里的情况有点不同。
如何通过 TCP 连接到 OpenShift 集群中的 IBM MQ?


OpenShift中的配置如下:


kind: Pod
apiVersion: v1
metadata:
  name: ibm-mq
  labels:
    app: ibm-mq
spec:
  containers:
    - resources:
        limits:
          cpu: '1'
          memory: 600Mi
        requests:
          cpu: '1'
          memory: 600Mi
      name: ibm-mq
      ports:
        - containerPort: 1414
          protocol: TCP
        - containerPort: 9443
          protocol: TCP
  containerStatuses:
      image: 'nexus-ci/docker-lib/ibm_mq:latest'

---
   
kind: Service
apiVersion: v1
metadata:
  name: ibm-mq
spec:
  ports:
    - name: admin
      protocol: TCP
      port: 9443
      targetPort: 9443
    - name: application
      protocol: TCP
      port: 1414
      targetPort: 1414
  selector:
    app: ibm-mq

---

kind: Route
apiVersion: route.openshift.io/v1
metadata:
  name: ibm-mq-admin
spec:
  host: ibm-mq-admin.my-domain.com
  to:
    kind: Service
    name: ibm-mq
    weight: 100
  port:
    targetPort: admin
  tls:
    termination: passthrough
    insecureEdgeTerminationPolicy: None
  wildcardPolicy: None

---

kind: Route
apiVersion: route.openshift.io/v1
metadata:
  name: ibm-mq-app
spec:
  host: ibm-mq-app.my-domain.com
  to:
    kind: Service
    name: ibm-mq
    weight: 100
  port:
    targetPort: application
  tls:
    termination: passthrough
    insecureEdgeTerminationPolicy: None
  wildcardPolicy: None

---

更新:最终创建并部署到 OpenShift 的小型 Web 应用程序接收 HTTP 请求并通过 JMS(输入/获取文本消息)与 MQ 交互,例如:

  • POST /queue/{queueName}/send + <body>;
  • GET /queue/{queueName}/receive

它使用 TCP 与 OpenShift 集群内的 MQ 交互,并接受外部 HTTP 连接作为常规 Web 应用程序。
其他解决方案似乎需要付出太多努力,但我接受了其中一个,因为它在理论上是正确且简单的。

【问题讨论】:

  • 您使用的是哪个版本的 mq 客户端 jar 文件? TLS 路由基于从客户端发送到 openshift 的 SNI。随着时间的推移,Java 中的 MQ 行为发生了变化。在 9.1 之前的 java 没有发送 SNI。在 9.2 中,它发送了一个基​​于频道名称的 SNI。在 9.2 中,它允许您发送要连接的主机名。
  • 您在问题的第一行提到端口 1414,然后在整个问题中不再使用它。 1414 是要侦听的默认 IBM MQ 端口。您是否尝试连接到您的主机名和端口 1414?
  • 这对ibm.com/docs/en/ibm-mq/…有帮助吗?
  • @MoragHughson 1414 是从容器(Pod)公开的端口,并通过 Service 传递给 Route。 Route 在内部使用它,而 1414 对外部世界不可见。 Route 的外部连接可以通过 HTTP (80) 或 HTTPS(443),然后根据配置(包括端口)Route 将流量重定向到 Service。
  • 是的,QM 和客户端应用程序都必须启用 TLS。没有它,您将无法连接。这篇文章 - 我写的github.com/ibm-messaging/mft-cloud/blob/mftubi/docs/… 描述了将 MQExplorer 连接到在 OpenShift 中运行的队列管理器的步骤。我认为这给了你一个想法。 MQExplorer 是一个 Java 应用程序。

标签: kubernetes containers openshift ibm-mq


【解决方案1】:

我不确定是否完全理解您的设置,但"Routes"只路由 HTTP 流量(仅在端口 80 或 443 上),而不是 TCP 流量。
如果你想从集群外部访问你的 MQ 服务器,有几种解决方案,一种是创建一个服务类型:"NodePort"

文档:https://docs.openshift.com/container-platform/4.7/networking/configuring_ingress_cluster_traffic/configuring-ingress-cluster-traffic-nodeport.html

您的服务不是 NodePort 服务。在您的情况下,它应该类似于

kind: Service
apiVersion: v1
metadata:
  name: ibm-mq
spec:
  type: NodePort
  ports:
    - port: 1414
      targetPort: 1414
      nodePort: 30001
  selector:
    app: ibm-mq

然后使用任何名称从外部访问。:30001
并删除无用的对应路由。如前所述,我假设您阅读了我指向您的文档,该文档说该路由仅在端口 80 或 443 上路由 HTTP 流量。

文档:https://kubernetes.io/docs/concepts/services-networking/service/#nodeport

【讨论】:

  • 很遗憾,我无法使用 NodePort 创建服务。 Error "Forbidden: may not be used when 'type' is 'ClusterIP'" for field "spec.ports[1].nodePort".。即使没有设置“类型”,也会得到这个。不知道为什么会这样。
  • 用(Pod、Service、2 Routes)的 YAML 配置更新了问题。
  • 其实我相信你的回答是完全正确的。看起来无法从容器外部访问队列。我必须在 OpenShift 上安装一些 ibmmq 客户端(带有 Web 界面)并完成它。
  • 您的服务不是 NopePort 服务。它必须有一个规范类型:NodePort。查看 Kubernetes 文档:kubernetes.io/docs/concepts/services-networking/service/…。而且您不需要路线....
【解决方案2】:

以下 Java 系统属性将由 9.2.1 及更高版本的 IBM MQ 类 JMS 读取,以告诉它在启动 TLS 连接时将 SNI 标头设置为远程系统的主机名:

com.ibm.mq.cfg.SSL.OutboundSNI=HOSTNAME

要以编程方式设置,只需使用 System.setProperty 方法,例如:

System.setProperty("com.ibm.mq.cfg.SSL.OutboundSNI","HOSTNAME");

注意:字符串 HOSTNAME 是字面意思,不能被实际主机名替换。


如果您无法从 9.2.1 或更高版本移至 com.ibm.mq.allclient.jar,则在 9.2.0.0 及更高版本中,您可以改用 com.ibm.mq.cfg.SSL.AllowOutboundSNI=NO,但在 9.2.1 及更高版本中已弃用。

【讨论】:

  • 我将客户端升级到最新版本 = 9.2.2.0;并设置属性com.ibm.mq.cfg.SSL.OutboundSNI,但错误是一样的。如果我们简化任务会怎样。假设我们使用最新版本的 MQ Explorer。它无法连接并出现类似错误。当我在本地运行相同的 Docker 映像并连接到 localhost:1414 时,连接很好。
  • 你是否使用TLS通道,这也是一个要求。 Shashi 在问题 cmets 中提供了一个很好的链接。
猜你喜欢
  • 2016-01-21
  • 1970-01-01
  • 2023-04-05
  • 2022-11-08
  • 1970-01-01
  • 2023-03-05
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多