Slide 1

Slide 1 text

拡張性の高い CNI プラグイン Coil v2 の紹介 サイボウズ株式会社 山本泰宇 @ymmt2005 1 Kubernetes Meetup Tokyo #35

Slide 2

Slide 2 text

About me 2 ▌@ymmt2005 ▌サイボウズで Neco プロジェクトを指揮 ⚫Kubernetes ネイティブなデータセンター ⚫ネットワークやストレージを k8s 上に実装 Kubernetes Meetup Tokyo #35

Slide 3

Slide 3 text

Agenda 3 ▌Kubernetes Network の基礎と実装 ▌サイボウズにおける組み合わせ実例 ▌Coil v2 ⚫機能および実装 ⚫デモ Kubernetes Meetup Tokyo #35

Slide 4

Slide 4 text

Kubernetes Network の基礎 4 Kubernetes Meetup Tokyo #35

Slide 5

Slide 5 text

The Kubernetes network model 5 ▌3つの条件を満たす実装なら何でもよい ⚫ Pods on a node can communicate with all pods on all nodes without NAT ⚫ Agents on a node (e.g. system daemons, kubelet) can communicate with all pods on that node ⚫ Pods in the host network of a node can communicate with all pods on all nodes without NAT ▌実装次第なもの ⚫IP アドレスの割り当て方式 ⚫Pod と Node の通信方式 ⚫ルーティング方式 ⚫外部ネットワークとの通信方式 Kubernetes Meetup Tokyo #35

Slide 6

Slide 6 text

Kubernetesのネットワーク機能 6 ▌Pod 間通信 ▌NetworkPolicy ▌Service (UDP/TCP LoadBalancer) ▌Ingress (HTTP LoadBalancer) Kubernetes Meetup Tokyo #35 あれ、Egress は・・? ☞標準仕様はありません

Slide 7

Slide 7 text

Container Networking Interface (CNI) 7 ▌ネットワーク機能をプラグインする規格 ▌インタフェースはコマンド呼び出し ⚫kubelet や containerd がプラグインを直接実行 ▌複数のプラグインを数珠繋ぎできる Kubernetes Meetup Tokyo #35

Slide 8

Slide 8 text

CNI の設定例 (JSON) 8 { "cniVersion": "0.4.0", "name": "k8s-pod-network", "plugins": [ { "type": "coil", }, { "type": "tuning", "mtu": 1400 }, { "type": "bandwidth", "capabilities": {"bandwidth": true} } ] } /opt/cni/bin にあるコマンド名 Pod のアノテーション で bandwidth 制御 apiVersion: v1 kind: Pod metadata: annotations: kubernetes.io/ingress-bandwidth: 1M kubernetes.io/egress-bandwidth: 1M ... Kubernetes Meetup Tokyo #35

Slide 9

Slide 9 text

代表的な実装方式 9 Kubernetes Meetup Tokyo #35

Slide 10

Slide 10 text

IP アドレスの割り当て方式 (IPAM) 10 ▌各ノードに Pod 用サブネットを割り当て ⚫node.spec.podCIDR フィールドで指定 ⚫kube-controller-manager に割り当てさせることも可能 ▌アドレスプール方式 ⚫用途に応じたプールを複数定義 ⚫グローバル IP アドレスを一部 Pod に割り当てる等 Kubernetes Meetup Tokyo #35 Flannel 他 Calico: Node 単位 Coil: Namespace 単位

Slide 11

Slide 11 text

Pod と Node の通信方式 11 ▌Linux Bridge ⚫node.spec.podCIDR の通信をブリッジ内で行う ⚫Node やブロードキャスト用アドレスが必要 ▌Point-to-point 方式 ⚫Veth 両端にリンクローカルアドレスを付与 ⚫Veth ひとつひとつをルーティングテーブルに登録 Kubernetes Meetup Tokyo #35 ちょっともったいない

Slide 12

Slide 12 text

