Slide 1

Slide 1 text

kube-proxy⼊⾨ Kubernetes Novice Tokyo # 2 8 ( 2 0 2 3 / 1 1 / 9 ) @bells 1 7

Slide 2

Slide 2 text

▶ @bells 1 7 ▶ Software Engineer@ 3 -shake inc. ▶ kubernetes & kubernetes-csi member ▶ Kubernetes Internal Organizer ▶ #kubenews ▶ X(Twitter): @bells 1 7 _ ▶ GitHub: @bells 1 7

Slide 3

Slide 3 text

今⽇話すこと ▶ kube-proxyについて ▶ kube-proxyが設定するiptablesについて

Slide 4

Slide 4 text

注意点 ▶ Kubernetes v 1 . 2 8 . 2 ベースでのお話になります ▶ KubernetesそのものやKubernetes Component全体の説明は簡単なものに なるかと思います ▶ あくまでkube-proxyの実装を追った結果での理解の説明になるので、 
 間違いが含まれている可能性があります ▶ 特にネットワーク初⼼者なので、ネットワーク周りの説明は 
 間違いが多いかも…

Slide 5

Slide 5 text

そもそもKubernetesとは?

Slide 6

Slide 6 text

Kubernetes とは? ▶ Kubernetesはコンテナオーケストレーターの1つ ▶ etcd/control plane/worker nodeによって構成されたクラスターを構築し、 
 様々なコンテナをKubernetes上のnodeで動作させたり、動作させてる 
 コンテナとネットワークをいい感じに連携できるようにすることができる ▶ デプロイするコンテナなどをmanifestファイルで宣⾔的に記述することで、 
 宣⾔した状態になるようにKubernetesがいい感じに調整処理を⾏ってくれる ▶ Googleが内部で運⽤していたコンテナ基盤であるBorgを 
 OSS向けに作り直したコンテナオーケストレーター ▶ また、KubernetesはCloud Native Computing Foundation(CNCF)に寄贈されており、 CNCFのGraduatedプロジェクトとしてコミュニティベースで管理されている

Slide 7

Slide 7 text

manifestをKubernetesに適⽤することで 宣⾔されたmanifestの通りにコンテナが作成される

Slide 8

Slide 8 text

Kubernetesコントローラー

Slide 9

Slide 9 text

https://github.com/kubernetes/website/blob/fb 6 3 6 4 da 0 afd 1 9 e 8 a 9 5 1 5 aaae 2 de 9 bc 7 4 a 0 a 6 abd/static/images/docs/components-of-kubernetes.png

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

基本パターン ▶ Managerプロセス全体の中で1つ、または複数のコントローラーが実⾏ される ▶ コントローラーは1つにつき、1種類のKubernetesリソースのみに対す る調整ループ(Reconciliation Loop)が実⾏される + 調整ループ: リソースのあるべき状態(Desired State)と実際の状態 (Actual State)を⽐較~あるべき状態になるように調整処理を⾏うもの + なので、2種類のリソースに対しては、最低2コントローラー以上が 
 あるのが基本

Slide 12

Slide 12 text

調整ループ ▶ 主に以下の2種類の⽅法で実⾏される + Event Handlers: 監視対象のKubernetes Resourceの更新といった、 なんらかのイベントを元に実⾏される + 無限ループによる定期実⾏: 設定値に基づいて数秒毎などの間隔で定 期実⾏が⾏われる

Slide 13

Slide 13 text

https://github.com/kubernetes/sample-controller/blob/master/docs/images/client-go-controller-interaction.jpeg

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

▶ Kubernetesのコードリーディングをする上で知っておくと良さそうなこと ▶ Kubernetes Internal # 1 こういったKubernetesコントローラー実装周りについてはコード リーディングについての記事の中で書いたので良ければ⾒てください

Slide 16

Slide 16 text

Kubernetes Core Component

Slide 17

Slide 17 text

https://github.com/kubernetes/website/blob/fb 6 3 6 4 da 0 afd 1 9 e 8 a 9 5 1 5 aaae 2 de 9 bc 7 4 a 0 a 6 abd/static/images/docs/components-of-kubernetes.png

Slide 18

Slide 18 text

Core Component ▶ etcd: API Serverのバックエンドで使⽤されている分散型のKVS ▶ Control Plane ▶ API Server: KubernetesのAPIリクエストを処理するサーバー ▶ Kube Controller Manager: Kubernetesの様々なリソースのためのロジックを動かす 
 様々なコントローラーを動作させるマネージャー ▶ Cloud Controller Manager: Kubernetesとクラウド(実⾏基盤)を連携するための 
 コントローラーを動作させるマネージャー ▶ Scheduler: PodをどのWorker Nodeに配置するかを決める ▶ Worker Node ▶ Kubelet: Worker Nodeで実⾏するコンテナを管理するアプリケーション ▶ Kube Proxy: Service/EndpointSliceリソースに基づくネットワーク設定を⾏うアプリケーション

