How to do Java Remote debugging with kubernetes pod? [duplicate] - java

I try to remote debug the application in attached mode with host: 192.168.99.100 and port 5005, but it tells me that it is unable to open the debugger port. The IP is 192.268.99.100 (the cluster is hosted locally via minikube).
Output of kubectl describe service catalogservice
Name: catalogservice
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=catalogservice
Type: NodePort
IP: 10.98.238.198
Port: web 31003/TCP
TargetPort: 8080/TCP
NodePort: web 31003/TCP
Endpoints: 172.17.0.6:8080
Port: debug 5005/TCP
TargetPort: 5005/TCP
NodePort: debug 32003/TCP
Endpoints: 172.17.0.6:5005
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
This is the pods service.yml:
apiVersion: v1
kind: Service
metadata:
name: catalogservice
spec:
type: NodePort
selector:
app: catalogservice
ports:
- name: web
protocol: TCP
port: 31003
nodePort: 31003
targetPort: 8080
- name: debug
protocol: TCP
port: 5005
nodePort: 32003
targetPort: 5005
And in here I expose the containers port
spec:
containers:
- name: catalogservice
image: elps/myimage
ports:
- containerPort: 8080
name: app
- containerPort: 5005
name: debug
The way I build the image:
FROM openjdk:11
VOLUME /tmp
EXPOSE 8082
ADD /target/catalogservice-0.0.1-SNAPSHOT.jar catalogservice-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n", "-jar", "catalogservice-0.0.1-SNAPSHOT.jar"]
When I execute nmap -p 5005 192.168.99.100 I receive
PORT STATE SERVICE
5005/tcp closed avt-profile-2
When I execute nmap -p 32003 192.168.99.100 I receive
PORT STATE SERVICE
32003/tcp closed unknown
When I execute nmap -p 31003 192.168.99.100 I receive
PORT STATE SERVICE
31003/tcp open unknown
When I execute kubectl get services I receive
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
catalogservice NodePort 10.108.195.102 <none> 31003:31003/TCP,5005:32003/TCP 14m
minikube service customerservice --url returns
http://192.168.99.100:32004

As an alternative to using a NodePort in a Service you could also use kubectl port-forward to access the debug port in your Pod.
kubectl port-forward allows using resource name, such as a pod name, to select a matching pod to port forward to since Kubernetes v1.10.
You need to expose the debug port in the Deployment yaml for the Pod
spec:
containers:
...
ports:
...
- containerPort: 5005
Then get the name of your Pod via
kubectl get pods
and then add a port-forwarding to that Pod
kubectl port-forward podname 5005:5005
In IntelliJ you will be able to connect to
Host: localhost
Port: 5005

Alternatively, you can use the Cloud Code Intellij plugin.
Also, if you use Fabric8, it provides the fabric8:debug goal.

There was a slip in the yaml you first posted as:
- containerPort: 5050
name: debug
Should be:
- containerPort: 5005
name: debug
You also need to use the external port of 32003 when configuring the IntelliJ debugger. With those changes it should work.
You may also want to think about how to make it more flexible. In the past when I've done this I've used a different form for the docker start command that allows you to turn remote debug on and off by an environment variable called REMOTE_DEBUG, which for you would be:
CMD if [ "x$REMOTE_DEBUG" = "xfalse" ] ; then java $JAVA_OPTS -jar catalogservice-0.0.1-SNAPSHOT.jar ; else java $JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n -jar catalogservice-0.0.1-SNAPSHOT.jar ; fi
You'll probably find you want to set the env var $JAVA_OPTS to limit jvm memory use to avoid issues in k8s.

Related

Docker postgres on local machine: connection to localhost:5432 refused. Check that the hostname and port are correct [duplicate]

