We have a Redis service running behind a Service with the ClusterIP
type.
This Redis must accessible by pods from the same namespace (a Gorush service).
The problem is that those pod can’t connect to the Redis service using its gorush-server-redis-svc:6379 name and reporting “Can’t connect redis server: connection refused“:
[simterm]
$ kk -n gorush-test logs gorush-server-55cd659dff-9wfbw time="2020/06/12 - 13:44:02" level=debug msg="Init App Status Engine as redis" 2020/06/12 13:44:03 Can't connect redis server: dial tcp 172.20.198.35:6379: connect: connection refused time="2020/06/12 - 13:44:03" level=error msg="storage error: dial tcp 172.20.198.35:6379: connect: connection refused"
[/simterm]
Although the service is present and must be working:
[simterm]
$ kk -n gorush-test get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE gorush-server-redis-svc ClusterIP 172.20.198.35 <none> 6379/TCP 102s
[/simterm]
Contents
The “no endpoints available for service” error
Okay, let’s try to debug the connection – at first, run a proxy from your local system to the Kubernetes API server as described in the Kubernetes: ClusterIP vs NodePort vs LoadBalancer, Services и Ingress — обзор, примеры:
[simterm]
$ kubectl proxy --port=8080 Starting to serve on 127.0.0.1:8080
[/simterm]
And try to connect to the Service with the curl
:
[simterm]
$ curl localhost:8080/api/v1/namespaces/gorush-test/services/gorush-server-redis-svc/proxy { "kind": "Status", "apiVersion": "v1", "metadata": { }, "status": "Failure", "message": "no endpoints available for service \"gorush-server-redis-svc\"", "reason": "ServiceUnavailable", "code": 503 }
[/simterm]
Although a pod with the Redis is running and is able to accept a connection – check with the port-forwadrd
.
Run it:
[simterm]
$ kk -n gorush-test port-forward gorush-server-redis-6566764cb7-9s8qk 6379:6379 Forwarding from 127.0.0.1:6379 -> 6379 Forwarding from [::1]:6379 -> 6379
[/simterm]
Check:
[simterm]
$ curl localhost:6379 curl: (1) Received HTTP/0.9 when not allowed
[/simterm]
Okay – Redis is really working, so what the issue with its Service?
And why it says “no endpoints”?
Check them:
[simterm]
$ kk -n gorush-test get endpoints NAME ENDPOINTS AGE gorush-server-redis-svc <none> 3m3s
[/simterm]
Indeed – <none>
.
Cause #1: labels mismatch
Now, check which labels arse set for the Service to chose pods – find its selector
:
[simterm]
$ kk -n gorush-test get svc gorush-server-redis-svc -o jsonpath={.spec.selector} map[applicaton:gorush-server-redis]
[/simterm]
Or check with it smanifest:
apiVersion: v1 kind: Service metadata: name: {{ .Chart.Name }}-redis-svc labels: application: {{ .Chart.Name }}-redis-svc spec: ports: - port: 6379 selector: applicaton: {{ .Chart.Name }}-redis
And now, check which labels are set to the pod itself:
[simterm]
$ kk -n gorush-test get deploy gorush-server-redis -o jsonpath={.spec.template.metadata.labels} map[application:gorush-server-redis]
[/simterm]
Its deployment manifest:
--- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: {{ .Chart.Name }}-redis spec: replicas: 1 template: metadata: labels: application: {{ .Chart.Name }}-redis spec: containers: - name: redis-master image: redis ports: - containerPort: 6379
And compare them:
- the Service’s selector:
map[
applicaton:gorush-server-redis]
- and pod’s lable:
map[
application:gorush-server-redis]
Here are the issue – applicaTOn и applicaTIOn.
So, the Service was created as its manifest have no syntax errors, but as it was looking for pods with a wrong label – it wasn’t able to find aa pods to acts as the Service’s backends and the Service wasn’t able to find where to send the traffic to, so it returned the 503 error.
Fix the typo, redeploy and check the Service:
[simterm]
$ curl -Lkk -n gorush-test describe svc gorush-server-redis-svc Name: gorush-server-redis-svc Namespace: gorush-test Labels: app.kubernetes.io/managed-by=Helm application=gorush-server-redis Annotations: meta.helm.sh/release-name: gorush-server meta.helm.sh/release-namespace: gorush-test Selector: application=gorush-server-redis Type: ClusterIP IP: 172.20.124.195 Port: <unset> 6379/TCP TargetPort: 6379/TCP Endpoints: 10.3.47.94:6379 ...
[/simterm]
Or:
[simterm]
$ kk -n gorush-test get endpoints NAME ENDPOINTS AGE gorush-server-redis-svc 10.3.47.94:6379 77m
[/simterm]
Endpoints: 10.3.47.94:6379
appeared – all done, fixed.
Cause #2: named port
The same error can appera when using named ports for a Service, for example:
apiVersion: v1 kind: Service metadata: name: gorush labels: app: gorush tier: frontend spec: selector: app: gorush tier: frontend type: LoadBalancer ports: - name: gorush protocol: TCP port: 80 targetPort: 8088
ports: – name: gorush
At this time an endpoint is created:
[simterm]
$ kubectl -n eks-dev-1-gorush get ep
NAME ENDPOINTS AGE
gorush 10.3.35.14:8088 44m
[/simterm]
But after performing an API-request it will fail with the same “message”: “no endpoints available for service \”gorush\””:
[simterm]
$ curl -sL localhost:8080/api/v1/namespaces/eks-dev-1-gorush/services/gorush/proxy/metrics | grep gorush | head
“message”: “no endpoints available for service \”gorush\””,
[/simterm]
In this case, the cause is in the port’s name, which needs to be added to the request via “:
” :
[simterm]
$ curl -sL localhost:8080/api/v1/namespaces/eks-dev-1-gorush/services/gorush:gorush/proxy/metrics | head
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile=”0″} 9.194e-06
go_gc_duration_seconds{quantile=”0.25″} 1.2092e-05
go_gc_duration_seconds{quantile=”0.5″} 2.1812e-05
go_gc_duration_seconds{quantile=”0.75″} 5.1794e-05
go_gc_duration_seconds{quantile=”1″} 0.000145631
go_gc_duration_seconds_sum 0.001080551
go_gc_duration_seconds_count 32
# HELP go_goroutines Number of goroutines that currently exist.
[/simterm]
services/gorush:gorush – here it is, and now it’s working.