끄적이는 보송

[AWS] 잘못된 ALB 설정으로 인한 웹 서비스 지연 분석 본문

STUDY/AWS

[AWS] 잘못된 ALB 설정으로 인한 웹 서비스 지연 분석

끄적이는 보송 2023. 5. 3. 13:57
반응형

문제 발생

External ALB가 외부 Client의 요청을 Private Subnet에 위치한 Web/WAS 서버에 전달하는, 아주 단순한 구조의 웹서비스 운영에 문제가 있었던 적이 있었다. Client가 웹에 요청을 보내면 20초 넘도로 오래 걸린다는 점이었다. 정말 단순한 이유였지만 기록 차원에서 남겨본다.

 

문제 분석

Client가 웹에 접속하는데 너무 느리다. 여기에는 정말 다양한 이유가 있을 수 있다. 내가 했던 것들을 나열해 보았다.

1. Client 마다 증상이 달랐다. 누구는 빠르게 접속이 되고, 누구는 그렇지 않았다. Client를 탄다는 이야기인데 아주 이상한 부분이었다.

2. Web/WAS 인스턴스의 타입은 t타입이었다. 보통 운영환경에 t타입은 사용하지 않는다. t타입의 공지된 스펙을 그대로 사용할 수 없을뿐더러 그러기 위해선 credit을 소모해야 하기 때문이다. 이 credit이 전부 소모되면 t타입 인스턴스의 스펙 절반도 못 내는 퍼포먼스를 보여준다. credit 소모가 우려되어 이를 무제한으로 설정하면 m타입보다 과금이 더 발생하는 마법이 발생한다. 나의 경우, 해당 인스턴스의 부하는 아주 적었다. 즉, 낮은 스펙으로 인한 인스턴스의 과부하는 문제가 아니다.

3. EBS Volume에는 여유가 있었다. 만약 꽉 차있었다면 새로운 데이터를 읽고 쓰는데 성능이 저하됐을 것이다. 디스크 공간이 부족해지면 캐시 메모리에 저장된 데이터가 더 이상 유지되지 못하고 매번 디스크에서 데이터를 불러오거나, 스왑 공간이 부족해지거나, 새로운 파일을 저장하기 위해 여러 작업을 수행하는 경우에도 많은 IOPS를 야기하기에 여러 가지로 성능 저하의 원인 될 수 있다. 여하튼 나의 경우 storage 크기는 문제가 아니었다.

4. EBS Volume IOPS도 문제없었다. 큰 읽기/쓰기 작업 없이 여유로웠다.

5. 웹브라우저의 개발자 모드로 확인해 보았다. 아래는 그냥 예시이다. Network 탭 혹은 Performance(촬영 모드)로 레코딩을 하면 HTTP 통신 과정을 들여다볼 수 있어 브라우저와 서버 간의 통신과정에서 어떤 문제가 있었는지 알 수 있다. 여기서 특정 페이지가 느리거나 그런 것은 발견되지 않았다. 다만 library를 외부에서 긁어오는 비 효율적인 모습은 보였어도 여기서도 지연은 0.5초 정도밖에 되지 않아 주원인은 아니었다. 다만 실제로 웹에 요청했을 때, 처음 initial connection에 아주 긴 pending이 발생했다. 이후 connection이 맺어지면 아주 빠르게 필요한 자원을 다운로드하는 것을 확인했다. 즉, application이 아닌 network 적인 문제가 있다는 것이다.

6. 도메인 설정 이상일 수 있어, ALB dns name으로 직접 접속해 보아도 문제는 동일했다. 즉, 도메인 설정에는 문제가 없다.

7. ALB 자체적으로 큰 부하는 없었다. EC2 인스턴스에 부하가 없는데 당연 ALB에도 부하는 없었고 요청량도 적었다. 아무리 scalable 한 서비스여도 pre-warming 없이 갑작스러운 부하는 ALB도 감당하기 힘들 수 있다.

