{"id":19926373,"url":"https://github.com/fullstackwithlawrence/production-ready-aws-eks","last_synced_at":"2026-06-06T13:31:06.470Z","repository":{"id":183573422,"uuid":"670373326","full_name":"FullStackWithLawrence/production-ready-aws-eks","owner":"FullStackWithLawrence","description":"Scaffolding to create a production-ready Kubernetes cluster","archived":false,"fork":false,"pushed_at":"2023-08-04T12:24:49.000Z","size":2301,"stargazers_count":11,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-19T22:38:45.847Z","etag":null,"topics":["aws","aws-eks"],"latest_commit_sha":null,"homepage":"https://www.youtube.com/@FullStackWithLawrence","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FullStackWithLawrence.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"github":"lpm0073","patreon":"FullStackWithLawrence"}},"created_at":"2023-07-24T23:08:35.000Z","updated_at":"2024-12-19T23:53:09.000Z","dependencies_parsed_at":"2023-07-25T01:51:54.389Z","dependency_job_id":null,"html_url":"https://github.com/FullStackWithLawrence/production-ready-aws-eks","commit_stats":null,"previous_names":["fullstackwithlawrence/010-most-important-kubernetes-video","fullstackwithlawrence/production-ready-aws-eks"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FullStackWithLawrence%2Fproduction-ready-aws-eks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FullStackWithLawrence%2Fproduction-ready-aws-eks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FullStackWithLawrence%2Fproduction-ready-aws-eks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FullStackWithLawrence%2Fproduction-ready-aws-eks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FullStackWithLawrence","download_url":"https://codeload.github.com/FullStackWithLawrence/production-ready-aws-eks/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241354994,"owners_count":19949291,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-eks"],"created_at":"2024-11-12T22:29:02.721Z","updated_at":"2026-06-06T13:31:06.465Z","avatar_url":"https://github.com/FullStackWithLawrence.png","language":"HCL","funding_links":["https://github.com/sponsors/lpm0073","https://patreon.com/FullStackWithLawrence"],"categories":[],"sub_categories":[],"readme":"[![Source code](https://img.shields.io/static/v1?logo=youtube\u0026label=YouTube\u0026style=flat-square\u0026color=red\u0026message=Video)](https://www.youtube.com/watch?v=vVgUT4okdsY)\n[![Documentation](https://img.shields.io/static/v1?\u0026label=Documentation\u0026style=flat-square\u0026color=000000\u0026message=Documentation)](https://blog.lawrencemcdaniel.com/production-ready-aws-elastic-kubernetes-service/)\n[![AGPL License](https://img.shields.io/github/license/overhangio/tutor.svg?style=flat-square)](https://www.gnu.org/licenses/agpl-3.0.en.html)\n[![hack.d Lawrence McDaniel](https://img.shields.io/badge/hack.d-Lawrence%20McDaniel-orange.svg)](https://lawrencemcdaniel.com)\n\n# Production-Ready AWS Elastic Kubernetes Service\n\nThis is the source code for my [Blog Article](https://blog.lawrencemcdaniel.com/production-ready-aws-elastic-kubernetes-service/) and [FullStackWithLawrence Youtube Video](https://www.youtube.com/watch?v=vVgUT4okdsY).\n\n[![Watch the video](https://i3.ytimg.com/vi/vVgUT4okdsY/maxresdefault.jpg)](https://www.youtube.com/watch?v=vVgUT4okdsY)\n\nTerraform scaffolding to create a production-ready Kubernetes cluster running inside its own VPC. Sets up spot pricing for EC2 instances, and installs and configures commonly needed packages including:\n\n- nginx-ingress-controller\n- cert-manager\n- metrics-server\n- prometheus\n- vertical pod autoscaler (vpa)\n\nConsists of the following source code: \n\n```console\n-------------------------------------------------------------------------------\nLanguage                     files          blank        comment           code\n-------------------------------------------------------------------------------\nHCL                             39            318            457           1410\nText                             1            118              0            553\nMarkdown                         2            101              0            260\nJSON                             1              0              0            176\nYAML                            10              1              3            163\n-------------------------------------------------------------------------------\nSUM:                            53            538            460           2562\n-------------------------------------------------------------------------------\n```\n\n## Usage\n\n```console\nfoo@bar:~$ git clone https://github.com/FullStackWithLawrence/010-most-important-kubernetes-video.git\nfoo@bar:~$ cd 010-most-important-kubernetes-video\nfoo@bar:~$ terraform init\nfoo@bar:~$ terraform apply\n```\n\n## How To Setup Your Local Environment\n\nThis document describes how to deploy a [Managed Kubernetes Service Cluster](https://aws.amazon.com/eks/) with [AWS cloud infrastructure](https://aws.amazon.com/).\n\nThis is a [Terraform](https://www.terraform.io/) based installation methodology that reliably automates the complete build, management and destruction processes of all resources. [Terraform](https://www.terraform.io/) is an [infrastructure-as-code](https://en.wikipedia.org/wiki/Infrastructure_as_code) command line tool that will create and configure all of the software and cloud infrastructure resources that are needed for running EKS. These Terraform scripts will install and configure all cloud infrastructure resources and system software on which EKS depends. This process will take around 15 minutes to complete and will generate copious amounts of console output.\n\nTerraform will create a dedicated [AWS Virtual Private Network (VPC)](https://aws.amazon.com/vpc/) to contain all other resources that it creates. This VPC serves as an additional 'chinese wall' that prevents these AWS resources and system software packages from being able to interact with any other AWS resources that might already exist in your AWS account. This additional layer is strongly recommended, and you will incur negligable additional AWS cost for adding this additional layer of security protection.\n\nThis EKS application stack consists of the following:\n\n* a AWS S3 bucket and DynamoDB table for managing Terraform state\n* a dedicated [AWS VPC](https://aws.amazon.com/vpc/)\n* a dedicated [AWS EKS Kubernetes cluster](https://aws.amazon.com/eks/)\n  * a configurable [Managed Node Group](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) with on-demand and spot-priced tier options\n  * AWS EKS Add-on [EFS CSI Driver](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html)\n  * AWS EKS Add-on [EBS CSI Driver](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html)\n  * AWS EKS Add-on [VPC CNI](https://docs.aws.amazon.com/eks/latest/userguide/managing-vpc-cni.html)\n  * AWS EKS Add-on [kube-proxy](https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html)\n  * AWS EKS Add-on [CoreDNS](https://docs.aws.amazon.com/eks/latest/userguide/managing-coredns.html)\n* Kubernetes [Vertical Pod Autoscaler](https://docs.aws.amazon.com/eks/latest/userguide/vertical-pod-autoscaler.html)\n* Kubernetes [Metrics Server](https://github.com/kubernetes-sigs/metrics-server)\n* Kubernetes [Prometheus](https://prometheus.io/)\n* Kubernetes [cert-manager](https://cert-manager.io/)\n* Kubernetes [Nginx Ingress Controller](https://docs.nginx.com/nginx-ingress-controller/)\n* Kubernetes [Karpenter](https://karpenter.sh/)\n\n**WARNINGS**:\n\n**1. The EKS service will create many AWS resources in other parts of your AWS account including EC2, VPC, IAM and KMS. You should not directly modify any of these resources, as this could lead to unintended consequences in the safe operation of your Kubernetes cluster up to and including permanent loss of access to the cluster itself.**\n\n**2. Terraform is a memory intensive application. For best results you should run this on a computer with at least 4Gib of free memory.**\n\n## I. Installation Prerequisites\n\nQuickstart for Linux \u0026 macOS operating systems.\n\n**Prerequisite:** Obtain an [AWS IAM User](https://aws.amazon.com/iam/) with administrator priviledges, access key and secret key.\n\nEnsure that your environment includes the latest stable releases of the following software packages:\n\n* [aws cli](https://aws.amazon.com/cli/)\n* [kubectl (Kubernetes cli)](https://kubernetes.io/docs/tasks/tools/)\n* [terraform](https://www.terraform.io/)\n* [helm](https://helm.sh/)\n* [k9s](https://k9scli.io/)\n\n### Install required software packages using Homebrew\n\nIf necessary, install [Homebrew](https://brew.sh/)\n\n```console\n/bin/bash -c \"$(curl -fsSL https://github.com//Homebrew/install/HEAD/install.sh)\"\necho 'eval \"$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)\"' \u003e\u003e /home/ubuntu/.profile\neval \"$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)\"\n```\n\nUse homebrew to install all required packages.\n\n```console\nbrew install awscli kubernetes-cli terraform helm k9s\n```\n\n### Configure the AWS CLI\n\nTo configure the AWS CLI run the following command:\n\n```console\naws configure\n```\n\nThis will interactively prompt for your AWS IAM user access key, secret key and preferred region.\n\n### Install Helm charts\n\nHelm helps you manage Kubernetes applications. Based on yaml 'charts', Helm helps you define, install, and upgrade even the most complex Kubernetes applications. Wolfram Application Server depends on multiple large complex subsystems, and fortunately, vendor-supported Helm charts are available for each of these.\n\nHelm charts first need to be downloaded and added to your local Helm repository. The helm charts will be automatically executed by Terraform at the appropriate time, so there is nothing further that you need to do beyond adding these charts to your local helm repository.\n\n```console\nhelm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/\nhelm repo add jetstack https://charts.jetstack.io\nhelm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx\nhelm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/\nhelm repo add prometheus-community https://prometheus-community.github.io/helm-charts/\nhelm repo add cowboysysop https://cowboysysop.github.io/charts/\nhelm repo update\n```\n\n### Setup Terraform\n\nTerraform is a declarative open-source infrastructure-as-code software tool created by HashiCorp. This repo leverages Terraform to create all cloud infrastructure as well as to install and configure all software packages that run inside of Kubernetes. Terraform relies on an S3 bucket for storing its state data, and a DynamoDB table for managing a semaphore lock during operations.\n\nUse these three environment variables for creating the uniquely named resources that the Terraform modules in this repo will be expecting to find at run-time.\n\n**IMPORTANT: these three settings should be consistent with the values your set in terraform.tfvars in the next section.**\n\n```console\nAWS_ACCOUNT=012345678912      # add your 12-digit AWS account number here\nAWS_PROFILE=default           # any valid aws cli profile name\nAWS_REGION=us-east-1          # any valid AWS region code.\nAWS_ENVIRONMENT=fswl          # any valid string. Keep it short -- 3 characters is ideal.\n```\n\nTo verify your AWS CLI identify\n\n```console\naws --version\naws sts get-caller-identity\n```\n\nIf necessary you can force the aws cli to recoginize your aws profile name with this command.\n\n```console\nexport AWS_PROFILE=default\naws sts get-caller-identity\n```\n\nThe IAM user returned in the console output should match the IAM username you set above.\n\nNext create an AWS S3 Bucket\n\n```console\nAWS_S3_BUCKET=\"${AWS_ACCOUNT}-terraform-tfstate-${AWS_ENVIRONMENT}\"\naws s3api create-bucket --bucket $AWS_S3_BUCKET --region $AWS_REGION --profile $AWS_PROFILE --create-bucket-configuration LocationConstraint=$AWS_REGION\n```\n\nThen create a DynamoDB table\n\n```console\nAWS_DYNAMODB_TABLE=\"terraform-state-lock-${AWS_ENVIRONMENT}\"\naws dynamodb create-table --profile $AWS_PROFILE --region $AWS_REGION --table-name $AWS_DYNAMODB_TABLE  \\\n               --attribute-definitions AttributeName=LockID,AttributeType=S  \\\n               --key-schema AttributeName=LockID,KeyType=HASH --provisioned-throughput  \\\n               ReadCapacityUnits=1,WriteCapacityUnits=1\n```\n\n## II. Deploy EKS\n\n### Step 1. Checkout the repository\n\n```console\ngit clone https://github.com/FullStackWithLawrence/010-most-important-kubernetes-video.git\n```\n\n### Step 2. Change directory to terraform\n\n```console\ncd 010-most-important-kubernetes-video/terraform/\n```\n\n### Step 3. Configure your Terraform backend\n\nEdit the following snippet so that bucket, region and dynamodb_table are consistent with your values of $AWS_REGION, $AWS_S3_BUCKET, $AWS_DYNAMODB_TABLE\n\n```console\nvim terraform/terraform.tf\n```\n\n```terraform\n  backend \"s3\" {\n    bucket         = \"012345678912-terraform-tfstate-fswl\"\n    key            = \"fswl/terraform.tfstate\"\n    region         = \"us-east-1\"\n    dynamodb_table = \"terraform-state-lock-fswl\"\n    profile        = \"default\"\n    encrypt        = false\n  }\n````\n\n### Step 4. Configure your environment by setting Terraform global variable values\n\n```console\nvim terraform/terraform.tfvars\n```\n\nRequired inputs are as follows:\n\n```terraform\naccount_id           = \"012345678912\"\naws_region           = \"us-east-1\"\ndomain               = \"example.com\"\nshared_resource_name = \"fswl\"\n```\n\nAnd there are additional optional inputs include the folowing:\n\n```terraform\ntags                 = {}\naws_profile          = \"default\"\naws_auth_users       = []\nkms_key_owners       = []\nshared_resource_name = \"fswl\"\ncidr                 = \"192.168.0.0/20\"\nprivate_subnets      = [\"192.168.4.0/24\", \"192.168.5.0/24\"]\npublic_subnets       = [\"192.168.1.0/24\", \"192.168.2.0/24\"]\ncluster_version      = \"1.27\"\ncapacity_type        = \"SPOT\"\nmin_worker_node      = 2\ndesired_worker_node  = 2\nmax_worker_node      = 10\ndisk_size            = 30\ninstance_types       = [\"t3.2xlarge\", \"t3a.2xlarge\", \"t2.2xlarge\"]\n```\n\n### Step 5. Run the following command to set up EKS\n\nThe Terraform modules in this repo rely extensively on calls to other third party Terraform modules published and maintained by [AWS](https://registry.terraform.io/namespaces/terraform-aws-modules). These modules will be downloaded by Terraform so that these can be executed locally from your computer. Noteworth examples of such third party modules include:\n\n* [terraform-aws-modules/vpc](https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latest)\n* [terraform-aws-modules/eks](https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest)\n\n```console\nterraform init\n```\n\nScreen output should resemble the following:\n\n![terraform-plan](https://github.com/FullStackWithLawrence/010-most-important-kubernetes-video/blob/main/doc/terraform-plan.png)\n\nTo deploy all resources run the following\n\n```console\nterraform apply\n```\n\nYou can optionally run Terraform modules individually. Some examples include\n\n```console\nterraform apply -target=module.eks\nterraform apply -target=module.metricsserver\nterraform apply -target=module.prometheus\nterraform apply -target=module.ingress_controller\n```\n\n### Step 5. Interact with the AWS EKS Kubernetes cluster\n\nthe AWS CLI provides a handy command-line tool for configuring kubectl for your new AWS EKS Kubernetes cluster. \n\n```console\nAWS_REGION=us-east-1\nEKS_CLUSTER_NAME=fswl\naws eks --region $AWS_REGION update-kubeconfig --name $EKS_CLUSTER_NAME --alias $EKS_CLUSTER_NAME\n```\n\nUse this command to verify that kubectl can access Kubernetes cluster resources.\n\n```console\n$ kubectl get namespaces\nNAME                 STATUS   AGE\ndefault              Active   3h\ningress-controller   Active   101m\nkube-node-lease      Active   3h\nkube-public          Active   3h\nkube-system          Active   3h\nmetrics-server       Active   106m\nprometheus           Active   105m\nvpa                  Active   106m\n```\n\nAfterwards, you can use k9s, a text-based gui, to view and interact with Kubernetes resources. k9s relies on kubectl to communicate with the AWS EKS Kuberenetes cluster.\n\n\n```console\nk9s\n```\n\nAfter successfully running the Terraform script the k9s home screen should look similiar to the following:\n\n![k9s home screen](https://github.com/FullStackWithLawrence/010-most-important-kubernetes-video/blob/main/doc/up-and-running.png \"K9s Home Screen\")\n\n### Step 6. Check out a real URL end point that your new cluster is hosting\n\nCoincidentally, the Prometheur Helm chart also installs an application named Grafana which includes a web-based console that will be accessible from the URL endpoint 'https://grafana.fswl.yourdomain.com'.\n\nYou can retrieve your custom credentials from the following Kubernetes secrets:\n(noting that your password will be different from the value shown in the screen shot example)\n\n![Grafana credentials](https://github.com/FullStackWithLawrence/010-most-important-kubernetes-video/blob/main/doc/grafana-signin-credentials.png \"Grafana Sign In\")\n\nOnce your logged in you should see a Grafana home page similar to the following:\n\n![Grafana home page](https://github.com/FullStackWithLawrence/010-most-important-kubernetes-video/blob/main/doc/grafana-home-page.png \"Grafana Home Screen\")\n\n### Trouble Shooting\n\n#### Error: Incompatible provider version\n\nThis is a known shortcoming of Terraform when run on macOS M1 platforms. See this [Terraform discussion forum thread](https://discuss.hashicorp.com/t/template-v2-2-0-does-not-have-a-package-available-mac-m1/35099/14) for trouble shooting ideas.\n\n```console\n│\n│ Provider registry.terraform.io/hashicorp/template v2.2.0 does not have a package available for your current platform, darwin_arm64.\n│\n│ Provider releases are separate from Terraform CLI releases, so not all providers are available for all platforms. Other versions of this provider may have different platforms supported.\n```\n\n#### Error loading state: BucketRegionError: incorrect region, the bucket is not in\n\nYou'll encounter this error if the AWS region code in which you are attempting to deploy to does not match the region for the AWS S3 bucket you created.\n\n#### Error: Error acquiring the state lock\n\nTerraform sets a 'lock' in the AWS DynamoDB table that you created in the Terraform Setup above. If a Terraform operation fails then on your next operation attempt you will likely encounter the following error response, indicating that the Terraform state is currently locked.\n\n```console\n│ Error: Error acquiring the state lock\n│\n│ Error message: ConditionalCheckFailedException: The conditional request failed\n│ Lock Info:\n│   ID:        e1bd1079-86dc-0cd5-ea98-4d8c5ddb4d5a\n│   Path:      123456789012-terraform-tfstate-fswl/fswl/terraform.tfstate\n│   Operation: OperationTypeApply\n│   Who:       ubuntu@ip-192-168-2-200\n│   Version:   1.5.2\n│   Created:   2023-07-10 17:11:39.939826727 +0000 UTC\n│   Info:\n│\n│\n│ Terraform acquires a state lock to protect the state from being written\n│ by multiple users at the same time. Please resolve the issue above and try\n│ again. For most commands, you can disable locking with the \"-lock=false\"\n│ flag, but this is not recommended.\n\n```\n\nYou can optionally execute the Terraform scripts without a lock, as follows:\n\n```console\nterraform apply -lock=false\n```\n\n\n## Contributing\n\nGive back to the open source community! If you have good ideas for how to improve this code then by all means, please seize the day and share your improvements by creating a pull request: fork this repo, make your changes, and then open a pull request; most of which can be done directly from Github.\n\n### Local development\n\nThis being the low budget one-man-band operation that it is, I'm reliant on the automated coding style enforcement and syntax checking capabilities of [pre-commit](https://pre-commit.com/), [black](https://pypi.org/project/black/) and [flake8](https://flake8.pycqa.org/), so you'll want to install these amazing tools **prior** to attempting a PR as I've also installed automated [Github Actions](https://github.com/features/actions) [CI](https://en.wikipedia.org/wiki/Continuous_integration) tools that will run these tests on all commits.\n\n```console\nfoo@bar:~$ pip install -r requirements-dev.txt\nfoo@bar:~$ pre-commit install\npre-commit installed at .git/hooks/pre-commit\nfoo@bar:~$ \nfoo@bar:~$ pre-commit\n```\n\n![pre-commit output](https://github.com/FullStackWithLawrence/010-most-important-kubernetes-video/blob/main/doc/pre-commit.png)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffullstackwithlawrence%2Fproduction-ready-aws-eks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffullstackwithlawrence%2Fproduction-ready-aws-eks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffullstackwithlawrence%2Fproduction-ready-aws-eks/lists"}