Bridge vs Point-to-Point 12 Kubernetes Meetup Tokyo #35 Node bridge Pod Pod Pod 10.1.2.0/24 10.1.2.1 10.1.2.2 10.1.2.3 10.1.2.4 Bridge は .0, .1, .255 が使えない 10.1.2.2 → Veth1 10.1.2.3 → Veth2 10.1.2.4 → Veth3 Pod Pod Pod 10.1.2.2 10.1.2.3 10.1.2.4 10.1.2.0/24 のアドレスすべて利用できる 169.254.1.1 169.254.1.1 169.254.1.1 169.254.1.2 169.254.1.2 169.254.1.2 Veth1 Veth2 Veth3

Slide 13

Slide 13 text

ルーティング方式 13 ▌オーバーレイネットワーク ⚫Pod 間通信のパケットを IPIP などでカプセル化 ⚫ノード間通信ができる環境ならどこでも動作 ▌BGP 等で経路広告 ⚫各ノードに割り当てられた Pod アドレスを広告 ⚫既存ネットワークにうまく適合させる必要がある Kubernetes Meetup Tokyo #35 お手軽だけど遅め

Slide 14

Slide 14 text

外部ネットワークへの通信 14 ▌Node NAT 方式 ⚫外部向けのパケットを Node のアドレスでNAT ⚫ノードが外部に通信できることが前提 ▌Gateway 方式 ⚫特定の Pod or Node を出口として経由 ⚫monzo/egress-operator や Calico Enterprise 等 Kubernetes Meetup Tokyo #35

Slide 15

Slide 15 text

NetworkPolicy 15 ▌Calico ⚫Policy-only モードで他のプラグインに組込可能 ⚫Veth の命名を Calico に合わせる必要あり ▌Cilium ⚫CNI の機能で Veth を使うプラグインに組込可能 Kubernetes Meetup Tokyo #35

Slide 16

Slide 16 text

Service type=LoadBalancer 16 ▌マネージドな場合、IaaS ベンダーが提供 ▌オンプレミスの場合選択肢は多くない ⚫自前で実装を頑張る ⚫MetalLB ⚫L2 mode: 特定 Node にトラフィック管理を任せる ⚫L3 mode: BGP で経路を広告 Kubernetes Meetup Tokyo #35 ロードバランスしてない…

Slide 17

Slide 17 text

PureLB 17 ▌つい最近発表された MetalLB 派生実装 ⚫ https://purelb.gitlab.io/docs/ ▌BGP を自力で話さないのが違い ⚫任意のルーティングソフトウェアと連携 ⚫Calico と併用可能 Kubernetes Meetup Tokyo #35

Slide 18

Slide 18 text

サイボウズにおける組み合わせ実例 18 Kubernetes Meetup Tokyo #35

Slide 19

Slide 19 text

ネットワーク環境 19 Kubernetes Meetup Tokyo #35 DC3 DC1 DC2 インターネット BGPで制御されたノードネットワーク 閉域網

Slide 20

Slide 20 text

実現したいこと 20 ▌既設 BGP ネットワークとの接続 ▌グローバル IP アドレスを動的に管理 ▌NetworkPolicy は必須 ▌LoadBalancer も必須 ▌Pod が外部ネットワークと自由に接続 Kubernetes Meetup Tokyo #35

Slide 21

Slide 21 text

Calico を使いたかったが… 21 ▌BIRD (BGPデーモン)が組み込まれていて 既設ネットワークとうまく接続できない ▌MetalLB と解決が困難な接続問題がある ⚫Issues with Calico https://metallb.universe.tf/configuration/calico/ Kubernetes Meetup Tokyo #35

Slide 22

Slide 22 text

Coil を開発して解決 22 ▌任意のルーティングソフトウェアと連携 ▌Calico, Cilium の NetworkPolicy と併用可能 ▌MetalLB と併用可能 Kubernetes Meetup Tokyo #35

Slide 23

Slide 23 text