Slide 19

Slide 19 text

▶ Cloud Controller Manager Deep Dive ▶ Kubernetes Internal # 2 Cloud Controller Managerについては以下のスライドで まとめてあるので参考にしてください

Slide 20

Slide 20 text

▶ Kubeletから読み解くKubernetesのコンテナ管理の裏側 ▶ Kubernetes Internal # 4 ▶ Kubeletから読み解くKubernetesのコンテナ管理の裏側 Kubeletについても以前発表しているセッションや書籍が あるので良ければ参考にしてください

Slide 21

Slide 21 text

https://github.com/kubernetes/website/blob/fb 6 3 6 4 da 0 afd 1 9 e 8 a 9 5 1 5 aaae 2 de 9 bc 7 4 a 0 a 6 abd/static/images/docs/components-of-kubernetes.png

Slide 22

Slide 22 text

kube-proxyとは?

Slide 23

Slide 23 text

kube-proxy とは? ▶ Worker Nodeで動作するCore Componentの1つ ▶ 主にServiceリソースとEndpointSliceリソースを元にネットワーク設定を 
 ⾏い、Serviceのエンドポイント(e.g. foo.bar.svc.cluster.local)にアクセス 
 した際にPodにリクエストが届くようにしてくれるコンポーネント ▶ 動作モードには下記の3つがある(userspaceというモードもあったが削除された) ▶ iptables(デフォルト) ▶ ipvs ▶ kernelspace(Windows⽤) ▶ IPv 4 とIPv 6 のデュアルスタックのサポートも有り

Slide 24

Slide 24 text

補⾜: ServiceとEndpointSliceの関係 apiVersion: discovery.k 8 s.io/v 1 kind: EndpointSlice metadata: name: np-service- 7 2 gzs namespace: default ... addressType: IPv 4 ports: - name: "" port: 8 0 8 0 protocol: TCP endpoints: - addresses: - 1 0 . 2 4 4 . 2 . 3 nodeName: kube-proxy-example-worker 2 targetRef: kind: Pod name: nginx- 6 c 6 6 5 6 d 8 f 6 - 6 zv 7 t namespace: default uid: 4 ad 3 a 7 cc- 3 1 4 4 - 4 2 fd- 9 3 e 4 - 1 6 0 4 4 5 ebcc 3 b ... Serviceで指定したセレクタにマッチしたPodの情報をEndpointSliceとして⽣成する LBで⾔うとServiceのCluster IPはLBに割り当てるIP、EndpointSliceはPodを紐付けるIP Poolのイメージ

Slide 25

Slide 25 text

今回の解説の前提 ▶ OS: Linuxを使⽤ ▶ 動作モード: iptablesモード ▶ IPv 4 のみを使⽤する想定です ▶ 設定値は基本デフォルトのものを想定してます ▶ 検証はkindで⾏っているのでCNIはkindnetが使⽤されています

Slide 26

Slide 26 text

kube-proxyの全体像はだいたいこんなん

Slide 27

Slide 27 text

ipt.Monitor ▶ ipt=iptablesのこと(多分) ▶ “KUBE-PROXY-CANARY” というチェインを下記のテーブルに作成する + mangle + nat + fi lter ▶ 作成後、上記チェインがあるかどうかを監視する ▶ もしチェインが削除されたらproxier.syncProxyRulesを実⾏して、再度“KUBE-PROXY-CANARY” チェインの作成~監視に戻る ▶ → “KUBE-PROXY-CANARY” チェインを作って監視することで iptables のルールを削除されてな いかをチェックしてる 
 (ルールが⼤量にあるとパフォーマンスに影響してくるからルールが存在しない空っぽの チェイ ンを作って監視してるとのこと)

Slide 28

Slide 28 text

ServiceCon fi g ▶ Serviceリソースの更新時に下記の処理を⾏う + kube-proxy⽤のデータキャッシュ処理 + proxier.syncProxyRulesの実⾏依頼

Slide 29

Slide 29 text

endpointSliceCon fi g ▶ EndpointSliceリソースの更新時に下記の処理を⾏う + kube-proxy⽤のデータキャッシュ処理 + proxier.syncProxyRulesの実⾏依頼

Slide 30

Slide 30 text

nodeCon fi g ▶ Nodeリソースの更新時に下記の処理を⾏う + kube-proxy⽤のデータキャッシュ処理 + proxier.syncProxyRulesの実⾏依頼 ▶ ここで処理されるNodeリソースはkube-proxyを実⾏しているNode⾃⾝のみ

Slide 31

Slide 31 text

watcher ▶ kube-proxy.confの内容変更を監視 ~ 検知したら⾃⾝のプロセスをkillする ▶ kube-proxyはDaemonSetやstatic podなどで起動されているはずなので、 
 killされたら再起動される

Slide 32

Slide 32 text

iptablesについて

Slide 33

Slide 33 text

