Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
GKE/Kubernetes の Service はどう動いているのか
株式会社アカツキ@apstndb
自己紹介
● 現職の前はニート
○ クラウドもインフラも未経験
● AWS 中心の企業の新規事業プロジェクトに参加(2016/6)○ GKE 上で RoR, NodeJS, Elixir/Phoenix(, Go)
● 世界で70人目の Google 公認プロフェッショナルクラウドアー
キテクトに(2017/2)
apstndb
● 皆さんご存知 OSI 7 階層モデル
○ アプリケーション層
○ プレゼンテーション層
○ セッション層
○ トランスポート層
○ ネットワーク層
○ データリンク層
○ 物理層
● 今回はネについて重点的にやります
経緯
● 自分の Kubernetes クラスタのネットワーク周りどう動いているか説
明できますか?
● Slack で説明しようとして理解していないことに気付く
経緯
● 分からないまま運用するのは怖い
● というわけで調べた
○ 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
目的
● 公式に説明されているものと検証した内容を両方合わせてよ
り深く理解しよう!
● ※ GCP 以外で動かしている方には自分たちの環境でどこが
違うかとかぜひコメントしていただきたいです!
Kubernetes の通信
Cluster Networking より
● Pod 内コンテナ間通信(localhost 通信)● Pod の通信(Kubernetes ネットワーク)● Pod から Service への通信(ClusterIP Service)● クラスタ外部から Service への通信(NodePort,
LoadBalancer Service)
Node 内の Pod 間通信
Node 内の仮想ブリッジ cbr0 の先は ARP 解決可能
● Node ←→ Pod, Pod ←→ Pod
Node
eth0
cbr0
vethxx vethyy
pod1 netns pod2 netnseth0eth0
Node を跨ぐ通信
Kubernetes ネットワークは下記を要求
1. 全 Pod はクラスタ内の全 Pod と直接(NAT なしで)通信可
2. 全 Node はクラスタ内の全 Pod と直接通信可
3. Pod は自分自身の IP アドレスにアクセス可
Node1 Node2
Pod1a
Pod1b
Pod2b
Pod2b
1
2
3
コンテナネットワークの実装
要件さえ満たせば実装は自由
● トンネリングによるオーバレイネットワーク
○ Flannel とか
● BGP ルーティング
○ Calico● L2, L3 転送
● 実装によっては NetworkPolicy のサポートがある
GCE/GKE での Node を超えた通信
● Pod への通信
○ Node のインスタンスは canIpForward=true 設定済
■ src が Pod のままパケットを別の Node に送信可
■ NAT 不要
● Pod からの通信
○ GCE ルートで Pod の IP アドレスから Node に転送
■ トンネリング等不要
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
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
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
① ②③
④⑤⑥
Service の動作モード
● ClusterIP○ クラスタ内の仮想 IP
● NodePort○ ClusterIP も持つ
○ Node のポートを通して外部からアクセス可能
● LoadBalancer○ NodePort も持つ
○ Service のクラウド LB を自動プロビジョニング
Service を支えるもの
● Endpoints○ Service のラベルセレクタに当てはまる Pod の IP アドレ
スとポートの対を保持するリソース
● kube-proxy○ Service と Endpoints を watch して各 Node の iptables
のルールを更新○ https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/iptables/
proxier.go
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
① ②
③④
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
(以下略)
NodePort Service
● Node がクラスタ外からの Service への通信ができるポートを
開く
● はじめにアクセスした Node に Pod が無くても中継
node2
NodePort Service
node1iptables
src:clientdst:node1
pod99app=target
internet
src:node1dst:pod99
src:pod99dst:node1
src:node1dst:client
①
②
③
④
各 Node の NodePort 宛のパケットは
● 構成する Pod に DNAT● 経路を逆に戻れるように SNAT
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
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①
転送ルールターゲットプール
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
LoadBalancer Service
● GCE では NodePort も割り当てられるが使わない
○ LB が Proxy や NAT として動作する環境で使われる
● クラスタ内で中継されることの弊害も
○ ホップ増によるコスト
○ クライアントの IP アドレスが取れない
○ 回避する場合は OnlyLocal■ 正しく使わないと Node の負荷に偏り
まとめ
● GKE も Kubernetes も魔法ではない
○ Linux, IaaS, ネットワークの知識があれば説明で
きる
● 環境ごとに違うものと同じものを認識してコミュニティ
の壁を壊そう
余談 - プライベートネットワークから 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
余談 - クラスタ外 GCE からの ClusterIP への接続
● ClusterIP への GCE ルートさえ設定すれば実は可能
● GCE ルートの転送先は固定
○ Node の更新時は注意
● 高価な GCE 転送ルールを使わずにクラスタ内通信で VIP を使いたいなら…
We are hiring!