Skip to content
You are reading dev: the documentation of main. The last release, 0.1.0, predates this site.

Prerequisites

Tick these before tofu apply runs opentofu/clusters/aws. The socle creates none of it.

  • An AWS account and a region (the root’s aws.region).
  • A cluster_name unique in the account: IAM names are per account, even across regions.
  • iam:CreateServiceLinkedRole, if the account has never run EKS, EC2 Spot or Auto Scaling.
  • With gateway_certificate: a public Route 53 hosted zone in the same account, for the domain or a parent of it.
  • GuardDuty, if wanted, turned on by the account owner.
  • A principal with a policy scoped to the services below, not AdministratorAccess. Credentials come from the ambient chain: a profile locally, an OIDC role in CI; no IAM access key.
  • The same principal creates the cluster: it becomes its first admin. Another principal later needs its own EKS access entry.
  • The runner’s public IP in cluster_endpoint_public_access_cidrs: Helm talks to the public endpoint during the apply.
ServiceWhat the apply needs
EC2VPC, subnets, routes, internet gateway, Elastic IPs, NAT Gateways, VPC endpoints and their security group, flow logs, the launch template
EKScluster, node group, add-ons (CreateAddon, DescribeAddon, UpdateAddon, DeleteAddon), Pod Identity associations, tags
IAMroles, inline policies, attachments; iam:CreatePolicy for the Crossplane boundary; iam:PassRole (see below)
KMStwo keys with rotation and key policy; kms:DescribeKey on the logs key
CloudWatch Logsthe control-plane and flow-log groups, retention, KMS key
ACM, Route 53with gateway_certificate only (see below)
STSGetCallerIdentity
Under the hood
  • iam:PassRole: the cluster and node roles to EKS, the flow logs role to VPC flow logs, the Crossplane and CSI drivers’ roles to pods.eks.amazonaws.com.
  • Without kms:DescribeKey on the logs key, CreateLogGroup with a kmsKeyId fails with AccessDeniedException.
  • ACM: RequestCertificate, DescribeCertificate, ListTagsForCertificate. Route 53: ListHostedZones, GetHostedZone, ChangeResourceRecordSets, GetChange, ListResourceRecordSets.
  • The first admin comes from bootstrap_cluster_creator_admin_permissions = true, through an EKS access entry.
  • An S3 bucket, versioned, Block Public Access on, encrypted (SSE-S3 is the default), apart from application data. No DynamoDB table: use_lockfile = true locks.
Terminal window
aws s3api create-bucket --bucket acme-tofu-state --region eu-west-3 \
--create-bucket-configuration LocationConstraint=eu-west-3
aws s3api put-bucket-versioning --bucket acme-tofu-state \
--versioning-configuration Status=Enabled
aws s3api put-public-access-block --bucket acme-tofu-state \
--public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

One key per cluster; expire only noncurrent versions:

terraform {
backend "s3" {
bucket = "acme-tofu-state"
key = "socle/aws/acme-prod.tfstate"
region = "eu-west-3"
use_lockfile = true
}
}
  • OpenTofu 1.13 or later: below it, tofu init of the public OCI modules fails with a 403 (Distribution).
  • The AWS CLI: the helm provider gets its token from aws eks get-token.
  • kubectl.
  • cosign, to verify the modules package: OpenTofu does not verify OCI signatures.
  • Elastic IPs: one per AZ per cluster, against a default of 5 per region. A third cluster on two AZs, or a second on three, needs an increase.
  • VPCs: one per cluster, 5 per region by default.
  • Also per cluster: one NAT Gateway per AZ, five interface endpoints, two Spot instances.