Upgrade to Pro — share decks privately, control downloads, hide ads and more …

kubelet は俺の上司。今日もコンテナを作る。

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

kubelet は俺の上司。今日もコンテナを作る。

Kubernetes ノード上で Pod がどのように構築されるのか、"ざっくり"にでも理解する手助けになればと思い、このようなスライドを作成しました。
スライドでは kubelet を「俺」の上司に見立てて、kubelet から振られる仕事を「俺」がどのようにこなすのかという観点で説明を行っています。

検証環境には Amazon EKS を使用しており、cni plugin の説明には amazon vpc cni plugin を用いています。
なお、手作業での再現を容易にするため、本説明ではコンテナランタイムを Docker としていますが、Containerd についても一部触れています。

Avatar for Shuntaro Azuma

Shuntaro Azuma

January 10, 2024
Tweet

More Decks by Shuntaro Azuma

Other Decks in Technology

Transcript

  1. あらすじ 第 1 章 kubelet は俺の上司。今日もコンテナを作る。 第 2 章 CNI

    plugin と IPAMD が退職。え、俺が仕事を引き継ぐんすか。
  2. 組織図 <従業員> kubelet 先輩 Docker さん CNI-plugin さん IPAMD さん

    俺 Kubernetes 株式会社(親会社) 株式会社 ノードA 株式会社 ノードB 株式会社 ノードC ※ 「俺」は実在しない架空のコンポーネント。本資料は EKS - Docker 環境を想定し作成したもの。 kubelet Docker 俺 CNI-plugin IPAMD <連絡網> <主な業務内容> ・コンテナの作成 ・IP アドレスの割り当て ・ルート(疎通性)の確保
  3. 第 1 章 kubelet は俺の上司。今日もコンテナを作る。 kubelet うちの会社(ノード A)で Pod を作ってほしいそうだ。

    おい、俺!まずは pause コンテナを作ってくれ。 あー、ネットワークの設定はしなくていいから。 Kubernetes 株式会社 はい、分かりました! pause コンテナ...??? 俺 kubelet Docker 俺 CNI-plugin IPAMD
  4. 第 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; }
  5. 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
  6. 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 章で詳しく説明
  7. # 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 コンテナの作成を要求し終えたところまで)
  8. 第 1 章 kubelet は俺の上司。今日もコンテナを作る。 kubelet おう。次はアプリコンテナの作成だな.. はい、分かりました! ネットワーク設定 終わったの?

    俺 CNI plugin kubelet Docker 俺 CNI-plugin IPAMD ネットワーク設定終わったよ〜 俺、仕事だ。先程作った pause コンテナと同じ Namespace にアプリコンテナ(nginx)を作れ!
  9. # 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 がネットワーク設定を終えたところまで)
  10. 第 1 章 kubelet は俺の上司。今日もコンテナを作る。 https://docs.docker.jp/engine/reference/run.html#network-settings kubelet 俺、仕事だ。先程作った pause コンテナと同じ

    Namespace にアプリコンテナ(nginx)を作れ! kubelet Docker 俺 CNI-plugin IPAMD Docker で何をすればいいのかというと…
  11. 第 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 イメージ図 は〜い
  12. 第 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
  13. 第 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 が存在する場合は、以下のようになる
  14. $ 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 ごとに異なる結果が 得られることがわかる
  15. 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
  16. <余談> 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
  17. kubelet Docker 俺 CNI-plugin IPAMD 第 2 章 CNI plugin

    と IPAMD が退職。え、俺が仕事を引き継ぐんすか。 kubelet Docker 俺 kubelet 今日からネットワーク設定も宜しく頼むよ! 早速 1 つ nginx Pod を作ってくれ。 ふえぇ〜(そもそもネットワーク設定って何をすればいいんだ) 俺
  18. 第 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 で稼働
  19. 第 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
  20. 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 だよ
  21. 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
  22. 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)
  23. 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)
  24. 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
  25. 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 の割り当てを行う
  26. 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
  27. まとめ 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. アクセス可能!