Recently, I needed an EKS cluster at work to test a scenario. I asked myself how to set this up as quickly as possible while minimising cost. I decided to use infrastructure as code. I searched the Internet for tutorials I could follow and found one from HashiCorp, which I decided to give a go.
https://developer.hashicorp.com/terraform/tutorials/kubernetes/eks
Table of Contents
Clone the git repository
The first step is to clone the repository and download the files on your local machine.
pgulian@Mac repo % git clone https://github.com/hashicorp-education/learn-terraform-provision-eks-clusterCloning into 'learn-terraform-provision-eks-cluster'...remote: Enumerating objects: 271, done.remote: Counting objects: 100% (111/111), done.remote: Compressing objects: 100% (42/42), done.remote: Total 271 (delta 87), reused 69 (delta 69), pack-reused 160 (from 2)Receiving objects: 100% (271/271), 107.81 KiB | 2.57 MiB/s, done.Resolving deltas: 100% (144/144), done.pgulian@Mac repo % cd learn-terraform-provision-eks-clusterpgulian@Mac learn-terraform-provision-eks-cluster %

Initialise the directory with terraform init command
After you have downloaded the files and changed the directory, you need to initialise the directory with the command below.
pgulian@Mac learn-terraform-provision-eks-cluster % terraform initInitializing modules...Downloading registry.terraform.io/terraform-aws-modules/vpc/aws 5.8.1 for vpc...- vpc in .terraform/modules/vpcDownloading registry.terraform.io/terraform-aws-modules/iam/aws 5.39.0 for irsa-ebs-csi...- irsa-ebs-csi in .terraform/modules/irsa-ebs-csi/modules/iam-assumable-role-with-oidcDownloading registry.terraform.io/terraform-aws-modules/eks/aws 20.8.5 for eks...- eks in .terraform/modules/eks- eks.fargate_profile in .terraform/modules/eks/modules/fargate-profile- eks.self_managed_node_group in .terraform/modules/eks/modules/self-managed-node-group- eks.eks_managed_node_group in .terraform/modules/eks/modules/eks-managed-node-groupDownloading registry.terraform.io/terraform-aws-modules/kms/aws 2.1.0 for eks.kms...- eks.kms in .terraform/modules/eks.kms- eks.self_managed_node_group.user_data in .terraform/modules/eks/modules/_user_data- eks.eks_managed_node_group.user_data in .terraform/modules/eks/modules/_user_dataInitializing provider plugins found in the configuration...- Reusing previous version of hashicorp/random from the dependency lock file- Reusing previous version of hashicorp/tls from the dependency lock file- Reusing previous version of hashicorp/time from the dependency lock file- Reusing previous version of hashicorp/null from the dependency lock file- Reusing previous version of hashicorp/cloudinit from the dependency lock file- Reusing previous version of hashicorp/aws from the dependency lock file- Installing hashicorp/null v3.2.2...- Installed hashicorp/null v3.2.2 (signed by HashiCorp)- Installing hashicorp/cloudinit v2.3.4...- Installed hashicorp/cloudinit v2.3.4 (signed by HashiCorp)- Installing hashicorp/aws v5.47.0...- Installed hashicorp/aws v5.47.0 (signed by HashiCorp)- Installing hashicorp/random v3.6.1...- Installed hashicorp/random v3.6.1 (signed by HashiCorp)- Installing hashicorp/tls v4.0.5...- Installed hashicorp/tls v4.0.5 (signed by HashiCorp)- Installing hashicorp/time v0.11.1...- Installed hashicorp/time v0.11.1 (signed by HashiCorp)Initializing the backend...Terraform has been successfully initialized!You may now begin working with Terraform. Try running "terraform plan" to seeany changes that are required for your infrastructure. All Terraform commandsshould now work.If you ever set or change modules or backend configuration for Terraform,rerun this command to reinitialize your working directory. If you forget, othercommands will detect it and remind you to do so if necessary.pgulian@Mac learn-terraform-provision-eks-cluster %


