使用redis.asyncio连接Redis集群时出现超时问题求助
Root Cause
When using kubectl port-forward to connect to your K8s-hosted Redis cluster, the async RedisCluster client fetches the cluster's node list from the initial forwarded node. These nodes are advertised using their internal K8s IP addresses or service names, which are not accessible from your local machine. Unlike redis-cli (which may fall back to the initial connection for basic operations), the async client attempts direct connections to each cluster node for shard-specific tasks, resulting in network timeouts.
Solutions
1. Configure Cluster to Advertise Reachable External Addresses
For Bitnami's redis-cluster chart, enable external access via LoadBalancer services to expose each node with a publicly reachable address:
- Update your
values.yaml:cluster: externalAccess: enabled: true service: type: LoadBalancer - Upgrade the release:
helm upgrade redis-cluster bitnami/redis-cluster -f values.yaml - Retrieve the external IPs and ports of each node:
kubectl get services -l app.kubernetes.io/name=redis-cluster - Update your client code to use one of these external addresses instead of
localhost:6379.
2. Forward All Cluster Nodes Locally
Forward each cluster node's port to a unique local port:
kubectl port-forward redis-cluster-0 6379:6379 & kubectl port-forward redis-cluster-1 6380:6379 & kubectl port-forward redis-cluster-2 6381:6379 & kubectl port-forward redis-cluster-3 6382:6379 & kubectl port-forward redis-cluster-4 6383:6379 & kubectl port-forward redis-cluster-5 6384:6379 &
Then, reconfigure your Redis cluster to advertise localhost with the forwarded ports (note: this is for local testing only, avoid in production):
redis-cli --cluster reconfigure localhost:6379 --cluster-yes --cluster-replicas 1 \ localhost:6379 localhost:6380 localhost:6381 \ localhost:6382 localhost:6383 localhost:6384
3. Workaround: Skip Full Cluster Coverage Check (Testing Only)
If you just need to validate basic functionality locally, modify your client to skip node reachability checks and increase timeouts:
import asyncio from redis.asyncio.cluster import RedisCluster async def test_redis_connection(): try: redis = RedisCluster.from_url( 'redis://localhost:6379', encoding='utf-8', decode_responses=True, skip_full_coverage_check=True, socket_timeout=10, socket_connect_timeout=10, retry_on_timeout=True ) await redis.set('key1', 'bar') value = await redis.get('key1') print(f"Connection successful, value: {value}") await redis.close() except Exception as e: print(f"Connection failed: {e}") asyncio.run(test_redis_connection())
This bypasses full cluster validation but doesn't leverage proper sharding, so it's not suitable for production.
4. Use a Local DNS Proxy for K8s Services
Tools like kubefwd map K8s internal service names to your local machine, allowing the async client to resolve and connect to cluster nodes using their internal addresses:
- Install
kubefwd:brew install kubefwd # macOS # Or download from official releases - Forward all services in your namespace:
kubefwd svc -n your-namespace - Your client can now connect using the cluster's internal service names (e.g.,
redis-cluster-0.redis-cluster-headless.default.svc.cluster.local).
Additional Checks
- Ensure your
redis-pyversion is compatible with your Redis cluster version (e.g., Redis 7.x requires redis-py 4.3.0+). - Verify that no local firewall rules are blocking connections to the forwarded ports.
内容的提问来源于stack exchange,提问作者Simone Di Cola