iptablesの基本 ▶ 外部ネットワークからパケットを受信した際にテーブルと 
 テーブル内のチェインの設定に応じてパケットのフィルタリングなどの 
 処理を⾏うことができる ▶ iptablesではnetlinkを介してカーネルのnet fi lterの設定を⾏うことが可能で、 
 net fi lterはネットワークパケット処理の各段階でフックを使ってコールバック関数を実⾏す ることで各種操作を実現してるらしい ▶ nftablesというiptablesの後継があるらしい ざっくりこんな感じという理解です

Slide 34

Slide 34 text

主なテーブルとチェイン ▶ fi lter: パケットフィルタリングに使われるテーブル + 主なチェイン: INPUT, FORWARD, OUTPUT ▶ nat: NAT処理に使われるテーブル + 主なチェイン: PREROUTING, OUTPUT, POSTROUTING ▶ mangle: パケットのTTL設定など、特定のパケットのヘッダー情報を変更する際に使⽤ + 主なチェイン: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING ▶ raw: パケットがコネクショントラッキングシステムをバイパスすることを許可するために使⽤ + 主なチェイン: PREROUTING, OUTPUT ▶ security: SELinux ルールの適⽤に使⽤される + INPUT, OUTPUT, FORWARD

Slide 35

Slide 35 text

https://stu ff philwrites.com/wp-content/uploads/ 2 0 1 4 / 0 9 /FW-IDS-iptables-Flowchart- 2 0 1 4 - 0 9 - 2 5 .png

Slide 36

Slide 36 text

例えばNodePortとCluster IPのServiceをそれぞれ使って Podにリクエストが届く際はこんな感じになる

Slide 37

Slide 37 text

kindで試した例

Slide 38

Slide 38 text

環境構築

Slide 39

Slide 39 text

kind-con fi g.yaml kind: Cluster apiVersion: kind.x-k 8 s.io/v 1 alpha 4 nodes: - role: control-plane - role: worker - role: worker # クラスター起動コマンド $ kind create cluster \ --name kube-proxy-example \ --con fi g kind-con fi g.yaml control-plane: 1 worker: 2 合計3台のノードを起動する

Slide 40

Slide 40 text

Service 
 type: ClusterIP apiVersion: v 1 kind: Service metadata: name: cip-service spec: selector: app: nginx ports: - protocol: TCP port: 8 0 type: ClusterIP

Slide 41

Slide 41 text

Service 
 type: NodePort apiVersion: v 1 kind: Service metadata: name: np-service spec: selector: app: nginx ports: - protocol: TCP port: 8 0 type: NodePort

Slide 42

Slide 42 text

Deployment apiVersion: apps/v 1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: a ff i nity: podAntiA ffi nity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 podA ffi nityTerm: labelSelector: matchExpressions: - key: app operator: In values: - nginx topologyKey: "kubernetes.io/hostname" containers: - name: nginx image: nginx ports: - containerPort: 8 0 2台をpreferredDuringSchedulingIgnoredDuringExecutionで分散配置してるのでworkerノードに1台ずつ配置されるはず

Slide 43

Slide 43 text

動作確認

Slide 44

Slide 44 text

クラスター外からの接続確認 $ docker exec -it 8 8 9 2 dd 1 4 0 b 3 e /bin/bash root@kube-proxy-example-control-plane:/# curl 1 9 2 . 1 6 8 . 2 2 8 . 4 : 3 1 7 8 6 -o /dev/null -w '% {http_code}\n' -s 200 # ノードのIPとNodePort: 接続できる root@kube-proxy-example-control-plane:/# curl 1 0 . 9 6 . 1 9 1 . 1 2 4 -o /dev/null -w '% {http_code}\n' -s 2 0 0 # np-serviceのClusterIP: 接続できる root@kube-proxy-example-control-plane:/# curl 1 0 . 9 6 . 2 2 0 . 1 8 8 -o /dev/null -w '% {http_code}\n' -s 2 0 0 # cip-serviceのClusterIP: 接続できる ちゃんと検証したことなかったけどクラスターに参加してるノードからならクラスター外からのアクセスも可能なのか

Slide 45

Slide 45 text

クラスター内からの接続確認 $ kubectl exec -it nginx- 5 9 b 8 fdd 4 6 4 -tq 6 k 6 -- bash root@nginx- 5 9 b 8 fdd 4 6 4 -tq 6 k 6 :/# curl np-service.default.svc.cluster.local -o /dev/null -w '%{http_code}\n' -s 2 0 0 root@nginx- 5 9 b 8 fdd 4 6 4 -tq 6 k 6 :/# curl cip-service.default.svc.cluster.local -o /dev/null -w '%{http_code}\n' -s 2 0 0

Slide 46

Slide 46 text

