Docker란? (도커의 네트워크 1)

고리·2022년 12월 18일
0

Docker

목록 보기
7/8
post-thumbnail

도커 네트워크를 이해하기 위해 도커 네트워크가 커널 레벨에서 어떻게 동작하는지 알아야 한다. 도커가 현재 어플리케이션의 런타임 환경으로 표준화되고 있는 이유는 실제 물리적인 하드웨어 성능을 오버헤드 없이 사용할 수 있기 때문이다. 이는 커널 기반의 기술로 구현된 도커가 갖는 특징이다. 다시 말해 커널 레벨에서의 네트워크 기능인 넷필터(Netfilter)를 사용한다.

이 넷필터를 설정할 수 있는 응용 프로그램이 iptable이다. 도커는 iptable을 기반으로 네트워크 처리를 한다. 어떤 ip에서 접근하는 것을 허용할 건지, 막을 건지, 프로토콜의 상태 추적, 계층 검사 등의 기능은 물론 엄청나게 많은 기능을 제공한다. 때문에 네트워크에 문제가 생기면 가장 먼저 iptable을 확인해야 한다.

과거에 iptable은 리눅스의 방화벽 역할을 수행했지만 지금은 클라우드 환경이 보편화되면서 수많은 vm을 다루다 보니 os 레벨로 보안을 유지하기 어려워졌다.


Table(테이블)이란?

iptable이라고 하면 결국은 테이블이다. 크게 3가지 테이블 중 2개의 테이블을 이해해 보자

  • NAT
  • FILTER
  • MANGLE

Filter 테이블

필터 테이블은 서버 안으로 패킷이 들어왔을 때 어떻게 패킷을 처리할지에 대한 규칙이다. 보통 서버(ex AWS, NaverCloud)의 시큐리티 그룹으로 들어가면 인바운드 룰을 추가하는데 이게 필터 테이블의 인풋이다.

예를 들어서 네이버 클라우드를 보면 access controler groupACG이라고 해서 inbound(to Instance) 규칙, outbound(from Instance)규칙이 있다. 이를 서버 관점에서 보면 서버로 뭐가 들어올 수 있고 나갈 수 있는 지를 정의하는 필터 테이블이다.


NAT 테이블

도커는 NAT를 잘 알아야 한다.

IP패킷의 포트 번호와 source, destination IP 주소를 바꿔가며 라우터를 통해 네트워크 트래픽을 주고받는 기술을 말하는데 여러 사설 IP가 하나의 공인 IP를 사용해 네트워크 통신을 하기 위해 주로 사용된다.
컴퓨터 네트워크 시간에 배운 거라 반가웠다ㅎ

공인 IP와 사설 IP는 IP 대역 자체가 다르다. 외부에서 클라이언트가 접속할 때는 공인 IP로 접근하지만 내부에서 특정 프로세스로 처리하기 위해서는 사설 IP로 변환이 되어야 한다. 내부에서 나갈 때도 사설 IP가 공인 IP로 바뀌어야 한다. 이 기능을 맡고 있는게 NAT 테이블이다.

  • Post Routing: 내부에서 밖으로 나갈 때
  • Pre Routing: 외부에서 내부로 들어올 때

도커는 내부적으로 NAT를 한번 더 사용한다.

HOST OS의 사설IP가 이미 존재하지만 도커는 HOST의 네트워크를 사용하지 않고 컨테이너별로 가상의 네트워크를 사용한다. 당연하게도 프로세스를 격리할 때 네트워크의 격리도 필요하기 때문이다. 이전에 작성한 게시글에서 도커는 namespace를 사용해 네트워크를 격리함을 배웠다.

도커는 docker0라고 하는 브릿지 네트워크를 기준으로 가상 네트워크를 만든다. 도커를 처음 설치하면 디폴트로 사용하게 되는 브릿지 네트워크가 docker0로 보통 IP주소가 127.17.0.1이다.

윈도우에서 VM에서 실행한 서비스에 접근하기 위해서는 디폴트로 연결된 네트워크가 NAT다. 포트 포워딩을 통해 HOST의 어떤 포트, VM의 어떤 포트를 매핑 시켜줄지 결정하는데 도커 네트워크도 이것과 같은 맥락이다.