I am building my first Springboot 2.0 application. I am trying to put my Springboot application into one docker container and my PostgresDB into another container.
My Dockerfile
FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD springboot-api-demo-0.1*.jar app.jar
RUN sh -c 'touch /app.jar'
EXPOSE 9443
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/urandom -jar /app.jar" ]
My docker-compose.yml file
version: "2.1"
services:
springboot-api-demo:
image: "fw/springboot-api-demo"
mem_limit: 1024m
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=local
- AWS_REGION=local
- ENVIRONMENT=local
- AUTH_ENABLED=false
postgres:
container_name: pgdb
image: postgres:9.6-alpine
environment:
- 'POSTGRES_ROOT_PASSWORD=postgres'
- 'POSTGRES_USER=postgres'
- 'POSTGRES_PASSWORD=postgres'
ports:
- "54321:5432"
I am using Springboot JPA Data 2.0 with below config data in my application.properties
spring.datasource.url= jdbc:postgresql://localhost:54321/java_learning
spring.datasource.username=postgres
spring.datasource.password=postgres
I can test that Both of the Images are up. Also from docker log and docker events, I see that postgres Container is running fine, even I can access it and also created a DB too.
But springboot container started but i died because it could not connect to postgress and throwing error below.
Unable to obtain connection from database: The connection attempt
failed
Note that my host machine already has Postgres on port 5432 thats why I did a port mapping ofr 54321:5432 on my postgres container. Here is Proof :) -
➜ springboot-api-demo git:(master) ✗ lsof -i:54321
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
com.docke 44345 shailendra.singh 18u IPv4 0xf62897fbdd69e31d 0t0 TCP *:54321 (LISTEN)
com.docke 44345 shailendra.singh 21u IPv6 0xf62897fbdd119975 0t0 TCP localhost:54321 (LISTEN)
➜ springboot-api-demo git:(master) ✗ lsof -i:5432
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
postgres 715 shailendra.singh 5u IPv6 0xf62897fbb43e03b5 0t0 TCP localhost:postgresql (LISTEN)
postgres 715 shailendra.singh 6u IPv4 0xf62897fbbaeea9bd 0t0 TCP localhost:postgresql (LISTEN)
I am not sure what is the problem. But my Springboot application is not able to connect my postgres container which is running fine with proper creadentials.
Try with :
spring.datasource.url= jdbc:postgresql://pgdb:5432/java_learning
The postgres database is not running on localhost, it's running in the other container which has an other IP (yet unknown).
Thanksfully, docker-compose automatically create a network shared among all the containers in the docker-compose.yml (unless explicitly said to do not), as a result you can magically use the service name as an hostname.
Also, you have a typo in the port, Postgres use 5432 by default, not 54321
You are pointing your application towards localhost, but this is not shared between containers.
To access another container you have to refer to its hostname.
you should use the following datasource url:
spring.datasource.url=jdbc:postgresql://pgdb:5432/java_learning
See this simple tutorial about connecting to a container from another container with docker compose: https://docs.docker.com/compose/gettingstarted/
You're missing networking configuration in your docker-compose.yml specification. By using "networks" you can effectively communicate between containers by their service name (using dns, the service name as the hostname).
Here is an updated docker-compose.yml:
version: "2.1"
services:
springboot-api-demo:
image: "fw/springboot-api-demo"
mem_limit: 1024m
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=local
- AWS_REGION=local
- ENVIRONMENT=local
- AUTH_ENABLED=false
networks:
- mynet
postgres:
container_name: pgdb
image: postgres:9.6-alpine
environment:
- 'POSTGRES_ROOT_PASSWORD=postgres'
- 'POSTGRES_USER=postgres'
- 'POSTGRES_PASSWORD=postgres'
ports:
- "54321:5432"
networks:
- mynet
networks:
mynet:
driver: bridge
Your database url should look like spring.datasource.url=jdbc:postgresql://postgres:5432/java_learning (notice the hostname, postgres, is equal to that of the service name.
Apart from the above solutions provided JDK 11 java container with the mentioned configuration (connecting postgres via IP, localhost, servicename .. with postgres container exposed to LAN) still doesn't work. Upgrade to JDK latest version (17 currently) works for me - do consider this also when you use JDK 11 and trying java container (docker) communicating with postgres container.

Error connecting Node.js web client to Java gRPC server