クラスターに参加してないノードからだとこんな感じ docker exec -it 8 8 9 2 dd 1 4 0 b 3 e /bin/bash root@kind-control-plane:/# curl 1 9 2 . 1 6 8 . 2 2 8 . 4 : 3 1 7 8 6 -o /dev/null -w '%{http_code}\n' -s 200 # ノードのIPとNodePort: 接続できる root@kind-control-plane:/# curl 1 0 . 9 6 . 1 9 1 . 1 2 4 -o /dev/null -w '%{http_code}\n' -s ^C # ノードのIPとNodePort: 接続できない root@kind-control-plane:/# curl 1 0 . 9 6 . 2 2 0 . 1 8 8 -o /dev/null -w '%{http_code}\n' -s ^C # cip-serviceのClusterIP: 接続できない kindのデフォルトクラスターが⽴ってたのでそれで検証した

Slide 47

Slide 47 text

iptablesの設定を確認してみる

Slide 48

Slide 48 text

PREROUTINGにKUBE-SERVICESが設定される Chain PREROUTING (policy ACCEPT) target prot opt source destination KUBE-SERVICES all -- 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* kubernetes service portals */ DOCKER_OUTPUT all -- 0 . 0 . 0 . 0 / 0 1 9 8 . 1 9 . 2 4 8 . 2 5 4 ↑は“iptables -t nat -L -n -v” コマンドをちょい整形したやつの⼀部です

Slide 49

Slide 49 text

KUBE-SERVICESに作成したServiceのCluster IPの 
 チェインが設定される Chain KUBE-SERVICES ( 2 references) pkts bytes target prot opt in out source destination 2 1 2 0 KUBE-SVC-OI 3 ES 3 UZPSOHIVZW tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 1 9 1 . 1 2 4 /* default/np-service cluster IP */ tcp dpt: 8 0 8 7 7 6 KUBE-SVC-TCOU 7 JCQXEZGVUNU udp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 0 . 1 0 /* kube-system/kube- dns:dns cluster IP */ udp dpt: 5 3 0 0 KUBE-SVC-ERIFXISQEP 7 F 7 OF 4 tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 0 . 1 0 /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt: 5 3 0 0 KUBE-SVC-JD 5 MR 3 NA 4 I 4 DYORP tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 0 . 1 0 /* kube-system/kube- dns:metrics cluster IP */ tcp dpt: 9 1 5 3 2 1 2 0 KUBE-SVC-ERVH 2 TYUWKPRTIBA tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 2 2 0 . 1 8 8 /* default/cip-service cluster IP */ tcp dpt: 8 0 0 0 KUBE-SVC-NPX 4 6 M 4 PTMTKRN 6 Y tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 0 . 1 /* default/kubernetes:https cluster IP */ tcp dpt: 4 4 3 6 3 6 0 KUBE-NODEPORTS all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL クラスターに参加してないノードだと↑のNAT設定が無いからCluster IPにアクセスしてもPodに通信が届かないっぽい?

Slide 50

Slide 50 text

Serviceを⾒ると”10.96.191.124”と”10.96.220.188”のIPが 
 設定されてるのが確認できる $ kubectl get svc np-service cip-service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE np-service NodePort 1 0 . 9 6 . 1 9 1 . 1 2 4 8 0 : 3 1 7 8 6 /TCP 1 9 h cip-service ClusterIP 1 0 . 9 6 . 2 2 0 . 1 8 8 8 0 /TCP 1 3 2 m

Slide 51

Slide 51 text

“statistic mode random probability 0 . 5 0 0 0 0 0 0 0 0 0 0 ”の設定によって “KUBE-SEP-XXX”のチェインがそれぞれ50%ずつの確率で選択される Chain KUBE-SVC-OI 3 ES 3 UZPSOHIVZW ( 2 references) pkts bytes target prot opt in out source destination 0 0 KUBE-MARK-MASQ tcp -- * * ! 1 0 . 2 4 4 . 0 . 0 / 1 6 1 0 . 9 6 . 1 9 1 . 1 2 4 /* default/np-service cluster IP */ tcp dpt: 8 0 3 1 8 0 KUBE-SEP-P 5 JHP 7 5 IHX 6 4 MSBB all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* default/np-service -> 1 0 . 2 4 4 . 1 . 4 : 8 0 */ statistic mode random probability 0 . 5 0 0 0 0 0 0 0 0 0 0 3 1 8 0 KUBE-SEP-VLQJIV 5 HGZHFWOG 3 all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* default/np-service -> 1 0 . 2 4 4 . 2 . 4 : 8 0 */ Chain KUBE-SVC-ERVH 2 TYUWKPRTIBA ( 1 references) pkts bytes target prot opt in out source destination 0 0 KUBE-MARK-MASQ tcp -- * * ! 1 0 . 2 4 4 . 0 . 0 / 1 6 1 0 . 9 6 . 2 2 0 . 1 8 8 /* default/cip-service cluster IP */ tcp dpt: 8 0 1 6 0 KUBE-SEP-KBDPBHDFQFJCC 6 G 2 all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* default/cip-service -> 1 0 . 2 4 4 . 1 . 4 : 8 0 */ statistic mode random probability 0 . 5 0 0 0 0 0 0 0 0 0 0 1 6 0 KUBE-SEP-RRD 2 VMIQOEDDLHII all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* default/cip-service -> 1 0 . 2 4 4 . 2 . 4 : 8 0 */ ↑は“iptables -t nat -L -n -v” コマンドをちょい整形したやつの⼀部です

