Kubernetes components

MetaDefender Cluster ships as two Helm charts. This page describes what each chart creates, how the components find each other, and how configuration is shared between them.

The two charts

Chart

Installs

Install order

md-cluster-services

MetaDefender Cluster Control Center, MetaDefender Cluster Identity Service, MetaDefender Cluster File Storage, and the bundled PostgreSQL / Redis / RabbitMQ. Also creates the shared mdcluster-config ConfigMap and mdcluster-secrets Secret.

First

md-cluster-instances

The MetaDefender Cluster Worker instances — ometascan (MetaDefender Core), api-gateway and callback-service. Consumes the ConfigMap and Secret created above.

Second

The split exists because the two halves have different lifecycles. MetaDefender Core services are long-lived and rarely change; MetaDefender Cluster Worker instances are scaled and upgraded frequently. Installing them as separate releases lets you upgrade or scale MetaDefender Cluster Workers without touching the MetaDefender Cluster Control Center.

Both charts read their configuration from the same values file, so a single override-values.yaml is passed to both helm install commands.

Workloads

Component

Workload

Service and port

control-center

Deployment, always 1

NodePort by default · 8892

identity-service

Deployment, always 1

ClusterIP · 8891

file-storage

StatefulSet

Headless · 8890

ometascan

StatefulSet

Shared headless worker · instance 8008

api-gateway

StatefulSet

Shared headless worker, plus its own api-gateway Service · instance 8899

callback-service

StatefulSet

Shared headless worker · instance 8894

Every MetaDefender Cluster Worker pod also runs an agent on 8893, which is the port the shared worker Service exposes; the instance ports above are what the deployed instance listens on.

Replica counts come from file-storage.replicas and workers.<name>.replicas, both defaulting to 1. MetaDefender Cluster Control Center and MetaDefender Cluster Identity Service are the exception: they are singletons whose replica count is fixed in the template and cannot be raised through values — running two MetaDefender Cluster Control Centers at once would corrupt the orchestration state.

The bundled infrastructure is three more single-pod Deployments, each with a ClusterIP Service: postgres on 5432, redis on 6379, and rabbitmq on 5672 with its management UI on 15672. They are intended for evaluation and test environments; production deployments should run them externally.

Architecture


Shared configuration

The md-cluster-services chart creates two objects that the MetaDefender Cluster MetaDefender Cluster Control Center, MetaDefender Cluster Identity Service, MetaDefender Cluster File Storage and worker pods all mount as environment variables — across both releases. (The bundled PostgreSQL, Redis and RabbitMQ pods do not get them; they read only the few credential values they need.)

Object

Rendered from

Contains

mdcluster-config ConfigMap

the env: block in your values file

Hostnames, ports, timeouts, file copy settings

mdcluster-secrets Secret

the secrets: block in your values file

Passwords, connection keys, the encryption key, the license key

Every container references both with envFrom, so adding a key to env: or secrets: makes it visible to all components without touching any template.

Because the ConfigMap and Secret belong to md-cluster-services, that chart must be installed first. Installing md-cluster-instances on its own leaves MetaDefender Cluster Worker pods unable to start.

Service discovery

Components address each other by Kubernetes Service DNS name. The names are not hardcoded in the templates — each is taken from a ConfigMap key, so renaming a Service is a values change:

Component

Service name comes from

Default

MetaDefender Cluster Control Center

env.CONTROL_CENTER_HOST

control-center

MetaDefender Cluster Identity Service

env.IDENTITY_HOST

identity-service

MetaDefender Cluster File Storage

env.FILE_STORAGE_SERVICE_NAMESPACE

file-storage

MetaDefender Cluster Workers

env.WORKER_SERVICE_NAMESPACE

worker

MetaDefender Cluster File Storage and the workers are fronted by headless Services, which give each pod a stable per-replica DNS name instead of load-balancing across them. This matters because the MetaDefender Cluster Control Center tracks individual instances rather than a pool: MetaDefender Cluster File Storage replica n is addressed as file-storage-<n>.file-storage:8890.

The MetaDefender Cluster Control Center receives that list as the FILE_STORAGE_SERVICES environment variable, which the chart builds at render time from file-storage.replicas. A consequence worth remembering: changing the MetaDefender Cluster File Storage replica count requires a helm upgrade so the list is rebuilt. Scaling the StatefulSet directly with kubectl scale leaves the MetaDefender Cluster Control Center unaware of the new replicas. MetaDefender Cluster Workers have no such dependency and can be scaled with kubectl

Both headless Services set publishNotReadyAddresses: true, so a pod's DNS name resolves as soon as the pod has an IP. Registration traffic can therefore reach the MetaDefender Cluster Control Center before the pod passes its readiness probe.

The installer staging volume

The MetaDefender Cluster Control Center distributes instance installers, so it needs those installer packages on disk at /app/installers before it starts.

The chart handles this with an initContainer named installers, built from the installers image. It copies the packaged installers onto an emptyDir volume, which the MetaDefender Cluster Control Center container then mounts read-only at /app/installers.

Because the volume is an emptyDir, it is recreated empty on every pod start and repopulated by the initContainer. The installers therefore always match the installers image tag in use, and nothing needs to be provisioned or backed up. The volume is fixed in the template and not configurable through values.

Per-component knobs

Every MetaDefender Cluster component — control-center, identity-service, file-storage, and each entry under workers — accepts the same optional settings. Structural details, such as whether a component is a Deployment or a StatefulSet, its rollout strategy and its pod security context, are fixed in the templates and deliberately not configurable.

The bundled postgres, redis and rabbitmq are the exception. They accept only enabled, image, pullPolicy, their ports, persistence and resources; their replica count and their probes are fixed.

Setting

Purpose

version

Image tag override; the image resolves to <DOCKER_REPO>:<component>-<version>, defaulting to MDCLS_VERSION

replicas

Desired pod count (ignored for the two singletons)

imagePullPolicy

Overrides the chart-level policy for this component

resources

Standard Kubernetes requests and limits

nodeSelector, affinity, tolerations

Standard pod scheduling controls

probes

Per-phase probe tuning

terminationGracePeriodSeconds

Graceful shutdown window

MetaDefender Cluster Workers accept several additional settings (listenPort, logLevel, isolate, upgradeInstances, service).