I have a gRPC server written in Java and I'm currently trying to create a web client, with React. However, I can't seem to manage the connection between the envoy proxy to which the client is connecting and the actual server.
I would expect to receive the same message as with the Java client, but I get the error "Http response at 400 or 500 level", receiving an empty response with the web client, while the Java server doesn't even get the request.
The server runs on port 8080, and the envoy proxy is configured on port 9090, which is the one used by the web client.
Dockerfile:
FROM envoyproxy/envoy-dev:latest
COPY ./envoy.yaml /etc/envoy/envoy.yaml
CMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml -l trace --log-path /tmp/envoy_info.log
envoy.yaml:
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 9090 }
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: m_service
cors:
allow_origin:
- "*"
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
expose_headers: grpc-status,grpc-message
enabled: true
http_filters:
- name: envoy.grpc_web
- name: envoy.cors
- name: envoy.router
clusters:
- name: m_service
connect_timeout: 0.25s
type: logical_dns
http2_protocol_options: {}
lb_policy: round_robin
hosts:
socket_address:
address: localhost
port_value: 8080
The commands I use for building and running the docker container are docker build -t m-server ., and docker run -p 9090:9090 -td m-server /bin/bash and the proto classes for the front-end are loaded statically.
If there's any more code that'd be useful to post, please let me know. Any advice is appreciated, thank you!
For me the solution was to change the command passed to run the container, thus docker run -p 9090:9090 -td m-server /bin/bash becoming docker run -d -p 9090:9090 -p 9901:9901 m-server. The main difference was putting -d instead of -td and the second port mapping is for the envoy server.
I am just learning Docker and from what I understood from the documentation, the explanation would be that I was running the container in detached mode, but with a pseudo-tty allocated, which is used in foreground mode. I've seen it here but the purpose was slightly different and at the time I misunderstood it as only keeping the container running was not what I needed.
Changing 'localhost' to '0.0.0.0', as suggested in this answer is also important.
Looks like Envoy is not forwarding the request to your Java server. Envoy has an admin interface https://www.envoyproxy.io/docs/envoy/latest/operations/admin . That and the Envoy log files should help troubleshoot this.
socket_address:
address: localhost
This is the problem. Your envoy tries to forward to itself if it's running as dockerized image, because localhost is not your docker host machine for running container (where grpc server is running) , but actually localhost of running container. Use docker compose, port mapping or external network. Good luck

docker-compose: no connection between containers

I have 3 microservices, and I run them with docker.
Dockerfile of each of them.
Frontend:
FROM node:alpine
LABEL maintainer="2262288#gmail.com"
WORKDIR /usr/app/front
EXPOSE 3000
COPY ./ ./
RUN npm install
CMD ["npm", "start"]
Backend 1 (back):
FROM openjdk:8-jdk-alpine
LABEL maintainer="2262288#gmail.com"
VOLUME /tmp
EXPOSE 8099
ARG JAR_FILE=build/libs/auth-0.0.3.jar
ADD ${JAR_FILE} digital.jar
ENTRYPOINT ["java","-jar","/digital.jar"]
Backend 2 (message):
FROM openjdk:8-jdk-alpine
LABEL maintainer="2262288#gmail.com"
VOLUME /tmp
EXPOSE 8082
ARG JAR_FILE=build/libs/sender-0.0.1.jar
ADD ${JAR_FILE} sender.jar
ENTRYPOINT ["java","-jar","/sender.jar"]
Frontend send REST-request to backend1, than, backend1 send REST-request to backend2 (message).
I published it on hub & run on external server in docker-compose:
version: '3.7'
services:
web:
image: account/front:0.0.1
restart: on-failure
ports:
- 80:3000
back:
image: account/back:0.0.3
restart: on-failure
ports:
- 8099:8099
message:
image: account/message:0.0.1
restart: on-failure
ports:
- 8082:8082
Backend services run on ports:
message_1_e8eb3b2d2477 | 2019-09-24 09:34:00.882 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8082 (http) with context path ''
back_1_1982cc6e57f7 | 2019-09-24 09:34:07.403 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8099 (http) with context path ''
As we see, each service run on its own port.
Than, I try to send request to front -> back -> message. back send request to message & reseive answer:
java.net.ConnectException: Operation timed out (Connection timed out)
Than, requests to message service not reach it.
When I send request directly with Postman, it works.
What's wrong?
UPD.
request from front to back:
http://81.100.122.90:8099/auth/register
body:
{"username":"ksgcf","password":"123","firstName":"John","lastName":"Doe","email":"398456234785#gmail.com"}
request from back to message (IP changed):
String url = "http://81.100.122.90:8082/email";
EmailMessageDto request = new EmailMessageDto(
dto.getEmail(),
"slava_rossii#list.ru",
"Email confirmation",
"Press link: http://dig.lamb.ru/confirm?username="
+ registrationToken.getUsername() + "&token=" + registrationToken.getToken()
);
So, I see this message when docker-compose run for the first time:
Creating network "project_default" with the default driver
First, when you use docker-compose all services are available via there names. So you can access message from back like this
$ docker-compose exec back ping message
PING message (172.24.0.3) 56(84) bytes of data.
64 bytes from message (172.24.0.3): icmp_seq=1 ttl=64 time=0.078 ms
64 bytes from message (172.24.0.3): icmp_seq=2 ttl=64 time=0.068 ms
Second, check port bindings. You have to bind 0.0.0.0 (not localhost which is default for most of the services and frameworks) to access to the service from other containers via network. It's same you get ordinary virtual machines.
You can check port availability with telnet
As example I'm checking is postresql available on 5432 from container called superset
$ docker-compose exec superset telnet postgres 5432
Trying 172.24.0.3...
Connected to postgres.
Escape character is '^]'.