Terraform has been successfully initialized!
Run the terraform plan command and inspect its output
The next step in the process is to run the terraform plan command. This command will generate a plan and show us which resources will be created in AWS.
pgulian@Mac learn-terraform-provision-eks-cluster % terraform planTerraform used the selected providers to generate the following execution plan. Resource actions are indicated with thefollowing symbols: + createTerraform planned the following actions, but then encountered a problem: # random_string.suffix will be created + resource "random_string" "suffix" { + id = (known after apply) + length = 8 + lower = true + min_lower = 0 + min_numeric = 0 + min_special = 0 + min_upper = 0 + number = true + numeric = true + result = (known after apply) + special = false + upper = true }Plan: 1 to add, 0 to change, 0 to destroy.Changes to Outputs: + region = "us-east-2"╷│ Error: Retrieving AWS account details: validating provider credentials: retrieving caller identity from STS: operation error STS: GetCallerIdentity, https response error StatusCode: 403, RequestID: 05dc8b84-9187-4a80-b8ba-5386066471c1, api error InvalidClientTokenId: The security token included in the request is invalid.│ │ with provider["registry.terraform.io/hashicorp/aws"],│ on main.tf line 4, in provider "aws":│ 4: provider "aws" {│ ╵pgulian@Mac learn-terraform-provision-eks-cluster %

Operation error STS: GetCallerIdentity, https response error StatusCode: 403
If you don’t specify any credentials, Terraform won’t be able to connect to the Cloud API. One way to expose credentials to Terraform is to use environment variables. You need to run a command similar to the one below.
pgulian@Mac learn-terraform-provision-eks-cluster % export AWS_ACCESS_KEY_ID=<YOUR-ACCESS-KEY-ID> pgulian@Mac learn-terraform-provision-eks-cluster % export AWS_SECRET_ACCESS_KEY=<YOUR-SECRET_ACCESS-KEY>
After you have exported the access keys, run the terraform plan command again.


Run the terraform apply command to deploy your infrastructure
After you have inspected the output of the terraform plan, the next step is to run the terraform apply command to deploy your infrastructure.


If you want to accept the actions described by the terraform apply command, enter yes to approve, and terraform will deploy your infrastructure.