Slide 52

Slide 52 text

ちなみにDNATする先が3つ以上ある場合こんな感じで 
 計算された数値が配置されるので各⾃0.2とかにはならないらしい https://github.com/kubernetes/kubernetes/issues/ 3 7 9 3 2

Slide 53

Slide 53 text

NodePort側の“KUBE-SEP-T 4 U 2 PF 7 3 XRV 2 7 O 6 N”チェインが選択された場合 
 DNATで”10.244.2.4:80”にアドレスが変換される Chain KUBE-SEP-VLQJIV 5 HGZHFWOG 3 ( 1 references) pkts bytes target prot opt in out source destination 2 1 2 0 KUBE-MARK-MASQ all -- * * 1 0 . 2 4 4 . 2 . 4 0 . 0 . 0 . 0 / 0 /* default/np-service */ 3 1 8 0 DNAT tcp -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* default/np-service */ tcp to: 1 0 . 2 4 4 . 2 . 4 : 8 0 ↑は“iptables -t nat -L -n -v” コマンドをちょい整形したやつの⼀部です

Slide 54

Slide 54 text

作成した各PodのIPを⾒ると”10.244.2.4”は 
 “kube-proxy-example-worker 2 ”で動いてることがわかる $ kubectl get pod -l app=nginx -o yaml | egrep "ip|nodeName" nodeName: kube-proxy-example-worker - ip: 1 0 . 2 4 4 . 1 . 4 nodeName: kube-proxy-example-worker 2 - ip: 1 0 . 2 4 4 . 2 . 4

Slide 55

Slide 55 text

EndpointSliceにもIPが設定されてるのがわかる $ kubectl get endpointslice np-service- 7 2 gzs cip-service- 2 7 ldz NAME ADDRESSTYPE PORTS ENDPOINTS AGE np-service- 7 2 gzs IPv 4 8 0 1 0 . 2 4 4 . 1 . 4 , 1 0 . 2 4 4 . 2 . 4 1 9 h cip-service- 2 7 ldz IPv 4 8 0 1 0 . 2 4 4 . 1 . 4 , 1 0 . 2 4 4 . 2 . 4 1 4 3 m

Slide 56

Slide 56 text

“kube-proxy-example-worker 2 ”のルーティングテーブルを確認すると 
 ”10.244.2.4”は”veth 1 ba 6 bf 7 1 ”というvethにルーティングされることがわかる 
 (このルーティングテーブルやvethはCNIのkindnetが設定したもののよう) $ ip route default via 1 9 2 . 1 6 8 . 2 2 8 . 1 dev eth 0 1 0 . 2 4 4 . 0 . 0 / 2 4 via 1 9 2 . 1 6 8 . 2 2 8 . 3 dev eth 0 1 0 . 2 4 4 . 1 . 0 / 2 4 via 1 9 2 . 1 6 8 . 2 2 8 . 5 dev eth 0 1 0 . 2 4 4 . 2 . 4 dev veth 1 ba 6 bf 7 1 scope host 1 9 2 . 1 6 8 . 2 2 8 . 0 / 2 4 dev eth 0 proto kernel scope link src 1 9 2 . 1 6 8 . 2 2 8 . 4 
 
 $ ip addr show 5 : vethd 7 b 5 df 7 f@if 3 : mtu 1 5 0 0 qdisc noqueue state UP group default link/ether 2 6 : 1 9 : 3 f: 7 9 : 5 5 : 2 0 brd ff : ff : ff : ff : ff : ff link-netns cni-d 1 e 5 dd 4 4 -b 7 8 c- 7 4 1 5 -f 0 0 0 - 0 d 6 0 e 1 2 2 0 b 0 2 inet 1 0 . 2 4 4 . 2 . 1 / 3 2 scope global vethd 7 b 5 df 7 f valid_lft forever preferred_lft forever … Vethの作成はkindnetが使⽤している ptp plugin が⾏っていて、ルーティングテーブルの作成は kindnet 本体が⾏っている

Slide 57

Slide 57 text

“kube-proxy-example-worker 2 ”がパケットを受信した場合”10.244.2.4”は 
 ローカルで動作しているPodなので次は fi lterテーブルのINPUTチェインに移る Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 3 6 2 8 7 0 KUBE-PROXY-FIREWALL all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 ctstate NEW /* kubernetes load balancer fi rewall */ 6 2 1 9 7 3 M KUBE-NODEPORTS all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* kubernetes health check service ports */ 3 6 2 8 7 0 KUBE-EXTERNAL-SERVICES all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 ctstate NEW /* kubernetes externally-visible service portals */ 6 4 3 9 7 3 M KUBE-FIREWALL all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 デフォルトがACCEPTで、上記チェインでは”10.244.2.3”宛のパケットがDROPなどはされないのでACCEPTされる(各チェインの詳細は省略) ちなみに↑は“iptables -t fi lter -L -n -v” コマンドをちょい整形したやつの⼀部です