kubernetes failed to start pod due to ContainerCannotRun

I am new to kubernetes. Recently set up kubernetes cluster with 1 master and 1 node.
I am able to start a docker container by running
sudo docker run <docker-image> in my node machine.
But i failed to start docker container as a pod using kubernetes yml file.
by running sudo kubectl create -f deployment.yml
I describe the pod information and saw this error message.
Last State: Terminated
Reason: ContainerCannotRun
Message: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"HOSTNAME\": executable file not found in $PATH": unknown
Exit Code: 128
docker container supposes to start a java executable.
this is my deployment file
kind: Service
apiVersion: v1
metadata:
name: service1-service
spec:
selector:
app: service1
ports:
- protocol: "TCP"
# Port accessible inside cluster
port: 26666
# Port to forward to inside the pod
targetPort: 26666
# Port accessible outside cluster
nodePort: 26666
type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: service1-depolyment
spec:
selector:
matchLabels:
app: service1
replicas: 1
template:
metadata:
labels:
app: service1
spec:
containers:
- name: service1
image: service1-docker-image
imagePullPolicy: Never
ports:
- containerPort: 26666
# args: ["HOSTNAME", "KUBERNETES_PORT"]
In this deployment file, I try to create a nginx and one java web applicaition service.
It is because i defined wrong apiVersion and kind ?
Any help would be appreciated.
Look at this error exec: \"HOSTNAME\": executable file not found in $PATH
I had a similar error since the container could not locate the docker "CMD" binary since I gave it the wrong path. Check the path to the file and that should do the trick.

Microservice can't reach config service in docker-compose

I currently have two microservices:
- service - port 8080, this microservice tries to fetch config from the other microservice.
- config - port 8888, this microservice is supposed to provide config.
For some reason my service is unable to fetch configuration from config microservice.
My config microservice should work because I can curl localhost:8888/service/default on my machine I receive:
{"name":"service","profiles":["default"],"label":null,"version":null,"state":null,"propertySources":[{"name":"classpath:/shared/service.yml","source":{"server.port":8080,"spring.security.user.password":"admin"}},{"name":"classpath:/shared/service.yaml","source":{"server.port":8080,"spring.security.user.password":"admin"}}]}
Error received (full)
service | 2019-06-06 21:31:06.721 INFO 1 --- [main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://config:8888
service | 2019-06-06 21:31:06.894 INFO 1 --- [main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://config:8888. Will be trying the next url if available
service | 2019-06-06 21:31:06.904 ERROR 1 --- [main] o.s.boot.SpringApplication : Application run failed
Docker-compose.yaml
version: '3.7'
services:
config:
container_name: config
build: ./config
ports:
- 8888:8888
service:
container_name: service
build: ./service
ports:
- 8080:8080
depends_on:
- config
Service Dockerfile:
FROM openjdk:8-jdk-alpine
ADD target/service.jar /app.jar
CMD [ "java", "-Xmx200m", "-jar", "/app.jar" ]
EXPOSE 8080
Service bootstrap.yaml
spring:
application:
name: service
cloud:
config:
uri: http://config:8888
fail-fast: true
service.yaml (has service configuration)
server:
port: 8080
spring:
security:
user:
password: admin # doesnt set since no connection
Config Dockerfile
FROM openjdk:8-jdk-alpine
ADD target/config.jar /app.jar
CMD [ "java", "-Xmx200m", "-jar", "/app.jar" ]
EXPOSE 8888
Config application.yaml
spring:
application:
name: config
profiles:
active: composite
cloud:
config:
server:
composite:
- type: native
search-locations: classpath:/shared
server:
port: 8888
shared/service.yaml (has service configuration)
server:
port: 8080
spring:
security:
user:
password: admin # doesnt set since no connection
Any ideas?
I found some similar issues, although they only had issues with their URI, mine is set correctly.
Microservice can not reach to Config Server on Docker Compose
Docker - SpringConfig - Connection refused to ConfigServer
When one service depends on another you have to make sure that the latter is fully started before connecting to it.
In your case, most probably, config is started but not ready (context started) at the time service is run. As #Ganesh Karewad and #asolanki pointed out, a solution is to implement a reconnection logic. Another solution is to make sure config is initialized and accepting connections before you run service.
You can achieve that with a script that waits until the config app is up. In alternative you could configure the config container with a health check command and after you start it, wait until it is marked as healthy. Then you can run the service container.
Similar issue discussed here and here
Hope that helps.

Categories