• Kubernetes(k8s)CNI(Calico)网络模型原理


    一、概述

    Calico 是一个联网和网络策略供应商。 Calico 支持一套灵活的网络选项,因此你可以根据自己的情况选择最有效的选项,包括非覆盖和覆盖网络,带或不带 BGP。 Calico 使用相同的引擎为主机、Pod 和(如果使用 Istio 和 Envoy)应用程序在服务网格层执行网络策略。Calico以其性能、灵活性而闻名。Calico的功能更为全面,更为复杂。它不仅提供主机和pod之间的网络连接,还涉及网络安全和管理。Calico CNI插件在CNI(container network interface)框架内封装了Calico的功能。

    GitHub地址: https://github.com/projectcalico/calico

    官方文档:https://projectcalico.docs.tigera.io/about/about-calico

    想了解flannel的小伙伴,可以参考我这篇文章:Kubernetes(k8s)CNI(flannel)网络模型原理

    其它CNI插件,可以查看k8s官网:https://kubernetes.io/docs/concepts/cluster-administration/addons/

    二、Calico 架构和核心组件

    Calico不使用重叠网络比如flannel和libnetwork重叠网络驱动,它是一个纯三层的方法,使用虚拟路由代替虚拟交换,每一台虚拟路由通过BGP协议传播可达信息(路由)到剩余数据中心;Calico在每一个计算节点利用Linux Kernel实现了一个高效的vRouter来负责数据转发,而每个vRouter通过BGP协议负责把自己上运行的workload的路由信息像整个Calico网络内传播——小规模部署可以直接互联,大规模下可通过指定的BGP route reflector来完成。

    在这里插入图片描述

    Calico 的核心组件:

    • Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等。

    • etcd:分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与kubernetes共用;

    • BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。在 Calico 的角色是监听 Host 上由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉剩余 Host 节点,从而实现网络互通。

    • BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数。

    三、什么是BGP?

    边界网关协议(BGP是运行于 TCP上的一种自治系统的路由协议,也是互联网上一个核心的去中心化自治路由协议。网络可达信息包括列出的自治系统(AS)的信息。这些信息有效地构造了 AS 互联的拓朴图并由此清除了路由环路,同时在 AS 级别上可实施策略决策。在互联网中,一个自治系统(AS)是一个有权自主地决定在本系统中应采用何种路由协议的小型单位。

    • BGP是路由器之间的通信协议,主要用于AS(AutonomousSystem,自治系统)之间的互联。

    • AS内部有多个BGP speaker,分为ibgp、ebgp,ebgp与其它AS中的ebgp建立BGP连接。

    • AS内部的BGP speaker通过BGP协议交换路由信息,最终每一个BGP speaker拥有整个AS的路由信

    可以把calico中的node节点当成一个AS,而node节点中的容器是AS中的router,calico通过BGP解析,将整个网络中容器地址的路由表绘制出来。

    在这里插入图片描述

    • IBGP(Internal BGP):当BGP运行于同一自治系统内部时,被称为IBGP

    • EBGP(External BGP):当BGP运行于不同自治系统之间时,称为EBGP

    BGP两种模式:

    • 全互联模式(node-to-node mesh)——全互联模式,每一个BGP Speaker都需要和其他BGP Speaker建立BGP连接,这样BGP连接总数就是N^2,如果数量过大会消耗大量连接。如果集群数量超过100台官方不建议使用此种模式。
    • 路由反射模式Router Reflection(RR)——RR模式中会指定一个或多个BGP Speaker为RouterReflection,它与网络中其他Speaker建立连接,每个Speaker只要与Router Reflection建立BGP就可以获得全网的路由信息。在calico中可以通过Global Peer实现RR模式。

    三、Calico 两种网络模式

    1)IPIP 模式

    • 从字面来理解,就是把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel,看起来似乎是浪费,实则不然。
    • 它的作用其实基本上就相当于一个基于IP层的网桥!
    • 一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。
    • ipip 的源代码在内核 net/ipv4/ipip.c 中可以找到。

    Calico的IPIP模式工作原理如下图:

    在这里插入图片描述

    Calico使用的这个tunl0设备,是一个IP隧道(IP tunnel)设备

    在上面的例子中,IP包进入IP隧道设备之后,就会被Linux内核的IPIP驱动接管。IPIP驱动会将这个IP包直接封装在一个宿主机网络的IP包中,如下所示:
    在这里插入图片描述

    2)BGP 模式

    • 边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。
    • 它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。
    • BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。
    • BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP,BGP 机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统。
    • BGP网络相比较IPIP网络,最大的不同之处就是没有了隧道设备 tunl0。 前面介绍过IPIP网络pod之间的流量发送tunl0,然后tunl0发送对端设备。BGP网络中,pod之间的流量直接从网卡发送目的地,减少了tunl0这个环节。

    在这里插入图片描述

    四、安装Calico插件

    1)通过helm安装Calico

    官方文档:https://projectcalico.docs.tigera.io/getting-started/kubernetes/helm

    # 添加源
    helm repo add projectcalico https://projectcalico.docs.tigera.io/charts
    
    # helm repo update  
    
    # 下载
    helm pull  projectcalico/tigera-operator --version v3.24.5
    # 解压
    tar -xf tigera-operator-v3.24.5.tgz
    
    # 安装,默认命名空间:calico-system
    helm install calico ./tigera-operator  --namespace tigera-operator --create-namespace
    
    # 检查tigera-operator所有资源
    kubectl get all -n tigera-operator
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2)通过yaml文件安装

    wget https://docs.projectcalico.org/manifests/calico.yaml
    kubectl apply -f calico.yaml
    
    # 查看
    kubectl get all -n kube-system|grep calico
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3)k8s flannel网络切换calico

    1、卸载flannel插件
    ### 1、查看已安装flannel信息
    cat /etc/cni/net.d/10-flannel.conflist
    
    ### 2、删除flannel布署资源
    kubectl delete -f kube-flannel.yml
    
    ### 3、清除flannel遗留信息,在集群各节点清理flannel网络的残留文件
    ifconfig cni0 down
    ip link delete cni0
    ifconfig flannel.1 down
    ip link delete flannel.1
    rm -rf /var/lib/cni
    rm -rf /etc/cni/net.d
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    2、开始安装Calico插件
    # 下载
    wget https://docs.projectcalico.org/manifests/calico.yaml
    
    # 安装
    kubectl apply -f calico.yaml
    
    # 查看
    kubectl get all -n kube-system|grep calico
    
    # 如果节点NotReady,重启以下容器或者kubelet试试
    systemctl restart containerd docker
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    五、网络策略

    关于网络策略,可以参考我这篇文章:【云原生】k8s 中的 hostNetwork 和 NetworkPolicy(网络策略)讲解与实战操作

    六、简单使用

    官方文档:https://projectcalico.docs.tigera.io/security/kubernetes-policy

    1)网络策略示例

    1、允许来自同一命名空间中的 Pod 的入口流量

    允许来自同一命名空间中的 Pod 的入口流量,在以下示例中,传入带有标签的 Pod 的 label color: red,仅当它们来自 pod 带有label color: red,才被允许转到80端口。

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-same-namespace
      namespace: default
    spec:
      podSelector:
        matchLabels:
          color: blue
      ingress:
      - from:
        - podSelector:
            matchLabels:
              color: red
        ports:
          - port: 80
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    2、允许来自不同命名空间中的 Pod 的入口流量

    在以下示例中,仅当传入流量来自带有标签 color: red的 Pod 时,才允许传入流量,在带有标签的命名空间中带有标签shape: square,在端口上 80.

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-same-namespace
      namespace: default
    spec:
      podSelector:
        matchLabels:
          color: blue
      ingress:
      - from:
        - podSelector:
            matchLabels:
              color: red
          namespaceSelector:
            matchLabels:
              shape: square
        ports:
        - port: 80
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2)固定Pod IP

    【示例1】pod
    利用注解 cni.projectcalico.org/ipAddrs

    # vi fixed-ip-test-pod.yaml
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: myapp-pod
      labels:
        app: myapp
      annotations:
        cni.projectcalico.org/ipAddrs: "[\"10.244.1.200\"]"
    spec:
      containers:
      - name: myapp-container
        image: busybox
        command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    【示例2】控制器 单pod
    利用注解 cni.projectcalico.org/ipAddrs

    # vi fixed-ip-test-deployment.yaml
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: fixed-ip-test
      namespace: default
      labels:
        k8s-app: cloudnativer-test
    spec:
      replicas: 1
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 1
      selector:
        matchLabels:
          k8s-app: cloudnativer-test
      template:
        metadata:
          labels:
            k8s-app: cloudnativer-test
          annotations:
            cni.projectcalico.org/ipAddrs: "[\"10.244.1.220\"]"
        spec:
          containers:
          - name: fixed-ip-test
            image: nginx:1.7.9
            imagePullPolicy: IfNotPresent
            ports:
            - name: http
              containerPort: 80
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    【示例3】控制器 多pod固定IP池

    需要创建额外IP池(除了默认IP池),利用注解cni.projectcalico.org/ipv4pools。

    这里先安装一个客户端工具calicoctl

    wget https://github.com/projectcalico/calico/releases/download/v3.24.5/calicoctl-linux-amd64
    mv calicoctl-linux-amd64 /usr/local/bin/calicoctl 
    chmod +x /usr/local/bin/calicoctl
    
    • 1
    • 2
    • 3

    编排

    # vi fixed-ip-test-deployment2.yaml
    # apiVersion: projectcalico.org/v3
    apiVersion: crd.projectcalico.org/v1
    kind: IPPool
    metadata:
      name: new-pool1
    spec:
      blockSize: 31
      cidr: 10.244.3.220/24
      ipipMode: Never
      natOutgoing: true
    ---
    # apiVersion: projectcalico.org/v3
    apiVersion: crd.projectcalico.org/v1
    kind: IPPool
    metadata:
      name: new-pool2
    spec:
      blockSize: 31
      cidr: 10.244.4.221/24
      ipipMode: Never
      natOutgoing: true
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: fixed-ip-test2
      namespace: default
      labels:
        k8s-app: cloudnativer-test
    spec:
      replicas: 3
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 1
      selector:
        matchLabels:
          k8s-app: cloudnativer-test
      template:
        metadata:
          labels:
            k8s-app: cloudnativer-test
          annotations:
            # 【注意】不能使用单引号
            "cni.projectcalico.org/ipv4pools": "[\"new-pool1\",\"new-pool2\"]"
        spec:
          containers:
          - name: fixed-ip-test
            image: nginx:1.7.9
            imagePullPolicy: IfNotPresent
            ports:
            - name: http
              containerPort: 80
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    查看

    # 查看ip池
    calicoctl get ippool
    kubectl get pods -owide
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    【温馨提示】要更改用于Pod的默认IP范围,请修改calico.yaml清单文件中CALICO_IPV4POOL_CIDR部分。

    七、Calico VS Flannel

    目前比较常用的是flannelcalico,flannel的功能比较简单,不具备复杂网络的配置能力,不支持网络策略;calico是比较出色的网络管理插件,单具备复杂网络配置能力的同时,往往意味着本身的配置比较复杂,所以相对而言,比较小而简单的集群使用flannel,考虑到日后扩容,未来网络可能需要加入更多设备,配置更多策略,则使用calico更好。

    1)Flannel

    • 优势:部署简单,性能一般。
    • 劣势:没办法实现固定 IP 的容器漂移,没法做子网隔离,对上层设计依赖程度高,没有 IPAM , IP 地址浪费,对 Docker 启动方法有绑定。

    2)Calico

    • Calico还以其先进的网络功能而闻名。网络策略是其最受追捧的功能之一。
    • 支持固定 IP 的配置。
    • 此外,Calico还可以与服务网格Istio集成,以便在服务网格层和网络基础架构层中解释和实施集群内工作负载的策略。这意味着用户可以配置强大的规则,描述Pod应如何发送和接受流量,提高安全性并控制网络环境。

    两个插件使用的都比较广泛,如果需要设置网络策略,规划更复杂的网络,固定IP等,就建议使用Calico;如果只是简单的使用网络插件的通讯功能就选择Flannel。

    关于Kubernetes(k8s)CNI(Calico)网络模型原理介绍与部署就先到这里了,有疑问的小伙伴,欢迎给我留言,后续会持续更新【云原生+大数据】相关的文章,请小伙伴耐心等待~

  • 相关阅读:
    《网络是怎样连接的》学习总结-第三章上
    Java面向对象编程
    spark封神之路(3)-spark运行架构
    面试:插件化相关---activity
    npm运行报错:无法加载文件 C:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本问题解决
    H5全栈实习day01:html重点标签+css选择器+css采用字体文本属性+display显示模式+浮动
    工具分享:Springboot+Netty+Xterm搭建一个网页版的SSH终端
    第19章_体系结构
    XML配置文件解析与建模
    安卓手机连接电脑实用技巧:实现文件传输与共享
  • 原文地址:https://blog.csdn.net/qq_35745940/article/details/127937447