Slide 58

Slide 58 text

話は変わってNodePortのNodeの宛先にリクエストされた場合 
 “KUBE-NODEPORTS”チェインにマッチする Chain KUBE-SERVICES ( 2 references) pkts bytes target prot opt in out source destination 2 1 2 0 KUBE-SVC-OI 3 ES 3 UZPSOHIVZW tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 1 9 1 . 1 2 4 /* default/np-service cluster IP */ tcp dpt: 8 0 8 7 7 6 KUBE-SVC-TCOU 7 JCQXEZGVUNU udp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 0 . 1 0 /* kube-system/kube- dns:dns cluster IP */ udp dpt: 5 3 0 0 KUBE-SVC-ERIFXISQEP 7 F 7 OF 4 tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 0 . 1 0 /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt: 5 3 0 0 KUBE-SVC-JD 5 MR 3 NA 4 I 4 DYORP tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 0 . 1 0 /* kube-system/kube- dns:metrics cluster IP */ tcp dpt: 9 1 5 3 2 1 2 0 KUBE-SVC-ERVH 2 TYUWKPRTIBA tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 2 2 0 . 1 8 8 /* default/cip-service cluster IP */ tcp dpt: 8 0 0 0 KUBE-SVC-NPX 4 6 M 4 PTMTKRN 6 Y tcp -- * * 0 . 0 . 0 . 0 / 0 1 0 . 9 6 . 0 . 1 /* default/kubernetes:https cluster IP */ tcp dpt: 4 4 3 6 3 6 0 KUBE-NODEPORTS all -- * * 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL ↑は“iptables -t nat -L -n -v” コマンドをちょい整形したやつの⼀部です

Slide 59

Slide 59 text

31786ポート宛にリクエストが来た場合 “KUBE-EXT-OI 3 ES 3 UZPSOHIVZW”チェインにジャンプして 
 更にそこから“KUBE-SVC-OI 3 ES 3 UZPSOHIVZW”に⾶ばされる Chain KUBE-NODEPORTS ( 1 references) target prot opt source destination KUBE-EXT-OI 3 ES 3 UZPSOHIVZW tcp -- 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* default/np-service */ tcp dpt: 3 1 7 8 6 Chain KUBE-EXT-OI 3 ES 3 UZPSOHIVZW ( 1 references) target prot opt source destination KUBE-MARK-MASQ all -- 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 /* masquerade tra ff i c for default/ np-service external destinations */ KUBE-SVC-OI 3 ES 3 UZPSOHIVZW all -- 0 . 0 . 0 . 0 / 0 0 . 0 . 0 . 0 / 0 ↑は“iptables -t nat -L -n -v” コマンドをちょい整形したやつの⼀部です

Slide 60

Slide 60 text

ざっくりだけどこの流れのようにPodにパケットが届きそうなのが確認できた

Slide 61

Slide 61 text

その他kube-proxyで設定されるiptables

Slide 62

Slide 62 text

natテーブル νΣΠϯ໊ δϟϯϓݩ આ໌ KUBE-SERVICES PREROUTING, OUTPUT ‧PREROUTINGなどで⾏うKubernetesのNAT処理の 
 エントリーポイント KUBE-POSTROUTING POSTROUTING ‧KUBE-MARK-MASQで設定したマークが無いパケットなら 
 何もしない 
 ‧マークがあれば、そのマークを消した上で 
 MASQUERADEチェインでIPマスカレード(SNAT)を⾏う KUBE-MARK-MASQ KUBE-SVC-XXX, KUBE-EXT-XXX, KUBE-SEP-XXX, ‧Podから通信を⾏う際にジャンプされる 
 ‧MARKチェインを使⽤してパケットに”0x 4 0 0 0 ”の 
 マークを付ける 
 ‧このマークはKUBE-POSTROUTINGでIPマスカレードを 
 するかの判定のために利⽤される KUBE-NODEPORTS KUBE-SERVICES ‧NodePortのためのノードへのアクセス処理⽤ 
 ‧更にKUBE-EXT-XXXへのジャンプしてServiceにつなげる 
 ‧NodePort⽤のポートへのアクセスかのチェックを⾏う KUBE-PROXY-CANARY 無し ‧natテーブルがkube-proxy外から削除されたかどうかを検出 するために作成されるチェイン 
 ‧そのためこのチェインを使ったnat処理などは特にされない ※ 動作検証したものとソースコードの実装からの解説が混ざってます

Slide 63

Slide 63 text

