홈/엔지니어/클라우드/Amazon EKS 실전 — 클러스터 구성, 배포 …
클라우드고급UbuntumacOSEKSKubernetesAWS

Amazon EKS 실전 — 클러스터 구성, 배포 전략, 운영 패턴

eksctl로 EKS 클러스터를 구성하고, ALB Ingress·HPA·Karpenter를 적용해 프로덕션 수준의 Kubernetes 워크로드를 운영하는 심화 가이드.

목차
  1. EKS 프로덕션 아키텍처 개요
  2. 사전 준비 — 도구 설치
  3. 클러스터 생성 — eksctl 선언형 설정
  4. Karpenter — 지능형 노드 오토스케일링
  5. ALB Ingress Controller + HTTPS 설정
  6. HPA — CPU/메모리 기반 Pod 오토스케일링
  7. 운영 — 핵심 명령어 모음
  8. 보안 강화 — IRSA와 NetworkPolicy

EKS 프로덕션 아키텍처 개요

EKS(Elastic Kubernetes Service)는 AWS 관리형 컨트롤 플레인 위에서 Kubernetes를 운영합니다. 프로덕션에서는 Multi-AZ 노드 그룹 + Karpenter 오토스케일링 + ALB Ingress 조합이 표준입니다.


사전 준비 — 도구 설치

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

# 버전 확인
eksctl version && kubectl version --client && helm version

클러스터 생성 — 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 — 지능형 노드 오토스케일링

Cluster Autoscaler 대신 Karpenter를 사용하면 미사용 노드를 빠르게 정리하고 비용을 절감합니다.

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

NodePool · 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 + HTTPS 설정

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/메모리 기반 Pod 오토스케일링

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분간 관망 후 스케일 다운
      policies:
        - type: Pods
          value: 2
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Percent
          value: 100
          periodSeconds: 30

운영 — 핵심 명령어 모음

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

# 강제 종료 없이 파드 재스케줄
kubectl drain node-id --ignore-daemonsets --delete-emptydir-data

# 비용 최적화: Spot 중단 시뮬레이션
kubectl taint nodes NODE_NAME karpenter.sh/disruption:NoSchedule-

보안 강화 — IRSA와 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 — 기본 차단 후 필요한 것만 허용
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 도구가 초안 작성에 사용될 수 있습니다. 명령어의 실행 여부와 검증 환경은 각 가이드에 기재된 근거를 확인하세요. 적용 전 사용 중인 버전의 공식 문서를 확인하고, 오류는 이메일로 알려주세요. 이메일로 제보

주제 관련 공식 문서(자동 연결 · 문장별 근거 아님)Kubernetes 공식 문서 ↗AWS 공식 문서 ↗

질문 & 답변 (Q&A)

이 가이드에 대해 궁금한 점을 질문해보세요. 확인 후 답변드립니다.