Skip to main content

Replica overrides

Replica overrides​

The number of pods that a component runs (its replica count) comes from the Helm chart bundled with the deployment's driver version, or from a default that the driver declares. A replica override sets the replica count of one component of one deployment. Styrmin applies it after the chart renders: it sets spec.replicas of every Deployment and StatefulSet that matches the component's label selector. The component needs no component container, and the driver needs no parameter or template code for it.

Order of precedence​

Styrmin takes each component's replica count from the first of these sources that is set:

  1. The replica override on the deployment.
  2. The driver default: components.<name>.replicas in the driver version, or 1 for a singleton component that declares no replicas.
  3. The chart's count. Styrmin does not change spec.replicas, so the count that the chart renders applies. Styrmin does not read this count, so the UI and styrminctl show the source without a number.

The API, the UI and the CLI show each source as follows:

SourceGraphQL ComponentReplicas.sourceComponent Overrides cardstyrminctl deployments get
Replica override of 3OVERRIDE3 (override)3 (override)
Driver default of 2DRIVER_DEFAULT2 (driver default)2 (driver default)
Singleton component without an overrideDRIVER_DEFAULT1 (driver default, singleton)1 (driver default, singleton)
The chart's countCHARTset by the chartchart

When you clear an override, the component returns to the next source in this order.

What a replica override changes and what it needs​

  • Only Deployment and StatefulSet workloads change. Styrmin sets spec.replicas on every Deployment and StatefulSet that the component's label selector matches. It does not change Job, CronJob or DaemonSet workloads. When the selector matches no Deployment and no StatefulSet, the override changes nothing and the deployment does not fail.
  • The count is a whole number from 1 to the server's maximum. A count of 0 or less is rejected with INVALID_REPLICA_COUNT. To run no pods, stop the component instead (see Stopped components). A new or changed count above the maximum is rejected with REPLICA_COUNT_ABOVE_MAXIMUM (see The maximum replica count).
  • Component scope only. There is no environment-wide or deployment-wide replica count, and no layering.
  • The cluster must have room for the new pods. Styrmin does not check the cluster's capacity before it scales a component. Pods that the cluster cannot place stay in the Pending phase, and the update task fails when its wait limit runs out.
  • Permissions are the same as for any other deployment config edit.

The maximum replica count​

Any user who can edit a deployment can set a replica override on any of its components. The server setting STYRMIN_MAX_REPLICA_COUNT limits the count that a user can set, so that a typing error such as 3000 does not fill a shared cluster with pods:

  • The default maximum is 20. In the Helm chart, set styrmin.maxReplicaCount.
  • A new or changed override above the maximum is rejected with REPLICA_COUNT_ABOVE_MAXIMUM before any task starts. The error contains the component name, the requested count and the maximum.
  • An override stored before an administrator lowered the maximum stays stored and applied. Sending it again unchanged is accepted, so other changes to the deployment do not fail.
  • Driver defaults (components.<name>.replicas) are not limited.

The maximum applies to each component, not to a deployment or a namespace. To limit the pods and resources of a whole deployment on a shared cluster, also add a Kubernetes ResourceQuota to its namespace.

When the update task completes​

A change to a replica count starts an update task, as any other config edit does. The task completes after the component's workloads report the new count as their updated, ready and available pods, and run no more pods than the new count. This applies to a scale-down as well as to a scale-up, so a completed task means that the change of count is done.

Singleton components​

A driver marks a component that must run exactly one pod with singleton: true, for example a database that runs as a single primary. For a singleton component:

  • Styrmin sets the count to 1, even when the chart renders more pods and the driver declares no replicas.
  • A replica override of exactly 1 is accepted.
  • A replica override greater than 1 is rejected with SINGLETON_REPLICA_OVERRIDE before any task starts, when you create the deployment, update it, change its driver version, or run styrminctl deployments apply.
  • When you change a deployment to a driver version that marks a component as singleton, and the deployment stores an override greater than 1 on that component, the change is rejected. Lower the override to 1 or clear it in the same request.

The singleton flag limits the replica count, not the number of pods that run at the same time. During a rolling update, the chart's update strategy can run a second pod of a singleton component for a short time, for example when a Deployment uses the RollingUpdate strategy with maxSurge above 0.

The driver version page shows which components are singleton components: see On the driver version page.

Stopped components​

Stopping a component and setting its replica count are separate operations. A stopped component runs 0 pods whatever its replica count is, and its override stays stored. When you start the component again, it returns to the count from the order of precedence.

Components are stopped and started with the stopComponents and startComponents GraphQL mutations, with styrminctl deployments stop-components and start-components, and by driver actions through the stop_components and start_components primitives.

While a component is stopped:

  • Deployment.componentReplicas reports the count that the component returns to when it starts, and Deployment.components[].enabled is false.
  • The Component Overrides card adds stopped: 0 pods to the component's replica line.
  • styrminctl deployments get adds , stopped: 0 pods to the component's replica cell, for example 3 (override), stopped: 0 pods.

