Docker Lab #9

반영환·2023년 7월 3일
0

Docker

목록 보기
18/18
post-thumbnail

Docker Week 5

Docker Networking

Docker 는 CNM ( Container Network Model ) 개념을 사용한다.

  • sandbox : 컨테이너의 격리 환경의 네트워크 구성

  • endpoint : 네트워크 인터페이스

  • network : 네트워크 인터페이스 그룹

Sandbox

Sandbox에는 컨테이너 네트워크 스택 구성을 포함한다. 스택에는 Container Network Interface,Routing Table, DNS Setting 등이 있다.

Sandbox는 Linux Network Namespace와 유사한 개념으로 구현될 수 있으며 네임스페이스 기술로 Ethernet Interface나 network 설정등이 격리된다 .

Sandbox에는 다수의 네트워크에 연결된 다수의 엔드포인트가 존재할 수 있고, CNM 특정상 특정 호스트의 특정 컨테이너와 연결돼있기에 컨테이너가 속한 호스트를 나타내는 로컬 범위를 가지고있다.

Endpoint

End Point는 Service EndPoint이며 특정 컨테이너에 의해 노출되는 다른 서비스들에 대해 동일한 네트워크에서 이들과의 연결을 제공한다.

동시에 Sandbox를 네트워크에 연결하기도 하며 veth pair, Open vSwitch 내부 포트 등으로 구현할 수 있다.

Endpoint는 하나의 Network에만 속할 수 있으며 연결된 경우에는 하나의 Sandbox에만 속할 수 있다.

Network

Network는 상호 통신 가능한 Endpoit 그룹이다. 이는 Linux Bridge, VLAN등으로 구현할 수 있다.

Docker에서는 Docker0가 Docker Bridge 역할을 하며 네트워크를 구성한다.

Network는 다수의 Endpoint로 구성된다.

Docker Network Driver

Bridge

default 네트워크 드라이버로 , docker0가 해당 드라이버를 사용한다.

Docker host 의 default network drivier로 컨테이너를 NAT를 사용해서 외부 네트워크로 포워딩.

172.17.0.0/16을 사용하여 DHCP로 컨테이너에 IP address 제공

172.17.0.1이 docker0에 할당

컨테이너에 할당된 IP 확인: docker inspect

None

docker run --net=none -d -it --name none-test

docker inspect none-test | grep IPAddress

# result

"SecondaryIPAddresses": null,
            "IPAddress": "",
                    "IPAddress": "",
                    

Host Network

Docker Host의 네트워크를 공유하며 호스트에서 사용중인 포트를 컨테이너에서 사용할 수 없다.

docker run --net=host -it --name host-test ubuntu

"Networks": {
                "host": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "74b6a637fc1d1dc023bb2fb0ada4968c436e0b79bc543711f97059f62278ad98",
                    "EndpointID": "",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "",
                    "DriverOpts": null
                }
            }

Macvlan

IP주소가 아닌 Mac주소를 컨테이너에 할당해서 네트워크의 물리장치로 표시할 수 있다.

docker daemon은 트래픽을 container의 mac address로 라우팅한다.

Mac Address를 사용하기 때문에 docker0가 존재하지 않는 네트워크이다. 대신 sub-interface라는 개념이 사용된다.

도커 호스트의 NIC인 eth0에 여러 개의 하위 인터페이스를 만들어 동시에 여러 개의 Mac Address를 가질 수 있도록 한다. 여기서 생긴 하위 인터페이스들이 서브 인터페이스이다.

서브 인터페이스에 여러 개의 container들이 할당되며 VLAN을 구성할 수 있게 된다.

Macvlan은 하나의 인터페이스 카드를 가상화 함으로써 여러 개의 맥 주소를 양산하는 것이고, 부모 인터페이스 ( eth0 ) 과 자식 인터페이스 ( sub-interface ) 로 나눌 수 있다.

mac0@eth0 식으로 자식 인터페이스를 @ 앞에, 부모 인터페이스를 @ 뒤에 표시한다.

Macvlan은 호스트와는 통신이 불가하고 Docker Network 내부적으로 컨테이너끼리 통신만 필요할 때 사용한다. 따라서 실무에서는 잘 사용하지 않는다고 한다.

