전공영역 공부 기록

ALB controller 잘못된 설정으로 발생한 장애

악분 2023. 10. 3. 00:12
반응형

안녕하세요. 이 글은 ALB controller가 어떻게 시큐리티 그룹을 관리하는지 설명합니다. 그리고 시큐리티 그룹을 잘못 설정하여 발생한 장애 사례를 공유합니다. 또한 장애를 직접 발생시킬 수 있는 예제코드를 제공합니다.

 

마주쳤던 장애를 잠깐 설명하면, 아래 그림에서 첫 번째 pod와 ALB를 삭제했더니 두 번째 ALB를 사용하지 못했습니다.

 

장애에 대한 설명은 영상으로도 만나 볼 수 있습니다.

 

 

1. ALB controller이란?

ALB Controller는 EKS가 AWS ELB(NLB 또는 ALB)를 사용할 수 있게 해줍니다. service 또는 ingress 생성/수정/삭제 이벤트가 발생하면, ALB controller가 이벤트를 감지하여 ELB를 관리합니다.

 

2. ALB controller가 관리하는 시큐리티 그룹

ALB controller가 ELB를 생성하면 시큐리티 그룹 두개를 생성합니다. 시큐리티 그룹은 생성한 ELB에 연결됩니다. 시큐리티 그룹 이름은 프론트엔드와 백엔드입니다.

 

시큐리티 그룹은 [ELB설정 -> Security메뉴]에 보입니다.

 

2.1 프론트엔드 시큐리티 그룹 역할

프론트엔드 시큐리티 그룹은 ELB에 접근할 때 어떤 포트와 출발지 주소를 허용할지 결정합니다.

 

아래 예제는 출발지 포트가 80번 포트일 때만 ELB에 접근가능합니다.

 

프론트엔드 시큐리티 그룹은 설명에 “Managed”라는 키워드가 있습니다.

 

2.2 백엔드 시큐리티 그룹 역할

백엔드 시큐리티 그룹은 ELB가 EKS pod에 접근하기 위해 사용됩니다.

 

EKS는 클러스터 시큐리티를 사용하여 EKS접근을 관리합니다. AWS 콘솔에서 만든 ELB는 EKS에 접근하지 못합니다. 시큐리티 그룹에 ELB접근을 허용하는 규칙이 없기 때문입니다.

 

그래서 ALB controller는 자신이 만든 ELB가 EKS에 접근 가능하도록 3가지 설정을 합니다.

  1. 백엔드 시큐리티 그룹 생성
  2. ELB에 백엔드 시큐리티 그룹 연결
  3. EKS 클러스터 시큐리티 그룹에 백엔드 시큐리티 그룹 허용 규칙 추가

 

백엔드 시큐리티 그룹은 설명에 “Shared Backend”라는 키워드가 있습니다.

3. 공용(shared) 백엔드 시큐리티 그룹

백엔드 시큐리티 그룹은 모든 ELB에서 공용으로 사용됩니다. 이러한 이유로 ELB 시큐리티 그룹 설명에 'Shard Backend'로 표시되어 있습니다

 

백엔드 시큐리티 그룹 한 개로 모든 ELB 타겟 그룹을 관리해야 합니다. 그래서 ALB controller는 타겟 그룹 포트를 범위로 관리합니다.

 

예를 들어 쿠버네티스에서 ingress 2개를 생성했다고 가정해봅시다. 타겟 그룹은 IP유형입니다. 첫 번째 pod 컨테이너 포트는 80/tcp이고 두 번째 pod 컨테이너 포트는 8080/tcp입니다. ALB controller는 클러스터 시큐리티 그룹 규칙에서 백엔드 시큐리티 그룹 포트를 어떻게 설정했을까요?

 

정답은 80-8080/tcp입니다. 80-8080은 첫 번째 pod 컨테이너 포트와 두 번째 pod 컨테이너 포트 범위입니다.

 

반응형

 

4. ELB 시큐리티 그룹 설정으로 발생한 장애

