Network 에사용되는용어정리 CIDR(Classless Inter-Domain Routing) RFC1918 IP Masquerade Bridge
Network 에사용되는용어정리 CIDR(Classless Inter-Domain Routing) l l 클래스없는도메인간라우팅기법점과숫자로이루어진 4부분의주소와 / 뒤의 0에서 32까지의숫자로이루어진다. A.B.C.D/N 과같은형태이다. CIDR Class Hosts Mask /32 1/256 C 1 255.255.255.255 /16 256 C, 1B 65,536 255.255.0.0 /12 16 B 1,048,574 255.240.0.0 /8 1 A 16,777,216 255.0.0.0 /1 128 A 2,147,483,648 128.0.0.0
Network 에사용되는용어정리 RFC1918 - Address Allocation for Private Internets l l 사설인터넷을위한주소할당 IPv4 주소부족을지연시킬목적으로정의되었음
Network 에사용되는용어정리 IP Masquerade l l l 외부인터넷에연결된하나의 IP 주소를통해등록된 IP 주소가없는내부컴퓨터를외부인터넷자원을공유할수있도록해주는네트워크의기법리눅스에서개발되고있는네트워킹기능 NAT(Network Address Translation) 의한형태
Network 에사용되는용어정리 Bridge l l OSI 모델의데이터링크계층에있는여러개의네트워크세그먼트를연결 OSI 모델 [ 물리계층-데이터링크계층-네트워크계층-전송계층 -세션계증-표현계층 -응용계층 ] 브리지는 MAC 어드레스로경로를찾는다
Bridge 를위한커널설정? [*] Networking support ---> Networking options ---> <*> Packet socket < > Packet: sockets monitoring interface <*> Unix domain sockets < > UNIX: socket monitoring interface...... < > PF_KEY sockets [*] TCP/IP networking [*] IP: multicasting [ ] IP: advanced router... -*- IP: TCP syncookie support... [*] Network packet filtering framework (Netfilter) --->...... <*> 802.1d Ethernet Bridging [*] IGMP/MLD snooping < > 802.1Q/802.1ad VLAN Support < > DECnet Support...
IP Masquerade 를위한커널설정? [*] Networking support ---> Networking options ---> [*] Network packet filtering framework (Netfilter) ---> --- Network packet filtering framework (Netfilter) [ ] Network packet filtering debugging [*] Advanced netfilter configuration [*] Bridged IP/ARP packets filtering Core Netfilter Configuration ---> <*> Netfilter connection tracking support -*- Connection mark tracking support <*> FTP protocol support <*> IRC protocol suppor <*> LOG target support <*> "conntrack" connection tracking match support <*> "limit" match support <*> "mac" address match support <*> "multiport" Multiple port match support <*> "state" match support
IP Masquerade 를위한커널설정? IP: Netfilter Configuration ---> <*> IPv4 connection tracking support (required for NAT) [*] proc/sysctl compatibility with old connection tracking <*> IP tables support (required for filtering/masq/nat) <*> Packet filtering <*> REJECT target support <*> IPv4 NAT <*> MASQUERADE target support < > ARP tables support
Docker - Networking Docker Container Docker Container Docker Container eth0 eth0 eth0 veth# veth# veth# docker0 bridge HOST eth0
Docker Networking [ on host machine ]
Docker # docker run -i -t --name hello ubuntu /bin/bash container on host machine
도커네트워크
도커네트워크 Daemon 1. 도커데몬네트워크인터페이스구성 2. 도커데몬네트워크초기화 3. Docker bridge 만들기 Driver networkdriver Driver graph driver exec driver bridge Network interface IP PORT Bridge ( docker0 ) Docker container
나 1 Docker Daemon 네트워크인터페이스구성 도커데몬은프로세스를시작할때마다, 네트워크환경을초기화한다. 궁극적으로이러한네트워크환경은도커컨테이너네트워크통신서비스를제공한다. 도커네트워크관련플래그매개변수는아래다섯개의매개변수에정의되어있다../docker/daemon/config.go flag.boolvar(&config.enableiptables, ) flag.boolvar(&config.enableipforward, ) flag.boolvar(&config.bridgeiface, ) flag.boolvar(&config.bridgeip, ) flag.boolvar(&config.intercontainercommunication, ) opts.ipvar(&config.defaultip, )
슬라이드 15 나 1 나연, 2015-02-01
Docker Daemon 네트워크초기화 1. 도커데몬시작플래그및네트워크플래그매개변수전달 2. 도커네트워크플래그매개변수전처리 3. 도커네트워크모드결정 4. Docker bridge 만들기 docker/daemon/daemon.go func NewDaemonFromDirectory
도커컨테이너 MTU 구성하기./docker/daemon/daemon.go // Apply configuration defaults if config.mtu == 0 { // FIXME: GetDefaultNetwork Mtu doesn't need to be public anymore config.mtu = GetDefaultNetworkMtu()./docker/daemon/config.go FUNC GetDefaultNetworkMtu () INT { if iface, err := networkdriver.getdefaultrouteiface(); err == nil { return iface.mtu return defaultnetworkmtu
도커네트워크플래그매개변수전처리 1. 브리지구성정보확인 // Check for mutually incompatible config options if config.bridgeiface!= "" && config.bridgeip!= "" { return nil, fmt.errorf("you specified -b & --bip, mutually exclusive options. Please specify only one.") 2. iptables 구성및컨테이너간의통신호환성확인 if!config.enableiptables &&!config.intercontainercommunication { return nil, fmt.errorf("you specified --iptables=false with --icc=false. ICC uses iptables to function. 3. 도커데몬의네트워크환경구성여부결정 config.disablenetwork = config.bridgeiface == disablenetworkbridge PID 파일구성 [ /var/run/docker.pid ]
도커네트워크모드결정 도커네트워크환경브리지모드를만들기위한특정모드를생성한다. if!config.disablenetwork { job := eng.job("init_networkdriver") job.setenvbool("enableiptables", config.enableiptables) job.setenvbool("intercontainercommunication", config.intercontainercommunication) job.setenvbool("enableipforward", config.enableipforward) job.setenv("bridgeiface", config.bridgeiface) job.setenv("bridgeip", config.bridgeip) job.setenv("defaultbindingip", config.defaultip.string()) if err := job.run(); err!= nil { return nil, err
Docker Bridge 만들기 2. 도커브리지장치이름확인 3. 브리지인터페이스장치찾기 1. 환경변수추출 4. 새로운브리지만들기 5. 브리지장치네트워크주소가져오기 6. 도커데몬의 iptables 구성 7. 네트워크장치패키포워딩 8. 네트워크처리기등록 docker/daemon/networkdriver/bridge/driver.go
도커브리지환경변수추출 var ( ) network *net.ipnet enableiptables = job.getenvbool("enableiptables") icc = job.getenvbool("intercontainercommunication") ipforward = job.getenvbool("enableipforward") bridgeip = job.getenv("bridgeip") if defaultip := job.getenv("defaultbindingip"); defaultip!= "" { defaultbindingip = net.parseip(defaultip) bridgeiface = job.getenv("bridgeiface")
도커브리지장치이름확인 usingdefaultbridge := false if bridgeiface == "" { usingdefaultbridge = true bridgeiface = DefaultNetworkBridge const ( DefaultNetworkBridge = "docker0" MaxAllocatedPortAttempts = 10 )
도커브리지인터페이스찾기 GetIfaceAddr 함수는 docker/daemon/networkdriver/utils.go 에구현되어있음 네트워크인터페이스의 IPv4 어드레스와 nil 를반환한다. addr, err := networkdriver.getifaceaddr(bridgeiface)
도커 bridgeiface 가생성되어있을경우 network = addr.(*net.ipnet) // validate that the bridge ip matches the ip specified by BridgeIP if bridgeip!= "" { bip, _, err := net.parsecidr(bridgeip) if err!= nil { return job.error(err) if!network.ip.equal(bip) { return job.errorf("bridge ip (%s) does not match existing bridge configuration %s", network.ip, bip)
도커 bridgeiface 가생성되어있지않을경우 // If we're not using the default bridge, fail without trying to create it if!usingdefaultbridge { job.logf("bridge not found: %s", bridgeiface) return job.error(err) // If the iface is not found, try to create it job.logf("creating new bridge for %s", bridgeiface) if err := createbridge(bridgeip); err!= nil { return job.error(err) job.logf("getting iface addr") addr, err = networkdriver.getifaceaddr(bridgeiface) if err!= nil { return job.error(err) network = addr.(*net.ipnet)
도커 createbridge 구현프로세서 docker0 네트워크브리지장치 IP 주소확인 createbridgeifcae 함수를통해 docker0 브리지장치를만든다. docker0 브리지장치를생성하는 IP 주소를바인딩한다 docker0 브리지장치를시작한다.
docker0 네트워크브리지장치 IP 주소확인 if len(bridgeip)!= 0 { _, _, err := net.parsecidr(bridgeip) if err!= nil { return err ifaceaddr = bridgeip else { for _, addr := range addrs { _, dockernetwork, err := net.parsecidr(addr) if err!= nil { return err if err := networkdriver.checknameserveroverlaps(nameservers, dockernetwork); err == nil { if err := networkdriver.checkrouteoverlaps(dockernetwork); err == nil { ifaceaddr = addr break else { log.debugf("%s %s", addr, err)
docker0 네트워크브리지장치 IP 주소확인 addrs = []string{ // Here we don't follow the convention of using the 1st IP of the range for the gateway. // This is to use the same gateway IPs as the /24 ranges, which predate the /16 ranges. // In theory this shouldn't matter - in practice there's bound to be a few scripts relying // on the internal addressing or other stupid things like that. // They shouldn't, but hey, let's not break them unless we really have to. "172.17.42.1/16", // Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23 "10.0.42.1/16", // Don't even try using the entire /8, that's too intrusive "10.1.42.1/16", "10.42.42.1/16", "172.16.42.1/24", "172.16.43.1/24", "172.16.44.1/24", "10.0.42.1/24", "10.0.43.1/24", "192.168.42.1/24", "192.168.43.1/24", "192.168.44.1/24",
createbridgeifcae 함수를통해 docker0 브리지장치를만든다. func createbridgeiface(name string) error { kv, err := kernel.getkernelversion() // only set the bridge's mac address if the kernel version is > 3.3 // before that it was not supported setbridgemacaddr := err == nil && (kv.kernel >= 3 && kv.major >= 3) log.debugf("setting bridge mac address = %v", setbridgemacaddr) return netlink.createbridge(name, setbridgemacaddr) Netlink 는사용자응용프로그램과커널사이양방향통신 (IPC) 방법으로, 리눅스에서제공하는소켓이다. libcontainer/netlink/netlink_linux.go syscall.syscall(syscall.sys_ioctl, uintptr(s), SIOC_BRADDBR, uintptr(unsafe.pointer(namebyteptr))) 네트워크브리지장치를만든후 setbridgemacaddress 위한 docker0 브리지장치 MAC 주소를구성
docker0 브리지장치를생성하는 IP 주소를바인딩한다. if netlink.networklinkaddip(iface, ipaddr, ipnet); err!= nil { return fmt.errorf("unable to add private network: %s", err) libcontainer/netlink/netlink_linux.go func NetworkLinkAddIp(iface *net.interface, ip net.ip, ipnet *net.ipnet) error { return networklinkipaction( syscall.rtm_newaddr, syscall.nlm_f_create syscall.nlm_f_excl syscall.nlm_f_ack, IfAddr{iface, ip, ipnet, )
docker0 브리지장치를시작한다. if err := netlink.networklinkup(iface); err!= nil { return fmt.errorf("unable to start network bridge: %s", err) // Bring up a particular network interface. // This is identical to running: ip link set dev $name up func NetworkLinkUp(iface *net.interface) error { s, err := getnetlinksocket() if err!= nil { return err defer s.close() wb := newnetlinkrequest(syscall.rtm_newlink, syscall.nlm_f_ack) msg := newifinfomsg(syscall.af_unspec) msg.index = int32(iface.index) msg.flags = syscall.iff_up msg.change = syscall.iff_up wb.adddata(msg) if err := s.send(wb); err!= nil { return err return s.handleack(wb.seq)
도커브리지네트워크주소가져오기 network = addr.(*net.ipnet)
도커데모의 iptables 구성하기 // Configure iptables for link support if enableiptables { if err := setupiptables(addr, icc); err!= nil { return job.error(err)
도커데모의 iptables 구성하기 새로운브리지의 NAT 기능 OPEN iptables -I POSTROUTING -t nat -s docker0_ip! -o docker0 -j MASQUERADE ICC 파라미터에의한도커컨테이너내부간통신허용여부결정 iptables -I FORWARD -i docker0 -o docker0 -j ACCEPT 허가된컨테이너에서발행하고, 다른컨테이너의패킷이전송되지않는다. iptables -I FORWARD -i docker0! -o docker0 -j ACCEPT 연결되어있는모든패킷을받아들인다. iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
도커데모의 iptables 구성하기
네트워크장치간의패킷포워팅기능 if ipforward { // Enable IPv4 forwarding if err := ioutil.writefile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n', 0644); err!= nil { job.logf("warning: unable to enable IPv4 forwarding: %s\n", err)
도커 iptable chain 만들기 // We can always try removing the iptables if err := iptables.removeexistingchain("docker"); err!= nil { return job.error(err) if enableiptables { chain, err := iptables.newchain("docker", bridgeiface) if err!= nil { return job.error(err) portmapper.setiptableschain(chain)
네트워크관련핸들러등록 for name, f := range map[string]engine.handler{ "allocate_interface": Allocate, "release_interface": Release, "allocate_port": AllocatePort, "link": LinkContainers, allocate_interface : 도커컨테이너전용 NIC를할당 release_interface : 네트워크장비자원의릴리스 allocate_port : 도커컨테이너포트를할당 link : 도커컨테이너작업사이의실현링크
도커네트워크설정확인하기 # docker run -i -t --name hello ubuntu /bin/bash
도커네트워크설정확인하기
도커네트워크설정확인하기
도커브리지새로만들기 기존 docker0 브리지인터페이스삭제하기 # service docker stop # ip link sert dev docker0 down # brctl delbr docker0 새로운브리지인터페이스생성하기 # brctl addr br0 # ip addr add 192.168.42.1/24 dev br0 # ip link set dev br0 up # echo DOCKER_OPTS= -b=br0 >> /etc/default/decker docker 컨테이너시작및접속하기 # service docker start # docker start hello # docker attach hello
on host machine container
도커컨테이너간 Point-to-point 연결하기 두개의도커컨테이너생성하기 # docker run -i -t --rm -- net=none ubuntu:latest /bin/bash # docker run -i -t --rm -- net=none ubuntu:latest /bin/bash 두개의도커컨테이너 PID 확인하기 # docker inspect -f '{{.State.Pid' df02179106aa 6009 # docker inspect -f '{{.State.Pid' afd01f3fe865 5954 namespace 만들기 # mkdir p /var/run/netns # ln s /proc/6009/ns/net /var/run/netns/6009 # ln s /proc/5954/ns/net /var/run/netnfs/5954
도커컨테이너간 Point-to-point 연결하기 peer 인터페이스를만든다. # ip link add A type veth peer name B # ip link set A netns 6009 # ip netns exec 6009 ip addr add 10.1.1.1/32 dev A # ip netns exec 6009 ip link set A up # ip netns exec 6009 ip route add 10.1.1.2/32 dev A # ip link set B netns 5954 # ip netns exec 5954 ip addr add 10.1.1.2/32 dev B # ip netns exec 5954 ip link set B up # ip netns exec 5954 ip route add 10.1.1.1/32 dev B
도커컨테이너간 Point-to-point 연결하기 통신확인하기 PID : 6009 PID : 5954
컨테이너생성시네트워크환경설정 컨테이너네트워크환경초기화 루프백네트워크스택만들기 veth* 네트워크스택만들기 netns 네트워크스택만들기
참조사이트 https://docs.docker.com/v1.2/articles/networking/ http://www.infoq.com/cn/articles http://en.wikipedia.org/wiki/classless_inter-domain_routing https://technet.microsoft.com/en-us/library/cc781097(v=ws.10).aspxc