Configure ClamAV cluster with Kubernetes deployment for high availability antivirus scanning

Advanced 45 min Jun 01, 2026 88 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Deploy a distributed ClamAV antivirus cluster on Kubernetes with persistent storage, load balancing, and monitoring for enterprise-grade threat detection and scanning.

Prerequisites

  • Kubernetes cluster with at least 3 nodes
  • kubectl configured with cluster access
  • NFS or similar shared storage for persistent volumes
  • Helm 3.x installed
  • Prometheus Operator for monitoring (optional)

What this solves

ClamAV cluster deployment on Kubernetes provides distributed antivirus scanning with high availability and automatic failover. This setup handles high-volume file scanning across multiple nodes, ensuring continuous threat detection without single points of failure. You'll configure persistent volumes for signature updates, implement load balancing for scan requests, and establish monitoring with alerting for cluster health.

Prerequisites and environment setup

Verify Kubernetes cluster requirements

Ensure your Kubernetes cluster meets the minimum requirements for ClamAV deployment with persistent storage and networking.

kubectl version --client --short
kubectl cluster-info
kubectl get nodes -o wide

Install required Kubernetes components

Install kubectl and Helm for managing the ClamAV cluster deployment and configuration.

sudo apt update
sudo apt install -y kubectl helm
curl https://get.helm.sh/helm-v3.13.0-linux-amd64.tar.gz | tar -xzf -
sudo mv linux-amd64/helm /usr/local/bin/
sudo dnf update -y
sudo dnf install -y kubectl
curl https://get.helm.sh/helm-v3.13.0-linux-amd64.tar.gz | tar -xzf -
sudo mv linux-amd64/helm /usr/local/bin/

Create ClamAV namespace and RBAC

Set up dedicated namespace and service accounts for secure ClamAV cluster operation.

kubectl create namespace clamav-cluster
kubectl config set-context --current --namespace=clamav-cluster

Install and configure ClamAV components

Install ClamAV on cluster nodes

Install ClamAV daemon and command-line tools on all Kubernetes nodes for container image building.

sudo apt update
sudo apt install -y clamav clamav-daemon clamav-freshclam clamav-base
sudo systemctl stop clamav-freshclam
sudo systemctl stop clamav-daemon
sudo dnf update -y
sudo dnf install -y epel-release
sudo dnf install -y clamav clamav-update clamav-scanner-systemd
sudo systemctl stop clamd@scan
sudo systemctl stop clamav-freshclam

Create ClamAV configuration ConfigMaps

Configure ClamAV daemon settings optimized for cluster deployment with TCP socket listening.

apiVersion: v1
kind: ConfigMap
metadata:
  name: clamav-config
  namespace: clamav-cluster
data:
  clamd.conf: |
    LogFile /var/log/clamav/clamd.log
    LogFileMaxSize 10M
    LogTime yes
    DatabaseDirectory /var/lib/clamav
    LocalSocket /var/run/clamav/clamd.sock
    TCPSocket 3310
    TCPAddr 0.0.0.0
    MaxConnectionQueueLength 30
    MaxThreads 20
    ReadTimeout 300
    CommandReadTimeout 30
    SendBufTimeout 500
    MaxQueue 200
    IdleTimeout 60
    ExcludePath ^/proc
    ExcludePath ^/sys
    User clamav
    AllowSupplementaryGroups yes
    ScanPE yes
    ScanELF yes
    ScanOLE2 yes
    ScanPDF yes
    ScanSWF yes
    ScanMail yes
    ScanPartialMessages yes
    ScanArchive yes
    MaxScanSize 500M
    MaxFileSize 100M
    MaxRecursion 20
    MaxFiles 15000
    MaxEmbeddedPE 40M
    MaxHTMLNormalize 40M
    MaxHTMLNoTags 8M
    MaxScriptNormalize 20M
    MaxZipTypeRcg 1M
    SelfCheck 600
    VirusEvent /usr/local/bin/virus-event.sh
  freshclam.conf: |
    DatabaseDirectory /var/lib/clamav
    UpdateLogFile /var/log/clamav/freshclam.log
    LogFileMaxSize 10M
    LogTime yes
    DatabaseOwner clamav
    DNSDatabaseInfo current.cvd.clamav.net
    DatabaseMirror db.local.clamav.net
    DatabaseMirror database.clamav.net
    MaxAttempts 3
    Checks 2
    ConnectTimeout 60
    ReceiveTimeout 60
    TestDatabases yes
    CompressLocalDatabase no