8. ALB의 응답시간을 빨랐다는 모니터링이 확인된다. 분명 client는 아주 느리게 서비스를 제공받고 있는데 ALB 입장에서는 빠르게 응답했다는 것이다. ALB Access Log를 활성화해서 로그를 까 보아도 응답시간은 아주 빨랐고 심지어 200을 return 했다. 여기서 더 이상한 것을 발견했다. ALB Access Log가 하나씩만 쌓인다는 점이다. 보통은 가용성을 위해 서로 다른 AZ의 Subnet에 ALB 노드를 배치하기 때문에 적어도 2개 이상씩 쌓이는 것이 일반적이다. 내가 분석한 ALB도 두 개의 가용영역에 배치되어 있다. 즉, 하나는 통신을 받은 적이 없고 그러니 로그에 쌓이지도 않았다는 것을 의미한다. 아주 이상하다.

 

문제 원인

아주 어이없게도 ALB의 설정이 문제의 원인이었다. 해당 ALB는 internet facing속성으로 외부 client의 요청을 받아 내부로 전달하기 위해서는 Node가 외부와 통신이 가능한 Public Subnet에 위치해야 한다. 하지만 나의 경우, 두 개의 ALB Node가 있는데 하나는 Public Subnet, 하나는 Private Subnet에 배치되어 잘못 생성되어 있었다. 그렇다면 DNS resolving에 문제 생기며, 모든 것이 설명이 된다. (내가 만든 거 아니다...)

먼저 테스트를 해보자. internet-facing ALB의 노드를 하나는 Public, 하나는 Private에 두어보았다.

dig alb-xxxxxxxxx.ap-northeast-2.elb.amazonaws.com

        ; <<>> DiG 9.10.6 <<>> alb-xxxxxxxxx.ap-northeast-2.elb.amazonaws.com
        ;; global options: +cmd
        ;; Got answer:
        ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34724
        ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

        ;; OPT PSEUDOSECTION:
        ; EDNS: version: 0, flags:; udp: 1232
        ;; QUESTION SECTION:
        ;alb-xxxxxxxxx.ap-northeast-2.elb.amazonaws.com.	IN A

        ;; ANSWER SECTION:
        alb-xxxxxxxxx.ap-northeast-2.elb.amazonaws.com.	60 IN A	3.38.xx.xx
        alb-xxxxxxxxx.ap-northeast-2.elb.amazonaws.com.	60 IN A	15.165.xx.xx

        ;; Query time: 138 msec
        ;; SERVER: 172.xx.xx.xx#53(172.xx.xx.xx)
        ;; WHEN: xxx xxx xx xx:xx:xx KST 2023
        ;; MSG SIZE  rcvd: 107

 그러나 반환된 두 개의 IP에 대해 curl을 이용해 접속을 시도해 보면 한쪽만 정상적으로 응답이 오는 것을 확인할 수 있다.

#정상 응답
curl http://3.38.xx.xx 
<h1> Here is INS-VPC-First-Private-Instance-01 WEB Server ap-northeast-2a <h1>
#비 정상 응답
curl http://15.165.xx.xx 
curl: (28) Failed to connect to 15.165.xx.xx port 80 after 75005 ms: Couldn't connect to server

외부 Client는 웹에 접속하기 위해 ALB를 탔을 것이고 여기서 랜덤 하게 Public Node 혹은 Priave Node로 전달 됐을 것이다. 하지만 Private Node가 Client가 보낸 요청을 받을 수는 있더라도 ALB가 해당 request에 대한 response를 보낼 때 Subnet이 속한 routing table을 참조하게 되는데 이때 외부로 나갈 수 있는 라우팅이 존재하지 않는 경우 응답을 보낼 수가 없게 된다. 

20초의 지연이 발생하는 것도 이것이 원인이었으며, Client 마다 현상이 달랐던 것도 Client 설정에 따라 다른 것으로 해석된다. 응답을 받지 못한 Client가 어떻게 동작(retry, timeout 등...)할지에 대한 부분은 OS에 설정된 기본 값에 의존하며 브라우저 설정에 따라도 일부 달라질 수 있다고 나는 이해하고 있다.

이런 이유 때문에 한쪽의 ALB 노드만 통신이 되고 있었던 거고, 아무런 로그가 쌓이지 않으니 ALB Access Log도 하나씩만 쌓였던 것이다.

반응형
Comments