natテーブル νΣΠϯ໊ δϟϯϓݩ આ໌ KUBE-SVC-XXX KUBE-SERVICES, KUBE-EXT-XXX ‧KUBE-SERVICES, KUBE-EXT-XXXからジャンプされる ‧ここから更に各Pod IPにDNATを⾏うKUBE-SEP-XXXへと 
 ジャンプする 
 ‧statistic mode random probabilityを使⽤して利⽤する 
 KUBE-SEP-XXXをランダムに振り分ける KUBE-EXT-XXX KUBE-NODEPORTS, KUBE-SERVICES ‧NodePortのためのノードアクセスの際にKUBE-NODEPORTS からジャンプしてくる 
 ‧また、externalPsを使⽤してる場合はKUBE-SERVICESから 
 ジャンプしてくる 
 ‧ここから更にKUBE-SVC-XXXにジャンプすることでServiceに 
 接続できるようにする KUBE-SEP-XXX KUBE-SVC-XXX ‧KUBE-SVC-XXXからジャンプされる 
 ‧このチェインに紐づくPod IPに対してDNATを⾏う KUBE-SVL-XXX KUBE-SERVICES ‧Serviceでspec.internalTra ff i cPolicy: Localを設定したときに 設定される 
 ‧KUBE-SVC-XXXの代わりにKUBE-SVL-XXXが設定される 
 ‧KUBE-SVC-XXXと違いローカルにいるPodにのみ 
 トラフィックを流す KUBE-FW-XXX KUBE-SERVICES ‧KUBE-EXT-XXXにジャンプするNATルールを設定する 
 ‧ Serviceでtype: LoadBalancerを利⽤していて、 spec.loadBalancerTra ffi cChainの設定時のみ 
 チェインが設定されるよう ※ 動作検証したものとソースコードの実装からの解説が混ざってます

Slide 64

Slide 64 text

fi lterテーブル νΣΠϯ໊ δϟϯϓݩ આ໌ KUBE-SERVICES FORWARD, OUTPUT ‧設定したServiceがEndpointを持たない場合にDROPもしくは REJECTを⾏う設定が追加される KUBE-EXTERNAL- SERVICES INPUT, FORWARD ‧Endpointが無いケースなどにREJECTやDROPが 
 設定されるよう KUBE-NODEPORTS INPUT ‧ Serviceでtype: LoadBalancerを利⽤していて、 
 .specexternalTra ffi cPolicy: Localを指定していて、 
 かつ.spec.healthCheckNodePortを指定している場合に 
 指定のポートからのパケットをACCEPTするよう KUBE-FORWARD FORWARD ‧FORWARDの際”ctstate INVALID”なパケットはDROPする ‧KUBE-MARK-MASQで設定される”0x 4 0 0 0 ”マークがあれば ACCEPTする 
 ‧”ctstate RELATED,ESTABLISHED”であればACCEPTする KUBE-PROXY- FIREWALL INPUT, FORWARD, OUTPUT ‧Serviceでtype: LoadBalancerを利⽤していて、 
 .spec.loadBalancerIPStringsを設定している場合のDROP設定を ⾏うよう KUBE-FIREWALL INPUT, OUTPUT ‧外部から127.0.0.0/8(ループバックアドレス)への 
 アクセスを⾏うパケットをDROPする KUBE-PROXY-CANARY 無し ‧ fi lterテーブルがkube-proxy外から削除されたかどうかを検出 するために作成されるチェイン 
 ‧そのためこのチェインを使った fi lter処理などは特にされない ※ 動作検証したものとソースコードの実装からの解説が混ざってます

Slide 65

Slide 65 text

mangleテーブル νΣΠϯ໊ δϟϯϓݩ આ໌ KUBE-PROXY-CANARY 無し ‧mangleテーブルがkube-proxy外から削除されたかどうかを検 出するために作成されるチェイン 
 ‧そのためこのチェインを使った処理などは特にされない 
 ‧ちなみにkube-proxyは他でmangleテーブルにチェインを設定 しないので、これはいらないんじゃないかという 
 気がするんだけどどうなんでしょう? ※ 動作検証したものとソースコードの実装からの解説が混ざってます

Slide 66

Slide 66 text

まとめ

Slide 67

Slide 67 text

まとめ ▶ kube-proxyのアーキテクチャとiptablesモードの際にkube-proxyが設定する 
 iptablesの設定について解説しました ▶ ちゃんとiptablesについて調べたのはこれが初めてだったので勉強になりました 
 (kube-proxyが⾏うiptablesの設定の概要は知ってましたが、改めてコード読んだり 
 動作確認してみて思ったんですけどiptablesっていろんなことできるんですね) ▶ 僕みたいにネットワークに詳しく無い⼈には勉強の取っ掛かりになるのでオススメです ▶ kube-proxyのコード読んだり動作検証した際のメモもあるので良ければ⾒てください

Slide 68

Slide 68 text

