无法正确连接到Kubernetes中的Redis

wri*_*mus 7 tcp redis node.js docker kubernetes

在我的macOS(不使用Minikube)上,我在这个例子之后模拟了我的Kubernetes集群,这意味着我已经按顺序执行了这个:

# Adding my own service to redix-proxy
kubectl create -f ./redis/redis-service.yaml

# Create a bootstrap master
kubectl create -f examples/storage/redis/redis-master.yaml

# Create a service to track the sentinels
kubectl create -f examples/storage/redis/redis-sentinel-service.yaml

# Create a replication controller for redis servers
kubectl create -f examples/storage/redis/redis-controller.yaml

# Create a replication controller for redis sentinels
kubectl create -f examples/storage/redis/redis-sentinel-controller.yaml

# Scale both replication controllers
kubectl scale rc redis --replicas=3
kubectl scale rc redis-sentinel --replicas=3

# Adding my own NodeJS web client server
kubectl create -f web-deployment.yaml
Run Code Online (Sandbox Code Playgroud)

唯一的区别在于redis-proxy.yaml我使用的是图像,image: kubernetes/redis-proxy而不是image: kubernetes/redis-proxy:v2因为我无法拉动后者.

这些是我传递给ioredis以创建我的Redis实例的对象(一个用于会话,一个用作主要实例):

config.js

main: {
  host: 'redis',
  port: 6379,
  db: 5
},
session: {
  host: 'redis',
  port: 6379,
  db: 6
}
Run Code Online (Sandbox Code Playgroud)

错误日志:

在我的Web客户端web-3448218364-sf1q0pod中,我在日志中重复了这个:

