Provision an AWS EKS Cluster with Terraform
Tags: aws, eks, containers, terraform
Published: 2022-03-07 06:44:23



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqtz4guxeweqjkfajtz7.png)

The Amazon Elastic Kubernetes Service (EKS) is the AWS service for deploying, managing, and scaling containerised applications with Kubernetes.

In this tutorial, you will deploy an EKS cluster using Terraform. Then, you will configure kubectl using Terraform output to deploy a Kubernetes dashboard on the cluster.

## Warning! 

AWS charges $0.10 per hour for each EKS cluster. As a result, you may be charged to run these examples. The most you should be charged should only be a few dollars, but we're not responsible for any charges that may incur.

## Prerequisites

The tutorial assumes some basic familiarity with Kubernetes and kubectl but does not assume any pre-existing deployment.
It also assumes that you are familiar with the usual Terraform plan/apply workflow. If you're new to Terraform itself, refer first to the Getting Started tutorial.
For this tutorial, you will need:

- an AWS account with the IAM permissions listed on the EKS module documentation,
- a configured AWS CLI
- AWS IAM Authenticator
- kubectl
- wget (required for the eks module)

**Install kubernetes-cli**

```
 ~/Documents/terraform/eks/learn-terraform-provision-eks-cluster  brew install kubernetes-cli                                                                                  
==> Fetching kubernetes-cli
==> Downloading https://ghcr.io/v2/homebrew/core/kubernetes-cli/manifests/1.26.1
Already downloaded: /Users/macpro/Library/Caches/Homebrew/downloads/63e7a94ebb853d4f726581e254842e45a6e8305d955f360e72af209f2f8adcbe--kubernetes-cli-1.26.1.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/kubernetes-cli/blobs/sha256:e421cee1a3cbf04cc5f7e95f1905c461a919dea708fcfe1c1fc4761eea6ddc74
Already downloaded: /Users/macpro/Library/Caches/Homebrew/downloads/1c5e71bb1412d2df34977944c140e00d844a3181516b65e03acfdf4fb8681de2--kubernetes-cli--1.26.1.monterey.bottle.tar.gz
==> Pouring kubernetes-cli--1.26.1.monterey.bottle.tar.gz
```

**Install wget**

```
 ~/Documents/terraform/eks/learn-terraform-provision-eks-cluster  brew install wget                                                                                         
==> Fetching wget
==> Downloading https://ghcr.io/v2/homebrew/core/wget/manifests/1.21.3_1-1
Already downloaded: /Users/macpro/Library/Caches/Homebrew/downloads/2ef23ba6d50b94e2e5b16bba0fe18c0df83f42785d49552605f46d361bd84f20--wget-1.21.3_1-1.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/wget/blobs/sha256:f97fc2639cd9d2d037c2bf1a94fa664ef2d81143ce8a1fb5b740ce2eb397889c
Already downloaded: /Users/macpro/Library/Caches/Homebrew/downloads/8968fe29268853ab8361398eb78165cc24477926249ee8eabfefca511edff2fd--wget--1.21.3_1.monterey.bottle.1.tar.gz
==> Pouring wget--1.21.3_1.monterey.bottle.1.tar.gz
🍺  /usr/local/Cellar/wget/1.21.3_1: 89 files, 4.2MB
==> Running `brew cleanup wget`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).


```

**Install aws-iam-authenticator**
```
 ~/Documents/terraform/eks/learn-terraform-provision-eks-cluster  brew install aws-iam-authenticator                                                                          
Running `brew update --auto-update`...
==> Fetching aws-iam-authenticator
==> Downloading https://ghcr.io/v2/homebrew/core/aws-iam-authenticator/manifests/0.6.2
Already downloaded: /Users/macpro/Library/Caches/Homebrew/downloads/e251185a1ea710821d02632d0f3ad0125077b35afb2d18c3277d77da16be0f70--aws-iam-authenticator-0.6.2.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/aws-iam-authenticator/blobs/sha256:aac61dd3e3363ee81e07273c388b21d9da51d41c820791cbb020e842b1e10d6f
Already downloaded: /Users/macpro/Library/Caches/Homebrew/downloads/fb62714ec96174597d8033155b61f67bb92d02dd6d479e35d19da3864a4663d1--aws-iam-authenticator--0.6.2.monterey.bottle.tar.gz
==> Pouring aws-iam-authenticator--0.6.2.monterey.bottle.tar.gz
🍺  /usr/local/Cellar/aws-iam-authenticator/0.6.2: 6 files, 51.0MB
==> Running `brew cleanup aws-iam-authenticator`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).

```