Create virus event handler script

Configure alert script for virus detection events with logging and notification capabilities.

apiVersion: v1
kind: ConfigMap
metadata:
  name: virus-event-script
  namespace: clamav-cluster
data:
  virus-event.sh: |
    #!/bin/bash
    ALERT_EMAIL="security@example.com"
    INFECTED_FILE="$CLAM_VIRUSEVENT_FILENAME"
    VIRUS_NAME="$CLAM_VIRUSEVENT_VIRUSNAME"
    TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
    HOSTNAME=$(hostname)
    
    echo "[$TIMESTAMP] VIRUS DETECTED on $HOSTNAME: $VIRUS_NAME in $INFECTED_FILE" | tee -a /var/log/clamav/virus-alerts.log
    
    # Send alert to monitoring system
    curl -X POST http://alertmanager:9093/api/v1/alerts \
      -H "Content-Type: application/json" \
      -d '[{
        "labels": {
          "alertname": "VirusDetected",
          "severity": "critical",
          "instance": "'$HOSTNAME'",
          "virus": "'$VIRUS_NAME'",
          "file": "'$INFECTED_FILE'"
        },
        "annotations": {
          "summary": "Virus detected by ClamAV",
          "description": "ClamAV detected virus '$VIRUS_NAME' in file '$INFECTED_FILE' on host '$HOSTNAME'"
        }
      }]' 2>/dev/null || true

Set up Kubernetes persistent volumes

Create persistent volume claims for ClamAV data

Configure persistent storage for virus signatures and logs with appropriate sizing for cluster operations.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: clamav-data-pvc
  namespace: clamav-cluster
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs-client
  resources:
    requests:
      storage: 5Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: clamav-logs-pvc
  namespace: clamav-cluster
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: nfs-client
  resources:
    requests:
      storage: 2Gi

Apply storage configuration

Create the persistent volume claims and verify their binding status.

kubectl apply -f clamav-storage.yaml
kubectl get pvc -n clamav-cluster
kubectl describe pvc clamav-data-pvc -n clamav-cluster

Deploy ClamAV cluster with high availability

Create ClamAV Deployment configuration

