在Kubernetes中无法正确连接Redis

7

在我的 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

唯一的区别在于 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
}

错误日志:

在我的Web客户端web-3448218364-sf1q0 pod中,日志中不断出现以下内容:

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

在我的 Redis redis-proxy pod 中,日志文件中反复出现以下信息:
Error connecting to read: dial tcp :0: connection refused

集群信息:

$ 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

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

apiVersion: v1
kind: Service
metadata:
  name: redis
spec:
  ports:
    - port: 6379
      targetPort: 6379
  selector:
    name: redis-proxy
    role: proxy

我相信我已经连接到端口为6379的redis,因为如果没有连接成功,我通常会得到另一个错误消息。进入我的Web容器 web-3448218364-sf1q0 的bash shell后,我看到printenv 变量是 REDIS_SERVICE_PORT=6379REDIS_SERVICE_HOST=10.91.251.170问题2:从我的错误日志中,dial tcp :0: 是什么意思?从我的交互式 Kubernetes 控制台中的服务和内部端点列中,我看到redis 服务如下:
redis:6379 TCP
redis:0 TCP

这个 0 TCP 和那个相关吗?我所有的服务在控制台中都列出了 0 TCP,但是如您所见,kubectl get svc 命令行中却没有。


1
请将您的 Redis 服务器连接到 Redis 主服务器,然后重试。关于 0 tcp,在您的 printenv 中是否看到了这个? - Farhad Farahi
2个回答

10

当Kubernetes服务表现不如预期时,始终首先要检查相应服务的端点。 在您的情况下,kubectl get ep redis

如果我的假设是正确的,它应该向您展示类似于以下内容:

NAME      ENDPOINTS   AGE
redis     <none>      42d
这意味着您的服务未选择/匹配任何Pod。 在您的服务规范中,有一个关键字selector:,这个选择器必须与您实际部署的标签匹配。 您正在选择所有具有标签name: redis-proxyrole: proxy的Pod,这些Pod可能不匹配任何Pod。 您可以运行kubectl get pod --show-labels=true以显示Pod上的标签并相应地更改您的服务。 我不知道此上下文中端口0表示什么。 有时它用于仅使用服务进行DNS解析。

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: {}

您可以看到 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"

它再次使用端口26379

来自ioredis文档(主机已针对您的用例进行修改):

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

redis.set('foo', 'bar');

哨兵技术上并不是代理,ioredis首先连接到哨兵以查找主节点,然后获取该节点的连接信息。

简而言之:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接