🎯 EKS 인프라 담당자 실무 가이드

📑 목차


1. 인프라 담당자가 항상 알고 있어야 할 것들

인프라 담당자는 “구성하는 사람”이 아니라 **“클러스터에서 일어나는 모든 일을 설명할 수 있는 사람”**이다.

1-1. 트러블슈팅 흐름 (머릿속에 즉시 떠올라야 함)

장애 발생
├── Pod 레벨?
│   ├── Pending    → 스케줄링 문제 (리소스, NodeSelector, Affinity, Taint)
│   ├── ImagePull  → ECR 권한, 이미지 태그 오류
│   ├── CrashLoop  → 애플리케이션 오류, 환경변수 누락, OOM
│   └── Running but 502 → readiness 미통과, preStop 누락
│
├── 네트워크 레벨?
│   ├── Pod → Pod 안됨  → NetworkPolicy, DNS, SG
│   ├── 외부 → Pod 안됨 → ALB → Ingress → Service → Pod 체인 확인
│   └── Pod → AWS 안됨  → IRSA, VPC 라우팅
│
└── 노드 레벨?
    ├── 노드 NotReady  → kubelet, 디스크, 메모리 압박
    ├── 노드 안 생김   → Karpenter 권한, EC2 쿼터, Spot 가용성
    └── 노드 갑자기 사라짐 → Spot 인터럽션 (SQS 이벤트 확인)

1-2. 항상 모니터링해야 할 지표

지표임계값 기준도구
Pod CPU/Memory 사용률request의 80% 초과 → HPA 동작 확인Prometheus
노드 수 변화급격한 증가 → 비용 알람Karpenter 로그
PVC 사용률85% 이상 → 확장 필요CloudWatch
ALB 5xx 비율1% 이상 → 즉시 조사CloudWatch ALB 메트릭
etcd 크기EKS는 AWS 관리, 그러나 오브젝트 수 과다 주의kubectl
인증서 만료일30일 이내 → 갱신 준비cert-manager alert

1-3. 비용 구조 이해 (매달 설명할 수 있어야 함)

EKS 비용 구조
├── Control Plane: $0.10/시간 (클러스터당 고정 ~$72/월)
├── 노드 (EC2)
│   ├── On-demand: 안정적, 비쌈
│   └── Spot: 최대 70% 절감, 중단 가능
├── ALB: $0.008/LCU + 시간당 $0.0225
├── NAT Gateway: $0.045/시간 + $0.045/GB  ← 데이터 전송 주의
└── EBS (PVC): gp3 기준 $0.08/GB/월

NAT Gateway 함정

Pod가 외부 API를 자주 호출하면 NAT Gateway 데이터 전송 비용이 예상 외로 크다. ECR 이미지 pull도 NAT를 탄다 → VPC Endpoint(S3, ECR) 설정으로 절감 가능.

1-4. 클러스터 업그레이드 주기 이해

EKS 버전 지원 정책
- 신규 버전 출시 후 약 14개월 지원
- 지원 종료 전 자동 강제 업그레이드 → 미리 해야 함

업그레이드 순서 (반드시 이 순서)
1. Control Plane 업그레이드 (AWS 콘솔 or CLI)
2. 시스템 노드그룹 업그레이드 (AMI 교체)
3. Karpenter NodeClass AMI 업그레이드
4. 애드온 업그레이드 (vpc-cni, coredns, kube-proxy)
5. 앱 호환성 확인

한 버전씩만

1.29 → 1.31 같은 두 버전 스킵은 지원 안 됨. 반드시 1.29 → 1.30 → 1.31 순서.


2. 현재 구조 진단

현재 구현된 것 (잘 된 것들)

영역구현 여부비고
EKS 클러스터OIDC, 시스템 노드그룹
Karpenter 노드 오토스케일링On-demand + Spot NodePool
IRSA서비스별 최소 권한
External Secrets OperatorSSM → K8s Secret
Argo CD App of AppsGitOps 자동화
ALB Controller + IngressHTTPS, SSL redirect
HPACPU 기반 스케일링
PDBKarpenter 통합
Graceful ShutdownpreStop + terminationGrace
Topology Spread멀티 AZ 분산
Probe 분리startup/liveness/readiness

