Skip to content

2.2 Prepare Provisioning Config

Set up and customise the infrastructure-as-code configuration before deploying.

Project Structure

The Formae IaC project lives at formae/cluster/aws/ with the following structure:

formae/cluster/aws/
├── main.pkl                    # Entry point — composes all modules
├── vars.pkl                    # Shared variables and defaults
├── bootstrap.pkl               # S3 bucket + IAM vmimport role (AMI pipeline)
├── schematic.yaml              # Talos Image Factory extensions config
├── PklProject                  # Pkl dependency declarations
├── PklProject.deps.json        # Dependency lock file
├── modules/
│   ├── network.pkl             # VPC, subnets, IGW, NAT, route tables
│   ├── security_groups.pkl     # Control plane + worker security groups
│   ├── iam.pkl                 # IAM role + instance profile
│   ├── storage.pkl             # Encrypted EBS gp3 volumes
│   ├── compute.pkl             # EC2 instances + volume attachments
│   └── loadbalancer.pkl        # NLB + target groups + listeners
├── envs/
│   └── demo.pkl                # Demo environment overrides
└── lib/
    └── aws/                    # Patched AWS schema (local override)

Dependencies

The project depends on two packages declared in PklProject:

formae/cluster/aws/PklProject
dependencies {
  ["formae"] {
    uri = "package://hub.platform.engineering/plugins/pkl/schema/pkl/formae/formae@0.81.0"
  }
  ["aws"] = import("./lib/aws/PklProject")
}
  • formae@0.81.0 — the Formae plugin providing forma.pkl, formae.pkl (Stack, Target, Prop, Resource types)
  • aws (local) — a patched copy of the @aws@0.1.0 schema under lib/aws/, fixing type issues in the upstream package (e.g. AvailabilityZone regex for af-south-1, Resolvable type unions)

To resolve dependencies:

cd formae/cluster/aws
pkl project resolve

Shared Variables (vars.pkl)

All configurable parameters are defined in vars.pkl. Key sections:

Cluster Identity

Variable Default Description
clusterName "rciis-testing" Kubernetes cluster name, used in resource naming and tags
environment "testing" Environment label (testing, demo, staging, prod)

AWS Region

Variable Default Description
region "af-south-1" AWS region for all resources
availabilityZones ["af-south-1a"] AZs for resource distribution
awsProfile null AWS CLI profile name (null = use env vars or instance role)

Network

Variable Default Description
vpcCidr "10.0.0.0/16" VPC address space
publicSubnetCidrs ["10.0.1.0/24"] One public subnet per AZ (NAT gateways, NLB)
privateSubnetCidrs ["10.0.11.0/24"] One private subnet per AZ (Kubernetes nodes)
enableNatGateway true Create NAT gateways for private subnet internet access
singleNatGateway false Share one NAT gateway across AZs (cost saving)

Compute

Variable Default Description
controlPlaneCount 3 Number of control plane nodes (1 = non-HA, 3 or 5 = HA)
workerCount 5 Number of worker nodes
controlPlaneInstanceType "t3.large" EC2 instance type for control plane
workerInstanceType "t3.xlarge" EC2 instance type for workers
enablePublicIp false Assign public IPs (false when using NAT)

Storage

Variable Default Description
rootVolumeSize 20 GB OS root EBS volume (gp3)
controlPlaneVolumeSize 100 GB CP data volume (gp3, 0 = no separate volume)
workerVolumeSize 200 GB Worker data volume (gp3)

Load Balancer

Variable Default Description
nlbInternal true Internal NLB (true) or internet-facing (false)
enableDeletionProtection false Prevent accidental NLB deletion
enableCrossZoneLoadBalancing true Distribute traffic across all AZs

Security

Variable Default Description
allowedAdminCidr null External CIDR for K8s API + Talos API access (null = VPC only)
enableSsm false Attach SSM policy to instance role
enableNodePort false Open NodePort range (30000-32767) on workers
cniType "cilium" Container Network Interface plugin

Tags

All resources are tagged with:

Tag Value
ManagedBy formae
Environment Value of environment variable
Project rciis
Cluster Value of clusterName variable

Environment Overrides

Create environment-specific configurations by amending vars.pkl. Example (envs/demo.pkl):

formae/cluster/aws/envs/demo.pkl
amends "../vars.pkl"

clusterName = "rciis-demo"
environment = "demo"
region = "af-south-1"
awsProfile = "cbt"
availabilityZones = List("af-south-1a")

// Single AZ, single NAT to reduce cost
vpcCidr = "10.2.0.0/16"
publicSubnetCidrs = List("10.2.1.0/24")
privateSubnetCidrs = List("10.2.11.0/24")
singleNatGateway = true

// Non-HA: 1 CP + 1 worker with small instances
controlPlaneCount = 1
workerCount = 1
controlPlaneInstanceType = "t3a.small"
workerInstanceType = "t3a.small"

To use an environment override, the vars.pkl import in main.pkl resolves the active environment. You can also override values via CLI flags:

formae apply --mode reconcile \
  --ami $AMI \
  --environment demo \
  --region af-south-1 \
  --control-plane-count 1 \
  --worker-count 1 \
  main.pkl

CLI-Configurable Properties

The following properties can be overridden at deploy time via CLI flags:

Flag Default Description
--ami (required) Talos AMI ID
--environment From vars.pkl Environment name
--region From vars.pkl AWS region
--control-plane-count From vars.pkl Number of CP nodes
--worker-count From vars.pkl Number of worker nodes
--cp-instance-type From vars.pkl CP instance type
--worker-instance-type From vars.pkl Worker instance type