Deploy ClamAV with multiple replicas, health checks, and resource limits for production workloads.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: clamav-cluster
  namespace: clamav-cluster
  labels:
    app: clamav
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: clamav
  template:
    metadata:
      labels:
        app: clamav
    spec:
      initContainers:
      - name: clamav-init
        image: clamav/clamav:1.3.1
        command: ["sh", "-c"]
        args:
        - |
          cp /etc/clamav/clamd.conf.template /etc/clamav/clamd.conf
          cp /etc/clamav/freshclam.conf.template /etc/clamav/freshclam.conf
          chown -R clamav:clamav /var/lib/clamav /var/log/clamav
          chmod 755 /usr/local/bin/virus-event.sh
          freshclam --foreground --config-file=/etc/clamav/freshclam.conf
        volumeMounts:
        - name: clamav-config
          mountPath: /etc/clamav/clamd.conf
          subPath: clamd.conf
        - name: clamav-config
          mountPath: /etc/clamav/freshclam.conf
          subPath: freshclam.conf
        - name: virus-event-script
          mountPath: /usr/local/bin/virus-event.sh
          subPath: virus-event.sh
        - name: clamav-data
          mountPath: /var/lib/clamav
        - name: clamav-logs
          mountPath: /var/log/clamav
      containers:
      - name: clamav
        image: clamav/clamav:1.3.1
        ports:
        - containerPort: 3310
          name: clamav-tcp
          protocol: TCP
        resources:
          requests:
            memory: "2Gi"
            cpu: "1000m"
          limits:
            memory: "4Gi"
            cpu: "2000m"
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - "echo 'PING' | nc -w 5 localhost 3310 | grep -q PONG"
          initialDelaySeconds: 120
          periodSeconds: 60
          timeoutSeconds: 10
          failureThreshold: 3
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - "echo 'PING' | nc -w 5 localhost 3310 | grep -q PONG"
          initialDelaySeconds: 30
          periodSeconds: 30
          timeoutSeconds: 5
          failureThreshold: 3
        volumeMounts:
        - name: clamav-config
          mountPath: /etc/clamav/clamd.conf
          subPath: clamd.conf
        - name: clamav-config
          mountPath: /etc/clamav/freshclam.conf
          subPath: freshclam.conf
        - name: virus-event-script
          mountPath: /usr/local/bin/virus-event.sh
          subPath: virus-event.sh
        - name: clamav-data
          mountPath: /var/lib/clamav
        - name: clamav-logs
          mountPath: /var/log/clamav
        env:
        - name: CLAMD_CONF_DatabaseDirectory
          value: "/var/lib/clamav"
        - name: CLAMD_CONF_TCPSocket
          value: "3310"
        - name: CLAMD_CONF_TCPAddr
          value: "0.0.0.0"
      - name: freshclam-updater
        image: clamav/clamav:1.3.1
        command: ["/bin/sh"]
        args:
        - -c
        - |
          while true; do
            sleep 3600
            freshclam --config-file=/etc/clamav/freshclam.conf --daemon-notify
          done
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "512Mi"
            cpu: "200m"
        volumeMounts:
        - name: clamav-config
          mountPath: /etc/clamav/freshclam.conf
          subPath: freshclam.conf
        - name: clamav-data
          mountPath: /var/lib/clamav
        - name: clamav-logs
          mountPath: /var/log/clamav
      volumes:
      - name: clamav-config
        configMap:
          name: clamav-config
      - name: virus-event-script
        configMap:
          name: virus-event-script
          defaultMode: 0755
      - name: clamav-data
        persistentVolumeClaim:
          claimName: clamav-data-pvc
      - name: clamav-logs
        persistentVolumeClaim:
          claimName: clamav-logs-pvc
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - clamav
              topologyKey: kubernetes.io/hostname

Apply ClamAV deployment

Deploy the ClamAV cluster and verify pod startup with proper resource allocation.

kubectl apply -f clamav-config.yaml
kubectl apply -f virus-event-configmap.yaml
kubectl apply -f clamav-deployment.yaml
kubectl get pods -n clamav-cluster -w

Configure high availability and load balancing

Create ClamAV Service for load balancing

Configure Kubernetes service to distribute scan requests across ClamAV cluster nodes with session affinity.

apiVersion: v1
kind: Service
metadata:
  name: clamav-service
  namespace: clamav-cluster
  labels:
    app: clamav
spec:
  type: ClusterIP
  sessionAffinity: None
  ports:
  - port: 3310
    targetPort: 3310
    protocol: TCP
    name: clamav-tcp
  selector:
    app: clamav
---
apiVersion: v1
kind: Service
metadata:
  name: clamav-headless
  namespace: clamav-cluster
  labels:
    app: clamav
spec:
  type: ClusterIP
  clusterIP: None
  ports:
  - port: 3310
    targetPort: 3310
    protocol: TCP
    name: clamav-tcp
  selector:
    app: clamav

Configure horizontal pod autoscaler

Enable automatic scaling based on CPU and memory utilization for handling variable scanning loads.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: clamav-hpa
  namespace: clamav-cluster
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: clamav-cluster
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60

