在EC2上的K8s集群中解决Flask应用连接Redis失败问题
Flask应用无法连接K8s集群Redis服务的排查与解决
环境与现状
- EC2上搭建的K8s集群已成功部署PHP+Redis留言板示例
- 现有Flask应用Docker镜像,尝试连接集群内Redis服务,但无法获取Redis值,推测连接失败
- 当前运行的Redis服务信息:
redis-follower ClusterIP 10.102.44.232 <none> 6379/TCP 16d redis-leader ClusterIP 10.108.164.219 <none> 6379/TCP 16d
相关配置与代码
Flask应用核心代码(main.py)
from flask import Flask from flask import render_template import os from redis import Redis, RedisError import socket app = Flask(__name__) @app.route("/") def sample_run_report(): redis_conn = Redis(host='redis-leader.default.svc.cluster.local', port=6379, db=0) redis_conn.set("key", "foo") val = redis_conn.get("key") return val if __name__ == "__main__": app.run(host='0.0.0.0')
Redis Leader部署配置
# SOURCE: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook apiVersion: apps/v1 kind: Deployment metadata: name: redis-leader labels: app: redis role: leader tier: backend spec: replicas: 1 selector: matchLabels: app: redis template: metadata: labels: app: redis role: leader tier: backend spec: containers: - name: leader image: "docker.io/redis:6.0.5" resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 6379
Flask应用Service与Deployment配置
apiVersion: v1 kind: Service metadata: name: redis-flask-python1-service spec: selector: app: redis-flask-python1 ports: - protocol: "TCP" port: 6000 targetPort: 5000 type: LoadBalancer --- apiVersion: apps/v1 kind: Deployment metadata: name: redis-flask-python1 spec: selector: matchLabels: app: redis-flask-python1 replicas: 1 template: metadata: labels: app: redis-flask-python1 spec: containers: - name: redis-flask-python1 image: docker.io/dechenw/redis-flask-python1 imagePullPolicy: IfNotPresent ports: - containerPort: 5000 imagePullSecrets: - name: regcred
排查与解决步骤
1. 验证Redis服务的网络连通性
先确认Flask应用Pod与Redis服务的连通性:
# 进入Flask应用Pod kubectl exec -it <你的Flask Pod名称> -- /bin/bash # 安装telnet(若Pod内无此工具) apt-get update && apt-get install telnet -y # 测试Redis地址与端口连通性 telnet redis-leader.default.svc.cluster.local 6379 # 若有redis-cli,直接测试连接 redis-cli -h redis-leader.default.svc.cluster.local ping
如果无法连通,检查命名空间是否匹配:若Flask应用与Redis在同一命名空间,可简化地址为redis-leader;若不在,需确认命名空间后缀是否正确。
2. 检查Redis服务的Endpoints关联状态
执行命令查看Redis Leader服务是否正确关联到Pod:
kubectl get endpoints redis-leader
如果返回的Endpoints为空,说明Redis Service的标签选择器与Deployment的Pod标签不匹配。留言板示例中Redis Service的选择器通常是app: redis, role: leader,需确认配置一致。
3. 完善代码的错误捕获逻辑
当前代码没有异常处理,无法明确报错原因,修改代码添加捕获:
@app.route("/") def sample_run_report(): try: # 添加超时时间,避免无限等待 redis_conn = Redis(host='redis-leader.default.svc.cluster.local', port=6379, db=0, socket_timeout=5) # 先执行ping测试连接 redis_conn.ping() redis_conn.set("key", "foo") val = redis_conn.get("key") return f"获取到值: {val.decode('utf-8')}" except RedisError as e: return f"Redis连接错误: {str(e)}" except Exception as e: return f"其他错误: {str(e)}"
重新构建镜像部署后,访问Flask服务即可看到具体错误信息。
4. 检查Redis Pod的运行状态
确认Redis Leader Pod是否正常启动:
# 查看Pod状态 kubectl get pods -l app=redis,role=leader # 查看Pod日志,排查Redis启动异常 kubectl logs <你的Redis Leader Pod名称>
确保日志中无启动报错,Redis服务正常运行。
5. 排查集群网络策略限制
若集群内配置了NetworkPolicy,需确认是否允许Flask应用所在Pod访问Redis的6379端口。未配置NetworkPolicy时,K8s默认允许所有Pod间通信。
内容的提问来源于stack exchange,提问作者dechen
相关产品推荐
相关产品推荐

