Skip to content

feat: Add Kubernetes support for Redis Enterprise client #579

@joshrotenberg

Description

@joshrotenberg

Summary

Redis Enterprise deployments on Kubernetes have different connectivity and authentication patterns than traditional on-premise deployments. This issue tracks the work needed to properly support K8s-based Redis Enterprise clusters.

Background

The current EnterpriseClient assumes:

  • Direct HTTPS access to a known URL (default: https://localhost:9443)
  • HTTP Basic Auth with username/password
  • Either full TLS certificate validation OR completely insecure mode (no middle ground)

In Kubernetes environments, Redis Enterprise clusters typically:

  • Run as pods behind Kubernetes Services
  • Store credentials in Kubernetes Secrets
  • Use self-signed certificates with a cluster-specific CA
  • May require mTLS for stricter security

Proposed Features

Phase 1: Custom CA Certificate Support (High Priority)

The most impactful change for K8s users. Allow specifying a custom CA certificate to validate the cluster's self-signed certs without disabling TLS verification entirely.

API Design:

EnterpriseClient::builder()
    .base_url("https://rec-api.redis.svc:9443")
    .username("admin")
    .password("secret")
    .ca_cert("/path/to/cluster-ca.crt")      // From file path
    // OR
    .ca_cert_pem(ca_cert_bytes)              // From PEM bytes
    .build()

Environment variable: REDIS_ENTERPRISE_CA_CERT

Implementation notes:

  • Use reqwest::Certificate::from_pem() to load the CA
  • Add certificate to client builder via .add_root_certificate()
  • Support both file path and raw PEM bytes for flexibility

Phase 2: Kubernetes Secret Integration (Medium Priority)

Optional feature (behind kubernetes feature flag) to read credentials and certificates directly from K8s Secrets.

API Design:

// Read credentials from K8s Secret
let client = EnterpriseClient::from_k8s_secret(
    "rec",           // secret name
    "redis",         // namespace
).await?;

// Or with more control
let client = EnterpriseClient::builder()
    .base_url("https://rec-api.redis.svc:9443")
    .credentials_from_secret("rec", "redis")
    .ca_cert_from_secret("rec", "redis", "proxy_cert")
    .build()
    .await?;

Implementation notes:

  • Use the kube crate for K8s API access
  • Feature-gated to avoid adding dependencies for non-K8s users
  • Support both in-cluster config and kubeconfig file

Phase 3: Service Discovery (Lower Priority)

Auto-discover Redis Enterprise Cluster API endpoint in a namespace.

let client = EnterpriseClient::discover_in_namespace("redis").await?;

Implementation notes:

  • Look for Services with appropriate labels
  • Find the REC API service (typically named <rec-name>-api or similar)
  • Combine with secret reading for full auto-configuration

Phase 4: mTLS / Client Certificates (Lower Priority)

Support client certificate authentication for stricter security requirements.

EnterpriseClient::builder()
    .base_url("https://rec-api.redis.svc:9443")
    .client_cert("/path/to/client.crt", "/path/to/client.key")
    .ca_cert("/path/to/ca.crt")
    .build()

Typical K8s Workflow Today (Manual)

For reference, here's what users currently have to do:

# Extract credentials from K8s Secret
USERNAME=$(kubectl get secret rec -n redis -o jsonpath='{ .data.username}' | base64 -d)
PASSWORD=$(kubectl get secret rec -n redis -o jsonpath='{.data.password}' | base64 -d)

# Extract CA certificate
kubectl get secret rec -n redis -o jsonpath='{.data.proxy_cert}' | base64 -d > /tmp/ca.crt

# Port-forward to access cluster (if not in-cluster)
kubectl port-forward svc/rec 9443:9443 -n redis &

# Set environment variables
export REDIS_ENTERPRISE_URL=https://localhost:9443
export REDIS_ENTERPRISE_USER=$USERNAME
export REDIS_ENTERPRISE_PASSWORD=$PASSWORD
export REDIS_ENTERPRISE_INSECURE=true  # Unfortunately required today

# Now use redisctl
redisctl enterprise cluster get

With Phase 1, users could at least use the CA cert instead of insecure mode:

export REDIS_ENTERPRISE_CA_CERT=/tmp/ca.crt
export REDIS_ENTERPRISE_INSECURE=false  # Proper TLS validation!

Tasks

Phase 1 Tasks

  • Add ca_cert and ca_cert_pem methods to EnterpriseClientBuilder
  • Support REDIS_ENTERPRISE_CA_CERT environment variable in from_env()
  • Update from_env() to load CA cert when env var is set
  • Add integration tests with self-signed certificates
  • Update documentation and README
  • Add to Python bindings (ca_cert parameter)

Phase 2 Tasks

  • Add kubernetes feature flag to Cargo.toml
  • Add kube crate as optional dependency
  • Implement credentials_from_secret() helper
  • Implement ca_cert_from_secret() helper
  • Implement from_k8s_secret() convenience constructor
  • Add tests with mocked K8s API
  • Document K8s integration

Phase 3 Tasks

  • Implement service discovery logic
  • Handle multiple REC deployments in same namespace
  • Add discover_in_namespace() method

Phase 4 Tasks

  • Add client_cert method to builder
  • Support PEM and file path for client certs
  • Test with mTLS-enabled clusters

Related

Labels

enhancement, kubernetes, enterprise

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions