Amazon EKS Ingress Grouping으로 비용 최적화하기

dongdorrong·5일 전
0

AWS

목록 보기
13/14

개요

Amazon EKS에서 여러 개의 Ingress를 사용할 때 발생하는 비용 문제를 해결하고, AWS Load Balancer Controller의 Ingress Grouping 기능을 활용하여 Application Load Balancer(ALB)를 효율적으로 공유하는 방법을 알아보겠습니다.

문제 상황

기본 Ingress 동작

Kubernetes에서 Ingress는 클러스터 외부에서 내부 서비스에 접근할 수 있도록 HTTP/HTTPS 라우팅을 제공하는 API 객체입니다. AWS Load Balancer Controller를 사용하면 Ingress 리소스가 생성될 때마다 자동으로 ALB가 프로비저닝됩니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 80

비용 문제

마이크로서비스 아키텍처에서는 여러 서비스가 각각의 Ingress를 가지게 되는데, 이는 다음과 같은 문제를 야기합니다:

  • 각 Ingress마다 별도의 ALB 생성: Ingress 하나당 ALB 하나가 생성됨
  • 높은 운영 비용: ALB는 시간당 요금이 부과되므로 불필요한 ALB가 많아질수록 비용 증가
  • 관리 복잡성: 여러 ALB를 개별적으로 관리해야 하는 부담

Ingress Grouping이란?

Ingress Grouping은 AWS Load Balancer Controller의 기능으로, 여러 Ingress 리소스가 하나의 ALB를 공유할 수 있게 해주는 기능입니다.

주요 특징

  • 단일 ALB 공유: 여러 Ingress가 하나의 ALB를 공유
  • 네임스페이스 간 공유 가능: 서로 다른 네임스페이스의 Ingress들도 그룹화 가능
  • 자동 규칙 병합: 컨트롤러가 자동으로 Ingress 규칙들을 병합하여 ALB에 적용
  • 비용 절감: ALB 개수 감소로 인한 직접적인 비용 절감 효과

사전 준비사항 및 설치

Ingress Grouping을 사용하기 위해서는 몇 가지 필수 구성요소들이 사전에 설치되고 설정되어야 합니다.

1. EKS 클러스터 요구사항

기본 요구사항

  • EKS 클러스터: Kubernetes 1.19 이상
  • 노드 그룹: EC2 또는 Fargate (또는 혼합)
  • VPC 설정: 최소 2개 이상의 가용 영역에 서브넷 구성
# EKS 클러스터 생성 (eksctl 사용 예시)
eksctl create cluster \
  --name my-cluster \
  --region us-west-2 \
  --nodegroup-name standard-workers \
  --node-type m5.large \
  --nodes 3 \
  --nodes-min 1 \
  --nodes-max 4 \
  --managed

2. AWS Load Balancer Controller 설치

Ingress Grouping은 AWS Load Balancer Controller v2.0 이상에서 지원됩니다.

2-1. IAM 정책 생성

먼저 AWS Load Balancer Controller가 사용할 IAM 정책을 생성합니다.

# IAM 정책 다운로드
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.2/docs/install/iam_policy.json

# IAM 정책 생성
aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document file://iam_policy.json

2-2. IAM 역할 및 서비스 계정 생성

# OIDC 공급자 생성 (한 번만 실행)
eksctl utils associate-iam-oidc-provider --region=us-west-2 --cluster=my-cluster --approve

# 서비스 계정 생성 및 IAM 역할 연결
eksctl create iamserviceaccount \
  --cluster=my-cluster \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --role-name AmazonEKSLoadBalancerControllerRole \
  --attach-policy-arn=arn:aws:iam::ACCOUNT-ID:policy/AWSLoadBalancerControllerIAMPolicy \
  --approve

2-3. Helm을 통한 Controller 설치

# Helm 차트 레포지토리 추가
helm repo add eks https://aws.github.io/eks-charts
helm repo update

# AWS Load Balancer Controller 설치
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=my-cluster \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller \
  --set region=us-west-2 \
  --set vpcId=vpc-xxxxxxxx

2-4. 설치 확인

# Controller 팟 상태 확인
kubectl get deployment -n kube-system aws-load-balancer-controller

# 로그 확인
kubectl logs -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller

3. VPC 및 서브넷 설정

3-1. 서브넷 태깅

ALB가 올바른 서브넷에 생성되도록 서브넷에 태그를 설정해야 합니다.

# 퍼블릭 서브넷 태깅 (인터넷 대면 ALB용)
aws ec2 create-tags \
    --resources subnet-12345678 subnet-87654321 \
    --tags Key=kubernetes.io/role/elb,Value=1

# 프라이빗 서브넷 태깅 (내부 ALB용)
aws ec2 create-tags \
    --resources subnet-abcdefgh subnet-hgfedcba \
    --tags Key=kubernetes.io/role/internal-elb,Value=1

# 클러스터별 태깅 (여러 클러스터 사용 시)
aws ec2 create-tags \
    --resources subnet-12345678 subnet-87654321 \
    --tags Key=kubernetes.io/cluster/my-cluster,Value=shared