Overrides on a component that the driver version no longer declares​

When you change a deployment to a driver version that no longer declares a component, Styrmin keeps that component's replica override and does not apply it. The override is then orphaned:

  • Deployment.componentReplicas has a row for the component with isOrphaned: true, isApplicable: false and count: null. override holds the stored value.
  • The Component Overrides card shows the override in the row of the component that the driver no longer declares, with a not applied badge.
  • styrminctl deployments get adds a row to the Components table, for example 3 (override, not applied: no longer declared).

Adding or changing an override on a component that the driver version does not declare is rejected with UNKNOWN_COMPONENT_REPLICA_OVERRIDE. The error lists the components that the driver version declares. Sending the stored value again unchanged is accepted, so an update that keeps the other component blocks does not fail. Removing the override always works.

In the UI​

To set or clear an override on an existing deployment:

  1. Open the deployment, go to the Settings tab, and click Update Settings.
  2. In the Edit configuration drawer, under Components, expand the component.
  3. Type the count in Replicas. When the field is empty, its placeholder shows the count that applies without an override, for example 2 (driver default), or set by the chart. For a count below 1, the drawer shows "Must be 1 or more. To run no pods, stop the component." While a count is below 1, not a whole number or above 2147483647, Review & apply stays disabled and names the component to fix. A count above the server's maximum is rejected when you apply.
  4. Click Review & apply. The review dialog lists one line per changed count, for example server: 3 → 1 pod. Confirm.

To clear the override, empty the Replicas field and apply. When you type a count on a component that had no override and then empty the field again, the drawer shows no change.

When the driver version also has a parameter that sets the component's count, such as Number of task worker replicas on infrahub driver version 4, the hint under Replicas names that parameter and says that the override applies when both are set.

A singleton component shows a read-only Replicas field with the value 1 (singleton). If such a component stores an override greater than 1, the drawer shows the stored value with a not applied badge and a button that removes it.

To set counts when you create a deployment, use the Component replicas section of the Deploy form. It lists each component of the selected driver version by name, with the same field. Leave a field empty to use the driver default or the chart's count. While a count is not valid, Deploy stays disabled and the form names the component to fix. The form deploys the driver version you select, and lists the versions of each driver newest first.

The Component Overrides card on the Settings tab shows a replica line for every component: the count and its source, an applied or not applied badge when an override is stored, and stopped: 0 pods for a stopped component.

On the driver version page​

On the driver's page, the Components tab shows, for each component of the selected driver version, a Replicas row (the driver default, or not set) and a Singleton row (yes or no).

With styrminctl deployments scale​

styrminctl deployments scale sets or clears the override of one component and keeps every other override of the deployment:

# task-worker runs 4 pods.
uv run styrminctl deployments scale <deployment-id> task-worker 4

# Remove the override: the driver default or the chart's count applies.
uv run styrminctl deployments scale <deployment-id> task-worker --clear

The command reads the stored component blocks and sends them back with only the count of that component changed. A change that another user writes between the read and the update is overwritten. The SDK method is client.deployments.scale(deployment_id, component, replicas), with replicas=None to clear the override.

With styrminctl deployments apply​

Set replicas on the component's entry in spec.config.components:

apiVersion: styrmin/v1
kind: Deployment
metadata:
name: my-app
spec:
driver: acme/my-driver
version: "1.4.2"
environment: production
config:
components:
- name: server
replicas: 3

