Not able to access external database in a pod using kubeadm-dind-cluster - kubernetes

I'm trying to configure a local environment to test kubernetes. I have chose to use kubeadm-dind-cluster and minikube.
I have the database deployed on a container outside the kubernetes and i'm trying to access it inside the pods created on kubernetes.
For this i have created a service without a pod selector and an endpoint as below:
apiVersion: v1
kind: Service
metadata:
name: db-service
spec:
ports:
- name: db-port
port: 1521
protocol: TCP
targetPort: 1521
apiVersion: v1
kind: Endpoints
metadata:
name: db-service
subsets:
- addresses:
- ip: 10.1.90.161
ports:
- name: db-port
port: 1521
protocol: TCP
The service was created successfully as shown below:
service output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db-service ClusterIP 10.111.130.231 <none> 1521/TCP 16m
endpoint output:
NAME ENDPOINTS AGE
db-service 10.1.90.161:1521 19m
The ping inside the container of the pod is not working.
Could you please tell me what i'm missing?

All looks good in your manifest files. Pinging endpoint from inside the pod is not a god way to verify the connectivity to your external database. Please check with telnet whether port is really opened:
telnet 10.1.90.161 1521

Related

Kubernetes service URL not responding to API call

I've been following multiple tutorials on how to deploy my (Spring Boot) api on Minikube. I already got it (user-service running on 8081) working in a docker container with an api gateway (port 8080) and eureka (port 8087), but for starters I just want it to run without those. Steps I took:
Push docker container or image (?) to docker hub, I don't know the proper term.
Create a deployment.yaml:
apiVersion: v1
kind: Service
metadata:
name: kwetter-service
spec:
type: LoadBalancer
selector:
app: kwetter
ports:
- protocol: TCP
port: 8080
targetPort: 8081
nodePort: 30070
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kwetter-deployment
labels:
app: kwetter
spec:
replicas: 1
selector:
matchLabels:
app: kwetter
template:
metadata:
labels:
app: kwetter
spec:
containers:
- name: user-api
image: cazhero/s6-kwetter-backend_user:latest
ports:
- containerPort: 8081 #is the port it runs on when I manually start it up
kubectl apply -f deployment.yaml
minikube service kwetter-service
It takes me to an empty site with url: http://192.168.49.2:30070 which I thought I could use to make API calls to, but apparently not. How do I make api calls to my application running on minikube?
Get svc returns:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d4h
kwetter-service LoadBalancer 10.106.42.56 <pending> 8080:30070/TCP 4d
describe svc kwetter-service:
Name: kwetter-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=kwetter
Type: NodePort
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.106.42.56
IPs: 10.106.42.56
Port: <unset> 8080/TCP
TargetPort: 8081/TCP
NodePort: <unset> 30070/TCP
Endpoints: 172.17.0.4:8081
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Type 6s service-controller LoadBalancer -> NodePort
Made an Ingress in the yaml, used kubectl get ing:
NAME CLASS HOSTS ADDRESS PORTS AGE
kwetter-ingress <none> * 80 49m
To make some things clear:
You need to have pushed your docker image cazhero/s6-kwetter-backend_user:latest to docker hub, check that at https://hub.docker.com/, in your personal repository.
What's the output of minikube service kwetter-service, does it print the URL http://192.168.49.2:30070?
Make sure your pod is running correctly by the following minikube command:
# check pod status
minikube kubectl -- get pods
# if the pod is running, check its container logs
minikube kubectl -- logs po kwetter-deployment-xxxx-xxxx
I see that you are using LoadBalancer service, where a LoadBalancer service is the standard way to expose a service to the internet. With this method, each service gets its own IP address.
Check external IP
kubectl get svc
Use the external IP and the port number in this format to access the
application.
http://REPLACE_WITH_EXTERNAL_IP:8080
If you want to access the application using Nodeport (30070), use the Nodeport service instead of LoadBalancer service.
Refer to this documentation for more information on accessing applications through Nodeport and LoadBalancer services.

Expose cluster in k8s on localhost

