【问题标题】:How can I pass input to Java application inside the Kubernetes container?如何将输入传递给 Kubernetes 容器内的 Java 应用程序?
【发布时间】:2020-03-15 06:48:14
【问题描述】:

我已配置托管在 AWS EKS 上的 Kubernetes 服务(LoadBalancer 类型)。服务的 pod 以交互模式运行(这是在 pod 中运行容器所必需的)。那里的容器正在运行一个简单的 Java .jar 应用程序,该应用程序接收输入并基于此生成输出。

问题:如何将输入传递给 Kubernetes 容器内的 Java 应用程序?

下面是 pod 的 yaml 配置部分,它确保它以交互模式运行:

spec:
  containers:
  - image: ardulat/mckinsey
    imagePullPolicy: Always
    name: anuar-mckinsey
    ports:
    - containerPort: 8080
      name: http
      protocol: TCP
    stdin: true
    tty: true

吊舱已启动并正在运行。从配置中可以看出,它接收 TCP 连接。

这里是pod的服务:

NAME             TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)          AGE
anuar-mckinsey   LoadBalancer   10.100.239.207   a8154210d09da11ea9c3806983848f2f-1085657314.us-east-2.elb.amazonaws.com   8080:32516/TCP

我可以通过查看容器中 Java 应用程序输出打印消息的 pod 的日志来确保正确配置了 pod 和服务。

已经尝试过

  • 以详细模式生成的 curl 应用程序:
*   Trying 18.190.142.22...
* TCP_NODELAY set
* Connected to a8154210d09da11ea9c3806983848f2f-1085657314.us-east-2.elb.amazonaws.com (18.190.142.22) port 8080 (#0)
> GET / HTTP/1.1
> Host: a8154210d09da11ea9c3806983848f2f-1085657314.us-east-2.elb.amazonaws.com:8080
> User-Agent: curl/7.63.0
> Accept: */*
>
* Empty reply from server
* Connection #0 to host a8154210d09da11ea9c3806983848f2f-1085657314.us-east-2.elb.amazonaws.com left intact
curl: (52) Empty reply from server
  • 以产生输出的详细模式通过 netcat 连接:
found 1 connections:
     1: flags=82<CONNECTED,PREFERRED>
    outif en0
    src 172.20.22.204 port 51144
    dst 18.190.142.22 port 8080
    rank info not available
    TCP aux info available

Connection to a8154210d09da11ea9c3806983848f2f-1085657314.us-east-2.elb.amazonaws.com port 8080 [tcp/http-alt] succeeded!

最后的想法:看起来配置是正确的,服务在 AWS EKS 上托管的集群上运行。日志产生正确的输出。但是,我无法将消息(通过 TCP 连接?)发送到容器内的 Java 应用程序。关于如何将输入传递给它的任何想法?

【问题讨论】:

  • 端口暴露了吗?
  • @ThorbjørnRavnAndersen 是的,端口暴露在服务和 pod 内部。端口在任何地方都是相同的,8080。您可以从 curl 和 nc 输出中看到连接在那里。
  • 这可能只是您命中的负载均衡器,而不是您的 pod。
  • @ThorbjørnRavnAndersen 好的,听起来很合理。有什么建议吗?
  • 仔细检查您的入口配置

标签: java amazon-web-services docker kubernetes


【解决方案1】:

根据 cmets 中的讨论,信息是 Java 应用程序使用 System.in 来接收输入。这通常相当于stdin

一种将输入发送到容器中的应用程序并获得输出的方法是通过attaching以原始终端模式发送到容器中的进程,它将本地stdinstdout与容器的:

kubectl -n <namespace> attach <pod-name> -c <container-name> -i -t

关于如何在不直接访问 pod 和使用服务的情况下从外部访问应用程序的附加问题,我建议:

  • 更改应用程序,使其创建ServerSocket 以侦听和接受特定端口号的连接。
  • 从套接字的输入流中读取各个行,并像输入来自System.in 一样处理它们。
  • 将结果写入套接字的输出流。
  • 像您已经拥有的那样通过 LoadBalancer Kubernetes 服务公开端口。

This here 可能是新代码的一个很好的起点。您可以使用telnet 127.0.0.1 &lt;port&gt;curl telnet://127.0.0.1:&lt;port&gt;/ 在本地以及不在容器中运行时测试应用程序。

在我看来,公开一个基于 HTTP 的服务似乎对这个应用程序来说有点过头了。

【讨论】:

    【解决方案2】:

    您可以使用环境变量来定义参数。

    env:
    - name: MESSAGE
      value: "hello world"
    command: ["/bin/echo"]
    args: ["$(MESSAGE)"]
    

    您刚刚在这里为您的 kubernetes pod 定义了一个参数。

    此外,最好将您的 pod 配置为使用 configMapSecrets

    【讨论】:

      【解决方案3】:

      如果您使用 docker 构建您的 kubernetes 映像,那么您可以在 docker 文件中使用 ENTRYPOINT 或 CMD 属性在启动应用程序时传递参数。请参考以下链接了解更多信息。

      https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

      【讨论】:

        猜你喜欢
        • 2017-01-19
        • 1970-01-01
        • 1970-01-01
        • 2013-08-06
        • 2020-04-07
        • 2021-03-21
        • 1970-01-01
        • 1970-01-01
        • 2016-03-02
        相关资源
        最近更新 更多