A simple K3s implementation for AWS
Perfect for Hobbyists and Entrepreneurs who want a setup with critical enterprise features without committing to EKS. This acts as a perfect starting point to deploy MVPs with scaling, monitoring, and good defaults for security in mind. In addition, it serves as a way to transition nicely into EKS since your apps would be built with Kubernetes in mind from the very beginning.
| Features | Full DiY |
SimpleK3s |
EKS |
|---|---|---|---|
| Setup Speed π | βοΈ | βοΈβοΈβοΈβοΈβοΈ | βοΈβοΈβοΈ |
| Cost Efficiency π€ | βοΈβοΈβοΈβοΈβοΈ | βοΈβοΈβοΈ | βοΈ |
| Kubernetes-Ready βοΈ | π« | β | β |
| High Availability π¦Ύ | π« | β | β |
| Auto Scaling π | π« | β | β |
| Monitoring π | π« | β | β |
| Deployer ποΈ | π« | β | β |
| QoL: ArgoCD π¦ | π« | β | π« |
| QoL: Grafana π₯ | π« | β | π« |
| QoL: Governance π¨ββοΈ | π« | β | π« |
| QoL: Secrets Mgmt π€« | π« | β | π« |
| Security π | βοΈ | βοΈβοΈβοΈ | βοΈβοΈβοΈβοΈβοΈ |
| Operational Ease π οΈ | βοΈ | βοΈβοΈβοΈβοΈβοΈ | βοΈβοΈβοΈβοΈβοΈ |
| Best For... π«₯ | Small Projects | Scalable MVPs | Full Production |
There are some useful commands/skills for your coding agents to utilize:
General Skills
- /check-versions (Helps scan through the entire repo for software used and their versions)
- WARNING: Very token intensive, use on a fresh claude session if possible.
- /test-out (Helps perform testcases and provide a report on the results)
- /introduce-contributor (Introduces the potential contributor to the project)
- /new-issue (Helps create a new issue based on the formatting outlined in this document)
Estimated monthly costs for common deployment profiles, plus a side-by-side comparison with equivalent EKS setups β see PRICING.md.
Every pull request and push to main runs a static analysis pipeline (no AWS credentials required):
tofu fmt/terraform fmtβ enforces consistent formattingtflintβ lint rules for naming, versioning, and AWS best practicestofu validate/terraform validateβ type-checks all five root modules (CI runs this under both tools)checkovβ security and compliance scan of Terraform resourcesshellcheckβ checks linting, syntax, validity of shell scripts
There are two main methods of easily testing changes locally:
- Test via shellscripts
./test-outs/test-out_shellscripts.sh # Perform shellscript checks
./test-outs/test-out_terraform.sh # Perform terraform checks- Test via Claude Code
# Within the claude terminal:
# Usage:
> /test-out "context of what you want to check"
# Examples:
> /test-out # Execute all tests
> /test-out all # Execute all tests
> /test-out relevant # Execute tests that's relevant
> /test-out shellscript # Execute tests related to shell scripts
> /test-out terraform # Execute tests related to terraform config
# Note:
# 1. Test scripts under testcases/ folder will be preferred by the LLM
# 2. The logs of the tests will be under the testcases/ folder
# 3. The LLM will prompt you to determine the order of tests to run- This is NOT meant to be a $0 or lowest possible price point setup.
- Remember, a webapp running on 1-2 instances will ALWAYS be cheaper than a Kubernetes cluster.
- This is NOT meant to replace managed Kubernetes services like
EKS.SimpleK3shelps get people started with Kubernetes before moving ontoEKS.
SimpleK3soffers ZERO guarantee or warranty of reliability.- Workloads or services that cannot fail at whatever the cost should explore managed services like
EKS.
- Workloads or services that cannot fail at whatever the cost should explore managed services like
- OpenTofu v1.11.2 or Terraform v1.14.3
- The commands below use
tofu; substituteterraformif you use Terraform β the configuration is compatible with both.
- The commands below use
- AWS account
- AWS profile with the correct IAM rights that can use Terraform
- A domain name (Approx. $15USD for 4 yrs)
awspackage (Helpful tool to interact with AWS resources for debugging and advanced usage)- Search up "Install aws cli" via a search engine
- https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
session-manager-pluginpackage (Used for connecting to instances without needing keypairs)- Search up "Install session-manager-plugin for aws cli" via a search engine
- https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html
This is used as a Terraform module for your AWS IaC Projects. In your Terraform configuration, add the following module to create the k3s cluster:
locals {
# IdP SSM Parameter Names
# idp_config's should have a JSON string the following format:
# {
# issuer = __IDP_ISSUER_URL__
# client_id = __IDP_CLIENT_ID__
# client_secret = __IDP_CLIENT_SECRET__
# domain = __IDP_HOSTED_UI_BASE_DOMAIN__
# }
# Use the module within ../modules/idp_cognito to create this config
idp_ssm_pstore_names = {
idp_config = "<SSM_PARAMETER_NAME_FOR_IDP_CONFIG>"
}
}
module "k3s_cluster" {
source = "<PATH_TO_MODULE>/k3s_cluster" # Path to the k3s cluster
nickname = var.nickname # Nickname that resources will use (e.g. Name, Tags, etc)
node_count = var.node_count # The number of nodes that K3s will start with
admin_ip_list = var.admin_ip_list # The list of IPs (in CIDR) to allow for admin SSH connections
vpc_id = module.vpc_cloud.vpc_id # The VPC that resources will be put inside of
subnet_ids = module.vpc_cloud.subnet_public_ids # The list of subnets that the cluster nodes reside in
# Optional, but highly recommended: Built-in Apps
applications = {
argocd = {
idp_ssm_pstore_names = local.idp_ssm_pstore_names
domain_name = local.domain_name
}
monitoring = {
idp_ssm_pstore_names = local.idp_ssm_pstore_names
domain_name = local.domain_name
}
}
}
# Optional variables:
# Networking:
# - controller_subnet_id : Override the subnet that the controller node will use
# (Default is the first subnet from `subnet_ids`)
# (controller subnet id MUST be found within `subnet_ids`)
# - controller_private_ip : Override the private IP for the controller node
# (Won't work if private IP is outside of subnet's CIDR block)
# - controller_private_ip_hostnum : Determine the last 3 digits of the controller's private IP
# (Doesn't get used if `controller_private_ip` is used)
# - k3s_nodeport_traefik_http : The Traefik nodeport that HTTP traffic goes through
# - k3s_nodeport_traefik_https : The Traefik nodeport that HTTPS traffic goes through
# Node Infra (EC2):
# - ec2_ami_id : The AMI id that the EC2 instances (Nodes) will use
# (default is Debian 13 for ARM on the us-east-1 region)
# (WARNING: The default value may not work depending on input VPC's region / instance type)
# - ec2_instance_type : The instance type that the K3s nodes will be made up of
# (Absolute minimum is t4g.small: Kubernetes can crash if cpu/memory is slow or constrained)
# (Highly recommend to upgrade to t4g.medium or t4g.large if you are planning to run 3 or more pods)
# - ec2_swapfile_size : Sets the size of the SWAPFILE
# (Default is 1G : Should be between 512M - 1G
# Too much leads to inconsistent k3s behavior because nodes to be responsive to work)
# (NOTE: In the context of Kubernetes, SWAPFILE isn't a solution to add more RAM, unfortunately
# SWAP should ONLY be used as an emergency cushion to avoid OOM issues)
# - ec2_ebs_volume_size : The disk size of the volume in Gb (Recommended minimum is 12)
# - ec2_ebs_volume_type : The volume type (Recommended is GP3 for performance and price for smaller volume sizes)- Initialize IdP
- Navigate to
./examples/ex_idp/ - Copy
./terraform.TEMPLATE.tfvarsfile to./terraform.tfvars - Modify
./terraform.tfvarsto your satisfaction (Like the DNS name) - Execute the following command(s):
AWS_PROFILE="your_aws_profile" tofu initAWS_PROFILE="your_aws_profile" tofu planAWS_PROFILE="your_aws_profile" tofu apply
- Navigate to
- Create your user in AWS Cognito
- Login to your AWS account
- Navigate to AWS
Cognito(In the AWS search bar, search forCognitoand click on it) - Find the relevant user pool (By default, the user pool's name is
idp-upl-idp-standalone) - Go inside of the user pool menu by clicking on the user pool's name
- At the left side, click on
Users(Found underUser management) - At the
Usersmenu, click on theCreate userbutton (around the top right side) - Fill out the form and click on
Create user- Email Address: Put an email address that you own
- Password: You could choose to set or generate a password (Setting a password can be used if the email you are using is invalid)
- Initialize example:
- Navigate to
./examples/ex_basic/ - Copy
./terraform.TEMPLATE.tfvarsfile to./terraform.tfvars - Modify
./terraform.tfvarsto your satisfaction (Like the DNS name) - Execute the following command(s):
AWS_PROFILE="your_aws_profile" tofu initAWS_PROFILE="your_aws_profile" tofu planAWS_PROFILE="your_aws_profile" tofu apply
- Navigate to
- aws ssm start-session --target
instance id (Found in AWS EC2 dashboard)--profileyour_aws_profile
- AWS Free Tier allows for 50K Monthly Active Users for AWS Cognito
- In other words, as long are you don't create and maintain more than 50K users per month, you can use it for free!
- Example IdP is set as a separate entity from the basic example to prevent the event where you need to constantly spin up and spin down the infra without redoing Cognito setups and eating into your users per month limit
- It is recommended that you keep the region of IdP and the Basic example the same (i.e. both on "us-east-1")
Interested in adding more features? Check out the CONTRIBUTING.md for code of conduct and a guide on how to make changes ot the project!