Because docker supports out of the box kubernetes (on my Mac) I thought I try it out and see if I can load balance a simple webservice. For that, I created a simple image, which exposes port 3000 and only returns Hello World. And I created a k8s config yaml
apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes
spec:
type: NodePort
externalIPs:
- 192.168.2.85
ports:
- port: 8080
targetPort: 3000
selector:
app: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes
spec:
replicas: 3
selector:
matchLabels:
app: hello-kubernetes
template:
metadata:
labels:
app: hello-kubernetes
spec:
containers:
- name: hello-kubernetes
image: hello/world:latest
ports:
- containerPort: 3000
Apply it
$> kubectl apply -f ./example.yaml
I see 3 pods running, and a service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-kubernetes NodePort 10.99.38.46 192.168.2.85 8080:30244/TCP 42m
I've used NodePort above, but I'm not sure if I can use Loadbalancer here as well.
Anyway, in the browser I get the message This site can’t be reached when I goto http://192.168.2.85:8080 or `http://192.168.2.85:30244 (I never know which port to use)
So, I think I'm close, but I still missed something :( Any help would be appreciated!
the port number is wrong.
use http://NODEIP:NODEPORT
in your case, try
http://NODEIP:30244
k explain service.spec.externalIPs
KIND: Service VERSION: v1
FIELD: externalIPs <[]string>
DESCRIPTION:
externalIPs is a list of IP addresses for which nodes in the cluster will
also accept traffic for this service. These IPs are not managed by
Kubernetes. The user is responsible for ensuring that traffic arrives at a
node with this IP. A common example is external load-balancers that are not
part of the Kubernetes system.
Problem here is we don't know your network settings. IS this minikube for mac? Is the 192.168.2.x network reachable for you? In my case using minikube all I had to do was to edit the externalIP to be reachable from my network. So what I did to get this working was:
minikube IP in my case 192.168.99.100 (IP address of minikubeVM)
changed externalIP to 192.168.99.100
k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-kubernetes NodePort 10.105.212.118 192.168.99.100 8080:32298/TCP 46m
And I was able to reach the application using 192.168.99.100:8080.
Also note that in your case you have 8081 port (But I guess P Ekambaram already mentioned this).

How to expose a Kubernetes service on a specific Nodeport?

