Setup Redis

How to deploy Redis for Mailu session storage and caching.

Problem

Mailu requires Redis for session storage and caching. You need to deploy Redis before deploying Mailu.

Solution

Deploy Redis using the Bitnami Helm chart. For most Mailu deployments, a simple single-instance Redis is sufficient since sessions can be regenerated if Redis fails.

Prerequisites

  • Helm 3 installed

  • Kubernetes cluster

  • Persistent storage (optional for session data)

Step 1: Add Bitnami Helm Repository

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

Step 2: Choose Deployment Mode

Option B: Master-Replica (High Availability)

Master with read replicas. Use when:

  • High availability is critical

  • Large deployments (500+ users)

  • Zero downtime required

Option C: Sentinel (Automatic Failover)

Redis with Sentinel for automatic failover. Use when:

  • Production critical workload

  • Automatic failover required

  • Multiple replicas with coordinator



Deploy Master-Replica Redis (High Availability)

Create Values File

Create redis-ha-values.yaml:

# Redis Master-Replica configuration
architecture: replication

auth:
  enabled: false  # Or true for authentication

replica:
  replicaCount: 2  # Number of read replicas

master:
  persistence:
    enabled: true
    size: 5Gi
    storageClass: longhorn

  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

replica:
  persistence:
    enabled: true
    size: 5Gi
    storageClass: longhorn

  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

metrics:
  enabled: true

Install Redis HA

helm install redis bitnami/redis \
  --namespace redis \
  --values redis-ha-values.yaml

# Wait for all pods
kubectl wait --for=condition=ready pod -n redis -l app.kubernetes.io/name=redis --timeout=300s

Verify Replication

# Check master
kubectl exec -n redis redis-master-0 -- redis-cli info replication

# Should show:
# role:master
# connected_slaves:2

# Check replica
kubectl exec -n redis redis-replicas-0 -- redis-cli info replication

# Should show:
# role:slave
# master_host:redis-master-0

Configure Mailu with HA Redis

Use the master service for writes:

redis: {
  host: 'redis-master.redis.svc.cluster.local',  // Write to master
  port: 6379,
}

Note: Mailu connects to master for both reads and writes. Read replicas are used automatically by the Redis client for load balancing.


Deploy Redis Sentinel (Automatic Failover)

Create Values File

Create redis-sentinel-values.yaml:

# Redis Sentinel configuration
sentinel:
  enabled: true
  replicas: 3  # Sentinel instances (odd number recommended)

  resources:
    requests:
      cpu: 50m
      memory: 64Mi
    limits:
      cpu: 200m
      memory: 128Mi

master:
  persistence:
    enabled: true
    size: 5Gi

  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

replica:
  replicaCount: 2
  persistence:
    enabled: true
    size: 5Gi

  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

auth:
  enabled: false  # Or true
  sentinel: false  # Sentinel auth (usually false for internal cluster)

metrics:
  enabled: true

Install Redis Sentinel

helm install redis bitnami/redis \
  --namespace redis \
  --values redis-sentinel-values.yaml

kubectl wait --for=condition=ready pod -n redis -l app.kubernetes.io/name=redis --timeout=600s

Verify Sentinel

# Check Sentinel status
kubectl exec -n redis redis-node-0 -- \
  redis-cli -p 26379 sentinel master mymaster

# Should show master details and number of slaves and sentinels

Configure Mailu with Sentinel

redis: {
  host: 'redis.redis.svc.cluster.local',  // Sentinel service
  port: 6379,  // Redis port (Sentinel handles failover)
  // Sentinel configuration in Mailu is automatic with standard Bitnami setup
}

Persistence Considerations

With Persistence (Default)

Pros:

  • Session data survives pod restarts

  • Cached data persists

  • Better for production

Cons:

  • Requires PVC storage

  • Slower restarts (load data from disk)

Without Persistence

Pros:

  • Faster pod restarts

  • No storage overhead

  • Simpler setup

Cons:

  • All sessions lost on restart (users must re-login)

  • Cache data regenerated on restart

When to disable persistence: Development/testing where session loss is acceptable.

