Home/Engineer/Cloud/Amazon EKS in Practice — Clu…
CloudAdvancedUbuntumacOSEKSKubernetesAWS

Amazon EKS in Practice — Cluster Setup, Deployment Strategies, and Operational Patterns

An in-depth guide to provisioning an EKS cluster with eksctl and running production-grade Kubernetes workloads with ALB Ingress, HPA, and Karpenter.

Contents
  1. EKS Production Architecture Overview
  2. Prerequisites — Installing Tools
  3. Creating a Cluster — Declarative Configuration with eksctl
  4. Karpenter — Intelligent Node Autoscaling
  5. ALB Ingress Controller and HTTPS Setup
  6. HPA — CPU- and Memory-Based Pod Autoscaling
  7. Operations — Essential Commands
  8. Hardening Security — IRSA and NetworkPolicy

EKS Production Architecture Overview

EKS (Elastic Kubernetes Service) runs Kubernetes on an AWS-managed control plane. In production, the standard combination is Multi-AZ node groups + Karpenter autoscaling + ALB Ingress.


Prerequisites — Installing Tools

Bash
# eksctl
curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin

# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl && sudo mv kubectl /usr/local/bin

# helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# check
eksctl version && kubectl version --client && helm version

Creating a Cluster — Declarative Configuration with eksctl

YAML
# cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: prod-cluster
  region: ap-northeast-2
  version: "1.29"

iam:
 withOIDC: true # IRSA(IAM Roles for Service Accounts)

managedNodeGroups:
  - name: system
    instanceType: m6i.large
    minSize: 2
    maxSize: 4
    desiredCapacity: 2
    availabilityZones: [ap-northeast-2a, ap-northeast-2b, ap-northeast-2c]
    labels:
      role: system
    taints:
      - key: CriticalAddonsOnly
        value: "true"
        effect: NoSchedule
    iam:
      attachPolicyARNs:
        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy

addons:
  - name: vpc-cni
    version: latest
  - name: coredns
    version: latest
  - name: kube-proxy
    version: latest
  - name: aws-ebs-csi-driver
    version: latest
    wellKnownPolicies:
      ebsCSIController: true
Bash
eksctl create cluster -f cluster.yaml
# kubeconfig
kubectl get nodes

Karpenter — Intelligent Node Autoscaling

Using Karpenter instead of Cluster Autoscaler lets you reclaim unused nodes quickly and cut costs.

Installing Karpenter

Bash
export CLUSTER_NAME=prod-cluster
export AWS_REGION=ap-northeast-2
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

# IRSA
eksctl create iamserviceaccount \
  --name karpenter \
  --namespace karpenter \
  --cluster $CLUSTER_NAME \
  --attach-policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/KarpenterControllerPolicy \
  --approve

# Helm
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter \
  --version v0.37.0 \
  --namespace karpenter --create-namespace \
  --set settings.clusterName=$CLUSTER_NAME \
  --set settings.interruptionQueue=$CLUSTER_NAME \
  --wait

Defining a NodePool and NodeClass

YAML
# karpenter-nodepool.yaml
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
  name: default
spec:
  template:
    spec:
      nodeClassRef:
        name: default
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand", "spot"]
        - key: node.kubernetes.io/instance-type
          operator: In
          values: ["m6i.large", "m6i.xlarge", "m6a.large", "m6a.xlarge"]
        - key: topology.kubernetes.io/zone
          operator: In
          values: ["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2c"]
  limits:
    cpu: 200
    memory: 400Gi
  disruption:
    consolidationPolicy: WhenUnderutilized
    consolidateAfter: 30s
---
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
  name: default
spec:
  amiFamily: AL2
  role: KarpenterNodeRole-prod-cluster
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: prod-cluster
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: prod-cluster
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 50Gi
        volumeType: gp3
        encrypted: true
Bash
kubectl apply -f karpenter-nodepool.yaml

ALB Ingress Controller and HTTPS Setup

Bash
# 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 \
  -n kube-system \
  --set clusterName=$CLUSTER_NAME \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller
YAML
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:ap-northeast-2:ACCOUNT:certificate/CERT-ID
    alb.ingress.kubernetes.io/ssl-redirect: "443"
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/healthcheck-path: /healthz
spec:
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80

HPA — CPU- and Memory-Based Pod Autoscaling

YAML
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 2
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 70
  behavior:
    scaleDown:
 stabilizationWindowSeconds: 300 # 5 after
      policies:
        - type: Pods
          value: 2
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Percent
          value: 100
          periodSeconds: 30

Operations — Essential Commands

Bash
#
kubectl top nodes
kubectl top pods -A

# Karpenter
kubectl get nodeclaims
kubectl get nodepools

# HPA
kubectl get hpa -w

#
kubectl set image deployment/api app=my-image:v2
kubectl rollout status deployment/api

#
kubectl rollout undo deployment/api
kubectl rollout history deployment/api --revision=3

# quit without
kubectl drain node-id --ignore-daemonsets --delete-emptydir-data

# : Spot when
kubectl taint nodes NODE_NAME karpenter.sh/disruption:NoSchedule-

Hardening Security — IRSA and NetworkPolicy

Bash
# IRSA: Pod IAM
eksctl create iamserviceaccount \
  --name s3-reader \
  --namespace production \
  --cluster $CLUSTER_NAME \
  --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
  --approve
YAML
# networkpolicy.yaml — after 
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: default-deny-all
 namespace: production
spec:
 podSelector: {}
 policyTypes: [Ingress, Egress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: allow-api-ingress
 namespace: production
spec:
 podSelector:
 matchLabels:
 app: api
 ingress:
 - from:
 - namespaceSelector:
 matchLabels:
 kubernetes.io/metadata.name: ingress-nginx
 ports:
 - port: 8080
#EKS#Kubernetes#AWS#Karpenter#HPA#ALB#DevOps
Editorial note

AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us

Topic-related official docs (auto-linked · not per-claim sources)Kubernetes documentation ↗AWS documentation ↗

Questions & answers

Ask a question about this guide. We'll review and reply.