1. <em id="vzzs9"></em>
      <tbody id="vzzs9"></tbody>

    2. <span id="vzzs9"></span>
      <progress id="vzzs9"></progress>
      首頁 運維干貨K8s CNI 插件選型和應用場景探討

      K8s CNI 插件選型和應用場景探討

      運維派隸屬馬哥教育旗下專業運維社區,是國內成立最早的IT運維技術社區,歡迎關注公眾號:yunweipai
      領取學習更多免費Linux云計算、Python、Docker、K8s教程關注公眾號:馬哥linux運維

      本文介紹容器環境常見網絡應用場景及對應場景的 Kubernetes CNI 插件功能實現。幫助搭建和使用云原生環境的小伙伴快速選擇心儀的網絡工具。

      常見網絡插件

      我們在學習容器網絡的時候,肯定都聽說過 Docker 的 bridge 網絡,Vethpair,VxLAN 等術語,從 Docker 到 Kubernetes 后,學習了 Flannel、Calico 等主流網絡插件,分別代表了 Overlay 和 Underlay 的兩種網絡傳輸模式,也是很經典的兩款 CNI 網絡插件。那么,還有哪些好用的 CNI 插件呢 ? 我們看看 CNCF Landscape:

      K8s CNI 插件選型和應用場景探討插圖

      拋去商業版 CNI,此次分享來聊聊幾款熱門開源 CNI 插件,分別為 Kube-OVN、Antrea、Cilium。Kube-OVN 和 Antrea 都是基于 OpenvSwitch 的項目,Cilium 使用 eBPF 這款革命性的技術作為數據路徑,亦是這兩年很火熱的一個開源容器項目。

      那么,又回到學習新產品的第一步,如何快速部署 K8s 體驗不同地 CNI 插件呢?還是交給我們親愛的 Kubekey 吧。

      Kubekey作為一個開源的 Kubernetes 和 KubeSphere集群部署工具,可以輕松的部署 Kubernetes 集群,提供節點管理、操作系統安全加固、容器運行時管理、網絡存儲安裝、Etcd 管理等。Kubekey 支持一鍵部署 Calico / Flannel / Cilium / Kube-OVN 等網絡插件,只需在 kk 的配置文件中注明 network 的 plugin 值即可:

        network:
          plugin: calico/kubeovn/cilium
          kubePodsCIDR: 10.233.64.0/18
          kubeServiceCIDR: 10.233.0.0/18
      

      對于 antrea,由于版本較新,目前可通過 addon 的形式添加 helm 文件的形式進行一鍵安裝:

        addons:
        - name: antrea
          namespace: kube-system
          sources: 
            chart: 
              name: antrea
              repo: https://charts.antrea.io
              # values:
      

      在此基礎上,可以通過以下一條命令

      ??  → kk create cluster --with-kubernetes --with-kubesphere
      

      創建一個 Kubernetes 集群并安裝 KubeSphere,在此之上體驗不同的 CNI 在 Kubernetes 的功能應用。畢竟,哪個運維人員不喜歡頁面友好的容器管理平臺呢?

      K8s CNI 插件選型和應用場景探討插圖1

      網絡應用場景

      現在我們已經有了一個 Kubernetes 集群,先來思考一下,容器網絡除了讓集群正常運行,能讓安裝 Kubernetes 后 Pending 的 CoreDNS running 起來以外還有哪些使用場景?

      K8s CNI 插件選型和應用場景探討插圖2

      這里我通過一張圖總結了七個主要使用的場景,應該也涵蓋大部分運維人員網絡需求。

      • 固定 IP。對于現存虛擬化 / 裸機業務 / 單體應用遷移到容器環境后,都是通過 IP 而非域名進行服務間調用,此時就需要 CNI 插件有固定 IP 的功能,包括 Pod/Deployment/Statefulset。
      • 網絡隔離。不同租戶或不同應用之間,容器組應該是不能互相調用或通信的。
      • 多集群網絡互聯。 對于不同的 Kubernetes 集群之間的微服務進行互相調用的場景,需要多集群網絡互聯。這種場景一般分為 IP 可達和 Service 互通,滿足不同的微服務實例互相調用需求。
      • 出向限制。對于容器集群外的數據庫 / 中間件,需能控制特定屬性的容器應用才可訪問,拒絕其他連接請求。
      • 入向限制。限制集群外應用對特定容器應用的訪問。
      • 帶寬限制。容器應用之間的網絡訪問加以帶寬限制。
      • 出口網關訪問。對于訪問集群外特定應用的容器,設置出口網關對其進行 SNAT 以達到統一出口訪問的審計和安全需求。 理完需求和應用場景,我們來看看如何通過不同的 CNI 插件解決以上痛點。

      網絡插件功能實現

      固定 IP

      基本上主流 CNI 插件都有自己的 IPAM 機制,都支持固定 IP 及 IP Pool 的分配,并且各個 CNI 插件殊途同歸的都使用了 Annotation 的方式指定固定 IP。對于 Pod,分配固定 IP,對于 Deployment,使用 IP Pool 的方式分配。對于有狀態的 Statefulset,使用 IP Pool 分配后,會根據 Pool 的分配順序記好 Pod 的 IP,以保證在 Pod 重啟后仍能拿到同樣的 IP。

      Calico

        "cni.projectcalico.org/ipAddrs": "[\"192.168.0.1\"]"
      

      Kube-OVN

      ovn.kubernetes.io/ip_address: 192.168.100.100
      ovn.kubernetes.io/ip_pool: 192.168.100.201,192.168.100.202
      

      Antrea

      Antrea IPAM 只能在 Bridge 模式下使用,因此可以在 Multus 的輔佐下,主網卡使用 NodeIPAM 分配,副網卡使用 Antrea IPAM 分配 VLAN 類型網絡地址。

          ipam.antrea.io/ippools: 'pod-ip-pool1'
          ipam.antrea.io/pod-ips: '<ip-in-pod-ip-pool1>'
      

      Cilium

      Not Yet!
      

      多集群網絡互聯

      對于多集群網絡互聯,假設有現有多個集群,不同的微服務運行在不同的集群中,集群 1 的 App01 需要和集群 2 的 App02 進行通信,由于他們都是通過 IP 注冊在集群外的 VM 注冊中心的,所以 App01 和 App02 只能通過 IP 通信。在這種場景下,就需要多集群 Pod 互聯互通。

      Calico

      對于 Calico 這種原生對 BGP 支持很好的 CNI 插件來說,很容易實現這一點,只要兩個集群通過 BGP 建立鄰居,將各自的路由宣告給對方即可實現動態路由的建立。若存在多個集群,使用 BGP RR 的形式也很好解決。但這種解決方式可能不是最理想的,因為需要和物理網絡環境進行配合和聯調,這就需要網絡人員和容器運維人員一同進行多集群網絡的建設,在后期運維和管理上都有不大方便和敏捷的感覺。

      那 Calico VxLAN 模式呢?

      既然說到 VxLAN,可以和 Kube-OVN、Antrea、Cilium 放到一起來看,四種 CNI 都支持 Overlay 的網絡模型,都支持通過 VxLAN/GENEVE 的形式建立隧道網絡打通容器網絡通信。這就賦予運維人員較高的靈活性,對于容器網絡的調教、IPAM 分配、網絡監控和可觀察性、網絡策略調整都由容器集群運維人員負責,而網絡人員則只需要提前劃好物理網絡大段,保證容器集群 Node 之間網絡互通即可。

      那如何去實現 overlay 網絡的多集群互聯呢?

      Submariner

      CNCF 有個沙箱項目叫 Submariner,它通過在不同集群建立不同的網關節點并打通隧道的形式實現多集群通信。從官方這張架構圖來說明:

      K8s CNI 插件選型和應用場景探討插圖3

      簡單來說,Submariner 由一個集群元數據中介服務(broker)掌握不同集群的信息(Pod/Service CIDR),通過 Route Agent 將 Pod 流量從 Node 導向網關節點(Gateway Engine),然后由網關節點打通隧道丟到另一個集群中去,這個過程就和不同主機的容器之間使用 VxLAN 網絡通信的概念是一致的。 要達成集群連接也很簡單,在其中一個集群部署 Broker,然后通過 kubeconfig 或 context 分別進行注冊即可。

      ??  → subctl deploy-broker --kubeconfig ~/.kube/config1
      ??  → subctl join --kubeconfig ~/.kube/config1 broker-info.subm --clusterid ks1 --natt=false --cable-driver vxlan --health-check=false
      ??  → subctl join --kubeconfig ~/.kube/config2 broker-info.subm --clusterid ks2 --natt=false --cable-driver vxlan --health-check=false
      ??  → subctl show all
      ? Showing Endpoints
      CLUSTER ID                    ENDPOINT IP     PUBLIC IP       CABLE DRIVER        TYPE
      ks1                           192.168.100.10  139.198.21.149  vxlan               local
      ks2                           192.168.100.20  139.198.21.149  vxlan               remote
      

      Cilium

      Cilium Cluster Mesh 和 Submariner 有異曲同工之妙,可以通過隧道形式或 NativeRoute 形式實現集群互聯。

      K8s CNI 插件選型和應用場景探討插圖4
      K8s CNI 插件選型和應用場景探討插圖5

      Cilium 開啟多集群網絡連接也很簡單:

      ??  → cilium clustermesh enable --context $CLUSTER1
      ??  → cilium clustermesh enable --context $CLUSTER2
      

      KubeOVN

      Kube-OVN 還提供一個 OVNIC 的組件,它運行一個路由中繼的 OVN-IC 的 Docker 容器,作為兩個集群的網關節點,將不同集群的 Pod 網絡進行連通。

      多集群服務互訪

      除了 Pod IP 的互聯互通,多集群網絡還可考慮集群間的 Service 互訪,Submariner、Cilium、Antrea 都能實現。Submariner 和 Antrea 都使用了 Kubernetes 社區的 MultiCluster Service 并在此之上結合自身組件實現多集群的服務訪問。MultiCluster Service 通過 ServiceExport 和 ServiceImport 的 CRD,ServiceExport 將需要公開的服務導出,然后通過 ServiceImport 將此服務導入到另一個集群。

      K8s CNI 插件選型和應用場景探討插圖6

      Submariner

      拿 Submariner[6] 實現舉例,有兩個集群 ks1 和 ks2,ks1 在 test 命名空間有一個服務 nginx,此時通過 ServiceExport 將 nginx 服務進行導出,Submariner 會把這個 nginx.test.svc.cluster.local 服務發現為 nginx.test.svc.clusterset.local,兩個集群的 coredns 都會建立一個新的 clusterset.local 的存根域,將所有匹配 cluster.set 的請求發送給 submariner 的服務發現的組件。同時 ServiceImport 導入到 ks2 集群,ks2 集群的 Pod 就可以通過 nginx.test.svc.clusterset.local 解析到 ks1 集群的 nginx Service。如果兩個集群都有 nginx 的同名服務,此時 submariner 就可以優先本地進行訪問,本地服務端點有故障后再訪問其他集群的 nginx 服務,是不是可以開始構建雙活服務了哈哈。

      Antrea

      Antrea 實現方式類似,也是結合 ServiceExport 和 ServiceImport 并進行封裝成 ResourceExport 和 ResourceImport 構建多集群服務,在每個集群選擇一個節點作為網關,通過網關打通不同集群隧道來實現多集群服務的訪問。

      K8s CNI 插件選型和應用場景探討插圖7

      Cilium

      Cilium 沒有用 MultiService 的概念,Cilium 通過 Global Service 的概念構建多集群訪問服務訪問。

      K8s CNI 插件選型和應用場景探討插圖8

      從這張圖可以看出,Cilium 更適合做多活集群的多集群服務訪問需求,通過對相應的服務添加 Annotation 的做法,把不同集群的服務設定為 global-service,并通過 shared-service 和 service-affinity 來控制服務是否能被其他集群訪問及服務親和性。以下是一個例子:

      apiVersion: v1
      kind: Service
      metadata:
        name: nginx
        annotations:
          io.cilium/global-service: 'true'
          io.cilium/shared-service: 'true'
          io.cilium/service-affinity: 'local'
          # Possible values:
          # - local
          #    preferred endpoints from local cluster if available
          # - remote
          #    preferred endpoints from remote cluster if available
          # none (default)
          #    no preference. Default behavior if this annotation does not exist   
      spec:
        type: ClusterIP
        ports:
          - port: 80
        selector:
          name: nginx
      

      以上,當有多集群互訪需求又不想 CNI 強相關時,可以嘗試玩一下 Submariner,作為 CNCF Landscape Network 中一個專注于多集群互訪的 SandBox 項目,Submariner 提供多集群網絡通信,服務發現,以及安全加密,是一個很好的選擇。

      網絡策略

      對于 Pod 網絡隔離、入向限制、出向限制的網絡場景,可以整合成網絡策略一同來說。主流開源 CNI 都支持 Kubernetes NetworkPolicy,通過 Network Policy,可以在 3 層或 4 層做相應的網絡安全限制。Network Policy 通過 Ingress 和 Egress 兩種進行網絡限制,默認都是放行的。也就是說,設置 Kubernetes 網絡策略,主要以白名單的形式對集群內的流量進行安全限制。

      比如只允許指定 label 的 Pod 訪問集群外數據庫(通過 CIDR 指定)

      apiVersion: networking.K8s.io/v1
      kind: NetworkPolicy
      metadata:
        name: ingress-allow
        namespace: default
      spec:
        podSelector: 
          matchLabels:
            role: db
        policyTypes:
        - Egress
      egress:
          - to:
              - ipBlock:
                  cidr: 192.168.100.40/24
            ports:
              - protocol: TCP
                port: 3306
      
      apiVersion: networking.K8s.io/v1
      kind: NetworkPolicy
      metadata:
        name: ingress-allow
        namespace: default
      spec:
        podSelector:
          matchLabels:
            role: app
        policyTypes:
          - Ingress
        ingress:
          - from:
              - ipBlock:
                  cidr: 172.17.0.0/16
                  except:
                    - 172.17.1.0/24
              - namespaceSelector:
                  matchLabels:
                    project: web-project
              - podSelector:
                  matchLabels:
                    role: web
      

      雖然 Network Policy 能滿足大多場景,但是不是感覺還是少了點東西?比如 7 層策略、基于 NodeSelector、Drop/Reject 類型的策略指定、指定 Egress 節點進行控制等高級能力。這個時候 Cilium 和 Antrea 就大放異彩了。

      Cilium

      Cilium 有兩個 CRD,CiliumNetworkPolicy 和 CiliumClusterwideNetworkPolicy,來實現單集群和多集群的網絡策略能力。Cilium 支持 3、4、7 層網絡策略。并增加 EndPoint Selector 和 Node Selector。除了普通的基于 PodSelector 和 CIDR 的限制,Cilium 可以支持更多種策略,比如:

      DNS 限制策略,只允許 app: test-app 的端點通過 53 端口去 kube-system 命名空間的 “K8s:K8s-app”: kube-dns 標簽的 DNS 服務器訪問 my-remote-service.com:

      apiVersion: "cilium.io/v2"
      kind: CiliumNetworkPolicy
      metadata:
        name: "to-fqdn"
      spec:
        endpointSelector:
          matchLabels:
            app: test-app
        egress:
          - toEndpoints:
            - matchLabels:
                "K8s:io.kubernetes.pod.namespace": kube-system
                "K8s:K8s-app": kube-dns
            toPorts:
              - ports:
                 - port: "53"
                   protocol: ANY
                rules:
                  dns:
                    - matchPattern: "*"
          - toFQDNs:
              - matchName: "my-remote-service.com"
      

      Http 限制策略 , 只允許 org: empire 標簽的端點對 deathstar 的 /v1/request-landing 進行 POST 操作:

      apiVersion: "cilium.io/v2"
      kind: CiliumNetworkPolicy
      metadata:
        name: "rule"
      spec:
        description: "L7 policy to restrict access to specific HTTP call"
        endpointSelector:
          matchLabels:
            org: empire
            class: deathstar
        ingress:
        - fromEndpoints:
          - matchLabels:
              org: empire
          toPorts:
          - ports:
            - port: "80"
              protocol: TCP
            rules:
              http:
              - method: "POST"
                path: "/v1/request-landing"

      kafka 策略控制:

      apiVersion: "cilium.io/v2"
      kind: CiliumNetworkPolicy
      metadata:
        name: "rule1"
      spec:
        description: "enable empire-hq to produce to empire-announce and deathstar-plans"
        endpointSelector:
          matchLabels:
            app: kafka
        ingress:
        - fromEndpoints:
          - matchLabels:
              app: empire-hq
          toPorts:
          - ports:
            - port: "9092"
              protocol: TCP
            rules:
              kafka:
              - role: "produce"
                topic: "deathstar-plans"
              - role: "produce"
                topic: "empire-announce"
      

      Antrea

      Antrea 除了增加現有 NetworkPolicy 功能外,抽象了 Antrea NetworkPolicy 和 Antrea ClusterNetworkPolicy 兩個 CRD 實現命名空間級別和集群級別的安全管理。,還提供了 Group,Tier 的概念,用于資源分組和優先級設計,嗯,果真是 NSX 的親兄弟。因此 Antrea 有零信任的網絡策略安全防護手段,可以實現嚴格的 pod 和命名空間隔離。

      網絡層 Antrea 增加了對 ICMP 和 IGMP,Mutlicast 的限制,禁 ping 人員狂喜。

      apiVersion: crd.antrea.io/v1alpha1
      kind: ClusterNetworkPolicy
      metadata:
        name: acnp-reject-ping-request
      spec:
          priority: 5
          tier: securityops
          appliedTo:
            - podSelector:
                matchLabels:
                  role: server
              namespaceSelector:
                matchLabels:
                  env: prod
          egress:
            - action: Reject
              protocols:
                - icmp:
                    icmpType: 8
                    icmpCode: 0
              name: DropPingRequest
              enableLogging: true
      

      基于 FQDN 的過濾:

      apiVersion: crd.antrea.io/v1alpha1
      kind: ClusterNetworkPolicy
      metadata:
        name: acnp-fqdn-all-foobar
      spec:
        priority: 1
        appliedTo:
        - podSelector:
            matchLabels:
              app: client
        egress:
        - action: Allow
          to:
            - fqdn: "*foobar.com"
          ports:
            - protocol: TCP
              port: 8080
        - action: Drop 
      

      設置不同類型的 Group,基于 Group 設置網絡策略,就不用對同類業務寫一堆 Label 了

      apiVersion: crd.antrea.io/v1alpha3
      kind: Group
      metadata:
        name: test-grp-with-namespace
      spec:
        podSelector:
          matchLabels:
            role: db
        namespaceSelector:
          matchLabels:
            env: prod
      ---
      # Group that selects IP block 10.0.10.0/24.
      apiVersion: crd.antrea.io/v1alpha3
      kind: Group
      metadata:
        name: test-grp-ip-block
      spec:
        ipBlocks:
          - cidr: 10.0.10.0/24
      ---
      apiVersion: crd.antrea.io/v1alpha3
      kind: Group
      metadata:
        name: test-grp-svc-ref
      spec:
        serviceReference:
          name: test-service
          namespace: default
      ---
      # Group that includes the previous Groups as childGroups.
      apiVersion: crd.antrea.io/v1alpha3
      kind: Group
      metadata:
        name: test-grp-nested
      spec:
        childGroups: [test-grp-sel, test-grp-ip-blocks, test-grp-svc-ref]
      

      Egress

      對于特定業務出集群需不暴露 IP 或符合安全審計需求的場景,需要 Pod IP -> External IP 對外部業務進行訪問。Cilium,Kube-OVN,Antrea 都有類似 Egress Gateway/Egress IP 的功能,特定標簽的 Pod 通過 SNAT 為 Egress IP 訪問集群外服務。

      Cilium

      apiVersion: cilium.io/v2
      kind: CiliumEgressGatewayPolicy
      metadata:
        name: egress-sample
      spec:
        selectors:
        - podSelector:
            matchLabels:
              app: snat-pod
              io.kubernetes.pod.namespace: default
        destinationCIDRs:
        - "0.0.0.0/0"
        egressGateway:
          nodeSelector:
            matchLabels:
              node.kubernetes.io/name: node1
          egressIP: 10.168.60.100
      

      KubeOVN

      apiVersion: v1
      kind: Pod
      metadata:
        name: pod-gw
        annotations:
          ovn.kubernetes.io/eip: 172.10.0.1
          #或ovn.kubernetes.io/snat: 172.10.0.1
      spec:
        containers:
        - name: eip-pod
          image: nginx:alpine
      

      Antrea:

      apiVersion: crd.antrea.io/v1alpha2
      kind: Egress
      metadata:
        name: egress-staging-web
      spec:
        appliedTo:
          namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: staging
          podSelector:
            matchLabels:
              app: web
        externalIPPool: external-ip-pool
        #或IP形式 egressIP: 10.10.10.1
      

      帶寬管理

      kube-ovn 和 Clium 都支持帶寬管理,kube-ovn 還支持 QoS 調整,只需要 Annotation 一下即可搞定:

      Kube-OVN

      apiVersion: v1
      kind: Pod
      metadata:
        name: qos
        namespace: ls1
        annotations:
          ovn.kubernetes.io/ingress_rate: "3"
          ovn.kubernetes.io/egress_rate: "1"
          ovn.kubernetes.io/latency: 3
          ovn.kubernetes.io/loss: 20
      

      Cilium

      apiVersion: v1
      kind: Pod
      metadata:
        annotations:
          kubernetes.io/egress-bandwidth: 10M
      ...
      

      以上。就是此次分享的全部內容了,讀到這里你可以也會感慨,從最早學 Docker,Vethpair 熟悉容器網絡原理,到搭建 K8s 后節點 NotReady 就 apply 個 Flannel 逐步了解 CNI 插件機制,到今天的 CNCF Network&Service Proxy 生態的花團錦簇,云原生網絡在日新月異的發展著,容器網絡從最初的連通性到現在演變出更多的玩法和適用性,不論是網絡功能、安全控制、網絡洞察和可觀測性,都在更好地為運維人員服務。若要體驗更多功能,快到開源社區選擇喜歡的容器網絡項目 Hands on Lab 吧!

      鏈接:https://mp.weixin.qq.com/s/GG7GX_E1oyZf-cmjk80OYg

      (版權歸原作者所有,侵刪)

      本文鏈接:http://www.abandonstatusquo.com/42848.html

      網友評論comments

      發表評論

      您的電子郵箱地址不會被公開。

      暫無評論

      Copyright ? 2012-2022 YUNWEIPAI.COM - 運維派 京ICP備16064699號-6
      掃二維碼
      掃二維碼
      返回頂部
      久久久久亚洲国内精品|亚洲一区二区在线观看综合无码|欧洲一区无码精品色|97伊人久久超碰|一级a爱片国产亚洲精品