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.0schema underlib/aws/, fixing type issues in the upstream package (e.g.AvailabilityZoneregex foraf-south-1,Resolvabletype unions)
To resolve dependencies:
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 |