Apply load balancing configuration

Deploy services and autoscaling configuration for high availability cluster operation.

kubectl apply -f clamav-service.yaml
kubectl apply -f clamav-hpa.yaml
kubectl get svc,hpa -n clamav-cluster
kubectl describe hpa clamav-hpa -n clamav-cluster

Implement monitoring and alerting

Deploy Prometheus monitoring for ClamAV

Configure Prometheus ServiceMonitor to collect ClamAV metrics and cluster health data.

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: clamav-metrics
  namespace: clamav-cluster
  labels:
    app: clamav
spec:
  selector:
    matchLabels:
      app: clamav
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics
---
apiVersion: v1
kind: Service
metadata:
  name: clamav-metrics
  namespace: clamav-cluster
  labels:
    app: clamav
spec:
  type: ClusterIP
  ports:
  - port: 9090
    targetPort: 9090
    protocol: TCP
    name: metrics
  selector:
    app: clamav-exporter
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: clamav-exporter
  namespace: clamav-cluster
spec:
  replicas: 1
  selector:
    matchLabels:
      app: clamav-exporter
  template:
    metadata:
      labels:
        app: clamav-exporter
    spec:
      containers:
      - name: clamav-exporter
        image: solsson/clamav-exporter:latest
        ports:
        - containerPort: 9090
          name: metrics
        env:
        - name: CLAMAV_HOST
          value: "clamav-service"
        - name: CLAMAV_PORT
          value: "3310"
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "128Mi"
            cpu: "100m"

Configure ClamAV alert rules

Set up Prometheus alerting rules for cluster health monitoring and virus detection events.

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: clamav-alerts
  namespace: clamav-cluster
  labels:
    app: clamav
spec:
  groups:
  - name: clamav.rules
    rules:
    - alert: ClamAVPodDown
      expr: up{job="clamav-service"} == 0
      for: 2m
      labels:
        severity: critical
      annotations:
        summary: "ClamAV pod is down"
        description: "ClamAV pod {{ $labels.instance }} has been down for more than 2 minutes"
    
    - alert: ClamAVHighMemoryUsage
      expr: container_memory_usage_bytes{pod=~"clamav-cluster-.*"} / container_spec_memory_limit_bytes > 0.9
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "ClamAV high memory usage"
        description: "ClamAV pod {{ $labels.pod }} is using more than 90% of allocated memory"
    
    - alert: ClamAVDatabaseOutdated
      expr: (time() - clamav_database_last_update_timestamp) > 86400
      for: 1m
      labels:
        severity: warning
      annotations:
        summary: "ClamAV virus database outdated"
        description: "ClamAV database on {{ $labels.instance }} hasn't been updated in over 24 hours"
    
    - alert: ClamAVVirusDetected
      expr: increase(clamav_virus_detected_total[5m]) > 0
      for: 0m
      labels:
        severity: critical
      annotations:
        summary: "Virus detected by ClamAV"
        description: "ClamAV detected {{ $value }} virus(es) in the last 5 minutes on {{ $labels.instance }}"
    
    - alert: ClamAVClusterUnhealthy
      expr: count(up{job="clamav-service"} == 1) < 2
      for: 3m
      labels:
        severity: critical
      annotations:
        summary: "ClamAV cluster unhealthy"
        description: "Less than 2 ClamAV pods are healthy, cluster availability at risk"

Apply monitoring configuration

Deploy monitoring and alerting components for comprehensive ClamAV cluster observability.

kubectl apply -f clamav-monitoring.yaml
kubectl apply -f clamav-alerts.yaml
kubectl get servicemonitor,prometheusrule -n clamav-cluster

Security hardening and network policies

Create network policies for ClamAV isolation

Implement network segmentation to restrict traffic to ClamAV pods and prevent lateral movement.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: clamav-network-policy
  namespace: clamav-cluster
