Docker
[도커 알아가기] 4. 도커 네트워크
begong
2025. 3. 11. 11:47
반응형
관련 글 목록
그동안 컨테이너 기술, 도커, 도커네트워크에 관하여 알아보았습니다.
현재 프로젝트에서 사용중인 bridge 네트워크의 구조에 대해서 알아보았으니, 문제가 될 만한 부분을 추측하고 원인을 찾아 해결해 보겠습니다.
그렇다면 포트포워딩 설정을 많이했을 때 왜 서버가 터졌는가?
원인 추측
- 많은 proxy 프로세스로 인한 과부하
- 포트매핑 별로 docker-proxy 프로세스가 생기기 떄문에 과부하가 발생할 수 있다.
테스트
- 테스트 환경
- M1 맥북에 우분투 18버전을 설치하여 최대한 클라우드 환경과 비슷하게 세팅하였습니다.
- CPU 2코어, 메모리 4GB (클라우드 메모리는 8GB)
- 컨테이너 실행을 위해 NGINX이미지를 이용
- 컨테이너 포트포워딩에 대한 테스트이기 때문에 별도의 설정은 하지 않았습니다.
- 모니터링 도구로 htop 활용
- M1 맥북에 우분투 18버전을 설치하여 최대한 클라우드 환경과 비슷하게 세팅하였습니다.
- idle 상태
-
- 포트 포워딩 없이 컨테이너 실행
-
docker run -d --name my1 nginx
- 포트 한개만 포워딩
-
docker run -d --name my1 -p 40000:40000 nginx
- process가 2개 생성된다.
- 메모리 사용량 1mb 증가
- 포트 500개 포트포워딩
-
docker run -d --name my1 -p 40001-40500:40001-40500 nginx
- process가 1000개 생성됨
- 메모리 사용량 1GB 가까이 증가
- cpu 사용량도 10퍼센트 이상 증가
- 포트 10000개 포트포워딩
-
-
docker run -d --name my1 -p 40001-50000:40001-50000 nginx
- 서버가 터진 모습
- 모니터링 프로세스가 터진 모습
- 10000개 포트매핑 실행 영상
- 메모리 overflow가 나면서 시스템이 멈춰버린다.
테스트 결과
- docker의 userland proxy로 인하여 포트포워딩 하나 당 docker-proxy 프로세스가 2개씩 생성됩니다.
- 생성되는 docker-proxy의 종류
- IPv4 포워딩
/usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 40478 -container-ip 172.17.0.2 -container-port 40478
- IPv6 포워딩
/usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 40478 -container-ip 172.17.0.2 -container-port 40478
- 생성되는 docker-proxy의 종류
- 포트포워딩 500개 당 메모리 약 900mb 할당
- 포트포워딩 설정 약 2000개 쯤, 메모리 overflow로 인하여 시스템이 터져버립니다.
결론
- 10000개의 포트포워딩을 했을 때 서버가 터지던 이유는 많은 프로세스가 생성되어 메모리 OVERFLOW가 발생 했기 때문입니다.
그렇다면 어떻게 해결할 것인가?
- STUN/TURN 서버의 경우 ICE CHECK를 할 경우 이용할 수 있지만, 미디어 패킷통신을 하려면 포트가 필요하므로 해결책이 될 수 없습니다.
- ipvlan, macvlan 네트워크 모드의 경우 클라우드 환경에서 IP 할당의 어려움과 시스템 아키텍쳐를 수정해야 하므로 해결방법에서 제외 하였습니다.
해결방안
- Userland Proxy 설정 해제
- Docker host 모드
1. Userland Proxy 설정 해제
- userland Proxy 사용 설정을 해제할 경우 docker-proxy 프로세스가 생성되지 않습니다.
- docker-proxy가 없으면 iptables에서 포트포워딩을 전담합니다
- docker daemon 설정파일 생성(수정)
{ "userland-proxy": false, }
sudo vi /etc/docker/daemon.json
- docker 재시작
systemctl restart
로 재실행 시, docker.socket때문에 완전 종료되지 않아 설정값이 적용안됨.sudo systemctl stop docker sudo systemctl stop docker.socket sudo systemctl start docker
- Userland Proxy 설정 해제 방법 (docker 24.0.7v)
userland proxy 설정 후 실행 테스트
- 도커 미실행 시
- iptables에 포워딩 관련 정보 없음
- iptables에 포워딩 관련 정보 없음
- 포트 포워딩1개
- userland proxy 사용 해제 시 iptables 만으로 동작
- docker-proxy 프로세스가 생기지 않는 것을 볼 수 있다.
- 포트포워딩 5000개
- 10000개하니 실행시간이 너무 오래걸려 5000개로 테스트 하였음
- 컨테이너 실행에 약 4분 소요
- 실행 시간이 길어질 수록 포트매핑속도가 줄어든다.
- (10000개 매핑시 10분이상 소요 예상)
- iptables에 설정된 정보
- 10000개하니 실행시간이 너무 오래걸려 5000개로 테스트 하였음
결과
- docker-proxy 프로세스 미실행으로 메모리 overflow가 발생하지 않아, 정상적으로 컨테이너를 실행 할 수 있었습니다.
- 포트매핑 설정 중 이미 사용중인 포트가 있으면, 종료되어 처음부터 다시 실행해야 했습니다.
- 포트 매핑 개수가 많아질 수록 컨테이너 실행 시간이 오래걸린다 (포트 포워딩 갯수를 2배 늘리면 세팅 시간은 그보다 더 늘어남)
해당 방법의 추가적인 단점
- docker 네트워크 간 통신 및 로컬 프로세스(loopback)의 접근 불가
- iptables와 NAT만으로는 위의 두 상황에서 통신이 불가능 합니다.
- 위의 상황에서 userland proxy가 TCP/UDP 프로세스를 실행하여 컨테이너와 호스트 시스템 간의 네트워크 트래픽을 중계해 줍니다.
2. Host 모드 사용
- 도커 공식문서에도 성능최적화, 컨테이너가 다양한 포트를 처리해야하는 상황에 host모드가 유용할 수 있다고 한다 https://docs.docker.com/engine/network/drivers/host/
- 호스트의 네트워크를 컨테이너와 공유하기때문에 포트포워딩을 하지 않아도 됩니다.
- 컨테이너 실행 시
--network host
옵션을 추가한다. - Host 모드의 단점
- 네트워크 격리 부족
- 호스트의 네트워크를 공유하기 때문에 container에서 보안 문제가 발생했을 경우 host에게 영향을 줄 수 있습니다.
- 포트 충돌 가능성
- 선점 포트에 대한 예외처리
- mediasoup 설정 시 연결 포트를 범위로 지정
- 연결을 시도하는 포트에대한 이용여부를 판단하는 로직을 미디어 서버에 적용해야 합니다.
- 컨테이너 실행 시
docker run -d --name my1 --network host nginx
- Host 모드 실행방법
결론
- userland-proxy설정을 끄는 방법은 가능하나 실행시간 증가 및 확장 가능성이 저하되는 문제가 발생하였습니다.
- 따라서 host 네트워크 모드를 활용하여 문제를 해결해보기로 결정하였습니다.
Host 모드로 코드 수정
- main.ts
0.0.0.0
로 주소를 바인딩해주어야 한다- 127.0.0.1은 컨테이너 내부의 네트워크를 가리키기 때문에 설정하지 않는다면 외부에서 접근 불가능하다
await app.listen(port, '0.0.0.0');
- back-media-cd.yml
- cd과정을 수정해주었습니다.
- 도커 실행 시
--network host
옵션을 주어 호스트 모드로 실행시킵니다.
- 도커 실행 시
- cd과정을 수정해주었습니다.
- name: 🐳 media 컨테이너 실행 run: | docker run -dit --network host --name media ${{secrets.DOCKER_REGISTRY_URL}}/media:${{ github.sha }}
결과
- 배포 후 정상적으로 호스트모드로 동작하는 것을 확인하였습니다.
참고문서
https://blog.ipspace.net/kb/DockerSvc/40-userland-proxy/
반응형