**Install awscli**
```
 ~/Documents/terraform/eks/learn-terraform-provision-eks-cluster  brew install awscli                                                                                      
==> Fetching awscli
==> Downloading https://ghcr.io/v2/homebrew/core/awscli/manifests/2.9.17
Already downloaded: /Users/macpro/Library/Caches/Homebrew/downloads/9cd748e86a4b630dc407cdbc87b047951d9d84afc83f87d678cc498535027f6d--awscli-2.9.17.bottle_manifest.json
==> Downloading https://ghcr.io/v2/homebrew/core/awscli/blobs/sha256:f57e358226684679f455bacba65c57359f42d814831391ac13e0778f84588dc0
Already downloaded: /Users/macpro/Library/Caches/Homebrew/downloads/b352ffeef1ffd5a6b2a3431d3f65bd33593f0fb15b0bd23f9f6ed1cece9bef02--awscli--2.9.17.monterey.bottle.tar.gz
==> Pouring awscli--2.9.17.monterey.bottle.tar.gz
==> Caveats
The "examples" directory has been installed to:
  /usr/local/share/awscli/examples

zsh completions and functions have been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/awscli/2.9.17: 13,147 files, 114.3MB
==> Running `brew cleanup awscli`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).

```

After you've installed the AWS CLI, configure it by running **aws configure**.

When prompted, enter your AWS Access Key ID, Secret Access Key, region and output format.

```
$ aws configure
AWS Access Key ID [None]: YOUR_AWS_ACCESS_KEY_ID
AWS Secret Access Key [None]: YOUR_AWS_SECRET_ACCESS_KEY
Default region name [None]: YOUR_AWS_REGION
Default output format [None]: json
```

## Set up and initialise your Terraform workspace

In your terminal, clone the following repository. It contains the example configuration used in this tutorial.

```
$ git clone https://github.com/hashicorp/learn-terraform-provision-eks-cluster

$ cd learn-terraform-provision-eks-cluster
```

In here, you will find six files used to provision a VPC, security groups and an EKS cluster. The final product should be similar to this:

**High-level Architecture**
![EKS Cluster](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kgoip0bcc7ez6zx4g41x.png)

1. vpc.tf provisions a VPC, subnets and availability zones using the AWS VPC Module. A new VPC is created for this tutorial so it doesn't impact your existing cloud environment and resources.
2. security-groups.tf provisions the security groups used by the EKS cluster.
3. eks-cluster.tf provisions all the resources (AutoScaling Groups, etc...) required to set up an EKS cluster using the AWS EKS Module.
4. outputs.tf defines the output configuration.
5. versions.tf sets the Terraform version to at least 0.14. It also sets versions for the providers used in this sample.

## Initialise Terraform workspace

