乐趣区

关于边缘计算:eBPF-完美搭档连接云原生网络的-Cilium

Cilium 作为近两年最火的云原生网络计划,堪称是风头无两。作为第一个通过 ebpf 实现了 kube-proxy 所有性能的网络插件,它的神秘面纱到底是怎么的呢?本文次要介绍 Cilium 的倒退演进,性能介绍以及具体应用示例。

背景

随着云原生的普及率越来越高,各大厂商基本上或多或少都实现了业务的 K8s 容器化,头部云计算厂商更是不用说。

而且随着 K8s 的 遍及,以后集群逐步呈现出以下两个特点:

  1. 容器数量越来越多,比方:K8s 官网单集群就曾经反对 150k pod
  2. Pod 生命周期越来越短,Serverless 场景下甚至短至几分钟,几秒钟

随着容器密度的增大,以及生命周期的变短,对原生容器网络带来的挑战也越来越大。

以后 K 8s Service 负载平衡 的实现现状

在 Cilium 呈现之前,Service 由 kube-proxy 来实现,实现形式有 userspaceiptablesipvs 三种模式。

Userspace

以后模式下,kube-proxy 作为反向代理,监听随机端口,通过 iptables 规定将流量重定向到代理端口,再由 kube-proxy 将流量转发到 后端 pod。Service 的申请会先从用户空间进入内核 iptables,而后再回到用户空间,代价较大,性能较差。

Iptables

存在的问题:

  1. 可扩展性差。随着 service 数据达到数千个,其管制面和数据面的性能都会急剧下降。起因在于 iptables 管制面的接口设计中,每增加一条规定,须要遍历和批改所有的规定,其管制面性能是O(n²)。在数据面,规定是用链表组织的,其性能是O(n)
  2. LB 调度算法仅反对随机转发。

Ipvs 模式

IPVS 是专门为 LB 设计的。它用 hash table 治理 service,对 service 的增删查找都是 O(1)的工夫复杂度。不过 IPVS 内核模块没有 SNAT 性能,因而借用了 iptables 的 SNAT 性能。

IPVS 针对报文做 DNAT 后,将连贯信息保留在 nf_conntrack 中,iptables 据此接力做 SNAT。该模式是目前 Kubernetes 网络性能最好的抉择。然而因为 nf_conntrack 的复杂性,带来了很大的性能损耗。

Cilium 的倒退

Cilium 是基于 eBpf 的一种开源网络实现,通过在 Linux 内核动静插入弱小的安全性、可见性和网络管制逻辑,提供网络互通,服务负载平衡,平安和可观测性等解决方案。简略来说能够了解为 Kube-proxy + CNI 网络实现。

Cilium 位于容器编排零碎和 Linux Kernel 之间,向上能够通过编排平台为容器进行网络以及相应的平安配置,向下能够通过在 Linux 内核挂载 eBPF 程序,来管制容器网络的转发行为以及安全策略执行。

简略理解下 Cilium 的倒退历程:

  1. 2016 Thomas Graf 创建了 Cilium, 现为 Isovalent (Cilium 背地的商业公司)的 CTO
  2. 2017 年 DockerCon 上 Cilium 第一次公布
  3. 2018 年 公布 Cilium 1.0
  4. 2019 年 公布 Cilium 1.6 版本,100% 代替 kube-proxy
  5. 2019 年 Google 全面参加 Cilium
  6. 2021 年 微软、谷歌、FaceBook、Netflix、Isovalent 在内的多家企业发表成立 eBPF 基金会(Linux 基金会下)

性能介绍

查看官网,能够看到 Cilium 的性能次要蕴含 三个方面,如上图:

  • 网络

    1. 高度可扩大的 kubernetes CNI 插件,反对大规模,高动静的 k8s 集群环境。反对多种租网模式:

      • Overlay 模式,反对 Vxlan 及 Geneve
      • Unerlay 模式,通过 Direct Routing(间接路由)的形式,通过 Linux 宿主机的路由表进行转发
    2. kube-proxy 替代品,实现了 四层负载平衡性能。LB 基于 eBPF 实现,应用高效的、可有限扩容的哈希表来存储信息。对于南北向负载平衡,Cilium 做了最大化性能的优化。反对 XDP、DSR(Direct Server Return,LB 仅仅批改转发封包的指标 MAC 地址)
    3. 多集群的连通性,Cilium Cluster Mesh 反对多集群间的负载,可观测性以及平安管控

<!—->

  • 可观测性

  1. 提供生产可用的可观测性工具 hubble, 通过 pod 及 dns 标识来辨认连贯信息
  2. 提供 L3/L4/L7 级别的监控指标,以及 Networkpolicy 的 行为信息指标
  3. API 层面的可观测性 (http,https)
  4. Hubble 除了本身的监控工具,还能够对接像 Prometheus、Grafana 等支流的云原生监控体系,实现可扩大的监控策略
  • 平安

    1. 不仅反对 k8s Network Policy,还反对 DNS 级别、API 级别、以及跨集群级别的 Network Policy
    2. 反对 ip 端口 的 平安审计日志
    3. 传输加密