3-2. 보안 그룹 설정 확인

# 클러스터 보안 그룹에 태그 추가 (필요시)
aws ec2 create-tags \
    --resources sg-xxxxxxxxx \
    --tags Key=kubernetes.io/cluster/my-cluster,Value=owned

4. 필수 어노테이션 및 IngressClass 설정

4-1. IngressClass 생성 (Kubernetes 1.18+)

# ingress-class.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: alb
spec:
  controller: ingress.k8s.aws/alb
kubectl apply -f ingress-class.yaml

4-2. 기본 설정 검증

# AWS Load Balancer Controller 버전 확인
kubectl get deployment aws-load-balancer-controller -n kube-system -o yaml | grep image:

# 서비스 계정 확인
kubectl get serviceaccount aws-load-balancer-controller -n kube-system -o yaml

# IAM 역할 확인
kubectl describe serviceaccount aws-load-balancer-controller -n kube-system

5. 설치 검증을 위한 테스트

5-1. 간단한 테스트 애플리케이션 배포

# test-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-app
  template:
    metadata:
      labels:
        app: test-app
    spec:
      containers:
      - name: app
        image: nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: test-service
  namespace: default
spec:
  type: NodePort
  selector:
    app: test-app
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  namespace: default
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: test-service
            port:
              number: 80
# 테스트 앱 배포
kubectl apply -f test-app.yaml

# Ingress 상태 확인
kubectl get ingress test-ingress

# ALB 생성 확인
kubectl describe ingress test-ingress

6. 문제 해결 가이드

6-1. 일반적인 문제들

문제 1: Controller Pod가 시작되지 않음

# 서비스 계정 권한 확인
kubectl describe serviceaccount aws-load-balancer-controller -n kube-system

# IAM 역할 정책 확인
aws iam list-attached-role-policies --role-name AmazonEKSLoadBalancerControllerRole

문제 2: ALB가 생성되지 않음

# Controller 로그 확인
kubectl logs -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller

# 서브넷 태그 확인
aws ec2 describe-subnets --subnet-ids subnet-12345678 --query 'Subnets[*].Tags'

문제 3: 권한 부족 오류

# IAM 정책이 최신인지 확인
aws iam get-policy-version \
    --policy-arn arn:aws:iam::ACCOUNT-ID:policy/AWSLoadBalancerControllerIAMPolicy \
    --version-id v1

6-2. 설치 완료 체크리스트

  • EKS 클러스터가 정상 작동 중
  • AWS Load Balancer Controller v2.0+ 설치 완료
  • IAM 정책 및 서비스 계정 설정 완료
  • 서브넷에 적절한 태그 설정 완료
  • IngressClass 리소스 생성 완료
  • 테스트 Ingress로 ALB 생성 확인 완료

실습: Ingress Grouping 구현

이제 모든 사전 준비가 완료되었으므로 Ingress Grouping을 실제로 구현해보겠습니다.

1. 기본 환경 준비

먼저 두 개의 네임스페이스에 각각 애플리케이션을 배포합니다.

# 네임스페이스 생성
kubectl create namespace blue-green-ns
kubectl create namespace orange-purple-ns

2. 애플리케이션 배포

각 네임스페이스에 색상별 애플리케이션을 배포합니다.

# blue-green-ns 네임스페이스의 애플리케이션
apiVersion: apps/v1
kind: Deployment
metadata:
  name: blue-app
  namespace: blue-green-ns
spec:
  replicas: 2
  selector:
    matchLabels:
      app: blue-app
  template:
    metadata:
      labels:
        app: blue-app
    spec:
      containers:
      - name: blue-app
        image: nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: blue-service
  namespace: blue-green-ns
spec:
  type: NodePort
  selector:
    app: blue-app
  ports:
  - port: 80
    targetPort: 80

3. Ingress Grouping 설정

가장 중요한 부분인 Ingress Grouping 설정입니다. alb.ingress.kubernetes.io/group.name 어노테이션을 사용합니다.

# blue-green-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: blue-green-ingress
  namespace: blue-green-ns
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/group.name: app-color-lb  # 그룹 이름 지정
spec:
  ingressClassName: alb
  rules:
  - http:
      paths:
      - path: /blue
        pathType: Prefix
        backend:
          service:
            name: blue-service
            port:
              number: 80
      - path: /green
        pathType: Prefix
        backend:
          service:
            name: green-service
            port:
              number: 80
# orange-purple-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: orange-purple-ingress
  namespace: orange-purple-ns
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/group.name: app-color-lb  # 동일한 그룹 이름
spec:
  ingressClassName: alb
  rules:
  - http:
      paths:
      - path: /orange
        pathType: Prefix
        backend:
          service:
            name: orange-service
            port:
              number: 80
      - path: /purple
        pathType: Prefix
        backend:
          service:
            name: purple-service
            port:
              number: 80

4. 결과 확인

배포 후 Ingress 상태를 확인해보면 두 Ingress가 동일한 ALB 주소를 공유하는 것을 볼 수 있습니다.

kubectl get ingress -A

