🔮
TCP_TW 옵션?
July 31, 2023
개요?
최근에 프로젝트를 진행하면서, 리눅스 커널단의 설정에 의해 이슈가 발생하였다.
그래서 이번 기회에 TCP_TW 설정에 대해 알아보고자 한다.
이전에 이슈가 된 설정은 tcp_tw_reuse
, tcp_tw_recycle
옵션이었는데, 이 옵션들은 TIME_WAIT
상태의 소켓을 재사용하는 옵션이다.
TIME_WAIT?
TIME_WAIT 상태는 TCP 연결이 종료된 후, 일정 시간 동안 유지되는 상태이다.
이슈
최근 azure 의 AKS
를 세팅하면서 외부 요청에 대한 타임아웃이 발생하는 이슈가 있었다.
환경
- AKS에 하나의 파드에 두개의 컨테이너를 띄운 상태
- NAT 게이트웨이를 사용
이슈 시나리오
- A컨테이너에서만 외부API를 호출하면 바로바로 응답이 옴
- B컨테이너에서만 외부API를 호출하면 바로바로 응답이 옴
- A컨테이너에서 외부API호출 후 바로 B컨테이너에서 외부API를 호출하면 타임아웃이 발생함
AKS초기 구성시에는 해당 현상이 발생하지 않았었다. 그런데, 어느 순간 해당 현상이 발생하기 시작했다.
서버 구축을 해주던 인프라팀에서 “tcp_tw_reuse, tcp_tw_recycle” 에 대한 세팅 이슈때문에 발생한것이라고 했다.
참고 블로그 해당 블로그 내용에서 NAT 를 사용할때 tcp_tw_recycle
을 활성화한 서버에 접속할경우 해당 이슈가 발생한다고 했다.
그렇다, AKS 초기 세팅에서는 발생하지 않았지만 NAT를 연결한 순간 발생한것으로 추측이된다.
재현해보자
Client / Server 띄우기
- 도커로 Client 와 Server 를 구축해보자
# 네트워크 생성
docker network create tw-net
# 서버
docker run -d --name server_test --net tw-net -p 91:80 -it --privileged ubuntu:20.04
apt update
apt install nginx
service nginx start
# 클라이언트
docker run -d --name client_test --net tw-net -p 92:80 -it --privileged ubuntu:20.04
# 필요한 라이브러리 설치
apt-get install net-tools
apt-get install vim
Client 에서 tcp_tw_reuse 활성화하기
- Client -> Server 호출해보기
- Docker 네트워크 상에서 Server IP를 확인하자.
$ docker network inspect tw-net
...
"Containers": {
"4e879dc9a3e1ced91553d6464d98361ab639bb229d21780234f254c9ab2e8763": {
"Name": "client_test",
"EndpointID": "aff17140447ea02482cf5dd79ee032bfc26ce5d4bfbd643396b71a354a3e2008",
"MacAddress": "02:42:ac:14:00:03",
"IPv4Address": "172.20.0.3/16",
"IPv6Address": ""
},
"911846c368f7419762ce537c1e002b5626b2f7a3953eec0addc945fac9914a6a": {
"Name": "server_test",
"EndpointID": "b0f83e1544bd7d1d7db17759324ea4b7018913c977e15f6b7fcd734bc1f54a41",
"MacAddress": "02:42:ac:14:00:02",
"IPv4Address": "172.20.0.2/16", <============ Server IP
"IPv6Address": ""
}
},
...
- 호출 해보자
root@4e879dc9a3e1:/# curl 172.20.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
정상적으로 호출되는것을 알 수 있다.
- 계속 호출해서 TIME_WAIT를 확인해보자
# 4번 호출후 확인
root@4e879dc9a3e1:/# netstat -n -t | grep 'TIME_WAIT'
tcp 0 0 172.20.0.3:42604 172.20.0.2:80 TIME_WAIT
tcp 0 0 172.20.0.3:42614 172.20.0.2:80 TIME_WAIT
tcp 0 0 172.20.0.3:42640 172.20.0.2:80 TIME_WAIT
tcp 0 0 172.20.0.3:42630 172.20.0.2:80 TIME_WAIT
각각의 다른 포트로 호출되는것을 확인할 수 있다.
그렇다면 포트를 하나로 줄이면 어떻게 될까? (포트를 고갈시켜보자)
- 포트를 하나로 줄여서 호출해보자
# 설정 파일
vim /etc/sysctl.conf
# 하단에 추가
net.ipv4.ip_local_port_range = 32768 32768
# 변경 내용 적용
sysctl -p
# 호출하기
root@4e879dc9a3e1:/# curl 172.20.0.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
root@4e879dc9a3e1:/# curl 172.20.0.2
curl: (7) Couldn't connect to server
root@4e879dc9a3e1:/# netstat -n -t | grep 'TIME_WAIT'
tcp 0 0 172.20.0.3:32768 172.20.0.2:80 TIME_WAIT
- 두번째 호출에서
curl: (7) Couldn't connect to server
발생한다.
- 그렇다면, 이때
tcp_tw_reuse
를 활성화하면 어떻게 될까?
# 설정 파일
vim /etc/sysctl.conf
# 하단에 추가
net.ipv4.tcp_tw_reuse = 1
# 변경 내용 적용
sysctl -p
# 여러번 호출하기
curl 172.20.0.2
- 정상 호출됨
결론
tcp_tw_reuse
를 활성화하면, TIME_WAIT 상태의 포트를 재사용할 수 있다.- 자세한 내용은 https://cyuu.tistory.com/139 여기를 참고
tcp_tw_recycle!?
- tcp_tw_recycle 은 Linux 4.12 on 2017 이후 제거 되었다고 한다 (참고)
- docker ubuntu 20.04 에서는
tcp_tw_recycle
설정이 없다. 그래서 다른 블로그의 테스트를 참고해보길 바란다.- tcp_tw_reuse와 tcp_tw_recycle 여기 블로그를 보면 자세한 내용을 확인할수있다.
회고
처음에 해당 현상이 발생했을때, azure의 네트워크 이슈인지 알았다.
나는 어플리케이션 레벨에서 이슈를 찾을려고 했다. 당연히 찾을 수 가 없었다.
이번의 계기로 다양한 범위에서 이슈를 찾기위한 노력이 필요하다는것을 알게 되었다.