현재 없는 것들 (실무에서 필요한 것들)

영역현재 상태실무 임팩트
Observability 스택장애 원인 파악 불가
NetworkPolicyPod 간 트래픽 무제한
cert-manager인증서 수동 관리
external-dnsRoute53 수동 관리
Velero (백업)K8s 리소스 복구 불가
ResourceQuota / LimitRange네임스페이스 리소스 폭주 가능
Terraform 원격 상태팀 협업 시 state 충돌
VPC EndpointECR/S3 NAT 비용 누수
Argo Rollouts배포 시 카나리/블루그린 불가

3. 실무 수준으로 올리기 위한 학습 로드맵

3-1. 즉시 필요 (배포 전 반드시)

Observability: Prometheus + Grafana + Loki

현재 상태: CloudWatch만 있음 → 컨테이너 레벨 메트릭/로그 없음
문제: Pod OOM 터져도 원인 파악 못 함, 느린 API 어디서 왜 느린지 모름
# kube-prometheus-stack (Prometheus + Grafana + AlertManager 한번에)
helm install prometheus prometheus-community/kube-prometheus-stack \
  -n monitoring --create-namespace \
  -f values/prometheus-values.yaml

핵심 대시보드:

  • USE 메트릭: Utilization, Saturation, Errors (노드/Pod 단위)
  • RED 메트릭: Rate, Errors, Duration (서비스 단위)
  • Karpenter 대시보드 (공식 Grafana 대시보드 ID: 20311)

NetworkPolicy: Pod 간 트래픽 제한

