21

Repeatable VPCs and Private Connectivity

Build the same isolated network contract in three AWS accounts before any Kubernetes workload exists.

Run it in the public monorepo

This course is built around the public Zheta Kubernetes Lab monorepo. The excerpt below is runnable source, not pseudocode.

Source: infra/modules/environment/main.tf

resource "aws_subnet" "private" {
  count             = 2
  vpc_id            = aws_vpc.this.id
  availability_zone = local.azs[count.index]
  cidr_block        = cidrsubnet(var.vpc_cidr, 4, count.index + 8)
  tags = merge(local.tags, {
    "kubernetes.io/role/internal-elb" = "1"
  })
}

Code to reality

Declared intent
Place environment workloads across two private availability-zone subnets.
Interpreter
Terraform and the AWS provider create subnets and label them for internal Kubernetes load balancers.
Software effect
EKS and its controllers discover private network placement from stable subnet IDs and tags.
Hardware effect
AWS allocates isolated address ranges and routes network interfaces across two physical zones.
Observable evidence
Terraform outputs, AWS subnet inventory, EKS node addresses, and a private connectivity probe agree.

Start with the people and the result they need

The source tables below remain the detailed contract. Begin with these customer paths:

  • D21-UC-01
    • Person: Platform engineer
    • Job: Create equivalent private network foundations in three isolated accounts
    • Observable result: Each plan contains non-overlapping public/private subnets, per-zone NAT, service endpoints, and private EKS placement
  • D21-UC-02
    • Person: Security reviewer
    • Job: Review private enterprise connectivity without claiming unimplemented telemetry
    • Observable result: Approved endpoint configuration is present and unsolicited ingress has no declared rule

Turn each customer job into a testable story

Now turn each customer job into a story with a result that an engineer can check:

  • D21-US-01
    • Story: As a platform engineer, I want one parameterised VPC module instantiated per account, so that fixes are reusable without sharing runtime state
    • Observable acceptance: Plans use the same module version, distinct account aliases, CIDRs, state keys, and resource IDs
  • D21-US-02
    • Story: As a security reviewer, I want missing runtime reachability evidence to block approval, so that a green Terraform plan is not mistaken for a safe…
    • Observable acceptance: Review names source, destination, protocol, expected result, current plan observation, account, time, run, and the missing Flow Log/runtime-proof…

Add real state and observable proof

Finally trace each story through the system that owns its state and the evidence that proves the outcome:

  • D21-FLOW-01
    • Trigger: Engineer proposes the network revision
    • Responsible systems: Terraform CLI, AWS provider, VPC, subnets, route tables, NAT, endpoints, KMS
    • Authoritative state: Reviewed Git revision plus one remote Terraform state per account/environment
    • Owned record: NetworkStackRevision
    • Observable evidence: Account ID, plan digest, state key, VPC/subnet/endpoint IDs, successful probe, environment, timestamp, and run ID
    • Failure signal: Provider-account mismatch, CIDR collision, public worker placement, missing endpoint, or apply error
  • D21-FLOW-02
    • Trigger: Reviewer evaluates network evidence before any apply
    • Responsible systems: IAM, security groups, route tables, endpoint declarations, policy gate
    • Authoritative state: Terraform plan before apply; AWS network APIs only after approved deployment
    • Owned record: ReachabilityEvidence
    • Observable evidence: Plan fields, missing-runtime-proof finding, actor, resource, protocol, account, environment, time, and run ID
    • Failure signal: Unexpected ingress rule, wrong endpoint target, or missing required runtime-proof control

The enterprise problem and today’s slice

Enterprise problem: A generated application can pass local tests yet leak data or become unreachable in AWS when routes, endpoints, and egress rules differ by environment. Whole-course context: The incoming evidence separates infrastructure state from workload state; today creates the network foundation consumed by every later EKS cluster. Today’s slice: We inspect the real reusable infra/modules/environment VPC declaration and instantiate it independently in dev, staging, and production AWS accounts. End-of-day evidence: Three reviewed plans identify account, VPC, public and private subnets, NAT routes, AWS service and optional enterprise connector endpoints, denied ingress expectation, environment, timestamp, and immutable run ID; VPC Flow Logs are explicitly a remaining gap because the current module does not declare them. Still unsolved: No AWS apply, EKS runtime, workload, public route, or Flow Log proof exists until owner-approved cloud execution.

