Skip to content

3.3 Configure Storage

The storage module (modules/storage.pkl) creates encrypted EBS gp3 volumes for Talos nodes. These are attached to EC2 instances by the compute module. This is deployed as part of formae apply via main.pkl.

Step 1: Configure Storage Variables

Open vars.pkl (or your environment override) and set the volume sizes:

formae/cluster/aws/vars.pkl
/// OS root EBS volume size in GB for all nodes (gp3).
rootVolumeSize: Int = 20

/// EBS volume size in GB for control plane nodes (gp3).
controlPlaneVolumeSize: Int = 100

/// EBS volume size in GB for worker nodes (gp3).
workerVolumeSize: Int = 200

Note

Setting controlPlaneVolumeSize = 0 skips creating separate data volumes for control plane nodes. The demo environment uses this to save cost:

formae/cluster/aws/envs/demo.pkl
// In envs/demo.pkl
rootVolumeSize = 50
controlPlaneVolumeSize = 0       // No separate CP data volume
workerVolumeSize = 100

Volume Layout Per Node

Each node has up to two EBS volumes:

Volume Device Created In Lifecycle
Root /dev/xvda compute.pkl (inline with EC2) Deleted with instance (deleteOnTermination = true)
Data /dev/xvdf storage.pkl (separate resource) Persists independently of instance

Step 2: Understand the Module

The module is at modules/storage.pkl.

Worker Volumes

One data volume per worker node, placed in the same AZ:

formae/cluster/aws/modules/storage.pkl
local workerVolumes: Listing<volume.Volume> = new {
  for (_idx in IntSeq(0, vars.workerCount - 1)) {
    new volume.Volume {
      label = "talos-worker-\(_idx + 1)"
      availabilityZone = vars.availabilityZones[_idx % vars.availabilityZones.length]
      size = vars.workerVolumeSize
      volumeType = "gp3"
      iops = 3000
      throughput = 125
      encrypted = true
      tags {
        for (_k, _v in vars.commonTags) {
          new aws.Tag { key = _k; value = _v }
        }
        new aws.Tag { key = "Name"; value = "talos-worker-\(_idx + 1)" }
        new aws.Tag { key = "NodeType"; value = "worker" }
        new aws.Tag { key = "NodeIndex"; value = "\(_idx + 1)" }
        new aws.Tag { key = "Component"; value = "storage" }
      }
    }
  }
}

Key points:

  • availabilityZone — round-robin across configured AZs using modulo (_idx % length)
  • volumeType = "gp3" — latest generation general purpose SSD
  • iops = 3000 / throughput = 125 — gp3 baseline performance
  • encrypted = true — EBS encryption at rest using the default AWS-managed KMS key

Control Plane Volumes (Conditional)

CP volumes are only created when controlPlaneVolumeSize > 0:

formae/cluster/aws/modules/storage.pkl
local controlPlaneVolumes: Listing<volume.Volume> = new {
  when (vars.controlPlaneVolumeSize > 0) {
    for (_idx in IntSeq(0, vars.controlPlaneCount - 1)) {
      new volume.Volume {
        label = "talos-cp-\(_idx + 1)"
        // ... same pattern as worker volumes
      }
    }
  }
}

The when guard means no CP data volumes are created in the demo environment where controlPlaneVolumeSize = 0.

Volume Attachment

The actual attachment of volumes to EC2 instances happens in modules/compute.pkl, not in this module. The storage module exports volume IDs that the compute module consumes:

formae/cluster/aws/modules/compute.pkl
// In compute.pkl
local workerVolumeAttachments: Listing<volAttach.VolumeAttachment> = new {
  for (_idx in IntSeq(0, vars.workerCount - 1)) {
    new volAttach.VolumeAttachment {
      label = "wk-vol-attach-\(_idx + 1)"
      device = "/dev/xvdf"
      volumeId = storage.workerVolumeIds[_idx]
      instanceId = workerInstances[_idx].res.instanceId
    }
  }
}

Step 3: Module Exports

formae/cluster/aws/modules/storage.pkl
/// EBS volume IDs for control plane nodes (used by compute module for attachment).
controlPlaneVolumeIds: Listing<volume.VolumeResolvable> = new {
  for (vol in controlPlaneVolumes) { vol.res.volumeId }
}

/// EBS volume IDs for worker nodes (used by compute module for attachment).
workerVolumeIds: Listing<volume.VolumeResolvable> = new {
  for (vol in workerVolumes) { vol.res.volumeId }
}
Export Consumed By
controlPlaneVolumeIds compute.pkl (volume attachments at /dev/xvdf)
workerVolumeIds compute.pkl (volume attachments at /dev/xvdf)

Customisation Summary

What to Change Where Variable
Root volume size vars.pkl rootVolumeSize
CP data volume size vars.pkl controlPlaneVolumeSize (0 = none)
Worker data volume size vars.pkl workerVolumeSize
Environment override envs/<name>.pkl Amend any of the above

Warning

IOPS (3000) and throughput (125 MB/s) are hardcoded in the module. To change these, edit modules/storage.pkl directly.