Configure ClamAV cluster with Kubernetes deployment for high availability antivirus scanning

Advanced 45 min Jun 01, 2026 850 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

Automated install script

Run this to automate the entire setup

Prefere não gerir isto sozinho?

Gerimos a infraestrutura de empresas que dependem do tempo de atividade. Totalmente gerida, com um contacto fixo que conhece o seu ambiente.

Tem um contacto fixo que conhece o seu ambiente

Roterdão 23:44 · acessível por mensagem, sem formulário de tickets