이 챕터에서는 ALB controller 잘못된 설정 때문에 만났던 장애를 설명합니다.

 

4.1 장애 상황

제 팀이 만났던 장애는 ALB와 ALB에 연결된 쿠버네티스 리소스를 삭제 한 후, 관련 없는 다른 ALB접속 오류가 발생했습니다. ALB에 연결된 pod는 정상 동작했습니다

 

4.2 장애 원인

장애의 원인은 EKS 클러스터 시큐리티 그룹 규칙에서 백엔드 시큐리티 그룹이 없어졌기 때문입니다. 

 

삭제하지 않은 ALB에 연결된 컨테이너 포트도 8080/tcp포트를 사용합니다. 그래서 백엔드 시큐리티 그룹 규칙에 8080/tcp가 있어야 합니다. 하지만 깔끔하게 삭제되어서 없어졌습니다.

 

백엔드 시큐리티 그룹이 없어진 이유를 찾아보니 ingress .metadata.annotations옵션을 사용했기 때문입니다. security-groups필드 사용하면, ALB controller가 더 이상 해당 ELB를 백엔드 시큐리티 그룹으로 관리하지 않습니다. 그러므로 ALB controller는 더 이상 클러스터 시큐리티 그룹 규칙에 백엔드 시큐리티 그룹을 추가하지 않습니다. 

참고자료: ALB controller문서

 

security-groups필드의 역할은 ALB에 연결할 시큐리티 그룹을 직접 설정합니다. 아래 예제는 실제 장애가 있었던 ingress 필드를 재현했습니다.

 

4.3 장애 분석 결과

결과적으로 장애가 발생한 이유는 ALB가 EKS pod에 접근을 못해서 발생했습니다. 클러스터 시큐리티 그룹 inbound규칙에 백엔드 시큐리티 그룹이 없어, ALB가 EKS pod에 접근이 불가능합니다.

 

4.4 장애 해결방법

장애를 해결한 방법은 간단했습니다. security-groups필드를 사용하더라도, ALB에 백엔드 시큐리티 그룹에 추가되도록 설정했습니다. ingress .metadata.annotations에 managed-backend-security-group-rules필드를 true로 설정하여 해결했습니다.

 

managed-backend-security-group-rules는 디폴트로 false로 되어 있으므로 아래 코드와 같이 true로 변경합니다.

 

5. 장애 재현

이 챕터는 [챕터 4]에서 말한 장애를 재현합니다.

 

5.1 시나리오

echo-server pod, service, ingress를 .metadata.name만 다르게 해서 2개를 배포합니다. 단, 두 번째 ingress는 ingress.annotations.security-groups를 사용합니다. 그리고 ingress.annotations.security-groups를 설정하지 않는 echo-server 쿠버네티스 리소스를 삭제합니다.

 

  1. echo-server pod, serivce, ingress를 생성합니다.
  2. 1번 과정에서 생성한 매니페스트에서 이름만 변경해서 생성합니다. 단, ingress는 ingress.annotations.security-groups를 설정합니다.
  3. 1번 과정에서 생성한 매니페스트를 삭제합니다.
  4. EKS 클러스터 시큐리티 그룹 규칙에서 백엔드 시큐리티 그룹이 있는지 확인합니다.
  5. 2번 과정에서 생성한 ALB에 접속하고 504에러를 확인합니다.

 

5.2 실습코드

실습코드는 제 github에 공개되어 있습니다.

git clone https://github.com/choisungwook/eks-alb-controller-backend.git example
cd example

 

5.3 실습환경 구축

장애를 재현하기 위해 EKS와 ALB controller를 구축해야 합니다.

 

■ EKS 생성

EKS는 eksctl도구를 사용하여 생성했습니다. t3.micro타입인 spot 인스턴스 2대를 사용했습니다.

cd eksctl
make install

 

■ ALB controller 생성

cd alb_controller
make install

 

5.4 첫 번째 echo-server pod, serivce, ingress 생성

echo-server pod, service, ingresse를 생성합니다.

