GKE中多微服务能否共享单个Redis服务?问题排查求助
看起来你遇到的问题是K8s集群中跨微服务访问Redis时,写入的数据无法被读取,但同服务内读写正常。我们一步步来排查和解决:
首先,确认写入操作是否真的成功
你在compute-service中的Set代码没有检查错误,有可能写入操作根本没成功。先修改代码加入错误校验:
rClient := redis.NewClient(&redis.Options{ Addr: "redis-service:6379", Password: "", // no password set DB: 0, // use default DB }) err := rClient.Set("trump", "value", 0).Err() if err != nil { log.Printf("Failed to set key: %v", err) // 这里可以加入错误处理逻辑 }
如果运行后出现错误,那问题出在写入环节,我们再针对性排查。
检查K8s资源的核心配置问题
1. Namespace是否一致
K8s的Service是命名空间级别的,如果你的redis-service、compute-service、web-service不在同一个Namespace下,redis-service:6379这个地址是无法解析的。
你可以用以下命令查看所有资源的Namespace:
kubectl get pods,services -A
如果确实分属不同Namespace,需要把Addr修改为:
Addr: "redis-service.<redis-namespace>.svc.cluster.local:6379",
替换<redis-namespace>为Redis所在的命名空间名称。
2. Redis容器的绑定模式问题
默认的Redis镜像(包括你用的k8s.gcr.io/redis:e2e)开启了保护模式(protected-mode yes),并且默认绑定127.0.0.1。这会导致只有容器内部的请求能访问Redis,其他Pod的请求会被拒绝。
解决方法是修改Redis Deployment的配置,让Redis绑定所有地址或者关闭保护模式:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: redis-service spec: selector: matchLabels: app: redis-service role: master tier: backend replicas: 1 template: metadata: labels: app: redis-service role: master tier: backend spec: containers: - name: redis-service image: k8s.gcr.io/redis:e2e # 添加启动命令,关闭保护模式或绑定0.0.0.0 command: ["redis-server", "--protected-mode", "no"] # 或者用这个命令绑定所有地址:command: ["redis-server", "--bind", "0.0.0.0"] resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 6379
修改后重新部署Redis:
kubectl apply -f your-redis-deployment.yaml
验证Redis实例中的数据
在修改配置后,我们可以直接进入Redis Pod查看数据是否真的被写入:
- 找到Redis Pod的名称:
kubectl get pods -l app=redis-service
- 进入Pod并执行redis-cli:
kubectl exec -it <redis-pod-name> -- redis-cli
- 执行
GET trump,如果能返回"value",说明写入成功,问题出在web-service的读取环节;如果返回(nil),说明写入环节有问题,回到第一步检查错误。
最后检查web-service的读取逻辑
确保web-service中的Redis客户端配置和compute-service完全一致,比如Addr、Password、DB都没有拼写错误。另外,推荐在读取时也加入更详细的错误判断:
val, err := rClient.Get("trump").Result() if err != nil { if errors.Is(err, redis.Nil) { log.Println("Key does not exist") } else { log.Printf("Failed to get key: %v", err) } } else { log.Printf("Got value: %s", val) } fmt.Fprintf(w, "Print Error: %v \n", err) fmt.Fprintf(w, "Print Value: %s \n", val)
内容的提问来源于stack exchange,提问作者MATT SHALLOW

