Share
Embed
kubelet は俺の上司。今日もコンテナを作る。
Kubernetes ノード上で Pod がどのように構築されるのか、"ざっくり"にでも理解する手助けになればと思い、このようなスライドを作成しました。
スライドでは kubelet を「俺」の上司に見立てて、kubelet から振られる仕事を「俺」がどのようにこなすのかという観点で説明を行っています。
検証環境には Amazon EKS を使用しており、cni plugin の説明には amazon vpc cni plugin を用いています。
なお、手作業での再現を容易にするため、本説明ではコンテナランタイムを Docker としていますが、Containerd についても一部触れています。
Shuntaro Azuma
January 10, 2024
Transcript
31 slides
-
あらすじ 第 1 章 kubelet は俺の上司。今日もコンテナを作る。 第 2 章 CNI
plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 -
組織図 <従業員> kubelet 先輩 Docker さん CNI-plugin さん IPAMD さん
俺 Kubernetes 株式会社(親会社) 株式会社 ノードA 株式会社 ノードB 株式会社 ノードC ※ 「俺」は実在しない架空のコンポーネント。本資料は EKS - Docker 環境を想定し作成したもの。 kubelet Docker 俺 CNI-plugin IPAMD <連絡網> <主な業務内容> ・コンテナの作成 ・IP アドレスの割り当て ・ルート(疎通性)の確保 -
第 1 章 kubelet は俺の上司。今日もコンテナを作る。 kubelet うちの会社(ノード A)で Pod を作ってほしいそうだ。
おい、俺!まずは pause コンテナを作ってくれ。 あー、ネットワークの設定はしなくていいから。 Kubernetes 株式会社 はい、分かりました! pause コンテナ...??? 俺 kubelet Docker 俺 CNI-plugin IPAMD -
第 1 章 kubelet は俺の上司。今日もコンテナを作る。 Pause コンテナとは Pod namespace を維持するためのコンテナ。Sandbox
と呼んだりもする。 一般的には、C 言語でシンプルに実装されたものを起動する。 https://github.com/kubernetes/kubernetes/blob/master/build/pause/linux/pause.c int main(int argc, char **argv) { … if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) return 1; if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) return 2; if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap, .sa_flags = SA_NOCLDSTOP}, NULL) < 0) return 3; for (;;) pause(); fprintf(stderr, "Error: infinite loop terminated\n"); return 42; } -
pause 第 1 章 kubelet は俺の上司。今日もコンテナを作る。 Docker さん、こんなコンテナ 作って貰ってもいいですか? 俺
Docker いいですよ〜 kubelet Docker 俺 CNI-plugin IPAMD $ docker run -d -it --network none --name pause kubernetes/pause:latest Name: pause Image: pause:latest Network: none -
kubelet 俺 第 1 章 kubelet は俺の上司。今日もコンテナを作る。 kubelet Docker 俺
CNI-plugin IPAMD kubelet 先輩、pause コンテナできました! pause Docker さん、こんなコンテナ 作って貰ってもいいですか? 俺 Docker いいですよ〜 $ docker run -d -it --network none --name pause kubernetes/pause:latest Name: pause Image: pause:latest Network: none おう! ネットワークの設定は CNI plugin にお願い するから、「俺」は休んでいいぞ。 CNI plugin、 ネットワークの設定宜しくー かしこまり〜 CNI plugin ※ 2 章で詳しく説明 -
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES e8e411bf7640 kubernetes/pause:latest "/pause" 3 seconds ago Up 2 seconds pause # docker inspect e8e411bf7640 | grep SandboxKey "SandboxKey": "/var/run/docker/netns/4a9f58af43f8", # ls -l /var/run/docker/netns/ total 0 -r--r--r-- 1 root root 0 Jan 15 13:44 4a9f58af43f8 -r--r--r-- 1 root root 0 Jan 15 01:56 default // まだ何もネットワーク設定は完了していない # ip -n 4a9f58af43f8 addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 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 ここまでの状況(「俺」が Docker に pause コンテナの作成を要求し終えたところまで) -
第 1 章 kubelet は俺の上司。今日もコンテナを作る。 kubelet おう。次はアプリコンテナの作成だな.. はい、分かりました! ネットワーク設定 終わったの?
俺 CNI plugin kubelet Docker 俺 CNI-plugin IPAMD ネットワーク設定終わったよ〜 俺、仕事だ。先程作った pause コンテナと同じ Namespace にアプリコンテナ(nginx)を作れ! -
# ip -n 4a9f58af43f8 addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
qdisc noqueue state UNKNOWN group default qlen 1000 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 3: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default link/ether 5a:09:86:44:45:4f brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 192.168.9.86/32 scope global eth0 valid_lft forever preferred_lft forever # ip -n 4a9f58af43f8 route default via 169.254.1.1 dev eth0 169.254.1.1 dev eth0 scope link ここまでの状況(CNI plugin がネットワーク設定を終えたところまで) -
第 1 章 kubelet は俺の上司。今日もコンテナを作る。 https://docs.docker.jp/engine/reference/run.html#network-settings kubelet 俺、仕事だ。先程作った pause コンテナと同じ
Namespace にアプリコンテナ(nginx)を作れ! kubelet Docker 俺 CNI-plugin IPAMD Docker で何をすればいいのかというと… -
第 1 章 kubelet は俺の上司。今日もコンテナを作る。 Docker さん、こんなコンテナ 作って貰ってもいいですか? 俺 Docker
kubelet Docker 俺 CNI-plugin IPAMD pause nginx Network Namespace Name: nginx Image: nginx:latest Network: container:pause $ docker run -d -it --network container:pause --name nginx nginx:latest イメージ図 は〜い -
第 1 章 kubelet は俺の上司。今日もコンテナを作る。 Docker さん、こんなコンテナ 作って貰ってもいいですか? 俺 Docker
できたよ〜 kubelet Docker 俺 CNI-plugin IPAMD pause nginx Network Namespace Name: nginx Image: nginx:latest Network: container:pause $ docker run -d -it --network container:pause --name nginx nginx:latest イメージ図 nginx -
第 1 章 kubelet は俺の上司。今日もコンテナを作る。 kubelet Docker 俺 CNI-plugin IPAMD
pause nginx Network Namespace kubelet うちの会社(ノード A)で 3 つ Pod を作るぞ! pause httpd Network Namespace pause Network Namespace alpine redis つまり複数の Pod が存在する場合は、以下のようになる -
$ k get po -A -o wide | grep ip-192-168-36-138.ap-northeast-1.compute.internal
default httpd 1/1 Running 0 5m2s 192.168.49.218 ip-192-168-36-138.ap-northeast-1.compute.internal default nginx 1/1 Running 0 5m9s 192.168.49.216 ip-192-168-36-138.ap-northeast-1.compute.internal … # ip netns 3884966eb9bd (id: 2) <= For httpd afc669a5cd86 (id: 1) <= For nginx default # ip netns exec 3884966eb9bd curl -I localhost HTTP/1.1 200 OK Server: Apache/2.4.52 (Unix) … # ip netns exec afc669a5cd86 curl -I localhost HTTP/1.1 200 OK Server: nginx/1.21.5 … 同一ノード上に httpd と nginx の Pod(コンテナ)があるときの挙動 期待通り netns ごとに異なる結果が 得られることがわかる -
kubelet Docker 俺 CNI-plugin IPAMD 第 1 章 kubelet は俺の上司。今日もコンテナを作る。
1. Pause コンテナを作る 2. Pause コンテナと関連する netns にネットワーク設定を行う 3. Pause コンテナと同じ netns にアプリコンテナを作る ※ 上記は、コンテナランタイムが Docker の時の話です Containerd の場合は、cri-plugin が netns を作成してから Pause コンテナを作成します https://github.com/containerd/containerd/blob/main/docs/cri/architecture.md -
<余談> hostNetwork: true を指定した Pod のネットワーク設定はどうなっているのか Ans. Pause コンテナが --net=host
で起動し、netns は作成されない 第 1 章 kubelet は俺の上司。今日もコンテナを作る。 $ k get po -n kube-system aws-node-m6kvm -o yaml | kubectl neat | grep hostNetwork hostNetwork: true # docker inspect --format='{{index .Config.Labels "io.kubernetes.sandbox.id"}}’ k8s_aws-node_aws-node-m6kvm_kube- system_...3e2edb96930f0c…. # docker inspect --format='{{index .HostConfig.NetworkMode}}' 3e2edb96930 <- Pause コンテナの ID host -
kubelet Docker 俺 CNI-plugin IPAMD 第 2 章 CNI plugin
と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 kubelet Docker 俺 kubelet 今日からネットワーク設定も宜しく頼むよ! 早速 1 つ nginx Pod を作ってくれ。 ふえぇ〜(そもそもネットワーク設定って何をすればいいんだ) 俺 -
第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 CNI plugin
とは Pod ネットワークを実現するためのネットワーク設定を行うプラグイン。 EKS 環境では、aws-cni が使用される。 IPAMD とは Pod に割り当てる IP アドレスを管理するプロセス。 aws-node DaemonSet として起動する。 https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md # ps axjf PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 1 4408 4408 2780 ? -1 Sl 0 0:05 /usr/bin/containerd-shim-runc-v2 … 4408 4427 4427 4427 ? -1 Ss 0 0:00 \_ bash /app/entrypoint.sh 4427 4490 4490 4427 ? -1 Sl 0 0:02 \_ ./aws-k8s-agent 4427 4491 4490 4427 ? -1 S 0 0:00 \_ tee -i aws-k8s-agent.log ホスト内では、IPAMD はプロセス名 aws-k8s-agent で稼働 -
第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 完成形 pause
Pod network namespace Host(ノード) veth veth eth0 (192.168.10.20/32) プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 nginx -
eth0 第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 Pod
network namespace Host(ノード) veth veth (192.168.10.20/32) プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 まずは、割り当てる IP addr を確認しよう どの IP が使えるのかな 俺 IPAMD さんがいたら 教えてくれたのに… pause nginx kubelet Docker 俺 CNI-plugin IPAMD <今まで> アサイン可能な IP 教えて 192.168.10.20/32 だよ -
eth0 第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 Pod
network namespace Host(ノード) veth veth プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 俺 // IMDS にアクセスし、ノードにアタッチされてる IP を確認する # curl 169.254.169.254/latest/meta- data/network/interfaces/macs/XX:XX:XX:XX:XX:XX/local-ipv4s 192.168.10.10 192.168.10.20 <--- この IP アドレスを使おう pause nginx まずは、割り当てる IP addr を確認しよう どの IP が使えるのかな https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html -
veth eth0 第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。
Pod network namespace Host(ノード) veth プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 次に veth peer を作成する 俺 # ip netns 7a1e266de76c default # ip link add veth-1 type veth peer name veth-1c # ip link set veth-1c netns 7a1e266de76c # ip link set veth-1 up # ip netns exec 7a1e266de76c ip link set veth-1c up pause nginx (192.168.10.20/32) -
eth0 第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 Pod
network namespace Host(ノード) veth veth プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 俺 // Pod namespace 側に veth-1c が存在していることを確認 # ip netns exec 7a1e266de76c ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 6: veth-1c@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 66:f2:19:c9:eb:cd brd ff:ff:ff:ff:ff:ff link-netnsid 0 // Host 側に veth-1 が作成されていることを確認 # ip link | grep veth-1 -A 1 7: veth-1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000 link/ether 2e:61:53:96:e4:9e brd ff:ff:ff:ff:ff:ff link-netnsid 2 pause nginx 次に veth peer を作成する (192.168.10.20/32) -
eth0 第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 Pod
network namespace Host(ノード) veth veth (192.168.10.20/32) プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 IP addr の割り当てを行う 俺 // IP アドレスを veth-1c にアサインする # ip netns exec 7a1e266de76c ip addr add 192.168.10.20/32 dev veth-1c // デフォルトゲートの追加 # ip netns exec 7a1e266de76c ip route add 169.254.1.1 dev veth-1c // デフォルトルートの追加 # ip netns exec 7a1e266de76c ip route add default via 169.254.1.1 dev veth-1c // デフォルトゲートのための静的 ARP エントリの追加 //(ホスト側の veth-1 の MAC アドレスを指定する) # ip netns exec 7a1e266de76c arp -i veth-1c -s 169.254.1.1 2e:61:53:96:e4:9e pause nginx -
eth0 第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 Pod
network namespace Host(ノード) veth veth (192.168.10.20/32) プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 俺 // Pod の IP アドレス宛の通信を veth-1 に流すように設定する # ip route add 192.168.10.20/32 dev veth-1 # ip route show default via 192.168.10.1 dev eth0 169.254.169.254 dev eth0 192.168.10.0/19 dev eth0 proto kernel scope link src 192.168.10.10 192.168.10.20 dev veth-1 scope link # ip rule add from all to 192.168.10.20 table main prio 512 # ip rule 0: from all lookup local 512: from all to 192.168.10.20 lookup main 1024: from all fwmark 0x80/0x80 lookup main 32766: from all lookup main 32767: from all lookup default pause nginx IP addr の割り当てを行う -
eth0 第 2 章 CNI plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 Pod
network namespace Host(ノード) veth veth (192.168.10.20/32) プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 これでアクセスできる! 俺 // 同一 VPC(ホスト)上から nginx コンテナ(アサインした IP) に // アクセス可能 $ curl -I 192.168.10.20 HTTP/1.1 200 OK … pause nginx -
まとめ pause Pod network namespace Host(ノード) veth veth eth0 (192.168.10.20/32)
プライマリ 192.168.10.10/32 セカンダリ 192.168.10.20/32 nginx 第 1,2 章を通しての作業手順 1. pause コンテナの作成 2. 割り当て可能な IP アドレスの確認 3. veth peer の作成 4. veth へ IP アドレスの割り当て 5. rule の作成(ルーティングテーブルの編集) 6. nginx コンテナの作成 7. アクセス可能!