実際の組み合わせ 23 • NetworkPolicy 実装 • LoadBalancer実装 • ノード間ルーティング • IPAM, ノード内ルーティング • 外部への NAT 接続 Coil BIRD (BGP) Calico MetalLB Kubernetes Meetup Tokyo #35

Slide 24

Slide 24 text

Coil v2 24 Kubernetes Meetup Tokyo #35

Slide 25

Slide 25 text

特徴 25 ▌効率的なアドレス管理 ▌任意のルーティングソフトウェアと連携 ▌IPv4/v6/デュアルスタックに対応 ▌カスタムリソースで制御 ▌Opt-in 方式の Egress NAT Kubernetes Meetup Tokyo #35

Slide 26

Slide 26 text

システム図 26 Kubernetes Meetup Tokyo #35

Slide 27

Slide 27 text

余談:Coil v1 → v2 27 ▌Coil v1 は k8s に詳しくない頃設計・開発 ⚫etcd に直接データ保存 ⚫専用 CLI による設定操作 ⚫Prometheus メトリクスなし ⚫CNI プラグインで直接ネットワーク操作 ▌Egress NAT 開発を期に v2 として全面刷新 Kubernetes Meetup Tokyo #35

Slide 28

Slide 28 text

実装詳解 28 Kubernetes Meetup Tokyo #35

Slide 29

Slide 29 text

CNI 処理を gRPC サーバーに委譲 29 ▌CNI はコマンド呼び出し ⚫コマンドは Pod で動かせない → ログが Pod ログとして取れない → メトリクスの収集も困難 ▌コマンドから gRPC サーバーに処理を委譲 ⚫gRPC サーバーは Pod で動作 Kubernetes Meetup Tokyo #35

Slide 30

Slide 30 text

システム図(再掲) 30 Kubernetes Meetup Tokyo #35

Slide 31

Slide 31 text

効率的なアドレス管理 31 ▌AddressPool ⚫アドレスブロック単位でノードに割り当て ⚫最小 1 アドレス単位 ▌Bridge を使わない ⚫1 アドレスも無駄なく利用可能 Kubernetes Meetup Tokyo #35 apiVersion: coil.cybozu.com/v2 kind: AddressPool metadata: name: internet spec: blockSizeBits: 0 subnets: - ipv4: 103.79.13.192/28 ipv6: …

Slide 32

Slide 32 text

プールの指定は Namespace 単位 32 ▌「インターネット用ノード」は不要 ▌ここに Squid pod を置けば、インターネット につながる HTTP Proxy のできあがり Kubernetes Meetup Tokyo #35 apiVersion: v1 kind: Namespace metadata: name: internet-egress annotations: coil.cybozu.com/pool: internet

Slide 33

Slide 33 text

豆知識:CNI における Pod の情報 33 ▌CNI は Kubernetes を前提としていない ⚫Pod の Namespace, Name は仕様にない ▌実際は CNI_ARGS 環境変数で渡される ⚫Kubernetes 用コンテナランタイムはすべて ⚫e.g. K8S_POD_NAMESPACE=test;K8S_POD_NAME=test-pod Kubernetes Meetup Tokyo #35

Slide 34

Slide 34 text

ルーティングソフトウェアとの連携 34 ▌各ノードが持つアドレスブロックを広告する必要がある ⚫Coil はブロックをカーネルのルーティングテーブル 119 に出力 ⚫ルーティングソフトウェアはテーブル 119 をインポートして広告 Kubernetes Meetup Tokyo #35 $ ip route show table 119 10.64.1.64/27 dev lo proto 30 103.79.13.194 dev lo proto 30 $ birdc show route table coiltab Table coiltab: 103.79.13.194/32 unicast [coil 2020-10-16] (10) dev lo 10.64.1.64/27 unicast [coil 2020-10-16] (10) dev lo

Slide 35

Slide 35 text

システム図(再々掲) 35 Kubernetes Meetup Tokyo #35

Slide 36

Slide 36 text