```
$ terraform init
 ~/Documents/terraform/eks/learn-terraform-provision-eks-cluster  main  terraform init                                                                                                       ✔  06:23:13
Initializing modules...
Downloading registry.terraform.io/terraform-aws-modules/eks/aws 19.0.4 for eks...
- eks in .terraform/modules/eks
- eks.eks_managed_node_group in .terraform/modules/eks/modules/eks-managed-node-group
- eks.eks_managed_node_group.user_data in .terraform/modules/eks/modules/_user_data
- eks.fargate_profile in .terraform/modules/eks/modules/fargate-profile
Downloading registry.terraform.io/terraform-aws-modules/kms/aws 1.1.0 for eks.kms...
- eks.kms in .terraform/modules/eks.kms
- eks.self_managed_node_group in .terraform/modules/eks/modules/self-managed-node-group
- eks.self_managed_node_group.user_data in .terraform/modules/eks/modules/_user_data
Downloading registry.terraform.io/terraform-aws-modules/vpc/aws 3.14.2 for vpc...
- vpc in .terraform/modules/vpc

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/tls from the dependency lock file
- Reusing previous version of hashicorp/cloudinit from the dependency lock file
- Reusing previous version of hashicorp/kubernetes from the dependency lock file
- Reusing previous version of hashicorp/aws from the dependency lock file
- Reusing previous version of hashicorp/random from the dependency lock file
- Installing hashicorp/tls v4.0.4...
- Installed hashicorp/tls v4.0.4 (signed by HashiCorp)
- Installing hashicorp/cloudinit v2.2.0...
- Installed hashicorp/cloudinit v2.2.0 (signed by HashiCorp)
- Installing hashicorp/kubernetes v2.16.1...
- Installed hashicorp/kubernetes v2.16.1 (signed by HashiCorp)
- Installing hashicorp/aws v4.46.0...
- Installed hashicorp/aws v4.46.0 (signed by HashiCorp)
- Installing hashicorp/random v3.4.3...
- Installed hashicorp/random v3.4.3 (signed by HashiCorp)

Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should 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, other
commands will detect it and remind you to do so if necessary.
```

## Provision the EKS cluster

In your initialised directory, run terraform apply and review the planned actions. Your terminal output should indicate the plan is running and what resources will be created.

```
$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
 <= read (data resources)

Terraform will perform the following actions:

  ## ...

Plan: 53 to add, 0 to change, 0 to destroy.

  ## ...

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:
```

This terraform apply will provision a total of 53 resources (VPC, Security Groups, AutoScaling Groups, EKS Cluster, etc...). Confirm the apply with a yes.

This process should take approximately 10 minutes. Upon successful application, your terminal prints the outputs defined in outputs.tf.

```
Apply complete! Resources: 53 added, 0 changed, 0 destroyed.

Outputs:

cluster_endpoint = "https://B7994AFC945AB5029A4E2BA8DB39B448.gr7.us-east-2.eks.amazonaws.com"
cluster_id = "education-eks-p8Zqwv78"
cluster_name = "education-eks-p8Zqwv78"
cluster_security_group_id = "sg-09378904e5421f22e"
config_map_aws_auth = [
  {
    "binary_data" = tomap(null) /* of string */
    "data" = tomap({
      "mapAccounts" = <<-EOT
      []

      EOT
      "mapRoles" = <<-EOT
      - "groups":
        - "system:bootstrappers"
        - "system:nodes"
        "rolearn": "arn:aws:iam::561656980159:role/education-eks-p8Zqwv782021011204012796010000000c"
        "username": "system:node:{{EC2PrivateDNSName}}"

      EOT
      "mapUsers" = <<-EOT
      []

      EOT
    })
    "id" = "kube-system/aws-auth"
    "metadata" = tolist([
      {
        "annotations" = tomap(null) /* of string */
        "generate_name" = ""
        "generation" = 0
        "labels" = tomap({
          "app.kubernetes.io/managed-by" = "Terraform"
          "terraform.io/module" = "terraform-aws-modules.eks.aws"
        })
        "name" = "aws-auth"
        "namespace" = "kube-system"
        "resource_version" = "942"
        "self_link" = "/api/v1/namespaces/kube-system/configmaps/aws-auth"
        "uid" = "f328b2d0-f099-4e72-a1b1-760781045f10"
      },
    ])
  },
]
kubectl_config = ...
## ...
```

## Clean up your workspace

Congratulations, you have provisioned an EKS cluster in a private subnet. 

Remember to destroy any resources you create once you are done with this tutorial. Run the destroy command and confirm with yes in your terminal. This will destroy all the 53 resources Terraform created. 

```
$ terraform destroy

```

**Ref: https://learn.hashicorp.com/tutorials/terraform/eks**