Skip to content

peter604/hiive

Repository files navigation

hiive EKS Cluster

Terraform + Kubernetes configuration to provision a private EKS cluster on AWS and expose an nginx application via an internet-facing ALB.

Disclaimer: This assignment is implemented with the assistance from Claude Code; all submitted code was reviewed, tested, and validated by me before submission.

and yes I caught Claude spit out something believable, but nonsense...
resource "aws_cloudwatch_metric_alarm" "pod_restarts" {
  alarm_name          = "${local.app_name}-pod-restarts-high"
  alarm_description   = "Pods restarting frequently — possible OOMKill, crash-loop, or failed liveness probe."
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "pod_number_of_container_restarts"
  namespace           = "ContainerInsights"
  period              = 300
  statistic           = "Sum"
  threshold           = 5
  treat_missing_data  = "notBreaching"
  alarm_actions       = local.alarm_actions
  ok_actions          = local.alarm_actions

  dimensions = {
    ClusterName = "${local.app_name}-eks"
    Namespace   = "default"
  }
}

Architecture

  • VPC — 3 private subnets (nodes/pods), 3 public subnets (ALB), single NAT gateway (via terraform module)
  • EKS — private API endpoint, managed node group (AL2023), Kubernetes 1.35 (via terraform module)
  • Add-ons — vpc-cni, kube-proxy, coredns, aws-ebs-csi-driver
  • Ingress — AWS Load Balancer Controller creates an internet-facing ALB from a Kubernetes Ingress resource
  • CI/CDGitHub Actions deploys via OIDC

Prerequisites

  • Terraform >= 1.14 (pinned via .terraform-version)
  • AWS CLI configured with sufficient IAM permissions to provision vpc + eks
  • kubectl and helm
  • AWS Cloud Shell

Getting Started

1. Bootstrap — first-time only

The GitHub Actions OIDC role must be created locally before CI can take over.

export AWS_PROFILE=hiive

# Init — backend doesn't support variable interpolation so profile is passed explicitly
terraform init -backend-config="profile=hiive"

# Create only the OIDC + IAM resources
terraform apply \
  -target=aws_iam_openid_connect_provider.github \
  -target=aws_iam_role.github_actions \
  -target=aws_iam_policy.github_actions \
  -target=aws_iam_role_policy_attachment.github_actions

# Add the role ARN as a secret in GitHub:
# repo → Settings → Secrets → Actions → AWS_ROLE_ARN
terraform output -raw github_actions_role_arn

2. Deploy infrastructure

After bootstrap, push to main — GitHub Actions runs terraform apply automatically.

To apply locally:

AWS_PROFILE=hiive terraform apply

To override instance type:

AWS_PROFILE=hiive terraform apply -var="eks_node_instance_type=t3.medium"

3. Get kubectl access

Since the EKS API endpoint is private, accessing eks via cloud-shell...

aws eks update-kubeconfig \
  --region ca-central-1 \
  --name hiive-eks

kubectl get nodes
# NAME                                          STATUS   ROLES    AGE   VERSION
# ip-10-0-2-181.ca-central-1.compute.internal   Ready    <none>   23h   v1.35.4-eks-7fcd7ec

4. Install AWS Load Balancer Controller

helm repo add eks https://aws.github.io/eks-charts
helm repo update

helm upgrade --install aws-load-balancer-controller eks/aws-load-balancer-controller \
  --namespace kube-system \
  --set clusterName=hiive-eks \
  --set serviceAccount.create=true \
  --set serviceAccount.name=aws-load-balancer-controller \
  --set "serviceAccount.annotations.eks\.amazonaws\.com/role-arn=$(terraform output -raw load_balancer_controller_role_arn)" \
  --set region=ca-central-1 \
  --set vpcId=$(terraform output -raw vpc_id) \
  --wait

kubectl get pods -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller
# NAME                                            READY   STATUS    RESTARTS   AGE
# aws-load-balancer-controller-5556b58d8d-md9xz   1/1     Running   0          14h
# aws-load-balancer-controller-5556b58d8d-p454x   1/1     Running   0          14h

5. Deploy nginx

# Patch the ALB security group ID into the ingress annotation
# k8s/nginx.yaml → alb.ingress.kubernetes.io/security-groups
terraform output -raw alb_security_group_id

kubectl apply -f k8s/nginx.yaml

# Wait ~60s for the ALB to provision, then get the public URL
kubectl get ingress nginx
# NAME    CLASS   HOSTS   ADDRESS                                                                  PORTS   AGE
# nginx   alb     *       k8s-default-nginx-61aae4aedd-1684337437.ca-central-1.elb.amazonaws.com   80      14h

Open the ADDRESS in a browser to see the nginx splash page.

CI/CD

Event Action
Pull request to main terraform plan
Push to main terraform apply

Workflow: .github/workflows/terraform.yml

Authentication is via GitHub Actions OIDC


Teardown

kubectl delete -f k8s/nginx.yaml
AWS_PROFILE=hiive terraform destroy

Requirements

Name Version
terraform ~> 1.14
aws ~> 6.28

Providers

Name Version
aws ~> 6.28

Modules

Name Source Version
vpc terraform-aws-modules/vpc/aws 6.6.1
eks terraform-aws-modules/eks/aws 21.20.0
irsa-ebs-csi terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc 5.52.0
irsa-aws-load-balancer-controller terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks 5.52.0

Resources

Name Type
aws_security_group.alb resource
aws_iam_openid_connect_provider.github resource
aws_iam_role.github_actions resource
aws_iam_policy.github_actions resource
aws_iam_role_policy_attachment.github_actions resource
aws_caller_identity.current data source
aws_availability_zones.available data source
aws_iam_policy.ebs_csi_policy data source
aws_iam_policy_document.github_actions data source

Inputs

Name Description Type Default Required
region AWS region string "ca-central-1" no
eks_node_instance_type EC2 instance type for EKS managed node group string "t3.small" no

Outputs

Name Description
cluster_endpoint Endpoint for EKS control plane
cluster_security_group_id Security group IDs attached to the cluster control plane
cluster_name Kubernetes cluster name
region AWS region
vpc_id VPC ID
alb_security_group_id Security group ID to assign to the nginx ALB via ingress annotation
load_balancer_controller_role_arn IAM role ARN for the AWS Load Balancer Controller
github_actions_role_arn IAM role ARN for GitHub Actions OIDC

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors