Slide 1

Slide 1 text

GKE/Kubernetes の Service はどう動いているのか 株式会社アカツキ @apstndb

Slide 2

Slide 2 text

自己紹介 ● 現職の前はニート ○ クラウドもインフラも未経験 ● AWS 中心の企業の新規事業プロジェクトに参加(2016/6) ○ GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) ● 世界で70人目の Google 公認プロフェッショナルクラウドアー キテクトに(2017/2)

Slide 3

Slide 3 text

apstndb ● 皆さんご存知 OSI 7 階層モデル ○ アプリケーション層 ○ プレゼンテーション層 ○ セッション層 ○ トランスポート層 ○ ネットワーク層 ○ データリンク層 ○ 物理層 ● 今回はネについて重点的にやります

Slide 4

Slide 4 text

経緯 ● 自分の Kubernetes クラスタのネットワーク周りどう動いているか説 明できますか? ● Slack で説明しようとして理解していないことに気付く

Slide 5

Slide 5 text

経緯 ● 分からないまま運用するのは怖い ● というわけで調べた ○ GKE/Kubernetes でなぜ Pod と通信できるのか ○ http://qiita.com/apstndb/items/9d13230c666db80e74d0 ● Google Cloud Next '17 にて Kubernetes の Tech Lead Tim Hockin から GKE/Kubernetes ネットワークの解説! ○ The ins and outs of networking in Google Container Engine and Kubernetes ○ https://www.youtube.com/watch?v=y2bhV81MfKQ

Slide 6

Slide 6 text

目的 ● 公式に説明されているものと検証した内容を両方合わせてよ り深く理解しよう! ● ※ GCP 以外で動かしている方には自分たちの環境でどこが 違うかとかぜひコメントしていただきたいです!

Slide 7

Slide 7 text

Kubernetes の通信 Cluster Networking より ● Pod 内コンテナ間通信(localhost 通信) ● Pod の通信(Kubernetes ネットワーク) ● Pod から Service への通信(ClusterIP Service) ● クラスタ外部から Service への通信(NodePort, LoadBalancer Service)

Slide 8

Slide 8 text

Node 内の Pod 間通信 Node 内の仮想ブリッジ cbr0 の先は ARP 解決可能 ● Node ←→ Pod, Pod ←→ Pod Node eth0 cbr0 vethxx vethyy pod1 netns pod2 netns eth0 eth0

Slide 9

Slide 9 text

Node を跨ぐ通信 Kubernetes ネットワークは下記を要求 1. 全 Pod はクラスタ内の全 Pod と直接(NAT なしで)通信可 2. 全 Node はクラスタ内の全 Pod と直接通信可 3. Pod は自分自身の IP アドレスにアクセス可 Node1 Node2 Pod1a Pod1b Pod2b Pod2b 1 2 3

Slide 10

Slide 10 text

コンテナネットワークの実装 要件さえ満たせば実装は自由 ● トンネリングによるオーバレイネットワーク ○ Flannel とか ● BGP ルーティング ○ Calico ● L2, L3 転送 ● 実装によっては NetworkPolicy のサポートがある

Slide 11

Slide 11 text

GCE/GKE での Node を超えた通信 ● Pod への通信 ○ Node のインスタンスは canIpForward=true 設定済 ■ src が Pod のままパケットを別の Node に送信可 ■ NAT 不要 ● Pod からの通信 ○ GCE ルートで Pod の IP アドレスから Node に転送 ■ トンネリング等不要

Slide 12

Slide 12 text

GCE/GKE での Node を超えた通信 Node ごとに設定される GCE ルート node1 PodCIDR: 10.76.0.0/24 node2 PodCIDR: 10.76.1.0/24 pod1 IP: 10.76.0.1 pod2 IP: 10.76.1.1 DEST_RANGE NEXT_HOP 10.76.0.0/24 node1 10.76.1.0/24 node2 src:10.76.0.1 dst:10.76.1.1

Slide 13

Slide 13 text

GCE/GKE での Pod からクラスタ外への通信 ● Pod の IP アドレスはプライベート ○ インターネットとの通信不可 ● インターネットあてのパケットは送信元を Node(GCE インスタンス) の IP アドレスに変換 ○ Source NAT(別名 IP マスカレード) -A POSTROUTING ! -d 10.0.0.0/8 -m comment --comment "kubenet: SNAT for outbound traffic from cluster" -m addrtype ! --dst-type LOCAL -j MASQUERADE

Slide 14

Slide 14 text

Pod からクラスタ外への通信 -A POSTROUTING ! -d 10.0.0.0/8 -m comment --comment "kubenet: SNAT for outbound traffic from cluster" -m addrtype ! --dst-type LOCAL -j MASQUERADE node1 pod1 src:pod1 dst:example.com src:node1-private dst:example.com src:node1-public dst:example.com NAT src:example.com dst:node1-public src:example.com dst:node1-private src:example.com dst:pod1 ① ② ③ ④ ⑤ ⑥

Slide 15

Slide 15 text

Service の動作モード ● ClusterIP ○ クラスタ内の仮想 IP ● NodePort ○ ClusterIP も持つ ○ Node のポートを通して外部からアクセス可能 ● LoadBalancer ○ NodePort も持つ ○ Service のクラウド LB を自動プロビジョニング

