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

547644032c698592a724b04b67f33d95?s=47 apstndb
April 20, 2017

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

2017/04/20 Kubernetes Meetup Tokyo #4

547644032c698592a724b04b67f33d95?s=128

apstndb

April 20, 2017
Tweet

Transcript

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

  2. 自己紹介 • 現職の前はニート ◦ クラウドもインフラも未経験 • AWS 中心の企業の新規事業プロジェクトに参加(2016/6) ◦ GKE

    上で RoR, NodeJS, Elixir/Phoenix(, Go) • 世界で70人目の Google 公認プロフェッショナルクラウドアー キテクトに(2017/2)
  3. apstndb • 皆さんご存知 OSI 7 階層モデル ◦ アプリケーション層 ◦ プレゼンテーション層

    ◦ セッション層 ◦ トランスポート層 ◦ ネットワーク層 ◦ データリンク層 ◦ 物理層 • 今回はネについて重点的にやります
  4. 経緯 • 自分の Kubernetes クラスタのネットワーク周りどう動いているか説 明できますか? • Slack で説明しようとして理解していないことに気付く

  5. 経緯 • 分からないまま運用するのは怖い • というわけで調べた ◦ 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
  6. 目的 • 公式に説明されているものと検証した内容を両方合わせてよ り深く理解しよう! • ※ GCP 以外で動かしている方には自分たちの環境でどこが 違うかとかぜひコメントしていただきたいです!

  7. Kubernetes の通信 Cluster Networking より • Pod 内コンテナ間通信(localhost 通信) •

    Pod の通信(Kubernetes ネットワーク) • Pod から Service への通信(ClusterIP Service) • クラスタ外部から Service への通信(NodePort, LoadBalancer Service)
  8. Node 内の Pod 間通信 Node 内の仮想ブリッジ cbr0 の先は ARP 解決可能

    • Node ←→ Pod, Pod ←→ Pod Node eth0 cbr0 vethxx vethyy pod1 netns pod2 netns eth0 eth0
  9. Node を跨ぐ通信 Kubernetes ネットワークは下記を要求 1. 全 Pod はクラスタ内の全 Pod と直接(NAT

    なしで)通信可 2. 全 Node はクラスタ内の全 Pod と直接通信可 3. Pod は自分自身の IP アドレスにアクセス可 Node1 Node2 Pod1a Pod1b Pod2b Pod2b 1 2 3
  10. コンテナネットワークの実装 要件さえ満たせば実装は自由 • トンネリングによるオーバレイネットワーク ◦ Flannel とか • BGP ルーティング

    ◦ Calico • L2, L3 転送 • 実装によっては NetworkPolicy のサポートがある
  11. GCE/GKE での Node を超えた通信 • Pod への通信 ◦ Node のインスタンスは

    canIpForward=true 設定済 ▪ src が Pod のままパケットを別の Node に送信可 ▪ NAT 不要 • Pod からの通信 ◦ GCE ルートで Pod の IP アドレスから Node に転送 ▪ トンネリング等不要
  12. 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
  13. 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
  14. 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 ① ② ③ ④ ⑤ ⑥
  15. Service の動作モード • ClusterIP ◦ クラスタ内の仮想 IP • NodePort ◦

    ClusterIP も持つ ◦ Node のポートを通して外部からアクセス可能 • LoadBalancer ◦ NodePort も持つ ◦ Service のクラウド LB を自動プロビジョニング
  16. Service を支えるもの • Endpoints ◦ Service のラベルセレクタに当てはまる Pod の IP

    アドレ スとポートの対を保持するリソース • kube-proxy ◦ Service と Endpoints を watch して各 Node の iptables のルールを更新 ◦ https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/iptables/ proxier.go
  17. 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 ① ② ③ ④
  18. 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 (以下略)
  19. NodePort Service • Node がクラスタ外からの Service への通信ができるポートを 開く • はじめにアクセスした

    Node に Pod が無くても中継
  20. 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
  21. 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
  22. 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 ① 転送ルール ターゲットプー ル
  23. 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
  24. LoadBalancer Service • GCE では NodePort も割り当てられるが使わない ◦ LB が

    Proxy や NAT として動作する環境で使われる • クラスタ内で中継されることの弊害も ◦ ホップ増によるコスト ◦ クライアントの IP アドレスが取れない ◦ 回避する場合は OnlyLocal ▪ 正しく使わないと Node の負荷に偏り
  25. まとめ • GKE も Kubernetes も魔法ではない ◦ Linux, IaaS, ネットワークの知識があれば説明で

    きる • 環境ごとに違うものと同じものを認識してコミュニティ の壁を壊そう
  26. 余談 - プライベートネットワークから 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
  27. 余談 - クラスタ外 GCE からの ClusterIP への接続 • ClusterIP への

    GCE ルートさえ設定すれば実は可能 • GCE ルートの転送先は固定 ◦ Node の更新時は注意 • 高価な GCE 転送ルールを使わずにクラスタ内通信で VIP を 使いたいなら…
  28. We are hiring!