Minikube: Exposing REST API from Docker container - docker

I currently have a Dockerised Spring Boot application with exposed Java REST APIs that I deploy on to my NUC (just a remote machine) and can connect to it from my Mac, via the NUCs static IP address. Both machines are on the same network.
I am now looking into hosting the Docker application in Kubernetes (Minikube)
(using this tutorial https://medium.com/bb-tutorials-and-thoughts/how-to-run-java-rest-api-on-minikube-4b564ea982cc).
I have used the Kompose tool from Kubernetes to convert my Docker compose files into Kubernetes deployments and services files. One of the services I'm trying to get working first simply opens up port 8080 and has a number of REST resources. Everything seems to be up and running, but I cannot access the REST resources from my Mac (or even the NUC itself) with a curl -v command.
After getting around a small issue with my Docker images (needing built to Minikube's internal Docker images repo), I can successfully deploy my services and deployments. There are a number of others, but for the purposes of getting past this step, I'll just include the one:
$ kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-f9fd979d6-hhgn8 1/1 Running 0 7h
kube-system etcd-minikube 1/1 Running 0 7h
kube-system kube-apiserver-minikube 1/1 Running 0 7h
kube-system kube-controller-manager-minikube 1/1 Running 0 7h
kube-system kube-proxy-rszpv 1/1 Running 0 7h
kube-system kube-scheduler-minikube 1/1 Running 0 7h
kube-system storage-provisioner 1/1 Running 0 7h
meanwhileinhell apigw 1/1 Running 0 6h54m
meanwhileinhell apigw-75bc5z1f5j-cklxt 1/1 Running 0 6h54m
$ kubectl get service apigw
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apigw NodePort 10.107.116.239 <none> 8080:32327/TCP 6h53m
$ kubectl cluster-info
Kubernetes master is running at https://192.168.44.2:8443
KubeDNS is running at https://192.168.44.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
However, I cannot hit this master IP address, or any expected open port using the static IP of my NUC. I have tried to use the service types LoadBalancer and NodePort for the service but the former hangs on pending for the external IP.
I have played about a little with exposing ports and port forwarding but haven't been able to get anything working (port 7000 is just an arbitrary number):
kubectl port-forward apigw 7000:8080
kubectl expose deployment apigw --port=8080 --target-port=8080
Here is my apigw deployment, service and pod yaml files:
apigw-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
io.kompose.service: apigw
name: apigw
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: apigw
strategy:
type: Recreate
template:
metadata:
creationTimestamp: null
labels:
io.kompose.network/networkinhell: "true"
io.kompose.service: apigw
spec:
containers:
image: meanwhileinhell/api-gw:latest
name: apigw
ports:
- containerPort: 8080
resources: {}
imagePullPolicy: Never
volumeMounts:
- mountPath: /var/log/gateway
name: combined-logs
hostname: apigw
restartPolicy: Always
volumes:
- name: combined-logs
persistentVolumeClaim:
claimName: combined-logs
status: {}
apigw-service.yaml
apiVersion: v1
kind: Service
metadata:
name: apigw
labels:
run: apigw
spec:
ports:
- port: 8080
protocol: TCP
selector:
app: apigw
type: NodePort
apigw-pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
io.kompose.service: apigw
name: apigw
spec:
containers:
- image: meanwhileinhell/api-gw:latest
name: apigw
imagePullPolicy: Never
resources: {}
ports:
- containerPort: 8080
Using kubectl create -f to create the services.
Ubuntu 18.04.5 LTS
Minikube v1.15.0
KubeCtl v1.19.4

Related

How does k8s cluster behave when accessed from its pod using kubectl?

I am working on a project with jenkins where I am already running the jenkins pod and want to run kubectl commands directly from the pod to connect with my host machine in order to do that I followed this SO question about k8s cluster remote access am on windows and have kubectl v1.23.3 installed on a jenkins pod I runned from my host machine k8s.
I managed to verify that running kubectl works properly on the jenkins pod (container):
kubectl create deployment nginx --image=nginx
kubectl create service nodeport nginx --tcp=80:80
when I ran kubectl get all from the jenkins container I get this output:
root#jenkins-64756886f7-2v92n:~/test# kubectl create deployment nginx --image=nginx
kubectl create service nodeport nginx --tcp=80:80
deployment.apps/nginx created
service/nginx created
root#jenkins-64756886f7-2v92n:~/test# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/jenkins-64756886f7-2v92n 1/1 Running 0 37m
pod/nginx-6799fc88d8-kxprv 1/1 Running 0 8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/jenkins-service NodePort 10.110.105.78 <none> 8080:30090/TCP 39m
service/nginx NodePort 10.107.115.5 <none> 80:32355/TCP 8s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/jenkins 1/1 1 1 39m
deployment.apps/nginx 1/1 1 1 8s
NAME DESIRED CURRENT READY AGE
replicaset.apps/jenkins-64756886f7 1 1 1 37m
replicaset.apps/nginx-6799fc88d8 1 1 1 8s
root#jenkins-64756886f7-2v92n:~/test#
Initially I had Jenkins deployment attached to a namespace called devops-cicd
Tested the deployment on my browser and worked fine
and this is the output from my host machine:
PS C:\Users\affes> kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d9h
and when I specify the namespace I get the same result as from Jenkins container:
PS C:\Users\affes> kubectl get all -n devops-cicd
NAME READY STATUS RESTARTS AGE
pod/jenkins-64756886f7-2v92n 1/1 Running 0 38m
pod/nginx-6799fc88d8-kxprv 1/1 Running 0 93s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/jenkins-service NodePort 10.110.105.78 <none> 8080:30090/TCP 41m
service/nginx NodePort 10.107.115.5 <none> 80:32355/TCP 93s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/jenkins 1/1 1 1 41m
deployment.apps/nginx 1/1 1 1 93s
NAME DESIRED CURRENT READY AGE
replicaset.apps/jenkins-64756886f7 1 1 1 38m
replicaset.apps/nginx-6799fc88d8 1 1 1 93s
I don't know what's causing the resources created on that namespace directly without even specifying the namespace, and is there a possible way to configure something that will allow me to deploy on default namespace instead?
This is my deployment manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: devops-cicd
spec:
selector:
matchLabels:
app: jenkins
workload: cicd
replicas: 1
template:
metadata:
namespace: devops-cicd
labels:
app: jenkins
workload: cicd
spec:
containers:
- name: jenkins
image: jenkins/jenkins:lts
volumeMounts:
- name: dockersock
mountPath: "/var/run/docker.sock"
- name: docker
mountPath: "/usr/bin/docker"
securityContext:
privileged: true
runAsUser: 0 # Root
restartPolicy: Always
volumes:
- name: dockersock
hostPath:
path: /var/run/docker.sock
- name: docker
hostPath:
path: /usr/bin/docker
---
apiVersion: v1
kind: Service
metadata:
namespace: devops-cicd
name: jenkins-service
spec:
selector:
app: jenkins
workload: cicd
ports:
- name: http
port: 8080
nodePort: 30090
type: NodePort
You may have a different namespace configured by default in the kubectl in the Jenkins pod. You can check it with the following command.
kubectl config view | grep namespace
To change the default namespace to `default, you can run the following command.
kubectl config set-context --current --namespace=default
Please find more details here.

Can't see my app on browser deploying with Kubernetes

hope you all well!
I need to see my app on the browser but I believe that I'm missing something here and hope you can help me with this.
[root#kubernetes Docker]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/my-app2-56d5c786dd-n7mqq 1/1 Running 0 19m
pod/nginx-86c57db685-bxkpl 1/1 Running 0 13h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31h
service/my-app2 ClusterIP 10.101.108.199 <none> 8085/TCP 12m
service/nginx NodePort 10.106.14.144 <none> 80:30525/TCP 13h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-app2 1/1 1 1 19m
deployment.apps/nginx 1/1 1 1 13h
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-app2-56d5c786dd 1 1 1 19m
replicaset.apps/nginx-86c57db685 1 1 1 13h
Overall you can see that everything is working fine right, looks the same to me.
To open this on my browser I'm using my IP address from Slave node where the container is allocated.
On my app I'm mapping the Hello like this #RequestMapping("/Hello")
On my dockerfile to build my image i used this:
[root#kubernetes project]# cat Dockerfile
FROM openjdk:8
COPY microservico-0.0.1-SNAPSHOT.jar microservico-0.0.1-SNAPSHOT.jar
#WORKDIR /usr/src/microservico-0.0.1-SNAPSHOT.jar
EXPOSE 8085
ENTRYPOINT ["java", "-jar", "microservico-0.0.1-SNAPSHOT.jar"]
So at the end, I think I need to call for my app this way.
---> ip:8085/Hello
[root#kubernetes project]# telnet kubeslave 8085
Trying 192.168.***.***...
telnet: connect to address 192.168.***.***: Connection refused
but I still see nothing...
Here is my deploy and service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app2
labels:
app: app
spec:
selector:
matchLabels:
app: app
role: master
tier: backend
replicas: 1
template:
metadata:
labels:
app: app
role: master
tier: backend
spec:
containers:
- name: appcontainer
image: *****this is ok*****:my-java-app
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 8085
apiVersion: v1
kind: Service
metadata:
name: my-app2
labels:
app: app
role: master
tier: backend
spec:
ports:
- port: 8085
targetPort: 8085
selector:
app: app
role: master
tier: backend
You have create a service which is of type ClusterIP(default). This type of service is only for accessing from inside the kubernetes cluster.For accessing it from browser you need to expose the pod via LoadBalancer or Nodeport service. LoadBalancer only works if you are one of supported public cloud otherwise Nodeport need to be used.
https://kubernetes.io/docs/tutorials/stateless-application/expose-external-ip-address/
https://kubernetes.io/docs/tasks/access-application-cluster/service-access-application-cluster/
Other than using service you can use kubectl proxy to access it as well.
If you are on Minikube then follow this
https://kubernetes.io/docs/tutorials/hello-minikube/

Kubernetes NodePort doesn't return the response from the container

I've developed a containerized Flask application and I want to deploy it with Kubernetes. However, I can't connect the ports of the Container with the Service correctly.
Here is my Deployment file:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: <my-app-name>
spec:
replicas: 1
template:
metadata:
labels:
app: flaskapp
spec:
containers:
- name: <container-name>
image: <container-image>
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5000
name: http-port
---
apiVersion: v1
kind: Service
metadata:
name: <service-name>
spec:
selector:
app: flaskapp
ports:
- name: http
protocol: TCP
targetPort: 5000
port: 5000
nodePort: 30013
type: NodePort
When I run kubectl get pods, everything seems to work fine:
NAME READY STATUS RESTARTS AGE
<pod-id> 1/1 Running 0 7m
When I run kubectl get services, I get the following:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
<service-name> NodePort 10.105.247.63 <none> 5000:30013/TCP
...
However, when I give the following URL to the browser: 10.105.247.63:30013, the browser keeps loading but never returns the data from the application.
Does anyone know where the problem could be? It seems that the service is not connected to the container's port.
30013 is the port on the Node not in the cluster IP. To get a reply you would have to connect to <IP-address-of-the-node>:30013. To get the list of nodes you can:
kubectl get nodes -o=wide
You can also go through the CLUSTER-IP but you'll have to use the exposed port 5000: 10.105.247.63:5000

kubectl is not looking for local image on one node but works fine on other node

I have a two node cluster in AWS:
[centos#node2 sample_code]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready master 3h v1.9.4+coreos.0
node2 Ready master,node 3h v1.9.4+coreos.0
and i have a simple deployment:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginxpinalabel
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.13
imagePullPolicy: Never
so when i tried to deploy this, i have 3 pods and which ever pods are in node1 are fine but on node2 it shows error:
NAME READY STATUS RESTARTS AGE
nginx-deployment-6c5ff867c5-dtjwr 0/1 ErrImageNeverPull 0 21m
nginx-deployment-6c5ff867c5-jvnvn 0/1 ErrImageNeverPull 0 21m
nginx-deployment-6c5ff867c5-kpzgf 1/1 Running 0 21m
but still i have nginx:1.13 in my registery of node2:
sudo docker images | grep nginx
10.3.5.206:5000/nginx 1.13 3f8a4339aadd 12 weeks ago 108.5 MB
Change the image name from 10.3.5.206:5000/nginx to nginx.

minikube service %servicename% --url return nothing

I'm trying to expose my api so I can send request to it. However when I used the command minikube service api --url I get nothing. All my pods are running fine according to kubectl get pods so I'm abit stuck about what this could be.
api-1007925651-0rt1n 1/1 Running 0 26m
auth-1671920045-0f85w 1/1 Running 0 26m
blankit-app 1/1 Running 5 5d
logging-2525807854-2gfwz 1/1 Running 0 26m
mongo-1361605738-0fdq4 1/1 Running 0 26m
jwl:.build jakewlace$ kubectl get services
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
api 10.0.0.194 <none> 3001/TCP 23m
auth 10.0.0.36 <none> 3100/TCP 23m
kubernetes 10.0.0.1 <none> 443/TCP 5d
logging 10.0.0.118 <none> 3200/TCP 23m
mongo 10.0.0.132 <none> 27017/TCP 23m
jwl:.build jakewlace$
jwl:.build jakewlace$ minikube service api --url
jwl:.build jakewlace$
Any help would be massively appreciated, thank you.
I realised that the question here could be perceived as being minimal, but that is because I'm not sure what more information I could show from the tutorials I've been following it should just work. If you need more information please do let me know I will let you know.
EDIT:
api-service.yml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
name: api
spec:
ports:
- name: "3001"
port: 3001
targetPort: 3001
selector:
io.kompose.service: api
status:
loadBalancer: {}
api-deployment.yml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
name: api
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: api
spec:
containers:
- image: blankit/web:0.0.1
name: api
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3001
resources: {}
restartPolicy: Always
status: {}
Your configuration is fine, but only missing one thing.
There are many types of Services in Kubernetes, but in this case you should know about two of them:
ClusterIP Services:
Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. This is the default.
NodePort:
Exposes the service on each Node’s IP at a static port (the NodePort). A ClusterIP service, to which the NodePort service will route, is automatically created. You’ll be able to contact the NodePort service, from outside the cluster, by requesting <NodeIP>:<NodePort>.
Note:
If you have a multi-node cluster and you've exposed a NodePort Service, you can access is from any other node on the same port, not necessarily the same node the pod is deployed onto.
So, getting back to your service, you should specify the service type in your spec:
kind: Service
apiVersion: v1
metadata:
...
spec:
type: NodePort
selector:
...
ports:
- protocol: TCP
port: 3001
Now if you minikube service api --url, it should return a URL like http://<NodeIP>:<NodePort>.
Note: The default Kubernetes configuration will chose a random port from 30000-32767. But you can override that if needed.
Useful references:
Kubernetes / Publishing services - service types
Kubernetes / Connect a Front End to a Back End Using a Service

Resources