EKS Coordinator And Agents

Use this page when you want to run LoadStrike coordinator and agent nodes on Amazon EKS. It explains the cluster shape, dependencies, and deployment flow.

What this page helps you do

What this page helps you do

Use this page when you want to run LoadStrike coordinator and agent nodes on Amazon EKS. It explains the cluster shape, dependencies, and deployment flow.

Who this is for

Teams moving from one machine to coordinator-and-agent execution or tighter workload targeting.

Prerequisites

  • A scenario that already works in a single-node run

By the end

A clearer cluster topology and the fields that must line up across nodes.

Use this page when

Use this page when execution topology, partitioning, or targeting changes how the run should be distributed.

Visual guide

Cluster topology diagram showing the coordinator, agents, and merged result.
Cluster settings matter because the coordinator, agents, and merged result all belong to the same workload definition.

Guide

When To Use EKS

Use EKS when a single machine cannot generate enough load, when you need production-like multi-node traffic patterns, or when you want repeatable CI or CD load jobs.

Architecture

The common setup is one coordinator pod, usually as a Job, and multiple agent pods, usually as a Deployment. The coordinator orchestrates scenarios and merges metrics, while the agents execute their assigned workload and stream node stats back over NATS.

Dependencies

The required pieces are EKS, kubectl, AWS CLI, Docker, ECR, and a NATS endpoint reachable by all test pods. Optional pieces include Redis for correlation-store persistence and S3 or PVC storage for reports.

Container Image

Build a .NET 8 runtime image that contains your test project and LoadStrike setup. Push that image to ECR and reference the same image tag in both the coordinator and agent manifests.

Runtime Configuration

Set LoadStrike keys such as NodeType, ClusterId, AgentGroup, AgentsCount, NatsServerUrl, AgentTargetScenarios, CoordinatorTargetScenarios, and ClusterCommandTimeoutMs through appsettings, environment variables, or CLI args.

Kubernetes Manifests

The usual manifest set includes Namespace, Secret, ConfigMap, a NATS deployment and service, an agent deployment, and a coordinator job. Keep the same ClusterId and AgentGroup values across all pods in one run.

Scaling Strategy

Scale agents through Deployment replicas and keep AgentsCount in coordinator config aligned with the number of agents you expect to be active. Scale gradually and watch CPU, memory, and network saturation on the worker nodes.

Security And IAM

Use Kubernetes Secrets for credentials, IRSA for AWS access, restricted RBAC for the test namespace, and NetworkPolicies that only allow the broker and target-system paths the run really needs.

Reports And Artifacts

Write reports to /reports inside the container and then persist them through PVC or object storage after the coordinator finishes. Agent reports are disabled in distributed mode by design.

Operational Checks

If the coordinator waits too long, check NATS connectivity, agent readiness, ClusterCommandTimeout, scenario targeting alignment, and broker credentials first.

Cluster setup samples

This sample uses environment variables so the same deployment artifact can boot either as the coordinator or as an agent while still joining the same clusterId.

If you run these examples locally, add a valid runner key before execution starts. Set it with WithRunnerKey("...") or the config key LoadStrike:RunnerKey.

EKS Dependencies and Runtime Config

using LoadStrike;

var clusterId = Environment.GetEnvironmentVariable("LOADSTRIKE_CLUSTER_ID") ?? "orders-cluster";
var nodeRole = Environment.GetEnvironmentVariable("LOADSTRIKE_ROLE") ?? "agent";
var natsUrl = Environment.GetEnvironmentVariable("LOADSTRIKE_NATS_URL")
    ?? "nats://nats.loadstrike.svc.cluster.local:4222";
var agentGroup = "perf-agents";

var submitOrdersScenario = LoadStrikeScenario.Create(
        "submit-orders",
        _ => Task.FromResult(LoadStrikeResponse.Ok(statusCode: "202")))
    .WithLoadSimulations(LoadStrikeSimulation.IterationsForConstant(1, 2));

