Access Elasticsearch from minikube/kubernetes - spring

I have a spring boot application which is deployed in Kubernetes on local windows machine using minikube. I also have Elasticsearch running on my local machine (http://localhost:9200).
I want to call Elasticsearch REST endpoints from this spring boot app.
I tried solving this by creating a service without selector but not sure what am i missing.
When accessing the spring boot app using http://#minikube_ip#:#Node_Port#, i get an error "No route to host".
i tried doing minikube ssh and executing curl command, from there also i get the same error. Clearly I am missing something here.
application.yaml
elasticsearch:
hosts:
- http://my-es:80
connectTimeout: 10000
connectionRequestTimeout: 10000
socketTimeout: 10000
maxRetryTimeoutMillis: 60000
deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: kube-es-app
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
run: kube-es-app
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
run: kube-es-app
spec:
containers:
- image: elastic-search-app:latest
imagePullPolicy: Never
name: kube-es-app
ports:
- containerPort: 8080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
---
kind: Service
apiVersion: v1
metadata:
name: my-es
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9200
---
kind: Endpoints
apiVersion: v1
metadata:
name: my-es
subsets:
- addresses:
- ip: <MY_LOCAL_MACHINE_IP>
ports:
- port: 9200
Commands I executed
docker build -t elastic-search-app .
kubectl create -f deployment.yaml
kubectl expose deployment/kube-es-app --type="NodePort" --port 8080
Can anyone help please? I am stuck

If I've got the description right, the Windows machine should have vbox network adapter connected to the Host-only-network the Minikube VM is connected to.
Minikube can access the host machine directly because both are in the same network.
The Minikube is in charge of NAT-ting packages from Pods outside. What you need is to allow Elasticsearch to listen to the vbox- or all interfaces, and enable its port in the Windows firewall. Then the Elasticsearch should be available via IP address of Windows in the Host-only-network.
Apart from that, you might create a service (if you need go by name instead of IP) as discussed here:
Connect to local database from inside minikube cluster,
Minikube:Exposing mysql as a service on localhost.

Related

Kubernetes timeout

I can't for the life of me get this to connect.
It is a golang application using Kubernetes.
The docker file runs just fine, the pod launches but the connection times out.
apiVersion: v1
kind: Service
metadata:
name: ark-service
namespace: ark
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30008
selector:
app: ark-api
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ark-backend
namespace: ark
spec:
replicas: 1
selector:
matchLabels:
app: ark-api
template:
metadata:
labels:
app: ark-api
spec:
imagePullSecrets:
- name: regcred
containers:
- name: ark-api-container
image: xxx
imagePullPolicy: Always
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- name: web
containerPort: 8080
I am able to boot the docker container just fine and it runs.
Turns out the container gets terminated and I have no idea why.
You could check wheather the port 8080 is listening inside the container
kubectl exec -it <pod_namen> -n <namespace> -- netstat -ntpl
if there is no netstat command in the container, you could try to build a base image with it.
Check whether the port 30080 is listening on the node. Run the following command on the node
netstat -ntpl | grep 30080
Also you could try not to specify the node port in the service yaml, let the kubernetes to choose the nodeport for you. That could avoid to specify the port which is already using in your node.
apiVersion: v1
kind: Service
metadata:
name: ark-service
namespace: ark
spec:
type: ClusterIP
selector:
component: ark-api
ports:
- port: 80
targetPort: 8080
Try using clusterIP instead of nodeport, if you are using any kind of Ingress then you have to create rules in your ingress config so It can expose your service to the outside web via your load balancer.
I deleted the service and used port forwarding and was able to boot everything. I'll have to circle back to the service to try and figure it out.

Unable to expose docker LoadBalancer service

I am trying to deploy a docker image which is in public repository. I am trying to create a loadbalancer service, and trying to expose the service in my system ip address, and not 127.0.0.1.
I am using a windows 10 , and my docker has WSL2 instead of hyper-v.
Below is my .yaml file. So, the service inside will run in port 4200, so to avoid any kind of confusion I was keeping all the ports in 4200.
apiVersion: v1
kind: Service
metadata:
name: hoopla
spec:
selector:
app: hoopla
ports:
- protocol: TCP
port: 4200
targetPort: 4200
clusterIP: 10.96.1.3
type: LoadBalancer
status:
loadBalancer:
ingress:
- ip: 192.168.0.144
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: hoopla
name: hoopla
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: hoopla
template:
metadata:
labels:
app.kubernetes.io/name: hoopla
spec:
containers:
- image: pubrepo/myimg:latest
name: hoopla
ports:
- containerPort: 4200
Can anybody help me here to understand what mistake I am making. I basically want to expose this on my system IP address.
The loadBalancer service type require a cloud provider's load Balancer ( https://kubernetes.io/docs/concepts/services-networking/service/ )
LoadBalancer: Exposes the Service externally using a cloud provider's load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created
If you want to expose your service to your local machine, use kubernetes service nodePort type for example, and if you just want to test your webapp, you can use the kubernetes service clusterIp type and make a port-forward, for example with your clusterIp service:
kubectl port-forward svc/hoopla 4200:4200

kubernetes Minikube : Node port service not accessible from outside

I am trying to deploy simple spring boot REST service on minikube (Windows-10). Below are my configuration
Docker file
FROM openjdk:8-jdk-alpine
ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/myservice/minikube-spring-boot-demo-0.0.1-SNAPSHOT.jar"]
ADD target/minikube-spring-boot-demo-0.0.1-SNAPSHOT.jar /usr/share/myservice/lib
ARG JAR_FILE
ADD target/${JAR_FILE} /usr/share/myservice/minikube-spring-boot-demo-0.0.1-SNAPSHOT.jar
EXPOSE 8080
docker image is running fine and i am able to run the app.
docker run -p 8080:8080 minikube-spring-boot-demo:0.0.1-SNAPSHO
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: minikube-spring-boot-demo
spec:
selector:
matchLabels:
app: minikube-spring-boot-demo
tier: backend
replicas: 3
template:
metadata:
labels:
app: minikube-spring-boot-demo
tier: backend
spec:
containers:
- name: demo-backend
image: nirajsonawane/minikube-spring-boot-demo:0.0.1-SNAPSHOT
imagePullPolicy: Always
ports:
- containerPort: 8080
Service
apiVersion: v1
kind: Service
metadata:
name: minikube-spring-boot-demo-service
spec:
selector:
app: minikube-spring-boot-demo
tier: backend
ports:
- port: 8080
targetPort: 8080
nodePort: 30008
type: NodePort
kubectl get all status
kubectl cluster-info
minikube logs
Service Details
i am not able to access the rest endpoint using service-ip:Nodeport/Uri
http://127.0.0.1:30008/hello
http://172.17.0.2:30008/hello
Anything i am missing here? any inputs will be useful.
output of netstat -a
minikube is running in a virtual machine. Services can't be accessed through either localhost or 127.0.0.1 out of the machine.
Try to run minikube service minikube-spring-boot-demo-service. It will show service details and open the service in the browser.
You can get you cluster ip using below command
kubectl get nodes -o wide
then run below to get nodeport
kubectl get svc -o wide -n <namespace>
get the port of your NodePort Svc
then your application will be running on http://:port(svc Nodeport )
In your case it might be running on
http://127.0.0.1:30008/hello

Debugging uWSGI in kubernetes

I have a pair of kubernetes pods, one for nginx and one for Python Flask + uWSGI. I have tested my setup locally in docker-compose, and it has worked fine, however after deploying to kubernetes somehow it seems there is no communication between the two. The end result is that I get 502 Gateway Error when trying to reach my location.
So my question is not really about what is wrong with my setup, but rather what tools can I use to debug this scenario. Is there a test-client for uwsgi? Can I use ncat? I don't seem to get any useful log output from nginx, and I don't know if uwsgi even has a log.
How can I debug this?
For reference, here is my nginx location:
location / {
# Trick to avoid nginx aborting at startup (set server in variable)
set $upstream_server ${APP_SERVER};
include uwsgi_params;
uwsgi_pass $upstream_server;
uwsgi_read_timeout 300;
uwsgi_intercept_errors on;
}
Here is my wsgi.ini:
[uwsgi]
module = my_app.app
callable = app
master = true
processes = 5
socket = 0.0.0.0:5000
die-on-term = true
uid = www-data
gid = www-data
Here is the kubernetes deployment.yaml for nginx:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
service: nginx
name: nginx
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
service: nginx
strategy:
type: Recreate
template:
metadata:
labels:
service: nginx
spec:
imagePullSecrets:
- name: docker-reg
containers:
- name: nginx
image: <custom image url>
imagePullPolicy: Always
env:
- name: APP_SERVER
valueFrom:
secretKeyRef:
name: my-environment-config
key: APP_SERVER
- name: FK_SERVER_NAME
valueFrom:
secretKeyRef:
name: my-environment-config
key: SERVER_NAME
ports:
- containerPort: 80
- containerPort: 10443
- containerPort: 10090
resources:
requests:
cpu: 1m
memory: 200Mi
volumeMounts:
- mountPath: /etc/letsencrypt
name: my-storage
subPath: nginx
- mountPath: /dev/shm
name: dshm
restartPolicy: Always
volumes:
- name: my-storage
persistentVolumeClaim:
claimName: my-storage-claim-nginx
- name: dshm
emptyDir:
medium: Memory
Here is the kubernetes service.yaml for nginx:
apiVersion: v1
kind: Service
metadata:
labels:
service: nginx
name: nginx
spec:
type: LoadBalancer
ports:
- name: "nginx-port-80"
port: 80
targetPort: 80
protocol: TCP
- name: "nginx-port-443"
port: 443
targetPort: 10443
protocol: TCP
- name: "nginx-port-10090"
port: 10090
targetPort: 10090
protocol: TCP
selector:
service: nginx
Here is the kubernetes deployment.yaml for python flask:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
service: my-app
name: my-app
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
service: my-app
strategy:
type: Recreate
template:
metadata:
labels:
service: my-app
spec:
imagePullSecrets:
- name: docker-reg
containers:
- name: my-app
image: <custom image url>
imagePullPolicy: Always
ports:
- containerPort: 5000
resources:
requests:
cpu: 1m
memory: 100Mi
volumeMounts:
- name: merchbot-storage
mountPath: /app/data
subPath: my-app
- name: dshm
mountPath: /dev/shm
- name: local-config
mountPath: /app/secrets/local_config.json
subPath: merchbot-local-config-test.json
restartPolicy: Always
volumes:
- name: merchbot-storage
persistentVolumeClaim:
claimName: my-storage-claim-app
- name: dshm
emptyDir:
medium: Memory
- name: local-config
secret:
secretName: my-app-local-config
Here is the kubernetes service.yaml for nginx:
apiVersion: v1
kind: Service
metadata:
labels:
service: my-app
name: my-app
spec:
ports:
- name: "my-app-port-5000"
port: 5000
targetPort: 5000
selector:
service: my-app
Debugging in kubernetes is not very different from debugging outside, there's just some concepts that need to be overlaid for the kubernetes world.
A Pod in kubernetes is what you would conceptually see as a host in the VM world. Every container running in a Pod will see each others services on localhost. From there, a Pod to anything else will have a network connection involved (even if the endpoint is node local). So start testing with services on localhost and work your way out through pod IP, service IP, service name.
Some complexity comes from having the debug tools available in the containers. Generally containers are built slim and don't have everything available. So you either need to install tools while a container is running (if you can) or build a special "debug" container you can deploy on demand in the same environment. You can always fall back to testing from the cluster nodes which also have access.
Where you have python available you can test with uswgi_curl
pip install uwsgi-tools
uwsgi_curl hostname:port /path
Otherwise nc/curl will suffice, to a point.
Pod to localhost
First step is to make sure the container itself is responding. In this case you are likely to have python/pip available to use uwsgi_curl
kubectl exec -ti my-app-XXXX-XXXX sh
nc -v localhost 5000
uwsgi_curl localhost:5000 /path
Pod to Pod/Service
Next include the kubernetes networking. Start with IP's and finish with names.
Less likely to have python here, or even nc but I think testing the environment variables is important here:
kubectl exec -ti nginx-XXXX-XXXX sh
nc -v my-app-pod-IP 5000
nc -v my-app-service-IP 5000
nc -v my-app-service-name 5000
echo $APP_SERVER
echo $FK_SERVER_NAME
nc -v $APP_SERVER 5000
# or
uwsgi_curl $APP_SERVER:5000 /path
Debug Pod to Pod/Service
If you do need to use a debug pod, try and mimic the pod you are testing as much as possible. It's great to have a generic debug pod/deployment to quickly test anything, but if that doesn't reveal the issue you may need to customise the deployment to mimic the pod you are testing more closely.
In this case the environment variables play a part in the connection setup, so that should be emulated for a debug pod.
Node to Pod/Service
Pods/Services will be available from the cluster nodes (if you are not using restrictive network policies) so usually the quick test is to check Pods/Services are working from there:
nc -v <pod_ip> <container_port>
nc -v <service_ip> <service_port>
nc -v <service__dns> <service_port>
In this case:
nc -v <my_app_pod_ip> 5000
nc -v <my_app_service_ip> 5000
nc -v my-app.svc.<namespace>.cluster.local 5000

Minikube VM hyperkit: Spring Boot: connect to local machine

I have a minikube cluster running on Mac OSX and a simple Spring Boot REST api that connects to Redis and Mongo DB, which I have installed and running locally.
I wish not to run Redis / MongoDb in a Docker container.
I will probably run them remotely in the cloud, therefore I would probably just connect to an external IP address.
What I don't understand is what IP address I should use to connect to my localhost machine.
I start up my Minikube with VM hyperkit.
Edit:
I also tried to start using virtualbox:
minikube start --vm-driver=virtualbox
In my spring boot application, I've configured:
spring.data.mongodb.host = 10.0.2.2
spring.redis.host = 10.0.2.2
But still, I get connection errors:
This works when I run the application locally on my host machine.
For the sake of completeness, this is my yaml file:
---
apiVersion: v1
kind: Service
metadata:
name: posts-api
labels:
app: posts-api
env: dev
spec:
type: NodePort
selector:
app: posts-api
ports:
- protocol: TCP
port: 8083
name: http
---
apiVersion: v1
kind: ReplicationController
metadata:
name: posts-api
spec:
replicas: 1
template:
metadata:
labels:
app: posts-api
spec:
containers:
- name: posts-api
image: kimgysen/posts-api:latest
ports:
- containerPort: 8083
livenessProbe:
httpGet:
path: /health
port: 8083
initialDelaySeconds: 120
timeoutSeconds: 3
I'll give you the answer I gave to someone with the same problem (different tech):
Kubernetes pod unable to connect to rabbit mq instance running locally
Replace the IP and port number, and the Service and Endpoints names as appropriate.

Resources