总结,Cilium 不仅包含了 kube-proxy + CNI 网络实现,还蕴含了泛滥可观测性和平安方面的个性。

装置部署

linux 内核要求 4.19 及以上

能够采纳 helm 或者 cilium cli,此处笔者应用的是 cilium cli(版本为 1.10.3

  • 下载 cilium cli
wget https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz​
tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
  • 装置 cilium
wget https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz
tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin

cilium install --kube-proxy-replacement=strict  # 此处抉择的是齐全替换,默认状况下是 probe,(该选项下 pod hostport 个性不反对)

  • 可视化组件 hubble(选装)
cilium hubble enable --ui
  • 期待 pod ready 后,查看 状态如下:
~# cilium status​
    /¯¯\​
 /¯¯__/¯¯\    Cilium:         OK​
 __/¯¯__/    Operator:       OK​
 /¯¯__/¯¯\    Hubble:         OK​
 __/¯¯__/    ClusterMesh:    disabled​
    __/​

DaemonSet         cilium             Desired: 1, Ready: 1/1, Available: 1/1​
Deployment        cilium-operator    Desired: 1, Ready: 1/1, Available: 1/1​
Deployment        hubble-relay       Desired: 1, Ready: 1/1, Available: 1/1​
Containers:       hubble-relay       Running: 1​
                  cilium             Running: 1​
                  cilium-operator    Running: 1​
Image versions    cilium             quay.io/cilium/cilium:v1.10.3: 1​
                  cilium-operator    quay.io/cilium/operator-generic:v1.10.3: 1​
                  hubble-relay       quay.io/cilium/hubble-relay:v1.10.3: 1
  • cilium cli 还反对 集群可用性查看(可选)
[root@~]# cilium connectivity test​
ℹ️  Single-node environment detected, enabling single-node connectivity test​
ℹ️  Monitor aggregation detected, will skip some flow validation steps​
✨ [kubernetes] Creating namespace for connectivity check...​
✨ [kubernetes] Deploying echo-same-node service...​
✨ [kubernetes] Deploying same-node deployment...​
✨ [kubernetes] Deploying client deployment...​
✨ [kubernetes] Deploying client2 deployment...​
⌛ [kubernetes] Waiting for deployments [client client2 echo-same-node] to become ready...​
⌛ [kubernetes] Waiting for deployments [] to become ready...​
⌛ [kubernetes] Waiting for CiliumEndpoint for pod cilium-test/client-6488dcf5d4-rx8kh to appear...​
⌛ [kubernetes] Waiting for CiliumEndpoint for pod cilium-test/client2-65f446d77c-97vjs to appear...​
⌛ [kubernetes] Waiting for CiliumEndpoint for pod cilium-test/echo-same-node-745bd5c77-gr2p6 to appear...​
⌛ [kubernetes] Waiting for Service cilium-test/echo-same-node to become ready...​
⌛ [kubernetes] Waiting for NodePort 10.251.247.131:31032 (cilium-test/echo-same-node) to become ready...​
⌛ [kubernetes] Waiting for Cilium pod kube-system/cilium-vsk8j to have all the pod IPs in eBPF ipcache...​
⌛ [kubernetes] Waiting for pod cilium-test/client-6488dcf5d4-rx8kh to reach default/kubernetes service...​
⌛ [kubernetes] Waiting for pod cilium-test/client2-65f446d77c-97vjs to reach default/kubernetes service...​
🔭 Enabling Hubble telescope...​
⚠️  Unable to contact Hubble Relay, disabling Hubble telescope and flow validation: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp [::1]:4245: connect: connection refused"​
ℹ️  Expose Relay locally with:​
   cilium hubble enable​
   cilium status --wait​
   cilium hubble port-forward&​
🏃 Running tests...

等 hubble 装置实现后,hubble-ui service 批改为 NodePort 类型, 即可通过 NodeIP+NodePort 来登录 Hubble 界面 查看相干信息。

Cilium 部署完后,有以下几个组件 operator、hubble(ui, relay),Cilium agent(Daemonset 模式,每个节点一个),其中要害组件为 cilium agent。

Cilium Agent 作为整个架构中最外围的组件,通过 DaemonSet 的形式,以特权容器的模式,运行在集群的每个主机上。Cilium Agent 作为用户空间守护程序,通过插件与容器运行时和容器编排零碎进行交互,进而为本机上的容器进行网络以及平安的相干配置。同时提供了凋谢的 API,供其余组件进行调用。

Cilium Agent 在进行网络和平安的相干配置时,采纳 eBPF 程序进行实现。Cilium Agent 联合容器标识和相干的策略,生成 eBPF 程序,并将 eBPF 程序编译为字节码,将它们传递到 Linux 内核。

相干命令介绍

Cilium agent 中内置了一些调试用的命令,上面介绍,agent 中的 cilium 不同与上述介绍的 cilium cli (尽管同为 cilium)。

  • cilium status

次要展现  cilium 的一些简略配置信息及状态,如下:

[root@~]# kubectl exec -n kube-system cilium-s62h5 -- cilium status
Defaulted container "cilium-agent" out of: cilium-agent, ebpf-mount (init), clean-cilium-state (init)
KVStore:                Ok   Disabled
Kubernetes:             Ok   1.21 (v1.21.2) [linux/amd64]
Kubernetes APIs:        ["cilium/v2::CiliumClusterwideNetworkPolicy", "cilium/v2::CiliumEndpoint", "cilium/v2::CiliumNetworkPolicy", "cilium/v2::CiliumNode", "core/v1::Namespace", "core/v1::Node", "core/v1::Pods", "core/v1::Service", "discovery/v1::EndpointSlice", "networking.k8s.io/v1::NetworkPolicy"]
KubeProxyReplacement:   Strict   [eth0 10.251.247.131 (Direct Routing)]
Cilium:                 Ok   1.10.3 (v1.10.3-4145278)
NodeMonitor:            Listening for events on 8 CPUs with 64x4096 of shared memory
Cilium health daemon:   Ok
IPAM:                   IPv4: 68/254 allocated from 10.0.0.0/24,
BandwidthManager:       Disabled
Host Routing:           Legacy
Masquerading:           BPF   [eth0]   10.0.0.0/24 [IPv4: Enabled, IPv6: Disabled]
Controller Status:      346/346 healthy
Proxy Status:           OK, ip 10.0.0.167, 0 redirects active on ports 10000-20000
Hubble:                 Ok   Current/Max Flows: 4095/4095 (100.00%), Flows/s: 257.25   Metrics: Disabled
Encryption:             Disabled
Cluster health:         1/1 reachable   (2021-08-11T09:33:31Z)
  • cilium service list

展现 service 的实现,应用时可通过 ClusterIP 来过滤,其中,FrontEnd 为 ClusterIPBackend 为 PodIP

[root@~]# kubectl exec -it -n kube-system cilium-vsk8j -- cilium service list
Defaulted container "cilium-agent" out of: cilium-agent, ebpf-mount (init), clean-cilium-state (init)
ID    Frontend                 Service Type   Backend
1     10.111.192.31:80         ClusterIP      1 => 10.0.0.212:8888
2     10.101.111.124:8080      ClusterIP      1 => 10.0.0.81:8080
3     10.101.229.121:443       ClusterIP      1 => 10.0.0.24:8443
4     10.111.165.162:8080      ClusterIP      1 => 10.0.0.213:8080
5     10.96.43.229:4222        ClusterIP      1 => 10.0.0.210:4222
6     10.100.45.225:9180       ClusterIP      1 => 10.0.0.48:9180
# 防止过多,此处不一一展现
  • cilium service get

通过 cilium service get < ID> -o json 来展现详情:

[root@~]# kubectl exec -it -n kube-system cilium-vsk8j -- cilium service get 132 -o json​
Defaulted container "cilium-agent" out of: cilium-agent, ebpf-mount (init), clean-cilium-state (init)​
{​
  "spec": {​
    "backend-addresses": [​
      {​
        "ip": "10.0.0.213",​
        "nodeName": "n251-247-131",​
        "port": 8080​
      }​
    ],​
    "flags": {​
      "name": "autoscaler",​
      "namespace": "knative-serving",​
      "trafficPolicy": "Cluster",​
      "type": "ClusterIP"​
    },​
    "frontend-address": {​
      "ip": "10.98.24.168",​
      "port": 8080,​
      "scope": "external"​
    },​
    "id": 132​
  },​
  "status": {​
    "realized": {​
      "backend-addresses": [​
        {​
          "ip": "10.0.0.213",​
          "nodeName": "n251-247-131",​
          "port": 8080​
        }​
      ],​
      "flags": {​
        "name": "autoscaler",​
        "namespace": "knative-serving",​
        "trafficPolicy": "Cluster",​
        "type": "ClusterIP"​
      },​
      "frontend-address": {​
        "ip": "10.98.24.168",​
        "port": 8080,​
        "scope": "external"​
      },​
      "id": 132​
    }​
  }​
}

还有很多有用的命令,限于篇幅,此处不一一展现,感兴趣的同学能够尝试摸索(cilium status --help)。

退出移动版