cd manifests
kubectl apply -f echo-server.yaml

 

ALB가 생성은 약 5분정도 소요됩니다. ALB가 생성된 후, ALB targert group에 백엔드 시큐리티 그룹이 있는지 확인합니다. 그리고 EKS 시큐리티 그룹 규칙에 백엔드 시큐리티 그룹이 있는지 확인합니다. 마지막으로 ALB DNS주소로 접속하면 두 번째 echo-server 응답이 오는지 확인합니다.

 

마지막으로 ALB DNS주소로 접속하면 첫 번째 echo-server 응답이 오는지 확인합니다.

 

5.5 두 번째 echo-server 생성

두 번째 echo-server는 ingress에 metadata.annotations.security-groups를 사용합니다.

 

AWS 콘솔에서 시큐리티 그룹을 생성합니다. VPC는 eksctl이 생성한 EKS VPC를 사용합니다. inbound는 모든 IP에 대해 80/tcp를 허용합니다. 시큐리티 그룹을 생성한 후 시큐리티 그룹 id를 잘 기억하세요. ingress생성 할 때 사용합니다.

 

두 번째 echo-server pod, service, ingresse를 생성합니다. 첫 번째 echo-sever와 다른 점은 두개입니다.

  • 각 쿠버네티스 리소스의 .metadata.name
  • ingress에 metadata.annotations.security-groups를 설정

 

ingress metadata.annotations.security-groups를 수정합니다. 시큐리티 그룹은 2개를 설정합니다.

  • 첫 번째 시큐리티 그룹: (첫 번째 echo-server ALB에 연결된) 백엔드 시큐리티 그룹
  • 두 번쨰 시큐리티 그룹: AWS 콘솔에서 생성한 시큐리티 그룹
cd manifests
vi echo-server-secondary.yaml

 

매니페스트를 수정한 후 배포합니다.

kubectl apply -f echo-server-secondary.yaml

 

ALB가 생성은 약 5분정도 소요됩니다. ALB가 생성된 후, ALB target group에 백엔드 시큐리티 그룹이 있는지 확인합니다. 그리고 ALB DNS주소로 접속하면 두 번째 echo-server 응답이 오는지 확인합니다.

 

5.6 장애 발생시키기

첫 번째 echo-server를 삭제하면 장애가 발생합니다. 두 번째로 생성한 ALB가 접속되지 않습니다.

cd manifests
kubectl apply -f echo-server.yaml

 

EKS 클러스터 시큐리티 그룹 규칙을 확인합니다. 백엔드 시큐리티 그룹이 사라졌습니다.

 

따라서 echo-server ALB는 EKS에 접근하지 못해 접속 오류가 발생합니다.

 

5.7 장애 해결방법

장애를 해결하려면 두 번째 echo-server의 ingress.metadata.annotations을 설정하면 됩니다. ALB에 백엔드 시큐리티 그룹을 연결하는 필드를 추가합니다.

$ kubectl -n default edit ingress echoserver-secondary
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver-secondary
  namespace: default
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/tags: Environment=dev,Team=test
    alb.ingress.kubernetes.io/security-groups: sg-0d571f4123d5fdf21, sg-0ce4ca243c8e63740
    # 추가
    alb.ingress.kubernetes.io/manage-backend-security-group-rules: "true"
spec:
  ingressClassName: alb
  rules:

 

5.8 실습환경 삭제

실습환경를 삭제하려면 삭제 순서가 중요합니다. 삭제 순서를 지키지 않으면 pod삭제가 되지 않아 EKS가 삭제되지 않습니다.

# 1. 매니페스트 삭제
kubectl delete -f manifests/

# 2. pod,service,ingress 삭제 확인
kubectl -n default get pod,service,ingress

# 3. 약  ALB controller 삭제
cd ./alb_controller/
make uninstall
cd ../

# 4. eksctl로 EKS 삭제
cd eksctl
make uninstall

 

6. ALB controller 코드 분석

팀원 중 한명이 ALB controller 코드를 분석하고 정리해주셨습니다.

반응형