# 기본 정책: pposiraegi 네임스페이스 내부 통신만 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: pposiraegi
spec:
  podSelector: {}
  policyTypes: [Ingress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-internal
  namespace: pposiraegi
spec:
  podSelector: {}
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: pposiraegi

NetworkPolicy는 VPC CNI 필요

EKS의 AWS VPC CNI는 NetworkPolicy를 지원한다. EKS 1.25+ 에서는 VPC CNI에 NetworkPolicy 컨트롤러가 내장됨.

ResourceQuota + LimitRange

# 네임스페이스 전체 상한 (폭주 방지)
apiVersion: v1
kind: ResourceQuota
metadata:
  name: pposiraegi-quota
  namespace: pposiraegi
spec:
  hard:
    requests.cpu: "8"
    requests.memory: 16Gi
    limits.cpu: "16"
    limits.memory: 32Gi
    pods: "50"
---
# 개별 컨테이너 기본값 (requests 없는 Pod 방지)
apiVersion: v1
kind: LimitRange
metadata:
  name: pposiraegi-limits
  namespace: pposiraegi
spec:
  limits:
    - type: Container
      default:
        cpu: 200m
        memory: 256Mi
      defaultRequest:
        cpu: 100m
        memory: 128Mi

3-2. 단기 (1-2개월)

cert-manager: 인증서 자동 갱신

현재: ACM 인증서를 수동으로 ARN 입력
문제: 갱신 까먹으면 HTTPS 인증서 만료 → 서비스 장애
helm install cert-manager jetstack/cert-manager \
  -n cert-manager --create-namespace \
  --set installCRDs=true
# Let's Encrypt ClusterIssuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your@email.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: alb

external-dns: Route53 자동 동기화

현재: Ingress 만들 때마다 Route53 레코드 수동 추가
문제: Ingress ADDRESS 바뀌면 DNS도 수동으로 바꿔야 함
helm install external-dns external-dns/external-dns \
  --set provider=aws \
  --set "domainFilters[0]=pposiraegi.com" \
  --set policy=sync

Ingress에 어노테이션만 추가하면 Route53이 자동 동기화:

annotations:
  external-dns.alpha.kubernetes.io/hostname: api.pposiraegi.com

VPC Endpoint: NAT 비용 절감

# ECR + S3 VPC Endpoint (데이터 전송 비용 절감)
resource "aws_vpc_endpoint" "s3" {
  vpc_id            = var.vpc_id
  service_name      = "com.amazonaws.${var.region}.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = [var.private_route_table_id]
}
 
resource "aws_vpc_endpoint" "ecr_dkr" {
  vpc_id              = var.vpc_id
  service_name        = "com.amazonaws.${var.region}.ecr.dkr"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = [var.private_subnet_a_id, var.private_subnet_b_id]
  security_group_ids  = [var.internal_sg_id]
  private_dns_enabled = true
}

ECR pull이 NAT를 통하지 않으면

노드 100대가 이미지 pull 할 때 NAT 데이터 비용이 0이 된다. Interface Endpoint는 시간당 $0.01이지만 트래픽 많으면 훨씬 이득.


3-3. 중기 (3-6개월)

Argo Rollouts: 안전한 배포 전략

현재: Deployment 교체 → 롤링 업데이트 (구버전 Pod 즉시 종료)
실무: 신버전 5% 트래픽 → 에러율 확인 → 점진 증가 → 100%
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: api-gateway
spec:
  strategy:
    canary:
      steps:
        - setWeight: 10     # 10% 트래픽 신버전
        - pause: {duration: 5m}   # 5분 관찰
        - setWeight: 50
        - pause: {duration: 5m}
        - setWeight: 100
      # 자동 롤백: 에러율 5% 초과 시
      analysis:
        templates:
          - templateName: success-rate
        args:
          - name: service-name
            value: api-gateway

Terraform Remote State: 팀 협업

# backend.tf
terraform {
  backend "s3" {
    bucket         = "pposiraegi-tfstate"
    key            = "infrastructure/terraform.tfstate"
    region         = "ap-northeast-2"
    dynamodb_table = "pposiraegi-tflock"   # 동시 apply 방지
    encrypt        = true
  }
}

언제 도입해야 하나

인프라 작업자가 2명 이상이 되는 순간 필수다. 혼자일 때도 state 파일 날리면 재앙이니 S3 백업은 해두는 게 낫다.

Velero: 재해 복구

쿠버네티스 리소스(Deployment, Secret, ConfigMap 등) + PV 데이터 백업
실수로 namespace 날려도 복구 가능
velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws \
  --bucket pposiraegi-velero-backup \
  --backup-location-config region=ap-northeast-2
 
# 매일 새벽 2시 백업
velero schedule create daily-backup \
  --schedule "0 2 * * *" \
  --ttl 168h  # 7일 보관

3-4. 심화 (실무 고수 레벨)

Service Mesh (Istio / Linkerd)

현재: 서비스간 통신이 암호화 안 됨, 재시도 로직 앱에 있음
Service Mesh 도입 시:
- mTLS: Pod 간 통신 자동 암호화
- 서킷 브레이커: 다운된 서비스로 연결 차단 (앱 코드 수정 없이)
- 분산 트레이싱: 요청이 어느 서비스에서 얼마나 걸렸는지 시각화
- 트래픽 미러링: 실제 트래픽을 새버전으로도 복사해서 테스트

Service Mesh 도입 비용

모든 Pod에 사이드카 컨테이너가 붙음 → CPU/Memory 약 10-15% 증가. 복잡도도 올라가니 규모가 작으면 오버엔지니어링이 될 수 있다.

OPA Gatekeeper / Kyverno: 정책 강제

"루트로 실행하는 컨테이너 배포 금지"
"resources.requests 없는 Deployment 거부"
"허가된 레지스트리(ECR)에서만 이미지 pull 허용"
같은 규칙을 코드로 강제
# Kyverno: ECR 외 이미지 차단 예시
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: restrict-image-registries
spec:
  validationFailureAction: Enforce
  rules:
    - name: validate-registries
      match:
        resources:
          kinds: [Pod]
      validate:
        message: "ECR 이미지만 허용됩니다."
        pattern:
          spec:
            containers:
              - image: "*.dkr.ecr.ap-northeast-2.amazonaws.com/*"

CoreDNS 튜닝

실무에서 DNS 쿼리가 레이턴시 병목이 되는 경우가 있다.
기본 ndots:5 설정이 불필요한 DNS 쿼리를 5번씩 날린다.
# Pod spec에서 DNS 쿼리 최적화
spec:
  dnsConfig:
    options:
      - name: ndots
        value: "2"    # 기본 5 → 2로 줄이면 외부 도메인 쿼리 빨라짐
      - name: single-request-reopen

4. 각 영역별 깊이있는 내용

4-1. Karpenter 심화: 실무에서 자주 만나는 상황

Spot 인터럽션 발생 시 흐름

1. AWS → SQS: "이 Spot 인스턴스 2분 후 회수"
2. Karpenter → SQS 폴링 → 인터럽션 감지
3. Karpenter → Pod cordon + drain (PDB 존중)
4. PDB: 최소 replicas 보장하면서 Pod 옮김
5. Karpenter → 새 노드 프로비저닝 (다른 인스턴스 타입/AZ)
6. 기존 노드 종료

Spot 인터럽션에 강한 구조

  • consolidationPolicy: WhenUnderutilized + Spot 다양한 인스턴스 타입
  • PDB minAvailable: 1 필수
  • 중요 서비스는 On-demand NodePool에 nodeSelector 고정

Karpenter 비용 최적화 전략

# 앱별로 On-demand / Spot 선택
# 중요 서비스 (user-service, order-service)
nodeSelector:
  karpenter.sh/capacity-type: on-demand
 
# 비용 절감 가능한 서비스 (api-gateway, product-service)
nodeSelector:
  karpenter.sh/capacity-type: spot

4-2. Argo CD 심화: GitOps 브랜치 전략

단순 구조 (소규모 팀)
  main 브랜치 → Argo CD가 자동 sync → 프로덕션 배포

환경 분리 구조 (실무)
  dev 브랜치   → Argo CD dev 앱  → dev 클러스터
  staging 브랜치 → Argo CD staging 앱 → staging 클러스터
  main 브랜치   → Argo CD prod 앱 → prod 클러스터

이미지 태그 자동 업데이트: Argo CD Image Updater
  ECR에 새 이미지 push → Image Updater가 k8s 레포 커밋 자동 생성 → Argo CD sync

4-3. IRSA 심화: 최소 권한 원칙 점검

# 실제로 어떤 AWS API를 호출하는지 CloudTrail로 확인
aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=Username,AttributeValue=<role-name> \
  --start-time $(date -d '7 days ago' +%s) \
  --output json | jq '.Events[].CloudTrailEvent' | jq -r '.eventName' | sort -u

권한 최소화 접근법

처음엔 넓게 주고, CloudTrail로 실제 사용 API 확인 → 나머지 제거. AWS IAM Access Analyzer를 활용하면 미사용 권한을 자동으로 찾아준다.

4-4. EKS 네트워크 심화: IP 고갈 문제

EKS 기본 VPC CNI: 노드당 ENI × IP 할당
문제: t3.medium = ENI 3개 × IP 6개 = 최대 18개 Pod (실제론 더 적음)
# 현재 노드별 가용 IP 확인
kubectl get nodes -o custom-columns=\
NAME:.metadata.name,\
MAX_PODS:.status.allocatable.pods

해결책: Prefix Delegation (EKS 1.24+)

기존: ENI당 IP 1개씩 할당 → IP 낭비
Prefix: ENI당 /28 CIDR(16개 IP) 할당 → 같은 ENI로 4배 더 많은 Pod

요약: 우선순위 학습 순서

즉시 (프로덕션 전)
  1. Prometheus + Grafana (관찰 없이는 운영 불가)
  2. NetworkPolicy (최소한의 보안)
  3. ResourceQuota / LimitRange (폭주 방지)

단기 (1-2개월)
  4. cert-manager (인증서 자동화)
  5. external-dns (Route53 자동화)
  6. VPC Endpoint (비용 절감)

중기 (3-6개월)
  7. Argo Rollouts (안전한 배포)
  8. Terraform Remote State (팀 협업)
  9. Velero (재해 복구)

심화 (고수 레벨)
  10. Service Mesh (Istio/Linkerd)
  11. OPA Gatekeeper / Kyverno (정책 코드화)
  12. EKS 업그레이드 전략 실습
  13. Prefix Delegation / CoreDNS 튜닝

핵심 마인드셋

실무 인프라 담당자의 역할은 **“구성”이 아니라 “설명”**이다. “왜 이 구조인가”, “장애가 나면 어디서 나는가”, “비용이 왜 이만큼인가”를 즉시 대답할 수 있을 때 실무 수준이다.