Customer use cases

Networks fail customers when reachability is accidental, so the contract must prove both an intended path and a denial. A virtual private cloud (VPC) is an isolated AWS network boundary.

Use case IDActorCustomer jobSuccess outcomeDenial or recovery evidence
D21-UC-01Platform engineerCreate equivalent private network foundations in three isolated accountsEach plan contains non-overlapping public/private subnets, per-zone NAT, service endpoints, and private EKS placementA plan with overlapping ranges or public worker placement is rejected
D21-UC-02Security reviewerReview private enterprise connectivity without claiming unimplemented telemetryApproved endpoint configuration is present and unsolicited ingress has no declared rulePlan evidence records the denied design expectation and a production gap for runtime reachability/Flow Log proof

Actor-centred user stories

Copying whole network stacks creates silent drift, while sharing one VPC collapses isolation. These stories require one module contract and three independent instances.

Story IDUse case IDsUser storyObservable acceptance conditions
D21-US-01D21-UC-01As a platform engineer, I want one parameterised VPC module instantiated per account, so that fixes are reusable without sharing runtime statePlans use the same module version, distinct account aliases, CIDRs, state keys, and resource IDs
D21-US-02D21-UC-02As a security reviewer, I want missing runtime reachability evidence to block approval, so that a green Terraform plan is not mistaken for a safe networkReview names source, destination, protocol, expected result, current plan observation, account, time, run, and the missing Flow Log/runtime-proof control

End-to-end product flows

A network plan is only an intermediate artifact; the customer-relevant result is a bounded private path that later workloads can use. The denied flow proves isolation rather than merely claiming it.

Flow IDUse case IDsPathTriggerNumbered stepsTerminal evidence
D21-FLOW-01D21-UC-01HappyEngineer proposes the network revision1. Assume the environment deployment role. 2. Select that environment’s remote state. 3. Plan the shared module with unique CIDR and Availability Zones. 4. Review routes, endpoints, encryption, and logs. 5. Apply only after approval. 6. Probe an approved AWS endpoint.Account ID, plan digest, state key, VPC/subnet/endpoint IDs, successful probe, environment, timestamp, and run ID
D21-FLOW-02D21-UC-02DeniedReviewer evaluates network evidence before any apply1. Resolve planned source and target. 2. Verify account/VPC variables. 3. Inspect planned routes, endpoints, and security groups. 4. Record that runtime denial and positive control are unavailable. 5. Block production acceptance.Plan fields, missing-runtime-proof finding, actor, resource, protocol, account, environment, time, and run ID

The engineer asks for private connectivity and finishes with a real network observation, not a plan exit code.

System design derived from the flows

A VPC module and its three instances solve different responsibilities: the module removes duplication, while each stack owns isolated addresses and state. AWS Identity and Access Management (IAM) limits which deployment role may change each account.

Use case IDEntry pointResponsible servicesAuthoritative storeFailure evidence
D21-UC-01infra/modules/environment consumed by infra/stacks/{dev,staging,prod}Terraform CLI, AWS provider, VPC, subnets, route tables, NAT, endpoints, KMSReviewed Git revision plus one remote Terraform state per account/environmentProvider-account mismatch, CIDR collision, public worker placement, missing endpoint, or apply error
D21-UC-02Network plan reviewIAM, security groups, route tables, endpoint declarations, policy gateTerraform plan before apply; AWS network APIs only after approved deploymentUnexpected ingress rule, wrong endpoint target, or missing required runtime-proof control

Terraform interprets the reusable declaration, but the AWS account owns the real routes and packets. The denial box adds the security consequence missing from a topology-only drawing.

DRY is the shared infra/modules/environment contract; SRP keeps each stack responsible for one account, while Terraform’s provider injection is IoC/DI at the infrastructure boundary. MVC and PubSub remain product-layer patterns and must not be invented inside the network module.