var waitForCompletionScenario = LoadStrikeScenario.Create(
        "wait-for-completion",
        _ => Task.FromResult(LoadStrikeResponse.Ok(statusCode: "200")))
    .WithLoadSimulations(LoadStrikeSimulation.IterationsForConstant(1, 2));

var runner = LoadStrikeRunner
    .RegisterScenarios(submitOrdersScenario, waitForCompletionScenario)
    .WithClusterId(clusterId)
    .WithAgentGroup(agentGroup)
    .WithNatsServerUrl(natsUrl);

if (string.Equals(nodeRole, "coordinator", StringComparison.OrdinalIgnoreCase))
{
    runner = runner
        .WithNodeType(LoadStrikeNodeType.Coordinator)
        .WithAgentsCount(3)
        .WithCoordinatorTargetScenarios("submit-orders")
        .WithAgentTargetScenarios("wait-for-completion")
        .WithReportFolder("/reports")
        .WithRunnerKey("rkr_your_remote_runner_key");
}
else
{
    runner = runner
        .WithNodeType(LoadStrikeNodeType.Agent)
        .WithAgentTargetScenarios("wait-for-completion");
}

runner.Run();

EKS Manifests (NATS, Agents, Coordinator)

EKS cluster

Provides the Kubernetes control plane and worker capacity for coordinator and agent pods.

NATS

Provides the coordinator-agent messaging layer for distributed execution.

Redis (optional)

Adds durable correlation-store support when you do not want in-memory correlation only.

Coordinator job

Starts the orchestrator that assigns work, merges stats, and writes final artifacts.

Agent deployment

Starts the scalable workers that execute the assigned scenarios.

PVC or object storage

Keeps coordinator-generated reports and artifacts after the job has completed.

apiVersion: v1
kind: Namespace
metadata:
  name: loadstrike
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nats
  namespace: loadstrike
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nats
  template:
    metadata:
      labels:
        app: nats
    spec:
      containers:
      - name: nats
        image: nats:2.10-alpine
        args: ["-js"]
        ports:
        - containerPort: 4222
---
apiVersion: v1
kind: Service
metadata:
  name: nats
  namespace: loadstrike
spec:
  selector:
    app: nats
  ports:
  - name: client
    port: 4222
    targetPort: 4222
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: loadstrike-cluster
  namespace: loadstrike
data:
  LoadStrike__ClusterId: orders-cluster
  LoadStrike__AgentGroup: perf-agents
  LoadStrike__NatsServerUrl: nats://nats.loadstrike.svc.cluster.local:4222
  LoadStrike__AgentTargetScenarios: kafka-consumer
  LoadStrike__CoordinatorTargetScenarios: http-source
  LoadStrike__ClusterCommandTimeoutMs: "180000"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: loadstrike-agent
  namespace: loadstrike
spec:
  replicas: 3
  selector:
    matchLabels:
      app: loadstrike-agent
  template:
    metadata:
      labels:
        app: loadstrike-agent
    spec:
      containers:
      - name: agent
        image: <aws-account-id>.dkr.ecr.<region>.amazonaws.com/loadstrike-tests:latest
        envFrom:
        - configMapRef:
            name: loadstrike-cluster
        env:
        - name: LoadStrike__NodeType
          value: Agent
        - name: LoadStrike__TargetScenarios
          value: kafka-consumer
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
          limits:
            cpu: "2"
            memory: "2Gi"
---
apiVersion: batch/v1
kind: Job
metadata:
  name: loadstrike-coordinator
  namespace: loadstrike
spec:
  backoffLimit: 0
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: coordinator
        image: <aws-account-id>.dkr.ecr.<region>.amazonaws.com/loadstrike-tests:latest
        envFrom:
        - configMapRef:
            name: loadstrike-cluster
        env:
        - name: LoadStrike__NodeType
          value: Coordinator
        - name: LoadStrike__AgentsCount
          value: "3"
        - name: LoadStrike__RunnerKey
          value: rkr_your_remote_runner_key
        - name: LoadStrike__ReportFolder
          value: /reports
        volumeMounts:
        - name: reports
          mountPath: /reports
      volumes:
      - name: reports
        persistentVolumeClaim:
          claimName: loadstrike-reports-pvc