How can I pass input to Java application inside the Kubernetes container?

11/19/2019

I have configured Kubernetes service (of type LoadBalancer) hosted on AWS EKS. The service's pods run in interactive mode (which is needed to run the container in the pod). The container in there is running a simple Java .jar application that receives input and produces output based on that.

The question: how can I pass input to Java application inside the Kubernetes container?

Here is the part of yaml configuration of the pod that ensures it runs in an interactive mode:

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

The pod is up and running. As you see from the configuration, it receives TCP connections.

Here is the service of the 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

I can ensure that the pod and service are configured correctly by looking at the logs of the pod that output a print message from Java application in the container.

Already tried:

  • curl application in a verbose mode that produces:
*   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
  • connecting via netcat in a verbose mode that produces the output:
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!

Final thoughts: so it seems like the configurations are right and the service runs on the cluster hosted on AWS EKS. The logs produce the right output. However, I can't send the message (through TCP connection?) to the Java application inside the container. Any thoughts on how I can pass the input to it?

-- Anuar Maratkhan
amazon-web-services
docker
java
kubernetes

3 Answers

12/24/2019

If you are using docker for building your kubernetes image, then you can use ENTRYPOINT or CMD attributes in your docker file for passing arguments while launching your application. Please refer below link for more information.

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

-- Ady
Source: StackOverflow

12/7/2019

You can use environment variables to define the arguments.

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

And you just defined an argument for your kubernetes pod here.

Besides it would be good to configure your pods to use a configMap or Secrets.

-- Amit kumar
Source: StackOverflow

11/19/2019

Based on the discussion in comments, the information was that the Java application uses System.in to receive the input. That is usually equivalent to stdin.

A way to send input to the application in the container and get output is by attaching to the process in the container in raw terminal mode, which connects the local stdin and stdout with the container's:

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

On the additional question about how to access the application from the outside without accessing pods directly and by using a Service, I'll suggest:

  • Change the application so that it creates a ServerSocket to listen and accept connections at a particular port number.
  • Read from the socket's input stream individual lines and have them processed as if the input were from System.in.
  • Write the result to socket's output stream.
  • Expose the port via a LoadBalancer Kubernetes Service like you already had.

This here could be a good starting point for the new code. You can use telnet 127.0.0.1 <port> or curl telnet://127.0.0.1:<port>/ to test the application locally and when not running it in a container.

Exposing an HTTP-based service instead, in my opinion, seems like an overkill for this application.

-- apisim
Source: StackOverflow