만약 도커 기반으로 NGINX서비스를 제공한다면 사용자가 공인 IP로 접근할 것이다. 이때 NAT 테이블의 Pre Routing이 공인 IP를 사설 IP로 바꿔 준다. 이렇게 바뀐 사설 IP를 도커의 브릿지 네트워크인 docker0가 NAT를 한 번 더 해주어 컨테이너의 사설IP로 바꿔준다. 이런 과정 때문에 도커에서 네트워크에 대한 정보를 확인하려면 NAT 테이블을 확인하면 된다.

도커가 편리한 점은 컨테이너를 만들면 도커 데몬이 자동으로 iptable 규칙 설정을 해준다. 그러나 이 규칙이라는 게 버그가 발생해 다 날아갈 수 있다. 그러면 컨테이너는 기동 중이지만 서비스 접근이 안 되는 상황이 발생한다.

iptable이 Filtering, NAT Rule 설정을 해주는데 이런 설정 도구가 도커만 있는 게 아니라서 충돌이 날 수 있는 것이다.

NAT 정보를 확인하기 위해 서비스 하나 띄워놓자

docker run -p 8080:80 -d nginx

이제 iptable의 NAT 테이블을 확인한다. -t로 테이블을 지정하자

sudo iptables -t nat -L -v -n

맨 위PREROUTING이 처음 만나는 테이블이다.
모든 프로토콜에 대해서 모든 접촉자source 0.0.0.0/0에 대해서, 모든 목적지destination에 대해서 타겟DOCKER으로 보내고 있다.

맨 밑을 보면 Chain DOCKER를 확인할 수 있다. Docker의 모든 iptables 규칙은 DOCKER 체인에 추가되며 도커 데몬이 기동할 때마다 자동으로 설정된다. 도커 체인이 정상적으로 없다면 수작업으로 추가해 주어야 한다.

맨 마지막 줄에서 포트 8080을 통해 들어오면 172.17.0.2:80으로 바꿔줘 라고 써있는 것을 확인할 수 있다. 이제 172.17.0.2:80을 확인해 보자

curl 172.17.0.2:80

앞에서 기동한 Nginx 서비스가 실행중인 것을 확인할 수 있다.


brctl 명령어로 브릿지 리스트를 확인해보자

brctl show

docker0라는 브릿지 이름을 기반으로 가상의 인터페이스가 생긴 것이다.

nginx 서비스를 하나 더 실행하면 컨테이너에 접근하기 위한 규칙이 추가된 것을 확인할 수 있다.

컨테이너가 추가될 때마다 HOST에 vethVirtual Ethernet이라는 네트워크 인터페이스가 생성된 것을 볼 수 있는데, 이는 도커 엔진이 자동으로 생성하며 각 컨테이너가 외부IP와 통신하기 위해 사용되는 가상 네트워크 인터페이스다.


Blocking

OS 레벨에서 ip 포워딩을 못 하게 막을 수 있다.

sudo sysctl -a | grep ip_forward

ip_forward가 1이면 ip 포워딩을 허용하는 것이다. 하지만 회사가 보안 문제로 인해 ip 포워딩을 못 하게 막으면 0이 된다.

이렇게 ip 포워딩을 할 수 없는 상황에서 당연하게도 어플리케이션 서비스는 가능해야 한다. 도커는 어플리케이션 레벨에서의 프록시를 제공해 이 문제를 해결해 준다. 프록시라는 프로세스가 포워딩을 해주기 때문에 서비스의 제공이 가능한 것이다.

하지만 위의 사진을 보면 알 수 있듯이 포트 별로 프록시 프로세스가 추가된다. 카프카처럼 사용하는 포트가 많다면 포트 포워딩 정책만큼 프록시 프로세스가 계속 추가될 것이다. 이러면 포트 포워딩 설정 만으로도 도커 프로세스가 차지하는 리소스가 점점 증가해 오버헤드가 증가하게 된다.

게다가 커널 기반의 네트워크 기술을 사용해 빠른 속도를 갖는 것이 장점인 도커가 커널 레벨이 아닌, 어플리케이션 레벨에서 포워딩을 해주기 때문에 속도가 느려진다.

도커 프록시가 실제로 그렇게 작동하는지 검증해보자

사진이 잘 안 보일 수 있는데 명령어를 통해 확인해 보자

sudo sysctl -a | grep ip_forward	#ip포워딩 block 확인
ps -ef | grep docker-proxy			#docker proxy실행 확인
curl 172.17.0.2:8080  				#ip 포워딩을 통해 접근(실패)
curl 172.17.0.2:80					#docker proxy를 통해 접근(성공)
profile
Back-End Developer

0개의 댓글