docker swarm's iptables
이전 포스팅 docker swarm에 이어서, 여기서는 swarm 통한 nginx 서비스 구축 후 iptables가 어떻게 셋팅되는 지 보도록 한다.
앞에서 설명한 내용에 기반하여, swarm 기반 nginx 서비스는 다음과 같이 구축했다.
CentOS 7 기반이다.
$ docker swarm init --advertise-addr 192.168.61.6
$ docker network create --driver overlay dvg_net
$ docker service create --name dvg_web --network dvg_net nginx:alpine
$ docker service create --name dvg_busybox --network dvg_net busybox sleep 86400
$ docker service update --publish-add published=80,target=80 dvg_web
요약하자면, 192.168.61.6 상에 단일 node로 swarm을 설치했고, dvg_net
overlay 네트워크를 추가한 다음 nginx 기반의 dvg_web
서비스와 busybox 기반의 dvg_busybox
서비스를 생성했다. 마지막으로 dvg_web
에 80번 port를 오픈하여 외부에서도 접근할 수 있도록 했다.
이 중 busybox 사용한 dvg_busybox 서비스 설치는 생략해도 된다.
설치 전/후에 docker network ls
로 확인한 네트워크 목록은 다음과 같다.
전
NETWORK ID NAME DRIVER SCOPE
7bc54b953c57 bridge bridge local
88d02561add3 host host local
0102130c5a4b none null local
후
NETWORK ID NAME DRIVER SCOPE
7bc54b953c57 bridge bridge local
c3fb70dc7592 docker_gwbridge bridge local # swarm 생성 시 자동 생성
lghg9ceculyj dvg_net overlay swarm # 직접 추가
88d02561add3 host host local
sodvstaktzgi ingress overlay swarm # swarm 생성 시 자동 생성
0102130c5a4b none null local
docker network inspect ...
명령으로 각 네트워크에 할당된 prefix를 정리하면 다음과 같다.
bridge
: 172.17.0.0/16docker_gwbridge
: 172.18.0.0/16dvg_net
: 10.0.1.0/24ingress
: 10.0.0.0/24
이제 iptables rule들을 보도록 하자. 먼저 docker 설치 후 iptables의 filter와 nat 테이블의 룰 리스트다.
$ iptables -S
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
$ iptables -S -t nat
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
docker에서 추가하는 chain 중 DOCKER-ISOLATION-STAGE-1
, DOCKER-ISOLATION-STAGE-2
chain은 docker bridge 간 격리를 위한 것이다. 지금은 docker0
하나에만 적용되어 있어서 이해하기가 쉽지 않지만, swarm 추가 후 docker_gwbridge
관련 rule이 추가되면 보다 이해하기 쉬울 것이다.
마지막으로 DOCKER-USER
chain을 거치는데, 여기에 각 사용자가 원하는 추가 iptables rule을 추가하면 된다. 그 외 다른 DOCKER*
chain은 docker가 관리하는 것이므로, 가급적 직접 건드리지 않도록 한다.
다음은 포스팅 처음의 swarm 추가 및 dvg_web
서비스 추가 작업에 따라 iptables에 추가되는 chain 및 rule이다.
filter (default) table:
-N DOCKER-INGRESS
-A FORWARD -j DOCKER-INGRESS
-A FORWARD -o docker_gwbridge -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker_gwbridge -j DOCKER
-A FORWARD -i docker_gwbridge ! -o docker_gwbridge -j ACCEPT
-A FORWARD -i docker_gwbridge -o docker_gwbridge -j DROP
-A DOCKER-INGRESS -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-INGRESS -p tcp -m state --state RELATED,ESTABLISHED -m tcp --sport 80 -j ACCEPT
-A DOCKER-INGRESS -j RETURN
-A DOCKER-ISOLATION-STAGE-1 -i docker_gwbridge ! -o docker_gwbridge -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-2 -o docker_gwbridge -j DROP
nat table:
-N DOCKER-INGRESS
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER-INGRESS
-A OUTPUT -m addrtype --dst-type LOCAL -j DOCKER-INGRESS
-A POSTROUTING -o docker_gwbridge -m addrtype --src-type LOCAL -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o docker_gwbridge -j MASQUERADE
-A DOCKER -i docker_gwbridge -j RETURN
-A DOCKER-INGRESS -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.2:80
-A DOCKER-INGRESS -j RETURN
docker_gwbridge 인터페이스가 추가됐고 그 외에 ingress overlay network를 위한 DOCKER-INGRESS filter가 추가된 것을 볼 수 있다. 그리고 dvg_web
에서 publish한 tcp 80 port 관련 rule을 확인할 수 있을 것이다.
다음은 iptables -vnL
명령의 실행 결과를 발췌 요약한 것이다. INPUT
, OUTPUT
, DOCKER
등 rule이 없는 chain들을 생략하고, anywhere (0.0.0.0/0
)로 동일한 값을 가지는 source
, destination
필드와 packet/byte count 등 불필요한 정보도 생략했다.
(이건 다 )docker_gw
뭐시기와 DOCKER-ISOLATION-
뭐시기 이름이 너무 길어서 그런 거다
Chain FORWARD (policy DROP 0 packets, 0 bytes)
target prot opt in out
DOCKER-USER all -- * *
DOCKER-INGRESS all -- * *
DOCKER-ISOLATION-STAGE-1 all -- * *
ACCEPT all -- * docker_gwbridge ctstate RELATED,ESTABLISHED
DOCKER all -- * docker_gwbridge
ACCEPT all -- docker_gwbridge !docker_gwbridge
ACCEPT all -- * docker0 ctstate RELATED,ESTABLISHED
DOCKER all -- * docker0
ACCEPT all -- docker0 !docker0
ACCEPT all -- docker0 docker0
DROP all -- docker_gwbridge docker_gwbridge
Chain DOCKER-INGRESS (1 references)
target prot opt in out
ACCEPT tcp -- * * tcp dpt:80
ACCEPT tcp -- * * state RELATED,ESTABLISHED tcp spt:80
RETURN all -- * *
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt in out
DOCKER-ISOLATION-STAGE-2 all -- docker_gwbridge !docker_gwbridge
DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0
RETURN all -- * *
Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target prot opt in out
DROP all -- * docker_gwbridge
DROP all -- * docker0
RETURN all -- * *
Chain DOCKER-USER (1 references)
target prot opt in out
RETURN all -- * *
참고목록
- iptables 기반 Docker 네트워크 격리 및 통신 설명
- Docker containers on same host but different bridges can't connect
- How to disable Docker Network Isolation?
- KANS 스터디 1주차 - 컨테이너 격리 & 도커 네트워크(작성중)
- An IPTABLES Primer