Upgrade to Pro — share decks privately, control downloads, hide ads and more …

設計Kubernetes Controller與CRD的實踐 - 以網路為例

設計Kubernetes Controller與CRD的實踐 - 以網路為例

淺談Kubernetes Controller與CRD的一些設計思考思路,並且使用一個簡單設計的Network Controller來做為範例

使用一些既有的Kubernetes Controller與CRD的時候,都會思考一下為什麼這兩個CRD是分開的,而這些卻沒有分離?甚至還會覺得分開設定很難用嗎?這個議程會簡單講述一些Controller設計上面的一些困難點,而拆分CRD如何幫助Controller設計。使用設計網路Controller做為一個範例來簡單比較幾種設計上的差異與使用。

Date Huang

August 01, 2023
Tweet

More Decks by Date Huang

Other Decks in Programming

Transcript

  1. Agenda • 試著設計一個Kubernetes Network Controller ◦ 以補足Bridge CNI的需求為範例 ◦ 做CRDs的分析與設計

    • 比較一下其他網路實現的差異 ◦ Nmstate.io • 順便比較一下其他種類Kubernetes Controller常見的設計與做法 ◦ Kubevirt
  2. 情境 • Bridge CNI還需要部份的手動設定,才能讓整個Bridge Network 可以正常運作 ◦ 例如說,需要手動建立Bridge,然後手動設定一個對外的介 面讓網路通行 •

    你可能會有多種的網路型態都用Bridge CNI來實現 ◦ 例如說VLAN Bridge、VXLAN Overlay Network等等 • 這邊我們用Kubernetes + Kubevirt做VM Cluster來探討網路需求
  3. 最開始 apiVersion: kvnet.kojuro.date/v1alpha1 kind: Bridge metadata: name: br0 spec: vlanFiltering:

    true uplink: mode: active-backup nics: - eth0 - eth1 Node1 Bridge Controller eth0 eth1 bond0 br0 Node2 Bridge Controller eth0 eth1 bond0 br0 Node3 Bridge Controller eth0 eth1 bond0 br0
  4. 最開始 apiVersion: kvnet.kojuro.date/v1alpha1 kind: Bridge metadata: name: br0 spec: vlanFiltering:

    true uplink: mode: active-backup nics: - eth0 - eth1 Node1 Bridge Controller eth0 eth1 bond0 br0 Node2 Bridge Controller eth0 eth1 bond0 br0 Node3 Bridge Controller eth0 eth1 bond0 br0 Watch Configure
  5. 拆出每個節點 • 因為不同節點可能會有不同設定,所以要把Bridge CRD做一層拆 解 ◦ 例如說Group A只有br0,或是Group B只有br1等等的 ◦

    或是Group A跟Group B都要br0,但是對外的網路介面名稱 不同 • 並使用Node Selector來選擇節點 ◦ 透過Label來選擇特定的節點 ◦ 例如說:kubernetes.io/arch: amd64
  6. Operator-SDK Reconcile Example func (r *MemcachedReconciler) Reconcile(ctx context.Context, req ctrl.Request)

    (ctrl.Result, error) { _ = context.Background() ... // Lookup the Memcached instance for this reconcile request memcached := &cachev1alpha1.Memcached{} err := r.Get(ctx, req.NamespacedName, memcached) ... }
  7. 拆出每個節點 • 重新設計資料結構成兩個部分 • BridgeConfig ◦ 負責選擇節點,並新增/更新/移除Bridge CR ◦ 紀錄Bridge的樣板

    ◦ 角色類似於DaemonSet • Bridge ◦ 實際上執行新增/更新/移除Linux上的bridge ◦ 實際紀錄Bridge的屬性跟設定 ◦ 角色類似於Pod
  8. 拆出每個節點 apiVersion: kvnet.kojuro.date/v1alpha1 kind: BridgeConfig metadata: name: br0-group-a spec: nodeSelector:

    matchLabels: kvnet.kojuro.date/group: GroupA bridgeName: br0 template: spec: vlanFiltering: true uplink: mode: active-backup nics: - eth0 apiVersion: kvnet.kojuro.date/v1alpha1 kind: Bridge metadata: labels: bridgeconfig: br0-group-a name: node1.br0 spec: vlanFiltering: true uplink: mode: active-backup nics: - eth0 --- apiVersion: kvnet.kojuro.date/v1alpha1 kind: Bridge metadata: labels: bridgeconfig: br0-group-a name: node2.br0 spec: vlanFiltering: true uplink: mode: active-backup nics: - eth0 Create Bridge Spec from Template
  9. Node1 Bridge Controller eth0 eth1 bond0 br0 Node2 Bridge Controller

    eth0 eth1 bond0 br0 Node3 Bridge Controller eth0 eth1 BridgeConfig Con BridgeConfig br0-group-a Bridge node1.br0 Bridge node2.br0 Check Create 2 Bridges
  10. Node1 Bridge Controller eth0 eth1 bond0 br0 Node2 Bridge Controller

    eth0 eth1 bond0 br0 Node3 Bridge Controller eth0 eth1 BridgeConfig Con BridgeConfig br0-group-a Bridge node1.br0 Bridge node2.br0 Get Bridge for Node1 Create
  11. 設計UplinkConfig & Uplink • UplinkConfig ◦ 負責選擇節點,並新增/更新/移除Uplink CR ◦ 紀錄Uplink的樣板

    • Uplink ◦ 實際上執行新增/更新/移除Linux上的Bond ◦ 實際紀錄Bonding的屬性跟設定 • BridgeConfig & Bridge也需要移除跟Uplink相關的欄位
  12. 修正BridgeConfig & Bridge apiVersion: kvnet.kojuro.date/v1alpha1 kind: BridgeConfig metadata: name: br0-group-a

    spec: nodeSelector: matchLabels: kvnet.kojuro.date/group: GroupA bridgeName: br0 template: spec: vlanFiltering: true apiVersion: kvnet.kojuro.date/v1alpha1 kind: Bridge metadata: labels: bridgeconfig: br0-group-a name: node1.br0 spec: vlanFiltering: true --- apiVersion: kvnet.kojuro.date/v1alpha1 kind: Bridge metadata: labels: bridgeconfig: br0-group-a name: node2.br0 spec: vlanFiltering: true
  13. UplinkConfig & Uplink apiVersion: kvnet.kojuro.date/v1alpha1 kind: UplinkConfig metadata: name: bond0-group-a

    spec: nodeSelector: matchLabels: kvnet.kojuro.date/group: GroupA bondName: bond0 template: spec: master: br0 mode: active-backup nics: - eth0 apiVersion: kvnet.kojuro.date/v1alpha1 kind: Uplink metadata: labels: uplinkconfig: bond0-group-a name: node1.bond0 spec: master: br0 mode: active-backup nics: - eth0 --- apiVersion: kvnet.kojuro.date/v1alpha1 kind: Uplink metadata: labels: uplinkconfig: bond0-group-a name: node2.bond0 spec: master: br0 mode: active-backup nics: - eth0
  14. Node1 Bridge Controller eth0 eth1 bond0 br0 Node2 Bridge Controller

    eth0 eth1 bond0 br0 Node3 Bridge Controller eth0 eth1 BridgeConfig Ctl BridgeConfig br0-group-a Bridge node1.br0 Bridge node2.br0 Uplink Controller UplinkConfig Ctl UplinkConfig bond0-group-a Uplink node1.bond0 Uplink node2.bond0 Uplink Controller Uplink Controller
  15. 使用者體驗 • 我們回頭分析一下使用者體驗 • 使用者可以做更多形式且彈性的設定 ◦ 因為設定都是獨立存在 • 使用者如果希望提供給Kubevirt VM使用的網路,需要:

    ◦ 新增BridgeConfig ◦ 新增UplinkConfig • 使用者設定方面變的比較複雜一些 ◦ 這時可以考慮提供WebUI Wizard或是CLI等等的方式,引導 使用者作出完整設定
  16. 設計模式 • 在這個設計模式下,擴充VXLAN的設計基本上也可以參照Uplink 設計出來 • 檢視CRDs欄位的設計 ◦ 將CRDs內的欄位關聯拆解 ◦ 避免多個Controller需要監看與覆寫同一CRD

    • 需考量Kubernetes Controller的觸發模式與Reconcile執行方式 ◦ 例如說:不能在Reconcile裡面sleep等待,會直接卡住整個 workqueue流程
  17. VXLAN apiVersion: kvnet.kojuro.date/v1alpha1 kind: VxlanConfig metadata: name: vxlan-group-a spec: nodeSelector:

    matchLabels: kvnet.kojuro.date/group: GroupA Vxlaname: vxlan10 template: spec: vxlanId: 10 master: vxbr10 apiVersion: kvnet.kojuro.date/v1alpha1 kind: Vxlan metadata: labels: vxlanconfig: vxlan-group-a name: node1.vxlan10 spec: vxlanId: 10 master: vxbr10 --- apiVersion: kvnet.kojuro.date/v1alpha1 kind: Vxlan metadata: labels: vxlanconfig: vxlan-group-a name: node2.vxlan10 spec: vxlanId: 10 master: vxbr10
  18. 設計模式 • 相較最初版的設計: ◦ 可以針對不同節點做不同設定 ◦ 每個獨立元件分離,皆可獨立使用 ◦ 新增元件的複雜度下降 ◦

    每一個CRD與Controller的責任範圍就限縮在該元件本身, 程式碼複雜度會下降,除錯也會相對容易
  19. Nmstate.io Example apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: detach-bridge-port-and-restore-eth spec:

    desiredState: interfaces: - name: br1 type: linux-bridge state: absent - name: eth1 type: ethernet state: up ipv4: dhcp: true enabled: true
  20. 分析Nmstate.io • 直接依賴NetworkManager(NM)來管理所有網路狀態 ◦ 對Nmstate.io Controller來說,只負責推送目前期望的設定 給NetworkManager,由NM來負責新增移除設定 ◦ 剩下的部分,Nmstate.io Controller一律不管

    • 一份設定檔案可以設定多個網路介面 ◦ 因為先前狀態與目前狀態之間的差異,全部由 NetworkManager以及Nmstatectl管理,所以不需要透過 CRDs來儲存或是管理相關需要清理的狀態 ◦ 所以一份設定檔並不會造成問題
  21. Nmstate.io Code • Reconcile ◦ https://github.com/nmstate/kubernetes-nmstate/blob/8293b460d92f2944c76c62287354e545 80ae0485/controllers/handler/nodenetworkconfigurationpolicy_controller.go#L226 • Push Network

    Config to NetworkManager ◦ https://github.com/nmstate/kubernetes-nmstate/blob/8293b460d92f2944c76c62287354e545 80ae0485/pkg/client/client.go#L152
  22. Kubernetes Controller主流做法 • Config-based Controller ◦ Nmstate.io ◦ Kubevirt •

    All on Kuberbetes Controller ◦ 我開頭的範例設計 kvnet ◦ Kube-ovn
  23. Kubernetes Controller主流做法 • Config-based Controller ◦ 權責分離,只負責推設定,其他部分由外部軟體負責處置 ◦ 分開維護,也比較容易抓錯誤的落點 ◦

    需要確保SSOT原則 • All on Kuberbetes Controller ◦ 把CRDs當作一種資料庫來處理,可能需要部份正規化 ◦ 所有項目依賴Controller Reconcile機制 ◦ 複雜度相對較高
  24. Ref • https://github.com/nmstate/kubernetes-nmstate/blob/main/pkg/client/client.go#L152 • The Kubernetes NMState project • KubeVirt

    源码阅读(二):virt-handler 源码解读 • Controller reconcile function | Kube by Example