User Defined Networking

네트워크를 사용자가 직접 정의할 수 있다.

이 또한 실무에서는 잘 사용안한다고 한다. 특별히 커스텀 할 일이 필요할 때 사용하자.

docker network create --driver bridge \
--subnet=10.15.20.0/24 \
--gateway=10.15.20.1 \
--aux-address 1=10.15.20.2 --aux-address 2=10.15.20.3 \
--opt com.docker.network.bridge.host_binding_ipv4=10.10.10.101 \
--opt com.docker.network.bridge.name=linuxbridge1 \
testbridge1
  • --driver bridge : 네트워크를 관리하는데 사용하는 드라이버

  • --aux -address=[] : 네트워크 드라이버가 사용하는 보조 ipv4 또는 ipv6

  • --gateway=[] : 마스터 서브넷에 대해 사용하는 ipv4 또는 ipv6 게이트웨이 Address

  • --ip-range=[] : 서브넷에서 컨테이너 ip 할당에 사용

  • --ipam-driver=default : IP 주소 관리 드라이버

  • -o, --opt=map[] : 드라이버의 특정 옵션을 설정

  • --subnet=[] : CIDR 형식의 서브넷으로 나타나는 네트워크 세그먼트


docker network create testNetwork

docker run -itd --name=c1 --net=testNetwork busybox
docker run -itd --name=c2 --net=testNetwork busybox