自力ルーティング 36 ▌全ノードが同一 L2 ネットワークにある場合、 Coil は自力でルーティング可能 ▌kind (Kubernetes in Docker) で手軽に動作可能 Kubernetes Meetup Tokyo #35

Slide 37

Slide 37 text

Calico NetworkPolicy 対応 37 ▌Calico は veth の名前を決め打ちしている ⚫同じ命名規則で実装しないと併用できない ▌Cilium は CNI の plugin チェーンを正し く使っており、任意の veth 名で併用可能 Kubernetes Meetup Tokyo #35 func calicoVethName(podName, podNS string) string { sum := sha1.Sum([]byte(fmt.Sprintf("%s.%s", podNS, podName))) return "cali" + hex.EncodeToString(sum[:])[:11] }

Slide 38

Slide 38 text

IPv4/v6/デュアルスタック 38 ▌AddressPool にどれを含めるかで決定 ⚫v4 だけなら v4 シングルスタック ⚫v6 だけなら v6 シングルスタック ⚫v4/v6 両方あればデュアルスタック ▌v4/v6 で機能差なし ▌余談:k8s のデュアルスタック対応は 1.20 で 一部再設計予定(second alpha) Kubernetes Meetup Tokyo #35

Slide 39

Slide 39 text

Opt-in 方式の Egress NAT 39 ▌Egress: 外部ネットワークへの出口を定義 Kubernetes Meetup Tokyo #35 apiVersion: coil.cybozu.com/v2 kind: Egress metadata: namespace: internet name: egress spec: destinations: - 0.0.0.0/0 replicas: 2 apiVersion: coil.cybozu.com/v2 kind: Egress metadata: namespace: domestic-network name: egress spec: destinations: - 172.20.0.0/16 - fd04::/64 replicas: 3

Slide 40

Slide 40 text

Egress から NAT Pod を作成 40 ▌Service で冗長化 Kubernetes Meetup Tokyo #35

Slide 41

Slide 41 text

NAT を利用したい Pod は Opt-in 41 ▌アノテーションで使いたい Egress を指定 Kubernetes Meetup Tokyo #35 apiVersion: v1 kind: Pod metadata: name: nat-client namespace: default annotations: egress.coil.cybozu.com/internet: egress egress.coil.cybozu.com/domestic-network: egress spec: …

Slide 42

Slide 42 text

クライアント Pod → Egress Pod 42 ▌外向けのパケットをそのまま送ると、Egress Pod に届かず捨てられてしまう ▌Egress の宛先ネットワークに送るパケットは、 Foo-over-UDP でトンネルして送る ⚫トンネル方式は色々あるが、Foo-over-UDP は UDP パケットなので Service で冗長化できる Kubernetes Meetup Tokyo #35

Slide 43

Slide 43 text

Foo-over-UDP 43 ▌IP パケットを以下のように加工して送信 ▌受信側で UDP ヘッダを除去 ▌IPIPトンネルデータとして処理 Kubernetes Meetup Tokyo #35 IPヘッダ(外行き) ペイロード IPヘッダ(Egress 行き) IPヘッダ(外行き) ペイロード UDPヘッダ 付加 IPヘッダ(Egress 行き) IPヘッダ(外行き) ペイロード

Slide 44

Slide 44 text

デモ 44 Kubernetes Meetup Tokyo #35

Slide 45

Slide 45 text

デモ内容 45 ▌AddressPool と AddressBlock ▌Squid Pod で外部通信 ▌Egress NAT 機能 ▌coild のログで CNI 動作確認 Kubernetes Meetup Tokyo #35

Slide 46

Slide 46 text

まとめ 46 Kubernetes Meetup Tokyo #35 ▌Coil v2 なら ⚫MetalLB, BIRD, Calico, Cilium と連携可能 ⚫外部ネットワークと簡単に接続 ⚫Kubernetes ネイティブで楽々導入&管理 ▌Check it out! ⚫https://github.com/cybozu-go/coil