Scale Resources

How to adjust CPU and memory resources for Mailu components.

Problem

You need to increase or decrease resource requests and limits for Mailu components based on your workload, user count, or cluster capacity.

Solution

The MailuChart accepts a resources configuration object that allows you to customize CPU and memory for each component. If not specified, components use sensible defaults from the component specifications.

Understanding Resource Configuration

Resource Requests: Guaranteed resources allocated to the pod. Used for scheduling decisions.

Resource Limits: Maximum resources the pod can use. Prevents runaway resource consumption.

Best Practice: Set requests to typical usage and limits to 2-3x requests to allow bursting.

Scale a Single Component

Adjust resources for a specific component (e.g., Dovecot for high IMAP load):

import { App } from 'cdk8s';
import { MailuChart } from 'cdk8s-mailu';

const app = new App();

new MailuChart(app, 'mailu', {
  namespace: 'mailu',
  domain: 'example.com',
  hostnames: ['mail.example.com'],
  subnet: '10.42.0.0/16',

  // ... other config ...

  resources: {
    dovecot: {
      requests: {
        cpu: '500m',      // Increased from default 200m
        memory: '2Gi',    // Increased from default 1Gi
      },
      limits: {
        cpu: '2000m',     // 4x request
        memory: '4Gi',    // 2x request
      },
    },
  },
});

app.synth();

Scale Multiple Components

Adjust resources for all heavy components in a high-load deployment:

resources: {
  // Front (Nginx) - handles all incoming connections
  front: {
    requests: { cpu: '200m', memory: '512Mi' },
    limits: { cpu: '1000m', memory: '1Gi' },
  },

  // Dovecot - memory-intensive for IMAP
  dovecot: {
    requests: { cpu: '500m', memory: '2Gi' },
    limits: { cpu: '2000m', memory: '4Gi' },
  },

  // Postfix - CPU-intensive for SMTP
  postfix: {
    requests: { cpu: '300m', memory: '1Gi' },
    limits: { cpu: '1000m', memory: '2Gi' },
  },

  // Rspamd - spam filtering
  rspamd: {
    requests: { cpu: '200m', memory: '1Gi' },
    limits: { cpu: '1000m', memory: '2Gi' },
  },

  // Admin - lightweight
  admin: {
    requests: { cpu: '100m', memory: '256Mi' },
    limits: { cpu: '500m', memory: '512Mi' },
  },
},

Component-Specific Scaling Guidelines

Dovecot (IMAP/POP3)

Memory-intensive - scales with concurrent user connections and mailbox operations.

Small deployment (< 50 users):

dovecot: {
  requests: { cpu: '200m', memory: '1Gi' },
  limits: { cpu: '1000m', memory: '2Gi' },
}

Medium deployment (50-500 users):

dovecot: {
  requests: { cpu: '500m', memory: '2Gi' },
  limits: { cpu: '2000m', memory: '4Gi' },
}

Large deployment (500+ users):

dovecot: {
  requests: { cpu: '1000m', memory: '4Gi' },
  limits: { cpu: '4000m', memory: '8Gi' },
}

ClamAV (Antivirus)

Very resource-intensive - requires significant memory for virus signature database.

Only if needed (add to resources config):

clamav: {
  requests: { cpu: '1000m', memory: '2Gi' },
  limits: { cpu: '4000m', memory: '4Gi' },
}

Note: ClamAV startup takes 5-10 minutes to download virus signatures. Consider if antivirus scanning is truly required for your use case.

Postfix (SMTP)

CPU-intensive - scales with email throughput.

High-volume mail server:

postfix: {
  requests: { cpu: '500m', memory: '1Gi' },
  limits: { cpu: '2000m', memory: '2Gi' },
}

Rspamd (Spam Filter)

Balanced workload - CPU for filtering, memory for Bayes database.

High spam volume:

rspamd: {
  requests: { cpu: '300m', memory: '1Gi' },
  limits: { cpu: '1500m', memory: '2Gi' },
}

Apply Changes

After modifying resource configuration:

# Regenerate manifests
npm run synth

# Apply updated configuration
kubectl apply -f dist/mailu.k8s.yaml

# Watch pod restarts
kubectl get pods -n mailu -w

Note: Changing resource requests may cause pods to be rescheduled to different nodes with sufficient capacity.

Verify Resource Usage

Check actual resource consumption to inform scaling decisions:

# Current resource usage
kubectl top pods -n mailu

# Per-component usage (sorted by memory)
kubectl top pods -n mailu --sort-by=memory

# Per-component usage (sorted by CPU)
kubectl top pods -n mailu --sort-by=cpu

Recommended monitoring period: Monitor for 24-48 hours covering peak usage times before adjusting resources.

Troubleshooting

Pod stuck in Pending state

Symptom: Pod shows Pending status with event “Insufficient memory” or “Insufficient cpu”.

Solution: Either reduce resource requests or add more node capacity to the cluster.

# Check pod events
kubectl describe pod -n mailu <pod-name> | grep -A 10 Events

OOMKilled pods

Symptom: Pod restarts with exit code 137, events show “OOMKilled”.

Solution: Increase memory limits for the affected component.

# Check recent pod restarts
kubectl get pods -n mailu
kubectl describe pod -n mailu <pod-name> | grep -A 5 "Last State"

CPU Throttling

Symptom: Application performance degraded, kubectl top shows CPU at limit.

Solution: Increase CPU limits to allow more bursting.

# Check if pod is hitting CPU limits
kubectl top pods -n mailu | grep <component-name>

See Also