INFO: ctn/53 on web-3448218364-sf1q0: Connected to Redis event
WARN: ctn/53 on web-3448218364-sf1q0: Redis Connection Error:  { [Error: read ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
INFO: ctn/53 on web-3448218364-sf1q0: Connected to Redis event
WARN: ctn/53 on web-3448218364-sf1q0: Redis Connection Error:  { [Error: read ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
INFO: ctn/53 on web-3448218364-sf1q0: Connected to Redis event
WARN: ctn/53 on web-3448218364-sf1q0: Redis Connection Error:  { [Error: read ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
WARN: ctn/53 on web-3448218364-sf1q0: Redis Connection Error:  { [Error: connect ETIMEDOUT] errorno: 'ETIMEDOUT', code: 'ETIMEDOUT', syscall: 'connect' }
WARN: ctn/53 on web-3448218364-sf1q0: Redis Connection Error:  { [Error: connect ETIMEDOUT] errorno: 'ETIMEDOUT', code: 'ETIMEDOUT', syscall: 'connect' }
WARN: ctn/53 on web-3448218364-sf1q0: Redis Connection Error:  { [Error: connect ETIMEDOUT] errorno: 'ETIMEDOUT', code: 'ETIMEDOUT', syscall: 'connect' }
WARN: ctn/53 on web-3448218364-sf1q0: Redis Connection Error:  { [Error: connect ETIMEDOUT] errorno: 'ETIMEDOUT', code: 'ETIMEDOUT', syscall: 'connect' }
INFO: ctn/53 on web-3448218364-sf1q0: Connected to Redis event
WARN: ctn/53 on web-3448218364-sf1q0: Redis Connection Error:  { [Error: read ECONNRESET] code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }
INFO: ctn/53 on web-3448218364-sf1q0: Connected to Redis event
Run Code Online (Sandbox Code Playgroud)

在我的Redis redis-proxypod中,我在日志中重复了这个:

Error connecting to read: dial tcp :0: connection refused
Run Code Online (Sandbox Code Playgroud)

群集信息:

$ kubectl get svc
NAME                      CLUSTER-IP      EXTERNAL-IP      PORT(S)          AGE
kubernetes                10.91.240.1     <none>           443/TCP          2d
redis                     10.91.251.170   <none>           6379/TCP         31m
redis-sentinel            10.91.250.118   <none>           26379/TCP        31m
web                       10.91.240.16    <none>           80/TCP           31m

$ kubectl get po
NAME                        READY     STATUS    RESTARTS   AGE
redis-2frd0                 1/1       Running   0          34m
redis-master                2/2       Running   0          34m
redis-n4x6f                 1/1       Running   0          34m
redis-proxy                 1/1       Running   0          34m
redis-sentinel-k8tbl        1/1       Running   0          34m
redis-sentinel-kzd66        1/1       Running   0          34m
redis-sentinel-wlzsb        1/1       Running   0          34m
web-3448218364-sf1q0        1/1       Running   0          34m

$ kubectl get deploy
NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
web         1         1         1            1           39m
Run Code Online (Sandbox Code Playgroud)

问题1)现在,我需要将我的应用程序实际连接到Redis pod.我应该连接到redis-proxypod吗?所以,我创建了这个redis-service.yaml服务:

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
    - port: 6379
      targetPort: 6379
  selector:
    name: redis-proxy
    role: proxy
Run Code Online (Sandbox Code Playgroud)

我相信我已连接到redis端口6379,因为如果是这样,我通常会收到另一条错误消息.进入我的Web容器的bash shell中web-3448218364-sf1q0,我看到printenv的变量REDIS_SERVICE_PORT=6379REDIS_SERVICE_HOST=10.91.251.170.

问题2)从我的错误日志中,它是什么意思dial tcp :0:?从我在服务和内部端点列下的交互式Kubernetes控制台,我看到这个redis服务:

redis:6379 TCP
redis:0 TCP
Run Code Online (Sandbox Code Playgroud)

0 TCP与此有关吗?我的所有服务都在控制台中列出了0个TCP,但正如您所看到的,不是来自CLI中的kubectl get svc.

Ohm*_*men 6

检查kubernetes服务未按预期方式运行时,总是要做的第一件事就是检查相应服务的端点。就你而言kubeclt get ep redis

如果我的假设是正确的,那么应该向您显示这样的内容

NAME      ENDPOINTS   AGE
redis     <none>      42d
Run Code Online (Sandbox Code Playgroud)

这意味着您的服务不会选择/匹配任何吊舱。

在服务规格中,selector:此选择器必须具有与您实际部署的标签相匹配的密钥。您正在为所有带有标签name: redis-proxyrole: proxy可能与任何吊舱都不匹配的吊舱进行选择。

您可以运行kubectl get pod --show-labels=true以在吊舱上显示标签,并相应地更改服务。

我不知道端口0在这种情况下意味着什么。有时,它仅用于对服务进行DNS解析。


Cha*_*ink 0

从您上面发布的部署来看:

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: redis
    redis-sentinel: "true"
    role: master
  name: redis-master
spec:
  containers:
    - name: master
      image: k8s.gcr.io/redis:v1
      env:
        - name: MASTER
          value: "true"
      ports:
        - containerPort: 6379
      resources:
        limits:
          cpu: "0.1"
      volumeMounts:
        - mountPath: /redis-master-data
          name: data
    - name: sentinel
      image: kubernetes/redis:v1
      env:
        - name: SENTINEL
          value: "true"
      ports:
        - containerPort: 26379
  volumes:
    - name: data
      emptyDir: {}
Run Code Online (Sandbox Code Playgroud)

可以看到sentinel的容器端口是26379

因此在服务中(来自示例)

apiVersion: v1
kind: Service
metadata:
  labels:
    name: sentinel
    role: service
  name: redis-sentinel
spec:
  ports:
    - port: 26379
      targetPort: 26379
  selector:
    redis-sentinel: "true"
Run Code Online (Sandbox Code Playgroud)

它再次使用端口26379

来自 ioredis 文档(根据您的用例修改主机):

var redis = new Redis({
  sentinels: [{ host: 'redis-sentinel', port: 26379 }],
  name: 'mymaster'
});

redis.set('foo', 'bar');
Run Code Online (Sandbox Code Playgroud)

从技术上讲,哨兵并不是代理,ioredis 首先连接到哨兵以查找哪个节点是主节点,然后给出该节点的连接信息。

太长;博士;

将服务更改回示例中使用的服务,并用作redis-sentinel主机和26379端口。