somasuraj/eks-github-runner-tf

Terraform scripts to set up an EKS cluster for GitHub Actions self-hosted runners.

★ 0Forks 0HCLGitHub ↗Compare

README

Terraform EKS Cluster for GitHub Actions Runners

This Terraform project provisions an AWS EKS cluster designed to host self-hosted GitHub Actions runners. It includes networking resources (VPC, subnets, NAT Gateway, etc.), IAM roles, and the EKS cluster itself with a managed node group (with configurable root EBS volume sizes) and essential add-ons.

Prerequisites

  1. AWS Account & CLI: Ensure you have an AWS account and the AWS CLI installed and configured with appropriate credentials (including the akshay profile) and region.
  2. Terraform: Install Terraform (version 1.0 or newer).
  3. kubectl: Install kubectl to interact with the EKS cluster.
  4. aws-iam-authenticator: (Optional, but recommended for kubectl access) Install aws-iam-authenticator.

Initial Setup: Terraform Backend (Manual Steps)

Before running Terraform, you need to manually create an S3 bucket and a DynamoDB table to store the Terraform state and manage locking.

1. Create S3 Bucket:

Replace your-unique-prefix-eks-tfstate and your-aws-region with your desired unique bucket name (e.g., github-runner-eks-tfstate) and AWS region (e.g., us-east-1). Ensure you run these commands with the akshay profile:

# For us-east-1, omit LocationConstraint
aws s3api create-bucket --bucket github-runner-eks-tfstate --region us-east-1 --profile akshay
# For other regions, you would use (example for us-west-2):
# aws s3api create-bucket --bucket github-runner-eks-tfstate --region us-west-2 --create-bucket-configuration LocationConstraint=us-west-2 --profile akshay

aws s3api put-bucket-versioning --bucket github-runner-eks-tfstate --versioning-configuration Status=Enabled --profile akshay
aws s3api put-bucket-encryption --bucket github-runner-eks-tfstate --server-side-encryption-configuration '{"Rules": [{"ApplyServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}]}' --profile akshay
aws s3api put-public-access-block --bucket github-runner-eks-tfstate --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" --profile akshay

2. Create DynamoDB Table:

Replace your-aws-region with your AWS region. Ensure you run this command with the akshay profile:

aws dynamodb create-table --table-name github-runner-eks-tf-lock-table --attribute-definitions AttributeName=LockID,AttributeType=S --key-schema AttributeName=LockID,KeyType=HASH --billing-mode PAY_PER_REQUEST --region us-east-1 --profile akshay

Note: The backend.tf file is already configured to use github-runner-eks-tfstate and github-runner-eks-tf-lock-table in us-east-1, and the akshay profile. Adjust these names in backend.tf if you choose different names during manual creation.

Directory Structure

.
├── backend.tf        # Configures S3 backend for Terraform state
├── main.tf           # Core infrastructure (VPC, EKS cluster, node groups, IAM roles, EKS Add-ons)
├── outputs.tf        # Declares outputs (cluster endpoint, IAM role ARNs, etc.)
├── README.md         # This file
├── variables.tf      # Input variables for customization
├── versions.tf       # Specifies provider versions
└── ebs.tf            # (Currently unused as EBS volumes are managed by node group configuration in `main.tf`)

Terraform Usage

Terraform is configured to use the akshay AWS profile as specified in main.tf and backend.tf.

  1. Initialize Terraform:

    Navigate to the project directory (/home/ubuntu/zenimax/eks-github-runner/) and run:

    terraform init
  2. Review Plan:

    (Optional, but recommended) See what resources Terraform will create/modify:

    terraform plan
  3. Apply Configuration:

    Provision the resources:

    terraform apply

    Type yes when prompted to confirm.

  4. Destroy Resources:

    To tear down all resources managed by this Terraform configuration:

    terraform destroy

    Type yes when prompted to confirm.

Configuration

Modify variables.tf or create a terraform.tfvars file to customize variables such as:

  • aws_region, project_name
  • vpc_cidr, public_subnet_cidrs, private_subnet_cidrs, availability_zones
  • cluster_name, cluster_version
  • node_group_name, node_group_instance_types, node group sizes
  • ebs_volume_size_gb: Root volume size in GB for EKS worker nodes (default: 20).
  • tags for resource tagging

Important IAM Customization:

  • Node Group Permissions: Review and update the aws_iam_policy.runner_node_custom_permissions resource in main.tf. This policy grants permissions to the EKS worker nodes (and thus to your GitHub Action runners). Tailor the Statement block to include the precise permissions your runners need (e.g., for ECR, S3, CodeCommit, etc.). The current example provides broad ECR access that should be scoped down.
  • ExternalDNS Permissions: The aws_iam_role.external_dns resource in main.tf has an assume role policy. If you deploy ExternalDNS with a service account name other than external-dns or in a namespace other than kube-system, you must update the Condition in this policy.

Modules Used

This project utilizes the following official Terraform AWS modules:

  • VPC: terraform-aws-modules/vpc/aws (creates VPC, subnets, IGW, NAT Gateways, route tables)
  • EKS: terraform-aws-modules/eks/aws (creates EKS cluster, control plane, node groups, IAM roles, and manages add-ons)

Resources Created

The Terraform script will provision the following major resources:

  1. Networking (via VPC module):
    • VPC
    • Public and Private Subnets across specified Availability Zones
    • Internet Gateway (IGW)
    • NAT Gateways (one per AZ for HA by default)
    • Public and Private Route Tables
    • Default VPC Security Group
  2. EKS Cluster & Nodes (via EKS module):
    • EKS Control Plane (Master Nodes)
    • EKS Managed Node Group (Worker Nodes in private subnets)
    • IAM Role for EKS Cluster (AmazonEKSClusterPolicy)
    • IAM Role for EKS Node Group (AmazonEKSWorkerNodePolicy, AmazonEC2ContainerRegistryReadOnly, AmazonEKS_CNI_Policy)
    • Cluster Security Group
    • Node Group Security Group
    • OIDC Provider for IRSA
  3. EKS Add-ons (configured in EKS module):
    • coredns
    • kube-proxy
    • vpc-cni (Amazon VPC CNI)
    • aws-ebs-csi-driver (for dynamic EBS volume provisioning by Kubernetes)
    • eks-pod-identity-agent (Amazon EKS Pod Identity Agent)
    • external-dns (for managing Route 53 records for Kubernetes services/ingresses)
    • metrics-server
    • amazon-cloudwatch-observability (for CloudWatch Container Insights)
  4. IAM (defined in main.tf or by EKS module):
    • Cluster IAM Role
    • Node Group IAM Role
    • IAM Policy and Role for ExternalDNS (for IRSA)
    • Custom IAM Policy for Node Group (for GitHub Actions runner specific permissions)

EBS Volumes

  • EBS root volumes for EKS worker nodes are automatically created and managed as part of the EKS managed node group configuration. The size of these root volumes can be configured using the ebs_volume_size_gb variable in variables.tf or terraform.tfvars.
  • (Pre-provisioned, standalone EBS volumes are no longer created by default by this configuration.)

Contributors

somasuraj

Issues