master:
  persistence:
    enabled: false

Monitoring Redis

Check Memory Usage

kubectl exec -n redis redis-master-0 -- \
  redis-cli info memory | grep used_memory_human

Check Connected Clients

kubectl exec -n redis redis-master-0 -- \
  redis-cli info clients | grep connected_clients

Check Hit Rate

kubectl exec -n redis redis-master-0 -- \
  redis-cli info stats | grep keyspace

Monitor Keys

# Count keys
kubectl exec -n redis redis-master-0 -- \
  redis-cli dbsize

# List all keys (be careful in production!)
kubectl exec -n redis redis-master-0 -- \
  redis-cli --scan

# List Mailu session keys
kubectl exec -n redis redis-master-0 -- \
  redis-cli --scan --pattern "session:*"

Scaling Redis

Increase Memory

Edit redis-values.yaml:

master:
  resources:
    requests:
      memory: 512Mi  # Increased
    limits:
      memory: 1Gi    # Increased

Apply changes:

helm upgrade redis bitnami/redis \
  --namespace redis \
  --values redis-values.yaml

# Pod will restart with new resources
kubectl rollout status statefulset -n redis redis-master

Add More Replicas (HA Mode)

Edit redis-ha-values.yaml:

replica:
  replicaCount: 3  # Increased from 2

Apply:

helm upgrade redis bitnami/redis \
  --namespace redis \
  --values redis-ha-values.yaml

Troubleshooting

Pod not starting

# Check pod status
kubectl describe pod -n redis redis-master-0

# Check logs
kubectl logs -n redis redis-master-0

# Common causes:
# - PVC not bound (check storage class)
# - Resource limits too low
# - Port already in use

Cannot connect to Redis

# Test from another pod
kubectl run -it --rm redis-test --image=redis:7 --restart=Never -- \
  redis-cli -h redis-master.redis.svc.cluster.local ping

# Should return: PONG

# Check service
kubectl get svc -n redis

Authentication errors

# Get Redis password
kubectl get secret -n redis redis -o jsonpath='{.data.redis-password}' | base64 -d

# Test with password
kubectl exec -n redis redis-master-0 -- \
  redis-cli -a "<password>" ping

High memory usage

# Check memory stats
kubectl exec -n redis redis-master-0 -- \
  redis-cli info memory

# Check key distribution
kubectl exec -n redis redis-master-0 -- \
  redis-cli --bigkeys

# Flush keys if needed (CAREFUL - deletes all data!)
# kubectl exec -n redis redis-master-0 -- redis-cli FLUSHALL

Replication lag (HA mode)

# Check replica status
kubectl exec -n redis redis-replicas-0 -- \
  redis-cli info replication | grep master_link_status

# Should show: master_link_status:up

# Check lag
kubectl exec -n redis redis-replicas-0 -- \
  redis-cli info replication | grep master_repl_offset

Performance Tuning

Optimize for Session Storage

Mailu primarily uses Redis for short-lived session data:

master:
  configuration: |-
    # Optimize for session storage
    maxmemory 256mb
    maxmemory-policy allkeys-lru  # Evict least recently used keys
    save ""  # Disable snapshotting if persistence disabled

Connection Pooling

Redis handles connections efficiently. Typical settings:

master:
  configuration: |-
    maxclients 1000
    timeout 300

Redis vs Alternatives

Why Redis for Mailu?

  • ✅ Fast in-memory storage

  • ✅ Built-in expiration (TTL) for sessions

  • ✅ Simple key-value model

  • ✅ Low resource overhead

  • ✅ Widely supported

Could You Use Memcached?

No, Mailu requires Redis specifically. Mailu uses Redis-specific features like:

  • Key expiration (TTL)

  • Hash data structures

  • Pub/sub (for certain operations)


Cleanup and Removal

Uninstall Redis

# Uninstall Helm release
helm uninstall redis --namespace redis

# Delete PVCs (data will be lost!)
kubectl delete pvc -n redis -l app.kubernetes.io/name=redis

# Delete namespace
kubectl delete namespace redis

Warning: This deletes all session data. Users will need to re-login to Mailu.


See Also