I have create a pod with the below yaml definition.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: praveensripati/docker-demo:1.2
ports:
- containerPort: 3000
And now I expose the pod, which creates a service.
kubectl expose pod myapp-pod --type=NodePort
The port 3000 on the container is exposed to port 31728 on the nodes. And I am able to do access the page using curl on port 31728.
kubectl get service myapp-pod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp-pod NodePort 10.107.254.254 <none> 3000:31728/TCP 5s
This time I wanted to expose the service not a random port, but on port 80. And so I specify the port number as 80, by using --port. The service details are a bit odd. It says that port 80 on the container is exposed to port 31316 on the nodes. Also, I am able to access the page using curl on the random port (31316 in this case) and not port 80.
kubectl expose pod myapp-pod --type=NodePort --target-port=3000 --port=80
kubectl get service myapp-pod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myapp-pod NodePort 10.105.123.73 <none> 80:31316/TCP 12s
I am not able to expose a service on a specific port and not on a random port. I tried a few combinations and read the k8s documentation, but no success.
How do I expose a service on a specific port instead of a random port?
Your question is about exposing the NodePort type of service on a specific port. For that you need to specify the nodePort field under ports in your service definition.
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 3000
nodePort: 32321
type: NodePort
Note that it has to be within a given range provided in the configs. Which defaults to 30000-32767. This range can be specified in the kube-apiserver configs using the --service-node-port-range option.
When an existing Dashboard service already exists, remove it.
kubectl delete service kubernetes-dashboard -n kube-system
Expose the Dashboard deployment as a NodePort.
kubectl expose deployment kubernetes-dashboard -n kube-system --type=NodePort
The above will assign a random port >= 30000. So use the Patch command to assign the port to a known, unused and desired port >= 30000.
kubectl patch service kubernetes-dashboard --namespace=kube-system --type='json' --patch='[{"op": "replace", "path": "/spec/ports/0/nodePort", "value":30000}]'
Caution: Never expose your dashboard publicly without authentication.
If your cluster does not have a LoadBalancer Provider, you can specify externalIPs in IP of nodes' network interface.
For example:
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
type: ClusterIP
externalIPs:
- 125.100.99.101 # Node1-IP
- 125.100.99.102 # Node2-IP
- 192.168.55.112 # Node2-IP2
selector:
pod: nginx
ports:
- name: http
port: 80
- name: https
port: 443
This will listen 80 and 443 on the specified node, and forward to the nginx service.
I had the same problem and the only way I found to do it without modifying the files was:
k expose --type=NodePort deployment nginx --port 80 --name nginx-ep-patch --overrides '{ "apiVersion": "v1","spec":{"ports": [{"port":80,"protocol":"TCP","targetPort":80,"nodePort":30080}]}}'
service/nginx-ep-patch exposed
In this way we path online the configuration and the port 30080 has been exposed:
$ k describe svc nginx-ep-patch
Name: nginx-ep-patch
Namespace: default
Labels: app=nginx
Annotations: <none>
Selector: app=nginx
Type: NodePort
IP: 10.96.51.148
Port: <unset> 80/TCP
TargetPort: 80/TCP
NodePort: <unset> 30080/TCP
Endpoints: 10.244.0.6:80
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
I will try to answer your query here.
Also, I am able to access the page using curl on the random port
(31316 in this case) and not port 80.
-- Because, kubernetes exposed the port 31316 on the host (maps to the service) and hence it can be accessed on host:31316.
-- Service port is visible only within the kubernetes cluster. You can exec into a pod container and do a curl on servicename:service port instead of the NodePort.
Note the terms - container port: the port container listens on. Service port: the port where kubernetes service is exposed on cluster internal ip and mapped to the container port. Nodeport: the port exposed on the host and mapped to kubernetes service.
we can expose Kubernetes service on specific node port.
Port value must be between 30000-32767.
We can expose service to specific port of below service types:
NodePort
LoadBalancer
Find the sample myservice.yaml file below:
apiVersion: v1
kind: Service
metadata:
name: app1
spec:
type: NodePort/LoadBalancer
ports:
- name: "80"
port: 80
nodePort: 32062
targetPort: 80
selector:
appone: app1
app: test
Note: In above service yaml file we can specify service type either NodePort or Loadbalancer.
For those who need to use kubectl commands, you can create a NodePort service with a specified port using create nodeport command:
kubectl create nodeport NAME [--tcp=port:targetPort] [--dry-run=server|client|none]
For example:
kubectl create service nodeport myservice --node-port=31000 --tcp=3000:80
You can check Kubectl reference for more:
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-service-nodeport-em-

expose kubernetes pod to internet

