Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
コンテナのネットワークインターフェース その実装手法とその応用について
Search
Tomofumi Hayashi
August 27, 2017
0
17
コンテナのネットワークインターフェース その実装手法とその応用について
July Tech Festa, August 2017
Tomofumi Hayashi
August 27, 2017
Tweet
Share
More Decks by Tomofumi Hayashi
See All by Tomofumi Hayashi
CNIふぉーびぎなーず
s1061123
0
13
4 rhtn tohayash-multus
s1061123
0
14
Opnfv primer how to get into opnfv
s1061123
0
5
Opnfv handson apex intro
s1061123
0
4
OpenStack Summit Boston DMA Appendix
s1061123
0
4
Software forwarding path
s1061123
0
6
OPNFV Meetup Tokyo #1 / Projects Summary
s1061123
0
5
nftables: the Next Generation Firewall in Linux
s1061123
0
68
ocamllec01-100605110859-phpapp01.pdf
s1061123
0
6
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
516
39k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
8
3.5k
Clear Off the Table
cherdarchuk
86
310k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
22
1.6k
Testing 201, or: Great Expectations
jmmastey
30
6.4k
Large-scale JavaScript Application Architecture
addyosmani
504
110k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
1
130
No one is an island. Learnings from fostering a developers community.
thoeni
16
2.1k
10 Git Anti Patterns You Should be Aware of
lemiorhan
649
58k
Rails Girls Zürich Keynote
gr2m
91
13k
What's in a price? How to price your products and services
michaelherold
238
11k
Practical Orchestrator
shlominoach
183
9.8k
Transcript
コンテナのネットワークインターフェース その実装手法とその応用について @JTF 2017, 2017/8/27 林 智史
[email protected]
id:s1061123, @s1061123
Agenda ×コンテナのネットワークについて ×実際の手法 ×コードの解説 ×応用
Agenda ×コンテナのネットワークについて × どんなインターフェイスで通信しているのか? × どうやって他のコンテナと分離しているのか? × 実際の手法 ×コードの解説 ×応用
コンテナで使ってるネットワークインターフェイスって? tom@kagaribi $ docker run -it --rm centos_test bash [root@5c747e947ec9
/]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN qlen 1 link/tunnel6 :: brd :: 3: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1 link/sit 0.0.0.0 brd 0.0.0.0 32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever [root@5c747e947ec9 /]#
コンテナで使ってるネットワークインターフェイスって? [root@5c747e947ec9 /]# ip -d a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu
65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN qlen 1 link/tunnel6 :: brd :: promiscuity 0 ip6tnl ip6ip6 remote :: local :: encaplimit 0 hoplimit 0 tclass 0x00 flowlabel 0x00000 (flowinfo 0x00000000) 3: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1 link/sit 0.0.0.0 brd 0.0.0.0 promiscuity 0 sit remote any local any ttl 64 nopmtudisc 6rd-prefix 2002::/16 32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 0 veth inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever ‘-d’ / ‘-details’ オプションを追加
コンテナで使ってるネットワークインターフェイスって? 32: eth0@if33: <BROADCAST, link/ether 02:42:ac:11 veth inet 172.17.0.2/16 sco
valid_lft forever p
コンテナで使ってるネットワークインターフェイスって? 32: eth0@if33: <BROADCAST, link/ether 02:42:ac:11 veth inet 172.17.0.2/16 sco
valid_lft forever p ifi_index = IFインデックス IFLA_IFNAME = 名前 対面のインターフェースの ifi_index or 対面の名前 veth = カーネルが提供する仮想 L2インターフェース
vethとは? × カーネルが提供するL2仮想インターフェース × OpenVZから由来 × Linuxカーネル内では <kernel>/drivers/net/veth.c で実装 ×
P2P (Point-to-point)での接続形態 × つまり相手(接続先)は一つ × 接続先はIFLA_LINK_NETNSIDで確認 × ‘ip link add’コマンドで作成可能 × 例: “ ip link add veth1 type veth peer name veth2”
Agenda ×コンテナのネットワークについて × どんなインターフェイスで通信しているのか? × どうやって他のコンテナと分離しているのか? × 実際の手法 ×コードの解説 ×応用
コンテナのネットワークの分離 namespace (名前空間)というものでネットワークを 含む各種リソースを分離 × PID_NS: pid空間を分離 × NET_NS: ネットワークを分離
(← これ!) × USER_NS: ユーザ権限を分離 × IPC_NS: メッセージキュー・shmemの分離 × UTS_NS: ホストネームの分離
コンテナのネットワークの分離 NET_NS: ×<kernel>/include/net/net_namespace.h に定義 × IPv4 (arp/ルーティング 含む) × IPv6
(neighbor/ルーティング 含む) × Unixドメインソケット × netfilter (例: iptables) × conntrack (NATテーブル) × その他(MPLS, sctp等) これらをNET_NS毎 に分離 コンテナ毎に分離
コンテナのネットワークの分離 ホスト NET_NS1 (ホストのNET_NS) NET_NS2 (dockerで作成) em1 192.168.1.1 bash bash
eth0 192.168.1.1 同じアドレスで も競合しない!
コンテナのネットワークの分離 'docker run --net host ...’ ‘docker run --net bridge
…’ ‘docker run --net none ...’
ホスト NET_NS1 (ホストのNET_NS) em1 192.168.1.1 bash ‘docker run --net host
… bash’ の場合 dockerで作成 '--net host': NET_NSを作成せずにホストのものをそのまま流用 (pidは分離)
‘docker run --net bridge … bash’ の場合 ホスト NET_NS1 (ホストのNET_NS)
em1 192.168.1.1 Bridge (docker0) NET_NS2 (dockerで作成) bash dockerで作成 veth veth '--net bridge': NET_NSを作成して、ホストのNET_NSにあるブリッジ(docker0)とvethで接続 lo
‘docker run --net none … bash’ の場合 ホスト NET_NS1 (ホストのNET_NS)
NET_NS2 (dockerで作成) em1 192.168.1.1 bash bash '--net none: NET_NSを作成して、他に何も行なわない lo しかしlo等のデバイスはNET_NS 作成時にカーネルが自動的に作 成 <kernel>/net/core/net_namespace.c: setup_net()
Agenda ×コンテナのネットワークについて ×実際の手法 ×dockerがどのように提供しているのか? ×k8sがどのように提供しているのか? ×コードの解説 ×応用
Agenda ×コンテナのネットワークについて ×実際の手法 ×dockerがどのように提供しているのか? ×k8sがどのように提供しているのか? ×コードの解説 ×応用
dockerの場合 × Docker自身はネットワークを作成しない × libnetworkを使用して作成 × libnetworkはドライバでどのようなネットワークを指 定可能 × ドライバでは以下のAPIを実装している
× Config × {Create,Delete}Network × {Create,Delete}Endpoint × Join, Leave
例 $ docker inspect test | jq .[]."NetworkSettings" { "Bridge":
"", "SandboxID": "be01b37c006ad9139c1f3b648dbf02d29761f630c33e9620d60fcd401aae0b5b", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/be01b37c006a", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "118e24eb9ef5727d3d43814866597b07c4429bc9b055b941285b6d7b6e300388", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null,
Agenda ×コンテナのネットワークについて ×実際の手法 ×dockerがどのように提供しているのか? ×K8sがどのように提供しているのか? × コンテナランタイム: docker × ネットワーク:
CNI (Calico) ×コードの解説 ×応用
例 $ docker inspect k8s_test1-node1_centos1-2797499804-fdqd1_default_018173b3-8247-11e7-b2d6- 525400075920_0 | jq .[]."NetworkSettings" {
"Bridge": "", "SandboxID": "", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": null, "SandboxKey": "", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "", "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "MacAddress": "", "Networks": null
例 $ kubectl get -o wide pod NAME READY STATUS
RESTARTS AGE IP NODE centos1-2797499804-fdqd1 1/1 Running 0 9m 192.168.58.193 k8s-node02 $ docker exec -it k8s_test1-node1_centos1-2797499804-fdqd1_default_018173b3-8247-11e7-b2d6-525400075920_0 bash [root@centos1-2797499804-fdqd1 /]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1 link/ipip 0.0.0.0 brd 0.0.0.0 4: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 22:e6:c3:21:5f:a7 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 192.168.58.193/32 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::20e6:c3ff:fe21:5fa7/64 scope link valid_lft forever preferred_lft forever
k8sの場合 k8sの場合は? × コンテナランタイム: docker × ネットワーク: CNI (Calico) 結果
× docker側はネットワークが無いという × k8sから見るとネットワークはあるという → 実際コンテナにはネットワークが見える
k8sのコンテナとネットワークの関係 1. kubectlでコンテナの起動命令 2. kubeletがdockerでコンテナを"--net none"で起動 実際にはdocker API経由なので NetworkMode =
"none" 1. コンテナはネットワーク無しで起動 →なのでdockerから見るとネットワークはなしで起動している 1. kubeletがCNIを起動してコンテナにネットワークを追加 →なのでk8sはネットワークを認識している& ネットワークが実際に存在する
Agenda ×コンテナのネットワークについて ×実際の手法 ×コードの解説 (超簡略版) × CNIがどのようにインターフェースをコンテナに関連付けしているのか? × CNIプロジェクト本家のbridgeプラグイン ×
github.com/containernetworking/plugins/main/bridge/bridge.g o × 500行程度 ×応用
bridge.go 489 func main() { 490 skel.PluginMain(cmdAdd, cmdDel, version.All) 491
} × https://github.com/containernetworking/cni に仕様書 × CNIは単体で実行できるものならなんでもOK (shell scriptも可) × 実装するものはADDとDELとVERSIONの3命令 × 必要な情報はSTDINと環境変数で提供 × STDIN: ネットワークの情報 (/etc/cni/net.d) × 環境変数: コマンド(ADD/DEL/VERSION)とコンテナの情報
bridge.go 310 func cmdAdd(args *skel.CmdArgs) error { //略 324 br,
brInterface, err := setupBridge(n) //略 329 netns, err := ns.GetNS(args.Netns) //略 335 hostInterface, containerInterface, err := setupVeth(netns, br, args.IfName, n.MTU, n.HairpinMode) //略 365 if err := netns.Do(func(_ ns.NetNS) error { //略 375 if err := ipam.ConfigureIface(args.IfName, result); err != nil { ブリッジを見つけて コンテナのNET_NSを 取得 Vethの作成とブリッ ジへの接続 コンテナのNET_NSに 移動して IPアドレスを設定
bridge.go コードから分かること: × vethはnetlink (kernelの機能)で作成可能 × netlinkのIFLA_NET_NS_FDでインターフェースを他のNET_NSに移動 × setns()システムコールを使うことでプログラム内で希望したNET_NSに移動 ×
Go言語ではnetlink, netns等のライブラリがgithubに存在すること → これらを使えばコンテナのネットワークを自由に変更可能?
Agenda ×コンテナのネットワークについて ×実際の手法 ×コードの解説 (超簡略版) ×応用 × ここまでの知見からツールを作ってみました × ツールの解説
× デモ
koko (Container Connector) https://github.com/redhat-nfvpe/koko netns, netlinkを使ってコンテナをp2pで接続するコマンド コンテナ: docker, netns, PID
インターフェース: veth, vxlan, vlan, macvlan Port-mirroring (network tapping) ingress, egress, both
demo1 × dockerとnetns間をvethで接続してping koko -d test1,eth0,192.168.1.1/24 -d test2,eth0,192.168.1.2/24
demo2 × dockerのコンテナにveth3を作成 × veth2が受信するパケットをミラーして、vxlanにして他のホストに送信 koko -d node1,mirror1,mirror:ingress:eth0 -x eth1,10.10.10.2,100
Agenda ×コンテナのネットワークについて ×実際の手法 ×コードの解説 ×応用
Thanks! Any questions? You can find me at @s1061123 &
[email protected]
SlidesCarnival icons are editable shapes. This means that you can:
• Resize them without losing quality. • Change fill color and opacity. • Change line color, width and style. Isn’t that nice? :) Examples:
Now you can use any emoji as an icon! And
of course it resizes without losing quality and you can change the color. How? Follow Google instructions https://twitter.com/googledocs/status/730087240156643328 ✋ 👆👉👍👤👦👧👨👩👪💃🏃💑❤😂 😉😋😒😭👶😸🐟🍒🍔💣📌📖🔨🎃🎈 🎨🏈🏰🌏🔌🔑 and many more... 😉