Date: 2026-01-17
Issue: Chronicle backend fails to download packages with uv - "dns error: failed to lookup address information"
✅ FIXED - Applied dnsPolicy: Default to all Kubernetes service deployments
- Problem: CoreDNS was blocking IPv6 AAAA DNS queries
- Impact: Applications couldn't resolve IPv6 addresses
- Fix: Removed AAAA blocking template from CoreDNS ConfigMap
- Result: DNS now returns both IPv4 and IPv6 addresses
- Problem: uv 0.6.10 (Rust-based) breaks with Kubernetes
ndots:5+ search domains - Impact: Even though DNS works, Rust resolver fails with "Name has no usable address"
- Fix: Added
dnsPolicy: Defaultto pod spec inkubernetes_manager.py - Result: uv now uses node DNS instead of K8s cluster DNS
| Component | DNS Library | K8s DNS (ndots:5) | Node DNS |
|---|---|---|---|
| Python (glibc) | getaddrinfo() | ✅ Works | ✅ Works |
| curl | c-ares | ✅ Works | ✅ Works |
| uv 0.6.10 (Rust) | Rust resolver | ❌ Broken | ✅ Works |
| uv 0.9.26 (Rust) | Rust resolver | ✅ Works | ✅ Works |
Key Finding: The issue was specific to how Rust's DNS resolver in uv 0.6.10 handles DNS search domain expansion in dual-stack environments.
File: kube-system/configmap/coredns
Before:
template IN AAAA . {
rcode NOERROR
}After: (removed AAAA blocking)
# No AAAA template - returns IPv6 records normallyFile: ushadow/backend/src/services/kubernetes_manager.py
Added at line 628:
"dnsPolicy": "Default", # Use node DNS, not cluster DNSImpact: All services deployed via ushadow backend will use simplified DNS
Created comprehensive documentation:
FIX_UV_DNS.md- Technical details and workaroundsCHRONICLE_IPV6_RESOLUTION.md- Chronicle-specific resolutiondocs/IPV6_DUALSTACK_CONFIGURATION.md- Updated with resolution- This file - Complete summary
# DNS returns both A and AAAA records
kubectl run test --image=busybox --rm -it -- nslookup pypi.org
# ✅ Shows both IPv4 and IPv6 addresses# Using Chronicle's base image
kubectl run test --image=python:3.12-slim-bookworm --rm -it -- \
python3 -c "import socket; print(len(socket.getaddrinfo('pypi.org', 443)))"
# ✅ Returns 24 addresses (IPv4 + IPv6)# Using Chronicle backend image with default K8s DNS
kubectl run test --image=ghcr.io/ushadow-io/chronicle/backend:nodeps1 --rm -it -- \
uv pip install setuptools
# ❌ dns error: failed to lookup address information# Using Chronicle backend image with dnsPolicy: Default
kubectl run test --image=ghcr.io/ushadow-io/chronicle/backend:nodeps1 \
--overrides='{"spec":{"dnsPolicy":"Default"}}' --rm -it -- \
uv pip install setuptools httpx
# ✅ Successfully downloaded both packages- ✅ Chronicle backend will deploy successfully
- ✅ All uv-based applications will work
- ✅ Simpler DNS configuration (no search domains)
- ✅ Slightly faster DNS resolution (fewer lookups)
⚠️ Can't use short Kubernetes service names (e.g.,http://redis)⚠️ Must use full DNS names for K8s services (e.g.,redis.default.svc.cluster.local)⚠️ Uses node DNS servers (typically 8.8.8.8, 192.168.1.1) instead of CoreDNS
If a service needs to talk to other K8s services, use full DNS names:
# Instead of:
REDIS_URL = "redis://redis:6379"
# Use:
REDIS_URL = "redis://redis.default.svc.cluster.local:6379"Or use IP addresses:
# Get service ClusterIP
kubectl get svc redis -o jsonpath='{.spec.clusterIP}'
# Use that IP in environment variable- Pro: uv 0.9.26 handles K8s DNS correctly
- Con: Requires rebuilding Chronicle image
- Con: Untested with Chronicle's dependencies
- Pro: Can still use cluster DNS with reduced ndots
- Con: More complex configuration
- Con: Still might have issues with Rust resolver
- Pro: Simple, proven to work
- Pro: No image changes needed
- Pro: Applies automatically to all future deployments
- Con: Requires full DNS names for K8s services
No action needed - the fix is automatic when deploying via ushadow backend.
Restart the deployment to pick up new DNS policy:
# Find Chronicle deployment
kubectl get deploy -A | grep chronicle
# Restart it
kubectl rollout restart deployment/chronicle-backend -n <namespace># Check DNS policy in running pod
kubectl get pod <chronicle-pod> -o yaml | grep dnsPolicy
# Should show: dnsPolicy: Default
# Check resolv.conf
kubectl exec <chronicle-pod> -- cat /etc/resolv.conf
# Should show simple nameserver config, no search domains
# Test uv
kubectl exec <chronicle-pod> -- uv pip list
# Should work without errors- Initial Issue: Chronicle crashes with "dns error" from uv
- First Investigation: Thought it was Calico IPv6 NAT bug
- CoreDNS Fix: Removed AAAA blocking (helped Python, not uv)
- Deep Dive: Discovered uv 0.6.10 + Kubernetes ndots incompatibility
- Solution: Applied dnsPolicy: Default
- Verification: Tested with actual Chronicle backend image ✅
- FIX_UV_DNS.md - Detailed technical fix
- docs/IPV6_DUALSTACK_CONFIGURATION.md - IPv6 setup
- Calico Issue #7638 - Similar symptoms (different cause)
- Rust DNS Resolver - Library used by uv
🟢 RESOLVED - Chronicle backend will now deploy successfully with uv package downloads working.
- Deploy Chronicle to verify fix works in production
- Monitor for any issues with K8s service discovery
- Update any hardcoded service URLs to use full DNS names if needed
- Consider upgrading to uv 0.9+ in future Chronicle image updates