spec:
  podSelector:
    matchLabels:
      app: clamav
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: default
    - namespaceSelector:
        matchLabels:
          name: monitoring
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: TCP
      port: 3310
    - protocol: TCP
      port: 9090
  egress:
  - to: []
    ports:
    - protocol: TCP
      port: 53
    - protocol: UDP
      port: 53
  - to: []
    ports:
    - protocol: TCP
      port: 80
    - protocol: TCP
      port: 443
  - to:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 9093
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all-default
  namespace: clamav-cluster
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Configure Pod Security Standards

Apply security contexts and pod security standards for hardened container execution.

apiVersion: v1
kind: LimitRange
metadata:
  name: clamav-limits
  namespace: clamav-cluster
spec:
  limits:
  - default:
      memory: "4Gi"
      cpu: "2000m"
    defaultRequest:
      memory: "2Gi"
      cpu: "1000m"
    type: Container
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: clamav-quota
  namespace: clamav-cluster
spec:
  hard:
    requests.cpu: "10"
    requests.memory: 20Gi
    limits.cpu: "20"
    limits.memory: 40Gi
    persistentvolumeclaims: "4"
    pods: "15"

Apply security hardening

Deploy network policies and resource constraints for secure cluster operation. For more advanced Kubernetes security, see our guide on configuring Kubernetes network policies for enhanced security.

kubectl apply -f clamav-network-policy.yaml
kubectl apply -f clamav-security-policy.yaml
kubectl get networkpolicy,limitrange,resourcequota -n clamav-cluster

Verify your setup

Test ClamAV cluster functionality

Verify that all ClamAV pods are running and responding to scan requests through the load balancer.

kubectl get pods -n clamav-cluster -o wide
kubectl logs -l app=clamav -n clamav-cluster --tail=50
kubectl exec -it deployment/clamav-cluster -n clamav-cluster -- clamdscan --version

Test virus scanning through service

Create a test file and scan it through the ClamAV service to verify cluster load balancing.

kubectl run clamav-test --image=busybox --rm -it --restart=Never -n clamav-cluster -- sh -c "
echo 'Testing ClamAV cluster' > /tmp/testfile.txt
echo 'PING' | nc clamav-service 3310
echo 'SCAN /tmp/testfile.txt' | nc clamav-service 3310
"

Verify monitoring and metrics

Check that monitoring components are collecting ClamAV metrics and alerting rules are active.

kubectl port-forward service/clamav-metrics 9090:9090 -n clamav-cluster &
curl -s http://localhost:9090/metrics | grep clamav
kubectl get servicemonitor,prometheusrule -n clamav-cluster

Test high availability failover

Simulate pod failure to verify cluster resilience and automatic recovery.

kubectl delete pod -l app=clamav --timeout=0s --grace-period=0 -n clamav-cluster
kubectl get pods -n clamav-cluster -w
kubectl get hpa clamav-hpa -n clamav-cluster

Common issues

Symptom Cause Fix
Pods stuck in Init state FreshClam database download failure kubectl logs POD_NAME -c clamav-init -n clamav-cluster and check internet connectivity
High memory usage warnings Large virus database or scan files Increase memory limits in deployment and adjust MaxScanSize in config
Service connection refused ClamAV not listening on TCP socket Check TCPSocket and TCPAddr settings in clamd.conf ConfigMap
Persistent volume mount fails Storage class not available kubectl get storageclass and update storageClassName in PVC
Network policy blocks scanning Overly restrictive ingress rules Add source namespace labels to network policy ingress rules
Autoscaler not working Metrics server not installed kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Virus detection alerts not firing Prometheus not scraping metrics Check ServiceMonitor labels match Prometheus configuration

Next steps

Running this in production?

Want this handled for you? Running ClamAV at scale adds a second layer of work: capacity planning, signature update monitoring, cross-cluster failover drills, and 24/7 threat response. Our managed platform covers monitoring, backups and incident response by default.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle infrastructure security hardening for businesses that depend on uptime. From initial setup to ongoing operations.