Unfortunately, Terraform is unable to deploy the infrastructure to AWS due to an error.
module.vpc.aws_nat_gateway.this[0]: Creation complete after 1m46s [id=nat-01a4f466a5322e30a]module.vpc.aws_route.private_nat_gateway[0]: Creating...module.vpc.aws_route.private_nat_gateway[0]: Creation complete after 1s [id=r-rtb-00770f646918a13c81080289494]╷│ Error: creating EKS Cluster (education-eks-lvSAyKf7): operation error EKS: CreateCluster, https response error StatusCode: 400, RequestID: e82d4e6d-93c2-468a-ab1b-3e4767734c13, InvalidParameterException: unsupported Kubernetes version 1.29│ │ with module.eks.aws_eks_cluster.this[0],│ on .terraform/modules/eks/main.tf line 27, in resource "aws_eks_cluster" "this":│ 27: resource "aws_eks_cluster" "this" {│ ╵pgulian@Mac learn-terraform-provision-eks-cluster %

InvalidParameterException: unsupported Kubernetes version 1.29
Change the Kubernetes version in main.tf file
If you inspect the error message carefully, you will discover why the terraform apply command failed. We tried to deploy an unsupported Kubernetes version, 1.29. If we check the supported Kubernetes versions in the AWS documentation, we will find that Kubernetes version 1.29 is already out of support.
Excerpt from AWS documentation:
Available versions on standard supportThe following Kubernetes versions are currently available in Amazon EKS standard support:1.361.351.341.33
https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html#available-versions
The first version supported by AWS is Kubernetes 1.34. You need to update the version in the file main.tf (line 56) from the current version, 1.29, to 1.34.


Rerun the terraform apply command
After you have updated the Kubernetes version to 1.34, rerun the terraform apply command. I added the ‘-auto-approve’ flag to skip entering yes when prompted to accept the changes.

Regrettably, I faced a new error.
╷│ Error: creating EKS Node Group (education-eks-lvSAyKf7:node-group-2-20260731085724462400000006): operation error EKS: CreateNodegroup, https response error StatusCode: 400, RequestID: 5200bb69-7b3a-47b4-b1bc-9bc8a2014ba7, InvalidParameterException: AMI Type AL2_x86_64 is only supported for kubernetes versions 1.32 or earlier│ │ with module.eks.module.eks_managed_node_group["two"].aws_eks_node_group.this[0],│ on .terraform/modules/eks/modules/eks-managed-node-group/main.tf line 383, in resource "aws_eks_node_group" "this":│ 383: resource "aws_eks_node_group" "this" {│

InvalidParameterException: AMI Type AL2_x86_64 is only supported for kubernetes versions 1.32 or earlier
Change the AMI type from ami_type = “AL2_x86_64” to ami_type = “AL2023_x86_64_STANDARD”
If we inspect the error message, we will see that AMI Type AL2_x86_64 is supported only for Kubernetes versions 1.32 or earlier. Since we have changed the Kubernetes version to 1.34, we need to update the AMI Type from ami_type = “AL2_x86_64” to ami_type = “AL2023_x86_64_STANDARD”. Open the main.tf file and change the ami_type on line 71.


Repeat the terraform apply -auto-approve command
After you have changed the main.tf file, run the terraform apply -auto-approve command again. Hopefully, we ran the command for the last time.
pgulian@Mac learn-terraform-provision-eks-cluster % terraform apply -auto-approverandom_string.suffix: Refreshing state... [id=lvSAyKf7]module.eks.module.kms.data.aws_caller_identity.current[0]: Reading...module.eks.data.aws_caller_identity.current: Reading...module.irsa-ebs-csi.data.aws_caller_identity.current: Reading...
Voila, this time the ‘terraform apply’ command completed successfully. The EKS cluster should be up and running.

Configure kubectl and verify the cluster
The last step, of this tutorial is to configure kubectl and verify the Kubernetes cluster.
You need to run the following aws command.
pgulian@Mac learn-terraform-provision-eks-cluster % aws eks --region $(terraform output -raw region) update-kubeconfig \ --name $(terraform output -raw cluster_name)Added new context arn:aws:eks:us-east-2:533267288394:cluster/education-eks-lvSAyKf7 to /Users/pgulian/.kube/configpgulian@Mac learn-terraform-provision-eks-cluster %

To verify your cluster you can run the following command.
pgulian@Mac learn-terraform-provision-eks-cluster % kubectl get nodesNAME STATUS ROLES AGE VERSIONip-10-0-1-96.us-east-2.compute.internal Ready <none> 9m32s v1.34.9-eks-bca9cf6ip-10-0-2-57.us-east-2.compute.internal Ready <none> 9m31s v1.34.9-eks-bca9cf6ip-10-0-2-8.us-east-2.compute.internal Ready <none> 9m32s v1.34.9-eks-bca9cf6pgulian@Mac learn-terraform-provision-eks-cluster %

Clean all resources by running the terraform destroy command
If you no longer need your EKS cluster, don’t forget to clean up all the resources you created. Otherwise, you will incur costs. To remove all the resources you created in this tutorial, run the command below.
pgulian@Mac learn-terraform-provision-eks-cluster % terraform destroy -auto-approverandom_string.suffix: Refreshing state... [id=lvSAyKf7]module.eks.module.eks_managed_node_group["one"].data.aws_partition.current: Reading...module.eks.module.eks_managed_node_group["two"].data.aws_partition.current: Reading...module.irsa-ebs-csi.data.aws_caller_identity.current: Reading...module.irsa-ebs-csi.data.aws_partition.current: Reading...

That’s all. If you encounter a similar problem, you will know the likely cause and how to fix it. I opened a GitHub issue and submitted a pull request to HashiCorp Education to update the tutorial so others can follow along. Until they merge the pull request, you can follow the steps outlined above.