NAMESPACE          NAME                    ADDRESS
blue-green-ns      blue-green-ingress      k8s-appcolorlb-xxx.elb.amazonaws.com
orange-purple-ns   orange-purple-ingress   k8s-appcolorlb-xxx.elb.amazonaws.com

고급 설정

1. 그룹 순서 제어 (Group Order)

Ingress 규칙의 평가 순서를 제어하려면 group.order 어노테이션을 사용합니다.

metadata:
  annotations:
    alb.ingress.kubernetes.io/group.name: my-group
    alb.ingress.kubernetes.io/group.order: '10'  # 낮은 숫자가 우선순위 높음

2. 그룹 이름 규칙

  • 길이: 63자 이하
  • 구성: 소문자, 숫자, -, .만 사용 가능
  • 시작/끝: 문자 또는 숫자로 시작하고 끝나야 함
# 올바른 예시
alb.ingress.kubernetes.io/group.name: my-app-group
alb.ingress.kubernetes.io/group.name: production.web-services

# 잘못된 예시
alb.ingress.kubernetes.io/group.name: -my-group-  # 잘못된 시작/끝
alb.ingress.kubernetes.io/group.name: My_Group   # 대문자와 언더스코어 사용 불가

보안 고려사항

1. 신뢰 경계(Trust Boundary)

동일한 Ingress Group에 속한 모든 사용자는 같은 신뢰 경계 내에 있어야 합니다. 다른 사용자가 동일한 그룹 이름을 사용하여 Ingress를 생성하면 기존 규칙을 덮어쓸 수 있습니다.

2. 그룹 이름 충돌 방지

# 권장: 명확하고 고유한 이름 사용
alb.ingress.kubernetes.io/group.name: team-a-production-services

# 비권장: 일반적인 이름 사용
alb.ingress.kubernetes.io/group.name: my-group

3. RBAC 설정

Ingress 리소스에 대한 적절한 RBAC 정책을 설정하여 권한이 있는 사용자만 특정 그룹에 접근할 수 있도록 제한해야 합니다.

제한사항 및 주의사항

1. ALB 규칙 제한

  • 기본 제한: ALB 리스너당 최대 100개의 규칙
  • 성능 영향: 규칙이 많아질수록 성능에 영향을 줄 수 있음
  • 모니터링: 규칙 수를 지속적으로 모니터링해야 함

2. 충돌 해결

기본적으로 Ingress 간의 규칙 순서는 네임스페이스/이름의 사전적 순서로 결정됩니다. 명시적인 순서 제어를 위해서는 group.order를 사용해야 합니다.

3. 디버깅 복잡성

여러 Ingress가 하나의 ALB를 공유하므로 문제 발생 시 원인 파악이 복잡할 수 있습니다.

모니터링 및 트러블슈팅

1. AWS Load Balancer Controller 로그 확인

kubectl logs -f -n kube-system -l app.kubernetes.io/instance=aws-load-balancer-controller

2. ALB 규칙 확인

# ALB ARN 확인
ALB_ARN=$(aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-mygroup`)].LoadBalancerArn' --output text)

# 리스너 규칙 확인
LISTENER_ARN=$(aws elbv2 describe-listeners --load-balancer-arn $ALB_ARN --query 'Listeners[0].ListenerArn' --output text)
aws elbv2 describe-rules --listener-arn $LISTENER_ARN

3. Ingress 상태 확인

kubectl describe ingress <ingress-name> -n <namespace>

실제 사용 사례

1. 마이크로서비스 환경

# API Gateway 패턴
alb.ingress.kubernetes.io/group.name: api-gateway
# /api/users -> user-service
# /api/orders -> order-service  
# /api/products -> product-service

2. 환경별 분리

# 개발 환경
alb.ingress.kubernetes.io/group.name: dev-services

# 스테이징 환경  
alb.ingress.kubernetes.io/group.name: staging-services

# 프로덕션 환경
alb.ingress.kubernetes.io/group.name: prod-services

비용 절감 효과

예시 계산

  • 기존 방식: 10개 서비스 = 10개 ALB = 월 $200+ (ALB 시간당 $0.0225 × 24시간 × 30일 × 10개)
  • Ingress Grouping: 10개 서비스 = 2개 ALB = 월 $40+ (그룹별로 분할)
  • 절약 효과: 월 $160+ 절약 (약 80% 비용 절감)

마무리

Ingress Grouping은 Amazon EKS에서 ALB 비용을 크게 절감할 수 있는 강력한 기능입니다. 특히 마이크로서비스 아키텍처를 사용하는 환경에서는 필수적으로 고려해야 할 기능입니다.

핵심 포인트:

  • alb.ingress.kubernetes.io/group.name 어노테이션으로 간단히 설정
  • ✅ 네임스페이스 간 Ingress 공유 가능
  • ✅ 상당한 비용 절감 효과
  • ⚠️ 보안 고려사항과 제한사항 숙지 필요
  • ⚠️ 적절한 모니터링과 관리 필요

다음에는 Target Group Binding을 활용한 고급 로드밸런싱 패턴에 대해서도 다뤄보겠습니다.

참고 자료

profile
DevOps 엔지니어 / 열심히 해서 잘하자

0개의 댓글