Learning objectives
- Read remote-state values as an explicit dependency between independently owned roots.
- Configure a private EKS API, five control-plane log types, and customer-managed secret encryption.
- Replace implicit cluster-creator access and
aws-authadministration with EKS access entries.
One-way state and resource ownership
The dependency points in one direction. The EKS root reads foundation outputs; the foundation never reads EKS state.
Control-plane contracts
| Terraform argument | AWS behavior | Plan question |
|---|---|---|
endpoint_private_access = trueendpoint_public_access = false | The Kubernetes API is reachable through VPC networking, not the public internet. | Where will CI and operators run so they can reach it? |
enabled_cluster_log_types | API, audit, authenticator, controller manager, and scheduler logs go to CloudWatch Logs. | Are all five present, and is log cost accepted? |
encryption_config | The foundation KMS key protects Kubernetes secrets. EKS 1.28+ also enables AWS-owned envelope encryption by default for API data. | Is this the same-region key and does its policy allow the operation? |
authentication_mode = "API" | IAM principals are managed with EKS access entries. | Are the administrator and bootstrap principals explicit? |
Lab: create a saved plan only
Use one CLI in one new working directory. Replace all example values before initialization.
export COURSE_ROOT="$PWD/learn-terraform/capstone"
export COURSE_AWS_PROFILE="replace-with-approved-aws-profile"
export COURSE_AWS_ACCOUNT_ID="replace-with-12-digit-account-id"
export COURSE_AWS_REGION="ap-south-1"
# Confirm the named profile, account, and region before either init.
ACTUAL_AWS_ACCOUNT_ID="$(aws --profile "$COURSE_AWS_PROFILE" --region "$COURSE_AWS_REGION" sts get-caller-identity --query Account --output text)"
test "$ACTUAL_AWS_ACCOUNT_ID" = "$COURSE_AWS_ACCOUNT_ID"
# Terraform choice in its own complete infra copy.
export TERRAFORM_EKS_DIR="$(mktemp -d)"
cp -R "$COURSE_ROOT/infra" "$TERRAFORM_EKS_DIR/infra"
cd "$TERRAFORM_EKS_DIR/infra/stacks/eks"
cp ../../environments/learning/eks.backend.hcl.example eks.backend.hcl
# Replace the bucket and KMS placeholders in this untracked copy.
terraform init -reconfigure -backend-config=eks.backend.hcl -backend-config="profile=$COURSE_AWS_PROFILE"
terraform validate
terraform plan -var-file=../../environments/learning/eks.tfvars -var="aws_profile=$COURSE_AWS_PROFILE" -var="expected_aws_account_id=$COURSE_AWS_ACCOUNT_ID" -out=tfplan
# OpenTofu alternative in a second complete infra copy.
export TOFU_EKS_DIR="$(mktemp -d)"
cp -R "$COURSE_ROOT/infra" "$TOFU_EKS_DIR/infra"
cd "$TOFU_EKS_DIR/infra/stacks/eks"
cp ../../environments/learning/eks.backend.hcl.example eks.backend.hcl
# Replace the bucket and KMS placeholders in this untracked copy.
tofu init -reconfigure -backend-config=eks.backend.hcl -backend-config="profile=$COURSE_AWS_PROFILE"
tofu validate
tofu plan -var-file=../../environments/learning/eks.tfvars -var="aws_profile=$COURSE_AWS_PROFILE" -var="expected_aws_account_id=$COURSE_AWS_ACCOUNT_ID" -out=tfplanThis chapter does not apply the plan. A private endpoint needs an approved VPC-connected execution path before cluster creation.
Review graph order and replacement
- Foundation remote state resolves before the EKS module knows subnet and KMS values.
- The cluster role policy attaches before the cluster; explicit access entries follow the cluster.
- The VPC CNI and Pod Identity Agent add-ons are created before managed nodes;
aws-nodereceivesAmazonEKS_CNI_Policythrough its dedicated Pod Identity role, never through worker roles. Node-dependent add-ons follow EC2 capacity. - A version increase is an EKS upgrade; downgrades are unsupported. Some creation settings replace the cluster.
- The certificate authority output is sensitive. That display flag does not remove it from state.
Failure drill
aws-auth the administration source of truth.Verify without AWS mutation
terraform -chdir=learn-terraform/capstone/infra/modules/eks test
tofu -chdir=learn-terraform/capstone/infra/modules/eks test
terraform fmt -check -recursive learn-terraform/capstone/infra
tofu fmt -check -recursive learn-terraform/capstone/infraThe tests use a mocked AWS provider and inspect planned arguments. They do not contact EKS.
Cleanup
Delete the two temporary working directories and saved plans. Do not run destroy: this is a plan-only checkpoint. After a future approved apply, remove workload states before EKS and foundation states.
Quick check
Why is an EKS access policy not an IAM policy?
It grants Kubernetes API authorization through EKS. IAM still controls authentication and AWS API calls.
Why keep Kubernetes and Helm providers out?
Terraform owns AWS infrastructure here. Argo CD later owns in-cluster desired state, leaving one reconciler per resource.
Recap and next
The control plane has a private endpoint, complete logs, explicit encryption, recoverable access, and managed add-ons, all derived from one-way foundation state.
Next: place platform, application, Spot, and Cassandra workloads on deliberate EC2 managed node groups.