I created a pod with an api and web docker container in kuberneters using a yml file (see below).
apiVersion: v1
kind: Pod
metadata:
name: test
labels:
purpose: test
spec:
containers:
- name: api
image: gcr.io/test-1/api:latest
ports:
- containerPort: 8085
name: http
protocol: TCP
- name: web
image: gcr.io/test-1/web:latest
ports:
- containerPort: 5000
name: http
protocol: TCP
It show my pod is up and running
NAME READY STATUS RESTARTS AGE
test 2/2 Running 0 5m
but I don't know how to expose it from here.
it seems odd I would have to run kubectl run .... again as the pod is already running. It does not show a deployment though.
if I try something like
kubectl expose deployment test --type="NodePort"--port 80 --target-port 5000
it complains about deployments.extensions "test' not found. What is the cleanest way to deploy from here?
To expose a deployment to the public internet, you will want to use a Service. The service type LoadBalancer handles this nicely, as you can just use pod selectors in the yaml file.
So if my deployment.yaml looks like this:
kind: Deployment
apiVersion: apps/v1beta2
metadata:
name: test-dply
spec:
selector:
# Defines the selector that can be matched by a service for this
deployment
matchLabels:
app: test_pod
template:
metadata:
labels:
# Puts the label on the pod, this must match the matchLabels
selector
app: test_pod
spec:
# Our containers for training each model
containers:
- name: mycontainer
image: myimage
imagePullPolicy: Always
command: ["/bin/bash"]
ports:
- name: containerport
containerPort: 8085
Then the service that would link to it is:
kind: Service
apiVersion: v1
metadata:
# Name of our service
name: prodigy-service
spec:
# LoadBalancer type to allow external access to multiple ports
type: LoadBalancer
selector:
# Will deliver external traffic to the pod holding each of our containers
app: test_pod
ports:
- name: sentiment
protocol: TCP
port: 80
targetPort: containerport
You can deploy these two items by using kubectl create -f /path/to/dply.yaml and kubectl create -f /path/to/svc.yaml. Quick note: The service will allocate a public IP address, which you can find using kubectl get services with the following output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
carbon-relay ClusterIP *.*.*.* <none> 2003/TCP 78d
comparison-api LoadBalancer *.*.*.* *.*.*.* 80:30920/TCP 15d
It can take several minutes to allocate the ip, just a forewarning. But the LoadBalancer's ip is fixed, and you can delete the pod that it points to and re-spin it without consequence. So if I want to edit my test.dply, I can without worrying about my service being impacted. You should rarely have to spin down services
You have created a pod, not a deployment.
Then you have exposed a deployment (and not your pod).
Try:
kubectl expose pod test --type=NodePort --port=80 --target-port=5000
kubectl expose pod test --type=LoadBalancer --port=XX --target-port=XXXX
If you already have pod and service running, you can create an ingress for the service you want to expose to the internet.
If you want to create it through console, Google Cloud provides really easy way to create an ingress from an existing service. Go to Services and Ingress tab, select the service, click on create ingress, fill the name and other mandatory fields.
or you can create using yaml file
apiVersion: "networking.k8s.io/v1"
kind: "Ingress"
metadata:
name: "example-ingress"
namespace: "default"
spec:
defaultBackend:
service:
name: "example-service"
port:
number: 8123
status:
loadBalancer: {}

Minikube expose MySQL running on localhost as service

I have minikube version v0.17.1 running on my machine. I want to simulate the environment I will have in AWS, where my MySQL instance will be outside of my Kubernetes cluster.
Basically, how can I expose my local MySQL instance running on my machine to the Kubernetes cluster running via minikube?
Kubernetes allows you to create a service without selector, and cluster will not create related endpoint for this service, this feature is usually used to proxy a legacy component or an outside component.
Create a service without selector
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 1443
targetPort: <YOUR_MYSQL_PORT>
Create a relative Endpoint object
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: <YOUR_MYSQL_ADDR>
ports:
- port: <YOUR_MYSQL_PORT>
Get service IP
$ kubectl get svc my-service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-service <SERVICE_IP> <none> 1443/TCP 18m
Access your MYSQL from service <SERVICE_IP>:1443 or my-service:1443
As of minikube 1.10, there is a special hostname host.minikube.internal that resolves to the host running the minikube VM or container. You can then configure this hostname in your pod's environment variables or the ConfigMap that defines the relevant settings.
Option 1 - use a headless service without selectors
Because this service has no selector, the corresponding Endpoints object will not be created. You can manually map the service to your own specific endpoints (See doc).
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
ports:
- port: 80
targetPort: 8080
---
kind: Endpoints
apiVersion: v1
metadata:
name: my-service
subsets:
- addresses:
- ip: 10.0.2.2
ports:
- port: 8080
Option 2 - use ExternalName service
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
type: ExternalName
externalName: minikube.host
The only caveat is that it needs to be able to resolve minikube.host. Simply add this line to the etc/hosts file should do it.
10.0.2.2 minikube.host
ExternalName doesn't support port mapping at the moment.
Another note: The IP 10.0.2.2 is known to work with Virtual Box only (see SO).
For xhyve, try replacing that with 192.168.99.1 (see GitHub issue and issue). A demo GitHub.
Just a reminder, if on Windows, open your firewall.