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

GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

GKE/Kubernetes の Service はどう動いているのか

株式会社アカツキ@apstndb

Page 2: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

自己紹介

● 現職の前はニート

○ クラウドもインフラも未経験

● AWS 中心の企業の新規事業プロジェクトに参加(2016/6)○ GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go)

● 世界で70人目の Google 公認プロフェッショナルクラウドアー

キテクトに(2017/2)

Page 3: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

apstndb

● 皆さんご存知 OSI 7 階層モデル

○ アプリケーション層

○ プレゼンテーション層

○ セッション層

○ トランスポート層

○ ネットワーク層

○ データリンク層

○ 物理層

● 今回はネについて重点的にやります

Page 4: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

経緯

● 自分の Kubernetes クラスタのネットワーク周りどう動いているか説

明できますか?

● Slack で説明しようとして理解していないことに気付く

Page 5: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

経緯

● 分からないまま運用するのは怖い

● というわけで調べた

○ 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

Page 6: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

目的

● 公式に説明されているものと検証した内容を両方合わせてよ

り深く理解しよう!

● ※ GCP 以外で動かしている方には自分たちの環境でどこが

違うかとかぜひコメントしていただきたいです!

Page 7: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

Kubernetes の通信

Cluster Networking より

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

LoadBalancer Service)

Page 8: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

Node 内の Pod 間通信

Node 内の仮想ブリッジ cbr0 の先は ARP 解決可能

● Node ←→ Pod, Pod ←→ Pod

Node

eth0

cbr0

vethxx vethyy

pod1 netns pod2 netnseth0eth0

Page 9: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

Node を跨ぐ通信

Kubernetes ネットワークは下記を要求

1. 全 Pod はクラスタ内の全 Pod と直接(NAT なしで)通信可

2. 全 Node はクラスタ内の全 Pod と直接通信可

3. Pod は自分自身の IP アドレスにアクセス可

Node1 Node2

Pod1a

Pod1b

Pod2b

Pod2b

1

2

3

Page 10: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

コンテナネットワークの実装

要件さえ満たせば実装は自由

● トンネリングによるオーバレイネットワーク

○ Flannel とか

● BGP ルーティング

○ Calico● L2, L3 転送

● 実装によっては NetworkPolicy のサポートがある

Page 11: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

GCE/GKE での Node を超えた通信

● Pod への通信

○ Node のインスタンスは canIpForward=true 設定済

■ src が Pod のままパケットを別の Node に送信可

■ NAT 不要

● Pod からの通信

○ GCE ルートで Pod の IP アドレスから Node に転送

■ トンネリング等不要

Page 12: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

GCE/GKE での Node を超えた通信

Node ごとに設定される GCE ルート

node1PodCIDR: 10.76.0.0/24

node2PodCIDR: 10.76.1.0/24

pod1IP: 10.76.0.1

pod2IP: 10.76.1.1

DEST_RANGE NEXT_HOP

10.76.0.0/24 node1

10.76.1.0/24 node2

src:10.76.0.1dst:10.76.1.1

Page 13: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

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

Page 14: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

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:pod1dst:example.com

src:node1-privatedst:example.com

src:node1-publicdst:example.com

NAT

src:example.comdst:node1-public

src:example.comdst:node1-private

src:example.comdst:pod1

① ②③

④⑤⑥

Page 15: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

Service の動作モード

● ClusterIP○ クラスタ内の仮想 IP

● NodePort○ ClusterIP も持つ

○ Node のポートを通して外部からアクセス可能

● LoadBalancer○ NodePort も持つ

○ Service のクラウド LB を自動プロビジョニング

Page 16: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

Service を支えるもの

● Endpoints○ Service のラベルセレクタに当てはまる Pod の IP アドレ

スとポートの対を保持するリソース

● kube-proxy○ Service と Endpoints を watch して各 Node の iptables

のルールを更新○ https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/iptables/

proxier.go

Page 17: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

node2

ClusterIP Service

● Service の ClusterIP へのパケットは Service を構成する Pod に転送(DNAT)

● Connection Tracking(conntrack) により ClusterIP から返ってきて

いるように見える

node1

pod1

src:pod1dst:svc1

src:pod99dst:pod1

iptables

src:pod1dst:pod99

src:svc1dst:pod1

pod99app=target

① ②

③④

Page 18: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

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

(以下略)

Page 19: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

NodePort Service

● Node がクラスタ外からの Service への通信ができるポートを

開く

● はじめにアクセスした Node に Pod が無くても中継

Page 20: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

node2

NodePort Service

node1iptables

src:clientdst:node1

pod99app=target

internet

src:node1dst:pod99

src:pod99dst:node1

src:node1dst:client

各 Node の NodePort 宛のパケットは

● 構成する Pod に DNAT● 経路を逆に戻れるように SNAT

Page 21: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

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

Page 22: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

node2

LoadBalancer Service

node1iptables

src:clientdst:external

pod99app=target

Network LB

src:node1dst:pod99

src:pod99dst:node1

src:externaldst:client

● GCE Network LB(Maglev) は DSR(Direct Server Return)○ 非 Proxy ○ iptables に渡る LB の外部 IP アドレスで振り分け

src:clientdst:external

Internet①

転送ルールターゲットプール

Page 23: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

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

Page 24: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

LoadBalancer Service

● GCE では NodePort も割り当てられるが使わない

○ LB が Proxy や NAT として動作する環境で使われる

● クラスタ内で中継されることの弊害も

○ ホップ増によるコスト

○ クライアントの IP アドレスが取れない

○ 回避する場合は OnlyLocal■ 正しく使わないと Node の負荷に偏り

Page 25: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

まとめ

● GKE も Kubernetes も魔法ではない

○ Linux, IaaS, ネットワークの知識があれば説明で

きる

● 環境ごとに違うものと同じものを認識してコミュニティ

の壁を壊そう

Page 26: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

余談 - プライベートネットワークから 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

Page 27: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

余談 - クラスタ外 GCE からの ClusterIP への接続

● ClusterIP への GCE ルートさえ設定すれば実は可能

● GCE ルートの転送先は固定

○ Node の更新時は注意

● 高価な GCE 転送ルールを使わずにクラスタ内通信で VIP を使いたいなら…

Page 28: GKE/Kubernetes の Service はどう動いているのか...GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go) 世界で70人目の Google 公認プロフェッショナルクラウドアー

We are hiring!