参考資料 ▶ https://github.com/kubernetes/kubernetes/tree/v 1 . 2 8 . 2 ▶ https://speakerdeck.com/ryusa/servicewotazunete 3 0 0 0 xing- kuberneteskodorideingufalselu ▶ https://qiita.com/Tocyuki/items/ 6 d 9 0 a 1 ec 4 dd 8 e 9 9 1 a 1 ce ▶ https://oxynotes.com/?p= 6 3 6 1 # 5 ▶ https://atmarkit.itmedia.co.jp/ait/articles/ 1 0 0 2 / 0 9 /news 1 1 9 .html ▶ https://hana-shin.hatenablog.com/entry/ 2 0 2 2 / 0 6 / 2 1 / 2 1 5 7 5 7 ▶ https://qiita.com/syui/items/ 2 7 0 2 0 b 9 7 0 7 7 5 a 0 c 5 0 8 ba ▶ https://www.digitalocean.com/community/tutorials/iptables-essentials-common- fi rewall- rules-and-commands ▶ https://www.asahi-net.or.jp/~aa 4 t-nngk/ipttut/output/explicitmatches.html ▶ https://github.com/torvalds/linux/blob/master/Documentation/networking/nf_conntrack- sysctl.rst ▶ https://tech-blog.rakus.co.jp/entry/ 2 0 2 2 0 3 0 1 /iptables ▶ https://linuxjm.osdn.jp/html/iptables/man 8 /iptables-extensions. 8 .html ▶ https://man.archlinux.org/man/conntrack. 8 .en ▶ https://nomeu.net/ 8 3 8 0 / ▶ https://knowledge.sakura.ad.jp/ 4 0 4 8 / ▶ https://docs.openshift.com/container-platform/ 4 . 1 0 /rest_api/network_apis/service- v 1 .html ▶ https://stackover fl ow.com/questions/ 7 5 8 3 5 1 6 9 /kubernetes-loadbalancer-how-does- healthchecknodeport-work ▶ https://github.com/kubernetes/kubernetes/pull/ 8 1 5 1 7 /commits/ 3 9 4 8 f 1 6 ff 4 0 6 0 9 5 5 b 7 f 2 5 d 2 6 d 2 6 1 b 9 9 5 8 9 9 6 3 ade ▶ https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ #preserving-the-client-source-ip ▶ https://kubernetes.io/docs/concepts/services-networking/service-tra ff i c-policy/ ▶ https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/ ▶ https://hyoublog.com/ 2 0 2 0 / 0 5 / 2 0 /kubernetes-externalip-service/ ▶ https://qiita.com/dingtianhongjie/items/ 8 f 3 c 3 2 0 c 4 eb 5 cf 2 5 d 9 de ▶ https://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/loopback-address-interface/ ▶ https://kubernetes.io/docs/reference/networking/virtual-ips/ ▶ https://kubernetes.io/docs/concepts/services-networking/service/ ▶ https://kubernetes.io/ja/docs/concepts/services-networking/connect-applications-service/ ▶ https://knowledge.sakura.ad.jp/ 2 2 6 3 6 / ▶ https://net fi lter.org/index.html ▶ https://madomadox.hatenablog.com/entry/ 2 0 2 1 / 0 1 / 0 3 / 1 9 0 7 3 0 ▶ https://qiita.com/bashaway/items/e 4 0 5 d 5 9 d 9 2 6 7 0 fbc 5 3 4 1 ▶ https://www.digitalocean.com/community/tutorials/a-deep-dive-into-iptables-and- net fi lter-architecture ▶ https://tech-blog.rakus.co.jp/entry/ 2 0 2 2 0 3 0 1 /iptables ▶ https://www.asahi-net.or.jp/~aa 4 t-nngk/ipttut/output/explicitmatches.html ▶ https://eng-entrance.com/linux- fi rewall ▶ https://github.com/kubernetes/kubernetes/issues/ 3 7 9 3 2 ▶ https://github.com/aojea/kindnet?tab=readme-ov- fi le#kindnet-components ▶ https://github.com/aojea/kindnet/blob/ 3 5 d 8 3 4 8 8 ea 2 b 5 ef 1 8 3 c 5 5 a 4 c 7 a 1 6 f 4 4 5 9 4 9 0 8 9 ae/ cmd/kindnetd/routes.go#L 2 7 -L 5 3

Slide 69

Slide 69 text

画像引⽤元 ▶ https://github.com/kubernetes/community/tree/master/icons ▶ https://github.com/kubernetes/kubernetes/tree/master/logo ▶ https://github.com/cncf/artwork/tree/master/projects/kubernetes ▶ https://github.com/kubernetes/kubeadm/tree/main/logos

Slide 70

Slide 70 text

コードリーディングメモ ▶ https://zenn.dev/bells 1 7 /scraps/ 5 e 4 1 da 5 9 8 a 8 2 6 6 ▶ コード読んだり動作検証したりのメモ⽤なのできれいに情報整理 できてるわけじゃないけどコードの中⾝読んでいきたい場合は 
 参考になるかも

Slide 71

Slide 71 text

Thanks / Question? ▶ @bells 1 7 ▶ Slide: https://speakerdeck.com/bells 1 7 ▶ @bells 1 7 _