docker network inspect testNetwork
# ---
...
 "Containers": {
            "26dc26e35843c12fc3036fc62e2af08d063f540b2712ce62f82ac6a9d0a0d1e5": {
                "Name": "c2",
                "EndpointID": "a4e2eb8d20bf8b18a90e4f5f0aac30ed21648d93a759c55612645efc1ee2dda4",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "4588f33b6a1b575f310c671e50738c0de22c19120eac74cd76b116bc1118b5f9": {
                "Name": "c1",
                "EndpointID": "07d915da6650b423a78e4256d2cc1d54eab5ed51ce686d481ea9b995c6eda5eb",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
       ...
# ---
        
docker network disconnect testNetwork c1

Multi Host Network

멀티 Docker Host 간 네트워크 연결은 overlay network 를 사용한다.

  • 요구사항
    - Swarm 모드 구성
    • key-value store 구성

SWARM 모드

여러 대의 서버로 구성된 클러스터를 관리하는 기능으로 VLAN을 이용해 여러 호스트 머신을 하나의 네트워크로 연결하여 하나의 시스템으로서 관리하는 것을 지원한다.

Swarm에서 클러스터를 구성하는 호스트를 노드라고 하며 노드에는 Manager Node , Worker Node 가 있다.

  • 매니저 노드는 클러스터 내의 노드를 관리하는 기능과 워커 노드의 기능을 수행한다.

  • 워커 노드는 주로 컨테이너를 실행하는 기능을 하며 이 노드가 다운되면 매니저 노드가 클러스터 내부 상황을 체크하여 다운된 컨테이너를 다른 워커 노드에서 재가동시킨다.

Ingress

Swarm mode에서 클러스터를 구성하면 자동적으로 Ingress라고 하는 오버레이 네트워크가 생성되며, 로드밸런싱 기능을 수행한다.

클러스터 네트워크의 단일 진입점 ( Gateway ) 역할과 들어오는 트래픽들의 로드 밸런싱 기능, 서비스 디스커버리 ( Eureka ) 기능을 제공한다.

외부에 포트를 공개한 서비스를 스웜에 배포하면 ingress 네트워크에 서비스를 참여시키고 두 개의 IP를 할당한다.

  1. 서비스에 대한 VIP (가상 ip)

  2. 서비스의 각 컨테이너에 대한 IP

각 노드들은 외부에 개시된 서비스 포트로 요청이 오면 ingress 의 VIP로 전달한다.

VIP에 전달된 요청은 다시 컨테이너의 IP로 전달된다.

docker network inspect ingress로 VIP와 컨테이너 IP를 확인할 수 있다.

docker network inspect ingress

...

"Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
} ]

...
"Containers": {
    "a59a9278818c607d24c93217f168e38083fc88b941f9bc33538cdd051ef34108":
        "Name": "web.2.qgwov6jteicig1dymm9q53b4m",
                "EndpointID":
"eb04a7f90873815b4822feed0ff0fdba5ccaa1c40ae67d7dbcb12ff68ba48bc4",
{
    "MacAddress": "02:42:0a:00:00:10",
    "IPv4Address": "10.0.0.16/24",
    "IPv6Address": ""
},
"be8dc1a24e1faa43d2e7d114eb416cdde1776000f7b09aad4e5a656b4f4a104d":
    "Name": "web.4.zraz0nn6av5tn6k3vbluhy7ic",
                "EndpointID":
"caf856bed5166d8b783ab874924b1508b4dac8440bb6d0f844c498bc8b14c65b",
{
    "MacAddress": "02:42:0a:00:00:12",
    "IPv4Address": "10.0.0.18/24",
    "IPv6Address": ""
},
"e2f839ccff0a3cecba360a32047c4f33695c9537e98bc46c53abd62a101abad1":
    "Name": "web2.1.j3tm0fqhedb5h3gx974zrztdi",
                "EndpointID":
"073903c2248d26fdc5f2beaa39589d705aba0b4d7625cfa1b85c2c0244fe1cc4",
                "MacAddress": "02:42:0a:00:00:16",
                "IPv4Address": "10.0.0.22/24",
                "IPv6Address": ""
            },
...
"Peers": [
            {
                "Name": "cc3ac47f58f5",
                "IP": "172.25.2.39"
}, {
                "IP": "172.25.2.40"
            },
            {
                "Name": "0ba0e8e80c54",
                "IP": "172.25.2.41"
"Name": "c9f5c311c2f4",

...

구성

Swarm 모드에서 사용되는 포트 정보

  • 클러스터 관리용 통신 포트: TCP 2377번

  • 노드 간 통신용 포트: TCP/UDP 7946번

  • 오버레이 네트워크 트래픽 용 포트: UDP 4789번

ip addr # 사설 ip 확인

# 매니저 노드 설정
docker swarm init --advertise-addr <매니저 node 사설IP>:2377

# 워커 노드 설정
docker swarm join --toke <토큰내용> <매니저 node 사설IP>:2377

# node 확인
docker node ls

서비스 운용

docker service create \
--name web \
--publish published=8080,target=80 \
--replicas 2 \
nginx

docker service ls

docker network ls

# 컨테이너가 어떤 노드에서 실행중인지 확인
docker service ps web 

# 서비스 컨테이너 규모 재설정
docker service scale web=4

# 컨테이너 개수를 줄일 때에는 가장 최근에 생성한 컨테이너를 먼저 중지한다.
docker service scale web=1

# service remove
docker service rm web
  • published : host port

  • target : container port

  • replicas : container 개수

롤링 업데이트

롤링 업데이트는 기동되어 있는 컨테이너의 이미지를 업데이트할 때 각 컨테이너를 차례대로 업데이트한다.
스웜은 롤링 업데이트만 지원한다.

docker service update \
 --update-parallelism 1 \
 --update-delay 10s \
 --update-order start-first \
 --image nginx:alpine \
web
  • --update-parallelism : 동시에 업데이트할 컨테이너 개수를 지정한다.
  • --update-delay : 업데이트 간 간격을 지정한다.
  • --update-order : start-first면 새 컨테이너를 먼저 생성한 뒤에 기존 컨테이너를 삭제한다. stop-first면 기존 컨테이너를 먼저 삭제하고 그 다음에 새 컨테이너를 생성한다.
  • --update-failure-action : 업데이트에 실패할 경우 이 값이 pause면 업데이트를 멈추고, continue면 업데이트를 계속하고, rollback이면 업데이트를 롤백한다.
  • --update-max-failure-ratio : 실패 비율이 지정한 값 이상이면 업데이트 실패로 간주한다.

스웜 노드 삭제

Manager Node에서 시행

# 워커노드 삭제
docker node ls
docker node rm -f <<worker node>>

#해당 노드에서 실행
docker swarm leave -f
profile
최고의 오늘을 꿈꾸는 개발자

0개의 댓글