Applying the same manifest again changes nothing. spec.config is replaced on every apply, so removing the replicas key (or the component's entry) and applying again clears the override. An omitted or empty spec.config is the exception: it keeps the stored configuration. When the override you remove is the only setting left, write components: [] instead of deleting spec.config. See the styrminctl reference.

When the manifest keeps a replica override on a component that the driver version no longer declares, apply stores it, does not apply it, and prints a warning on stderr. The exit code does not change:

warning: my-app: replica override is stored on worker but not applied: the driver version does not declare worker. Remove it from the manifest, or load a driver version that declares components.worker and apply again

With the Python SDK or GraphQL​

The override is ComponentConfigInput.replicas on deploy, updateDeployment and updateDeploymentVersion (in input). It is read back from Deployment.componentReplicas, which has one row per component that the driver version declares and one row per orphaned override, sorted by component name. Each row has component, count, source, override, singleton, isOrphaned and isApplicable.

from styrmin_sdk import StyrminClient
from styrmin_sdk.models import ComponentConfigInput, UpdateDeploymentInput

# The client reads its token from STYRMIN_TOKEN, or takes token=... explicitly.
async with StyrminClient(server_address="https://styrmin.example") as client:
await client.deployments.update(
deployment_id,
input=UpdateDeploymentInput(
components=[ComponentConfigInput(name="server", replicas=3)],
),
)

deployment = await client.deployments.get(deployment_id)
for row in deployment.component_replicas:
print(row.component, row.count, row.source, row.is_applicable)

components replaces every stored component block, and leaving replicas out of a block clears it. Resubmit the env vars, command, args, image and replica override of every component you want to keep. To change only one count, use client.deployments.scale() or styrminctl deployments scale.

styrminctl deployments update and deployments update-version --config take the same payload as JSON:

# Warning: this payload replaces every stored component block. It deletes
# the env var, image, command and args overrides of server, and every
# override of the other components. To change only the count, use
# `styrminctl deployments scale <deployment-id> server 3`.
uv run styrminctl deployments update <deployment-id> \
--config '{"components": [{"name": "server", "replicas": 3}]}'

The SDK and styrminctl reject a count that is not a whole number, such as true or "3", before they send the request.

The driver version's defaults are on ComponentConfig.replicas and ComponentConfig.singleton (ApplicationDriverVersion.componentConfigs).

Scaling a component whose pods share a ReadWriteOnce volume​

A volume with the ReadWriteOnce access mode can be attached to one node at a time. When the pods of a component mount one shared PersistentVolumeClaim with this access mode, a pod that Kubernetes places on another node cannot attach the volume and stays in the Pending phase. The update task then fails when its wait limit runs out. The server component of the infrahub drivers mounts such a volume: see Scaling server above 1 pod.

Replica counts that a driver parameter sets​

In Styrmin v0.1.49 and earlier, a driver could set a replica count only through a parameter that its values.j2.yml passes to the chart. A replica override also applies on such a driver version: Styrmin sets spec.replicas after the chart renders, so the override replaces the count that the parameter passed to the chart.

infrahub driver version 5 and infrahub-enterprise driver version 4 replace their replicas_server and replicas_task_worker parameters with driver defaults. A deployment that changed one of these parameters must move the value to a replica override before it changes driver version. See Migrate the infrahub replica parameters.

When something goes wrong​

What you seeWhyWhat to do
The write fails with INVALID_REPLICA_COUNTThe count is 0 or lessFix the count. To run no pods, stop the component
The write fails with REPLICA_COUNT_ABOVE_MAXIMUMThe count is above the server's maximum, 20 by defaultLower the count, or ask an administrator to raise STYRMIN_MAX_REPLICA_COUNT
The write fails with VALIDATION_ERROR and the message Int cannot represent ...The count is above 2147483647 or is not a whole number. The API reads every replica count as a GraphQL Int and rejects other values before it checks the countFix the count. The SDK and styrminctl reject a count that is not a whole number before they send the request
The write fails with UNKNOWN_COMPONENT_REPLICA_OVERRIDEThe driver version does not declare that componentCheck the component name against the components listed in the error
The write fails with SINGLETON_REPLICA_OVERRIDEThe driver version marks the component as a singleton componentSet the override to 1 or clear it
A driver version change fails with RETIRED_PARAMETER_VALUEThe target driver version no longer declares a parameter that the deployment sets to a value other than its defaultFollow Change a deployment's driver version, and for the infrahub replica parameters Migrate the infrahub replica parameters
Pods stay in the Pending phase and the update task failsThe cluster cannot place the new pods, or the pods share a ReadWriteOnce volumeOpen the deployment's Pods tab to read the reason, then lower the count or add capacity
A component does not run the count of its overrideThe override is orphaned, or the component is stoppedCheck the replica line on the Component Overrides card

Upgrading and rolling back Styrmin​

  • Upgrade the agent chart together with the server. Styrmin's agent sets the replica counts, and an agent of v0.1.49 or earlier does not:
    • it rejects a deployment context that contains a replica override;
    • it ignores replicas in a driver declaration, so a component of the infrahub 5 or infrahub-enterprise 4 driver, or of a driver that moved its count to components.<name>.replicas, runs the chart's count without any message.
  • Upgrade the SDK and styrminctl after the server. deployments get of v0.1.50 and later reads Deployment.componentReplicas, so it fails against a server of v0.1.49 or earlier.
  • A driver version loaded with v0.1.49 or earlier that already sets components.<name>.replicas to a whole number has it applied as the driver default from v0.1.50. No example driver set this key before v0.1.50. When a stored replicas or singleton value is not valid, Styrmin ignores that key and logs a warning that names the component, the key and its value. When singleton: true and a replicas above 1 are both stored, Styrmin ignores replicas, so the component runs 1 pod. The deployment stays readable.
  • Mark single-primary components before you upgrade. As soon as the server runs v0.1.50 or later, a user can set a replica override on any component, even on a driver version loaded with v0.1.49 or earlier, whose author could not mark components as singleton. If you maintain a driver, load a version that marks such components with singleton: true and move your deployments onto it.
  • Clear every replica override before you roll Styrmin back to v0.1.49 or earlier: those releases reject a deployment config that contains a replicas key.

Limits​

  • No autoscaling. Styrmin does not detect a HorizontalPodAutoscaler that a chart includes, and does not work with one.
  • No default at environment or cluster level.
  • No scale action in the UI. Change the count in the Edit configuration drawer. styrminctl deployments scale changes one count from the command line.
  • One pod at a time is not guaranteed for a singleton component during a rolling update.

Next steps​