{"id":30876320,"url":"https://github.com/howdoicomputer/polarstomps-infra","last_synced_at":"2025-09-08T02:08:58.750Z","repository":{"id":204340778,"uuid":"711586971","full_name":"howdoicomputer/polarstomps-infra","owner":"howdoicomputer","description":"A repository for a reference architecture for AWS, EKS, and ArgoCD","archived":false,"fork":false,"pushed_at":"2023-12-14T14:45:33.000Z","size":81,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2023-12-14T16:01:33.357Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/howdoicomputer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-10-29T18:04:28.000Z","updated_at":"2023-12-14T16:01:39.352Z","dependencies_parsed_at":null,"dependency_job_id":"268acf70-819f-4019-ba53-9fb1edb66003","html_url":"https://github.com/howdoicomputer/polarstomps-infra","commit_stats":null,"previous_names":["howdoicomputer/aws-cdktf-example","howdoicomputer/polarstomps-infra"],"tags_count":0,"template":null,"template_full_name":null,"purl":"pkg:github/howdoicomputer/polarstomps-infra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howdoicomputer%2Fpolarstomps-infra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howdoicomputer%2Fpolarstomps-infra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howdoicomputer%2Fpolarstomps-infra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howdoicomputer%2Fpolarstomps-infra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/howdoicomputer","download_url":"https://codeload.github.com/howdoicomputer/polarstomps-infra/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howdoicomputer%2Fpolarstomps-infra/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274121957,"owners_count":25225801,"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","status":"online","status_checked_at":"2025-09-08T02:00:09.813Z","response_time":121,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2025-09-08T02:08:48.815Z","updated_at":"2025-09-08T02:08:58.737Z","avatar_url":"https://github.com/howdoicomputer.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# polarstomps-infra\n\nThis project is intended to be a simple, toy reference architecture in AWS using the TypeScript version of [cdktf](https://github.com/hashicorp/terraform-cdk).\n\nI originally started this project as a way to keep my AWS skills fresh while I was working with GCP. However, it ended up being used as a demo for an interview with a company called Polarsteps. I passed the interview but decided to stay in America as the housing crisis in the Netherlands was - and is - worse than here. This is why it's named \"polarstomps\" as I thought that'd be fun.\n\nThis infrastructure repository deploys:\n\n* Three logical environments (dev/stage/prod) whose boundaries are defined by AWS primitives (VPCs, security groups, etc) and the EKS clusters themselves\n* Three EKS/Kubernetes clusters on AWS with each having a managed node pool\n* ArgoCD and Argo Rollouts for gitops pull based deployments\n* Karpenter as the autoscaling mechanism\n* AWS LB Controller in order to use ALBs as ingresses for workloads\n* The VPC CNI add-on for EKS for VPC connectivity (automatic network interface management)\n* The container observability add-on for EKS for sending logs to CloudWatch\n\n# polarstomps App\n\nThere is a Polarstomps application that is meant to be deployed to the infrastructure this repo sets up. The application and deployment manifests are separate as that's what adheres to best practices. The application itself is just a simple Golang webapp built with HTMX.\n\nIt lives here: https://github.com/howdoicomputer/polarstomps\nThe k8s manifests for it live here: https://github.com/howdoicomputer/polarstomps-argo\n\n## Setting Up\n\nThe repository uses [devenv](https://devenv.sh/) as a way of setting up developer workspace dependencies. If you have devenv installed then CDing into the directory will take care of most CLI tools.\n\nOtherwise, you'll need to install:\n\n* cdktf CLI and general Nodejs stuff\n* helm\n* argocd\n* kubectl\n* awscli\n* terraform\n\nIf you're on a Mac then homebrew will handle most of those dependencies.\n\n### Credentials\n\nThis project uses Terraform Cloud to handle storing Terraform state. You'll need to setup an account there and then use `cdktf login` to cache credentials. Also, you will need to go into your Terraform Cloud project and turn on local execution for your pipeline. Also also, you need to change the Terraform organization specified in `main.ts` from 'howdoicomputer' to whatever yours is.\n\nAdditionally, the AWS SDK and CLI requires AWS credentials to be set. I use root account credentials (be extremeley careful doing this - it's definitely not best practice to provision root account credentials) and I set then in an `.envrc` that is loaded by [direnv](https://direnv.net/). See the `sample-envrc`. `.envrc` is added to `.gitignore` to prevent you from committing your secrets.\n\n### Ingress IP Address\n\nIn order to access the Kubernetes control plane you need to specify your source IPv4 address. This is a hobby project so my source IP address is what I usually get from `whatismyipaddress.com`. Take your source address (or address range) and specify it via the `blessedSourceIP` option for the Environment constructor.\n\n## Deploying\n\n``` sh\ncdktf get\ncdktf deploy\n```\n\n## Administration\n\nIn order to generate a password for the ArgoCD UI:\n\n``` sh\nargocd admin initial-password -n argocd\n```\n\nIn order to setup your local kubeconfig:\n\n``` sh\naws eks update-kubeconfig --name development|staging|production\n```\n\nIn order to look at your ArgoCD deployments:\n\n``` sh\nkubectl port-forward svc/argocd-server -n argocd 8080:443\n```\n\nIn order to deploy the Guestbook example ArgoCD app:\n\n``` sh\nargocd app create guestbook --repo https://github.com/argoproj/argocd-example-apps.git --path guestbook --dest-server https://kubernetes.default.svc --dest-namespace default\n```\n\nIn order to watch and/or debug autoscaling events:\n\n``` sh\nkubectl logs -f -n karpenter -l app.kubernetes.io/name=karpenter -c controller\n```\n\nIf autoscaling is working, then you'll see events like this:\n\n``` sh\n{\"level\":\"INFO\",\"time\":\"2023-12-14T08:24:51.212Z\",\"logger\":\"controller.nodeclaim.lifecycle\",\"message\":\"launched nodeclaim\",\"commit\":\"5eda5c1\",\"nodeclaim\":\"default-xbbj9\",\"nodepool\":\"default\",\"provider-id\":\"aws:///us-west-2b/i-001dcff2ad199d02d\",\"instance-type\":\"t3.medium\",\"zone\":\"us-west-2b\",\"capacity-type\":\"spot\",\"allocatable\":{\"cpu\":\"1930m\",\"ephemeral-storage\":\"17Gi\",\"memory\":\"3246Mi\",\"pods\":\"17\"}}\n```\n\n## Secrets\n\nI was too lazy to codify the Helm chart installs for AWS Secrets Manager integration so the bootstrapping is here:\n\n``` sh\nhelm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts\nhelm repo add aws-secrets-manager https://aws.github.io/secrets-store-csi-driver-provider-aws\nhelm install -n kube-system csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver --set syncSecret.enabled=true\nhelm install -n kube-system secrets-provider-aws aws-secrets-manager/secrets-store-csi-driver-provider-aws\n```\n\nAny namespace that needs access to secrets needs a SecretProviderClass:\n\n``` sh\napiVersion: secrets-store.csi.x-k8s.io/v1\nkind: SecretProviderClass\nmetadata:\n  name: eks-aws-secrets\n  namespace: mynamespace\nspec:\n  provider: aws\n  parameters:\n    objects: |\n        - objectName: \"eksSecret\"\n          objectType: \"secretsmanager\"\n```\n\n## Environment\n\nFor this implementation, an environment is a logical construct that exists as a VPC with an EKS cluster within it. The cidrs for the VPCs are `/16`s and each subnet is a `/24` with three private subnets and three public subnets. Each subnet public/private pair corresponds to an availability zone. The private subnets are where k8s worker nodes are deployed to and the public subnets are where load balancers live.\n\nThe difference between a private and public subnet is whether or not there is a route to an internet gateway defined. Most of the setup around subnets are handled by the [VPC](https://registry.terraform.io/modules/terraform-aws-modules/vpc/aws/latest) terraform module.\n\nCode wise, an environment is handled by the `Environment` class and configured by the `EnvironmentOptions` interface.\n\nExample:\n\n``` typescript\n    const dev = new Environment(this, \"development\", {\n      env: \"development\",\n      cidr: \"10.1.0.0/16\",\n      blessedSourceIP: \"CHANGEME\",\n      privateSubnets: [\"10.1.1.0/24\", \"10.1.2.0/24\", \"10.1.3.0/24\"],\n      publicSubnets: [\"10.1.4.0/24\", \"10.1.5.0/24\", \"10.1.6.0/24\"],\n      enableNatGateway: true,\n      singleNatGateway: true,\n      enableDnsHostnames: true,\n    });\n```\n\n## Cost Profile\n\nThis codebase tries not to incur unnecessary costs but they are inevitable.\n\nFor example,\n\n* AWS NAT Gateway - charged per-hour it exists and the data coming through it\n* The Karpenter nodes are spot-bid and can increase cost if you give a reason to scale\n\n# Terraform Modules Used\n\nMost of the heavy lifting is done by these modules:\n\n* terraform-aws-modules/{vpc,eks,karpenter,irsa}\n* DNXLabs/eks-lb-controller\n\nWithout them the amount of code needed to create all of these resources with the associated IAM primitives would be immense.\n\n# Terraform Destroy\n\nSince the AWS LB Controller creates load balancers on its own per an applications ingress specification Terraform has no idea about them. Therefore, if you are going to do a `cdktf destroy` to clean up your resources then make sure to undeploy any workloads using ALBs for ingress otherwise the destroy action will never be able to complete.\n\n## Production\n\nPlease don't use this for production. If you want a reference for setting up EKS on AWS with all the bells and whistles then this might be able to help you out.\n\n## TODO\n\n* Create a hosted database within AWS and have the polarstomps application access it\n* There is a cdktf bug regarding modules referring to each other. This requires a hardcoding an ARN in the codebase. I should look more deeply into fixing this.\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhowdoicomputer%2Fpolarstomps-infra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhowdoicomputer%2Fpolarstomps-infra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhowdoicomputer%2Fpolarstomps-infra/lists"}