Slide 16

Slide 16 text

Service を支えるもの ● Endpoints ○ Service のラベルセレクタに当てはまる Pod の IP アドレ スとポートの対を保持するリソース ● kube-proxy ○ Service と Endpoints を watch して各 Node の iptables のルールを更新 ○ https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/iptables/ proxier.go

Slide 17

Slide 17 text

node2 ClusterIP Service ● Service の ClusterIP へのパケットは Service を構成する Pod に 転送(DNAT) ● Connection Tracking(conntrack) により ClusterIP から返ってきて いるように見える node1 pod1 src:pod1 dst:svc1 src:pod99 dst:pod1 iptables src:pod1 dst:pod99 src:svc1 dst:pod1 pod99 app=target ① ② ③ ④

Slide 18

Slide 18 text

ClusterIP Service に連動した iptables ● ClusterIP から Service 個別のルールに振り分け ○ -A KUBE-SERVICES -d 10.79.255.4/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3 ● Service 個別のルールから Endpoints に確率で振り分け ○ -A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-BWZ646KDVNVKXICT ○ -A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-EV2NQKURMPKCP5UI ● Endpoint の IP アドレスに実際に DNAT するルール ○ -A KUBE-SEP-EV2NQKURMPKCP5UI -s 10.76.0.9/32 -m comment --comment "default/hostnames:" -j KUBE-MARK-MASQ ○ -A KUBE-SEP-EV2NQKURMPKCP5UI -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.76.0.9:9376 (以下略)

Slide 19

Slide 19 text

NodePort Service ● Node がクラスタ外からの Service への通信ができるポートを 開く ● はじめにアクセスした Node に Pod が無くても中継

Slide 20

Slide 20 text

node2 NodePort Service node1 iptables src:client dst:node1 pod99 app=target internet src:node1 dst:pod99 src:pod99 dst:node1 src:node1 dst:client ① ② ③ ④ 各 Node の NodePort 宛のパケットは ● 構成する Pod に DNAT ● 経路を逆に戻れるように SNAT

Slide 21

Slide 21 text

NodePort Service に連動した iptables ● # 経路を戻ってこれるよう SNAT ○ -A KUBE-NODEPORTS -p tcp -m comment --comment "default/hostnames:" -m tcp --dport 31358 -j KUBE-MARK-MASQ ● # Service のルールを処理する ○ -A KUBE-NODEPORTS -p tcp -m comment --comment "default/hostnames:" -m tcp --dport 31358 -j KUBE-SVC-NWV5X2332I4OT4T3

Slide 22

Slide 22 text

node2 LoadBalancer Service node1 iptables src:client dst:external pod99 app=target Network LB src:node1 dst:pod99 src:pod99 dst:node1 src:external dst:client ② ③ ④ ⑤ ● GCE Network LB(Maglev) は DSR(Direct Server Return) ○ 非 Proxy ○ iptables に渡る LB の外部 IP アドレスで振り分け src:client dst:external Internet ① 転送ルール ターゲットプー ル

Slide 23

Slide 23 text

LoadBalancer Service に連動した iptables ● ExternalIP = LoadBalancer の IP アドレスは Service に転送 ● -A KUBE-SERVICES -d 104.199.232.159/32 -p tcp -m comment --comment "default/hostnames: loadbalancer IP" -m tcp --dport 80 -j KUBE-FW-NWV5X2332I4OT4T3 ● -A KUBE-FW-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames: loadbalancer IP" -j KUBE-MARK-MASQ ● -A KUBE-FW-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames: loadbalancer IP" -j KUBE-SVC-NWV5X2332I4OT4T3 ● -A KUBE-FW-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames: loadbalancer IP" -j KUBE-MARK-DROP

Slide 24

Slide 24 text

LoadBalancer Service ● GCE では NodePort も割り当てられるが使わない ○ LB が Proxy や NAT として動作する環境で使われる ● クラスタ内で中継されることの弊害も ○ ホップ増によるコスト ○ クライアントの IP アドレスが取れない ○ 回避する場合は OnlyLocal ■ 正しく使わないと Node の負荷に偏り

Slide 25

Slide 25 text

まとめ ● GKE も Kubernetes も魔法ではない ○ Linux, IaaS, ネットワークの知識があれば説明で きる ● 環境ごとに違うものと同じものを認識してコミュニティ の壁を壊そう

Slide 26

Slide 26 text

余談 - プライベートネットワークから Pod への通信 ● 実はプライベートネットワーク内なら GKE クラスタの外との直 接通信も可能 ● > NOTE: This is environment specific. Some environments will not need any masquerading at all. Others, such as GCE, will not allow pod IPs to send traffic to the internet, but have no problem with them inside your GCE Project. ○ from Creating a Custom Cluster from Scratch

Slide 27

Slide 27 text

余談 - クラスタ外 GCE からの ClusterIP への接続 ● ClusterIP への GCE ルートさえ設定すれば実は可能 ● GCE ルートの転送先は固定 ○ Node の更新時は注意 ● 高価な GCE 転送ルールを使わずにクラスタ内通信で VIP を 使いたいなら…

Slide 28

Slide 28 text

We are hiring!