I set up a simple redis ClusterIP service to be accessed by a php LoadBalancer service inside the Cluster. The php log shows the connection timeout error. The redis service is not accessible.
'production'.ERROR: Operation timed out {"exception":"[object] (RedisException(code: 0):
Operation timed out at /var/www/html/vendor/laravel/framework/src/Illuminate/Redis
/html/vendor/laravel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php(109):
Redis->connect('redis-svc', '6379', 0, '', 0, 0)
My redis service is quite simple so I don't know what went wrong:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
io.kompose.service: redis
name: redis
spec:
replicas: 1
strategy: {}
template:
metadata:
labels:
io.kompose.service: redis
spec:
containers:
- image: redis:alpine
name: redis
resources: {}
ports:
- containerPort: 6379
restartPolicy: Always
status: {}
---
kind: Service
apiVersion: v1
metadata:
name: redis-svc
spec:
selector:
app: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379
type: ClusterIP
I verify redis-svc is running, so why it can't be access by other service
kubectl get service redis-svc git:k8s*
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
redis-svc ClusterIP 10.101.164.225 <none> 6379/TCP 22m
This SO kubernetes cannot ping another service said ping doesn't work with service's cluster IP(indeed) how do I verify whether redis-svc can be accessed or not ?
---- update ----
My first question was a silly mistake but I still don't know how do I verify whether the service can be accessed or not (by its name). For example I changed the service name to be the same as the deployment name and I found php failed to access redis again.
kubectl get endpoints did not help now.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis
...
status: {}
---
kind: Service
apiVersion: v1
metadata:
name: redis
...
my php is another service with env set the redis's service name
spec:
containers:
- env:
- name: REDIS_HOST # the php code access this variable
value: redis-svc #changed to "redis" when redis service name changed to "redis"
----- update 2------
The reason I can' set my redis service name to "redis" is b/c "kubelet adds a set of environment variables for each active Service" so with the name "redis", there will be a REDIS_PORT=tcp://10.101.210.23:6379 which overwrite my own REDIS_PORT=6379
But my php just expect the value of REDIS_PORT to be 6379
I ran the yaml configuration given by you and it created the deployment and service. However when I run the below commands:
>>> kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d14h
redis-svc ClusterIP 10.105.31.201 <none> 6379/TCP 109s
>>>> kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.99.116:8443 5d14h
redis-svc <none> 78s
As you see, the endpoints for redis-svc is none, it means that the service doesn't have an endpoint to connect to. You are using selector labels as app: redis in the redis-svc. But the pods doesn't have the selector label defined in the service. Adding the label app: redis to the pod template will work. The complete working yaml configuration of deployment will look like:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
io.kompose.service: redis
name: redis
spec:
replicas: 1
strategy: {}
template:
metadata:
labels:
io.kompose.service: redis
app: redis
spec:
containers:
- image: redis:alpine
name: redis
resources: {}
ports:
- containerPort: 6379
restartPolicy: Always
status: {}
Related
I have this docker-compose.yml and Docker for Desktop Windows with a local kubernetes cluster (the default docker-desktop context) running:
version: '3'
services:
web:
image: customnode
ports:
- "3000:3000"
labels:
kompose.service.type: nodeport
datastore:
image: custommongo
ports:
- "27017:27017"
docker-compose up -d works perfectly and exposes my NodeJS on port 3000 on 127.0.0.1.
I'm trying to migrate that the my k8s cluster, so following https://kompose.io/getting-started/
Page above says "If you don’t already have a Kubernetes cluster running, minikube is the best way to get started"... I am already running the OOTB Docker for Desktop cluster so I assume I don't need minikube.
kompose convert
INFO Kubernetes file "datastore-service.yaml" created
INFO Kubernetes file "web-service.yaml" created
INFO Kubernetes file "datastore-deployment.yaml" created
INFO Kubernetes file "web-deployment.yaml" created
Here are the web-deployment and web-service YAMLS:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.service.type: nodeport
kompose.version: 1.16.0 (0c01309)
creationTimestamp: null
labels:
io.kompose.service: web
name: web
spec:
replicas: 1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
io.kompose.service: web
spec:
containers:
image: customnode
name: web
ports:
- containerPort: 3000
resources: {}
restartPolicy: Always
status: {}
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.service.type: nodeport
kompose.version: 1.16.0 (0c01309)
creationTimestamp: null
labels:
io.kompose.service: web
name: web
spec:
ports:
- name: "3000"
port: 3000
targetPort: 3000
selector:
io.kompose.service: web
type: NodePort
status:
loadBalancer: {}
Finally, running kompose up:
kompose up
[36mINFO[0m We are going to create Kubernetes Deployments, Services and PersistentVolumeClaims for your Dockerized application. If you need different kind of resources, use the 'kompose convert' and 'kubectl create -f' commands instead.
INFO Deploying application in "default" namespace
INFO Successfully created Service: datastore
INFO Successfully created Service: web
INFO Successfully created Deployment: datastore
INFO Successfully created Deployment: web
Output of kubectl get svc:
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
datastore ClusterIP 10.103.***.*** <none> 27017/TCP 76s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23m
web NodePort 10.106.***.*** <none> 3000:32033/TCP 76s
As you can see, no external IP as I'd expect. I'm sure this is a lack of knowledge on my part, rather than a bug, so what am I missing?
Extenal IP is assigned only for LoadBalancer type service. A LoadBalancer controller must be installed on the cluster for LoadBalancer service to work. Else LoadBalancer service behaves exactly as a NodePort service. Most cloud providers have support for LoadBalancer services.
For NodePort type services, the service binds to a random port in node port range on all the nodes. In your case you can see, the service is bound to port 32033 - 3000:32033/TCP.
The Node Port range is configured for as an argument to Kubernetes API server with the option --service-node-port-range (by default 30000-32767). When you create a NodePort type service, a random free port is picked from this range. If you want to choose a custom port, you can specify nodePort attribute in the Port object.
Eg:
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose convert
kompose.service.type: nodeport
kompose.version: 1.16.0 (0c01309)
creationTimestamp: null
labels:
io.kompose.service: web
name: web
spec:
ports:
- name: "3000"
port: 3000
targetPort: 3000
nodePort: 30002 ###### You can choose node port here if needed
selector:
io.kompose.service: web
type: NodePort ####### Change this line to LoadBalancer if you want an external IP
status:
loadBalancer: {}
l tried to set up a dvwa environment in k8s, l found it not work as usual when l exposed the dvwa pods's port.
l tried exposing a nginx sample to make sure my k8s env is working. And yes nginx works well in my local machine
Here is some information
# dvwa.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: dvwa
spec:
replicas: 2
selector:
app: dvwa
template:
metadata:
labels:
app: dvwa
spec:
containers:
- name: dvwa
image: citizenstig/dvwa:latest
ports:
- containerPort: 3306
# dvwa_service.yaml
apiVersion: v1
kind: Service
metadata:
name: dvwa
spec:
ports:
- port: 3306
selector:
app: dvwa
type: NodePort
$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
AGE SELECTOR
dvwa NodePort 10.98.238.130 <none>
3306:32393/TCP 7m15s app=dvwa
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP
35h <none>
nginx NodePort 10.97.143.32 <none>
80:31961/TCP 5m51s app=nginx
When l ssh into one of my k8s machine and typed curl 10.97.143.32:80, it returns the nginx page, but curl 10.98.238.130:3306 not works, the docker image is citizenstig/dvwa which expose 80 and 3306, l also tried using 80 port in dvwa_service.yaml but still not work.
Can anyone help me??? Thanks in advance!
targetPort is missing in your service definition
Try below service definition
apiVersion: v1
kind: Service
metadata:
name: dvwa
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: dvwa
type: NodePort
can you get into the dvwa pod and run localhost:3306
do you get any response?
I have a problem with accessible my service from outside.
First of all, here is my conf yaml files:
nginx-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
namespace: development
spec:
selector:
matchLabels:
app: my-nginx
replicas: 2
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:1.7.9
ports:
- containerPort: 80
nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: development
spec:
type: LoadBalancer
selector:
app: my-nginx
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
metallb-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 51.15.41.227-51.15.41.227
Then i have created the cluster. Command kubectl get all -o wide prints:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
pod/my-nginx-5796dcf6c4-rxl6k 1/1 Running 1 20h 10.244.0.16 scw-7d6c86
pod/my-nginx-5796dcf6c4-zf7vd 1/1 Running 0 20h 10.244.1.4 scw-7a7908
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/nginx-service LoadBalancer 10.100.63.177 51.15.41.227 80:30883/TCP 54m app=my-nginx
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/my-nginx 2 2 2 2 20h my-nginx nginx:1.7.9 app=my-nginx
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/my-nginx-5796dcf6c4 2 2 2 20h my-nginx nginx:1.7.9 app=my-nginx,pod-template-hash=5796dcf6c4
Everythink is fine, also kubectl describe service/nginx-service prints:
Name: nginx-service
Namespace: development
Labels:
Annotations:
Selector: app=my-nginx
Type: LoadBalancer
IP: 10.100.63.177
LoadBalancer Ingress: 51.15.41.227
Port: http 80/TCP
TargetPort: 80/TCP
NodePort: http 30883/TCP
Endpoints: 10.244.0.16:80,10.244.1.4:80
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal IPAllocated 56m metallb-controller Assigned IP "51.15.41.227"
Curl command inside master server curl 51.15.41.227 prints Welcome to nginx blablabla. Next i tried to open from another network, it doesn't work, however i added node port it works curl 51.15.41.227:30883. All this i did on a bare-metal. I expected to happen curl 51.15.41.227 from external host should reach result.
What did i do wrong?
Definitely it will work with http://51.15.41.227 or 51.15.41.227:80. You can upvote answer by pressing up button.
You should definitely use the node port 30883(randomly assigned port) while accessing from External Network. Otherwise it don't know where to route the request.
curl http://51.15.41.227:30883
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
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