Data model and ownership

Network identity must remain independent in each account or deleting dev could mutate production. Durable infrastructure and evidence records are sufficient for this slice.

Generated-application database: Not created in this slice — network intent, AWS resource state, Terraform mappings, and reachability evidence are durable without generated-application domain data.

Record or entityStore and ownerPrimary keyForeign key or opaque referenceTenant keyMaterial constraintLifecycle and deletionUse case IDs
NetworkStackRevisionGit and remote Terraform backend, owned by Infrastructure Platformenvironment plus commit SHAOpaque AWS account and state object referencesenvironment_idOne account, role, CIDR, and state key per environment; CIDRs never overlapPlan, approve, apply, supersede; destroy only after cluster/data dependencies retireD21-UC-01, D21-UC-02
ReachabilityEvidenceEvidence Store, owned by Security Operationsevidence_idOpaque planned VPC, source, target, and run referencesenvironment_idExpected and observed plan result plus explicit missing runtime proof are mandatoryAppend plan review; replace gap only with real applied-path evidence; retain by audit policyD21-UC-01, D21-UC-02

The same VPC now owns a lifecycle record, while successful and denied traffic converge on immutable evidence without transferring network authority to the evidence service.

Declare and inspect the network contract

An environment can silently target the wrong account, so validate caller identity before planning. Run this labelled snippet from the public zheta-kubernetes-lab monorepo; its stable inputs are infra/modules/environment and infra/stacks/dev (with sibling staging and prod stacks).

: "${AWS_PROFILE:?set the approved AWS profile}" "${AWS_REGION:?set the intended AWS region}" "${EXPECTED_ACCOUNT_ID:?set the intended 12-digit AWS account}"
actual_account="$(aws --profile "$AWS_PROFILE" --region "$AWS_REGION" sts get-caller-identity --query Account --output text)"
[ "$actual_account" = "$EXPECTED_ACCOUNT_ID" ] || { echo "AWS account mismatch" >&2; exit 1; }
aws --profile "$AWS_PROFILE" --region "$AWS_REGION" sts get-caller-identity                         # Prove which account the shell can change.
terraform -chdir=infra/stacks/dev init -reconfigure -backend-config=backend.hcl
terraform -chdir=infra/stacks/dev plan -out=plan.bin -var-file=environment.tfvars
terraform -chdir=infra/stacks/dev show -json plan.bin > plan.json

backend.hcl and environment.tfvars are intentionally operator-supplied and uncommitted; the committed examples do not grant AWS authority. The module’s current network is private EKS placement with NAT egress and selected endpoints, not a fully private cluster with no internet egress.

Effect fieldWhat happens
Declared intentCreate one dev network from the shared module without sharing staging or production state
InterpreterTerraform reads configuration and the AWS provider calls account-scoped APIs
Software effectThe plan records proposed VPC, subnet, route, endpoint, encryption, and logging changes
Hardware effectPlanning creates none; apply later allocates provider network and logging capacity
EvidenceCaller account, plan digest, resource addresses, state key, and reviewed JSON

Three authorization planes and lifecycle rule

Network reachability does not grant product authority, or a private packet could become an administrator session. The provider plane owns organizations and release policy; the hosted-runtime plane owns VPC, EKS network, workload identity, and deployment; each generated application owns its tenants, sessions, roles, and domain rows.

Decision rule: promote the same module revision, never credentials or state; retire application traffic and data dependencies before destroying a cluster, and destroy the cluster before its VPC.

Key takeaways

Private networking is a tested product boundary, not a collection of subnets.

  • Reuse module code while isolating accounts, CIDRs, roles, and state.
  • Prove both an approved path and a denied path.
  • A local Kind network shares one laptop and does not prove AWS failure-domain isolation.

Checklist

The network foundation is ready only when all three stacks are reviewable and independent.

  • [ ] Dev, staging, and production target distinct AWS accounts and state keys
  • [ ] Private subnets have no accidental public ingress path
  • [ ] Endpoint success and ingress denial evidence share one run window
  • [ ] Destruction order protects clusters and managed data