关于后端:深入探索-Cilium-的工作机制

34次阅读

共计 7047 个字符,预计需要花费 18 分钟才能阅读完成。

这篇之前写 Kubernetes 网络学习之 Cilium 与 eBPF 记录的内容,隔了几个月终于想起把笔记实现,作为摸索 Cilium 工作原理的入门,也还是 Cilium 冰山一角,像是高级的网络策略、网络加密、BGP 网络、服务网格等方面并没有深刻。如果浏览过程中有发现任何问题,也烦请纠正。

本文基于 Cilium v1.12 及 Kubernetes v1.25。

试验环境

咱们应用 k8e 创立集群,因为 k8e 应用 Cilium 作为默认的 CNI 实现。在我的 homelab 上做个双节点(ubuntu-test1: 192.168.1.21ubuntu-test2: 192.168.1.22)的集群。

Master 节点

curl -sfL https://getk8e.com/install.sh | API_SERVER_IP=192.168.1.21 K8E_TOKEN=ilovek8e INSTALL_K8E_EXEC="server --cluster-init --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config" sh -

工作节点

curl -sfL https://getk8e.com/install.sh | K8E_TOKEN=ilovek8e K8E_URL=https://192.168.1.21:6443 sh -

部署示例利用,通过批改 nodeName 将两个 pod 别离调度两个节点上。

NODE1=ubuntu-test1
NODE2=ubuntu-test2
kubectl apply -n default -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: curl
  name: curl
spec:
  containers:
  - image: curlimages/curl
    name: curl
    command: ["sleep", "365d"]
  nodeName: $NODE1
---
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: httpbin
  name: httpbin
spec:
  containers:
  - image: kennethreitz/httpbin
    name: httpbin
  nodeName: $NODE2
EOF

Cilium 组件

Agent

cilium-agent 运行在集群的各个节点上(上图的 Cilium Daemon)。接管来自 Kubernetes 或者 Cilium API 的形容网络、服务负载平衡、网络策略以及可见性和监控需要的配置。

Agent 监控如 Kubernetes 等编排零碎中容器或者负载的生命周期变动,治理着用来管制进出容器的网络拜访的 eBPF 程序;对外(CNI Plugin、CLI)提供 API 来操作配置、Endpoint、Node、Policy、Service、IP 地址等资源。

API 蕴含如下几个模块:

  • daemon
  • endpoint
  • ipam
  • metrics
  • policy
  • prefilter
  • recorder
  • service

CLI

Cilium CLI 客户端,与 cilium-agent 一起装置。通过 Cilium REST API 与同节点上的本地 agent 进行交互。通过 CLI 能够查看本地 agent 的状态,也能够间接拜访 eBPF map 的内容以便随时验证状态。

cilium
CLI for interacting with the local Cilium Agent

Usage:
  cilium [command]

Available Commands:
  bpf         Direct access to local BPF maps
  cleanup     Remove system state installed by Cilium at runtime
  completion  Output shell completion code
  config      Cilium configuration options
  debuginfo   Request available debugging information from agent
  encrypt     Manage transparent encryption
  endpoint    Manage endpoints
  fqdn        Manage fqdn proxy
  help        Help about any command
  identity    Manage security identities
  ip          Manage IP addresses and associated information
  kvstore     Direct access to the kvstore
  lrp         Manage local redirect policies
  map         Access userspace cached content of BPF maps
  metrics     Access metric status
  monitor     Display BPF program events
  node        Manage cluster nodes
  policy      Manage security policies
  prefilter   Manage XDP CIDR filters
  preflight   cilium upgrade helper
  recorder    Introspect or mangle pcap recorder
  service     Manage services & loadbalancers
  status      Display status of daemon
  version     Print version information

Flags:
      --config string   config file (default is $HOME/.cilium.yaml)
  -D, --debug           Enable debug messages
  -h, --help            help for cilium
  -H, --host string     URI to server-side API

Use "cilium [command] --help" for more information about a command.

Operator

Cilium Operator 负责管理集群中的职责,逻辑上应该为整个集群解决一次,而不是为集群中的每个节点解决一次。Operator 不参加任何转发或者网络策略的决策。即便 Operator 短暂不可用,集群通常会持续运行,除了某些操作可能会失败。

Operator 容许多实例运行,但由 leader 实例实现特定操作,比方 Node CIDR 的调配。

CNI Plugin

Cilium 的 CNI 实现,当 pod 调度到某个节点后,该节点的容器运行时会调用 Cilium CNI 实现一系列的网络配置。CNI Plugin 会与 Agent 组件通过 REST API 进行交互,比方调用 API 调配 IP 地址、创立 Endpoint 等。

对这部分有趣味的能够看下之前的文章《Kubernetes 网络学习之 Cilium 与 eBPF》。

IPAM

Cilium 管理网络 Endpoint,Endpoint 应用的 IP 地址,由 IPAM 调配和治理。

反对 多种 IPAM 模型,默认应用 Cluster Scope cluster-pool,通过 cilium-config 中的字段 ipam 来设置。

cluster-scope IPAM 模型为各个集群 node 调配 PodCIDRs,而后在各个 node 上应用 host-scope 分配器调配 IP 地址。

这个 PodCIDRs 的调配与 Flannel 中的 PodCIDRs 调配 的不同:后者应用 v1.Node 上由 Kubernetes 调配的 podCIDR,这个与 Cilium 的 Kubernetes Host Scope 相似;而 Cilium 的 cluster-scope 应用的 PodCIDRs 则是由 Cilium operator 来调配和治理的,operator 将调配的 PodCIDR 附加在 v2.CiliumNode 上。

Agent 启动后,从 v2.CiliumNode 上获取 podCIDRs,而后在 CNI 插件调用时为 pod 调配 IP 地址。

eBPF

eBPF 是一种 Linux 内核字节码解释器,最后用于过滤网络数据包,例如 tcpdump 和套接字过滤器。尔后,它扩大了额定的数据结构,如哈希表和数组,以及反对数据包解决、转发、封装等的其余操作。

Cilium 利用 eBPF 执行外围数据门路过滤、解决、监控和重定向,并须要任何 Linux 内核版本 4.8.0 或更高版本的 eBPF 性能。

Linux 内核始终是实现监控 / 可观测性、网络和平安性能的现实中央。不过很多状况下这并非易事,因为这些工作须要批改内核源码或加载内核模块,最终实现模式是在已有的层层形象之上叠加新的形象。eBPF 是一项革命性技术,它能在内核中运行沙箱程序(sandbox programs),而无需批改内核源码或者加载内核模块。

将 Linux 内核变成可编程之后,就能基于现有的(而非减少新的)形象层来打造更加智能、性能更加丰盛的基础设施软件,而不会减少零碎的复杂度,也不会就义执行效率和安全性。

概念

标签 Label

标签是解决大量资源的通用、灵便且高度可扩大的形式,在 Kubernetes 中与 标签选择器 一起被广泛应用。简略来说,一个标签就是一个 keyvalue 的组合:key=value(应用时也可不提供 value)。

在 Cilium 中标签有些许不同:每个标签都有个前缀 :,这个 source 示意该标签是衍生自哪里。创立 Pod 时,衍生来的标签会带有 k8s: 前缀,如 k8s:io.kubernetes.pod.namespace=default;而应用 docker run [...] -l foo=bar 运行的容器,则带有标签 container:foo=bar

除了方才提到的 k8s:container:,还有两种 reserved:unspec:。前者示意是 Cilium 的保留标签,后者则示意没有指定起源。

端点 Endpoint

Cilium 通过为容器调配 IP 地址使其在网络上可用。多个容器能够共享同一个 IP 地址,就像一个 Kubernetes Pod 中能够有多个容器,这些容器之间共享网络命名空间,应用同一个 IP 地址。这些共享同一个地址的容器,Cilium 将其组合起来,成为 Endpoint(端点)。

留神,这个 Endpoint 与 Kubernetes 原生资源 v1.Endpoints 相似但却不同,Cilium 为其提供了 CRD CiliumEndpoint。本文中提到 Endpoint 除非特地阐明,都是指 CiliumEndpoint

kubectl get CiliumEndpoint -n default
NAME      ENDPOINT ID   IDENTITY ID   INGRESS ENFORCEMENT   EGRESS ENFORCEMENT   VISIBILITY POLICY   ENDPOINT STATE   IPV4          IPV6
curl      2580          1979          <status disabled>     <status disabled>    <status disabled>   ready            10.42.0.171
httpbin   205           20965         <status disabled>     <status disabled>    <status disabled>   ready            10.42.1.205

能够看到咱们部署的示例利用对应的 Endpoint 信息,进一步查看 Endpoint curl 的详细信息:

apiVersion: cilium.io/v2
kind: CiliumEndpoint
metadata:
  creationTimestamp: "2023-05-20T05:15:24Z"
  generation: 1
  labels:
    app: curl
  name: curl
  namespace: default
  ownerReferences:
  - apiVersion: v1
    kind: Pod
    name: curl
    uid: d34675ea-8f4d-4bad-a1c4-02d183380846
  resourceVersion: "1197"
  uid: c4d7cdb5-c3a8-4ff8-bf03-d6623a0ec00a
status:
  encryption: {}
  external-identifiers:
    container-id: 60dbc4edc0e5bf70b5290feea448559693b7fb51f7b1c3cf996b310c6cd8a576
    k8s-namespace: default
    k8s-pod-name: curl
    pod-name: default/curl
  id: 2580
  identity:
    id: 1979
    labels:
    - k8s:app=curl
    - k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
    - k8s:io.cilium.k8s.policy.cluster=default
    - k8s:io.cilium.k8s.policy.serviceaccount=default
    - k8s:io.kubernetes.pod.namespace=default
  networking:
    addressing:
    - ipv4: 10.42.0.171
    node: 192.168.1.21
  policy:
    egress:
      enforcing: false
      state: <status disabled>
    ingress:
      enforcing: false
      state: <status disabled>
  state: ready
  visibility-policy-status: <status disabled>

Endpoint 大部分信息都集中在 status 局部。 为了分别 Endpoint,每个 Endpoint 都有一个在 Node 节点范畴上惟一的 ID。 比方应用 Endpoint curl 的 ID 2580,在所在节点的 agent 中执行 cilium endpoint get 2580 同样能够失去与 status 局部雷同的信息。

除此以外每个 Endpoint 还有一个 Identity(身份),身份是用于执行在 Endpoint 之间执行根本连贯的信息,在集群范畴内惟一。身份中蕴含了标签信息,这些标签信息是创立 Endpoint 时从 Pod 或者容器来的。

比方这里咱们创立 Pod curl,容器运行时将 Pod 相干的信息作为执行 CNI ADD 操作的参数 CNI_ARGS 传递给 CNI 插件(这里是 Cilium CNI,对这部分有趣味的能够看下之前的文章《认识一下容器网络接口 CNI》)。Cilium CNI 将这些信息以及其余内容作为创立 Endpoint 的根据,传递给 cilium-agent 来创立 Endpoint。这些信息最终作为 identity.labels 存在。

节点 Node

Cilium 中节点是集群的成员,每个节点上都必须运行 cilium-agent。与 Endpoint 一样,Cilium 也提供了 CRD CiliumNode,前面文中提到的节点,如非特指均是 Cilium 的 CiliumNode

kubectl get CiliumNode
NAME           AGE
ubuntu-test1   14m
ubuntu-test2   13m

工作机制

上面只是简略概括了 Cilium 在几个场景下的工作原理,疏忽了大量的细节。

新节点退出

Cilium Agent 以 DaemonSet 的形式部署,运行在各个 Node 节点上。当有新的节点退出时,Operator 会监测到新的节点退出,为节点调配 Pod CIDR 并创立 CiliumNode

新的 Agent 实例调度到该节点上运行,接着为节点上的 CLI、CNI 等操作提供 API 的反对;加载根底 BPF 程序;初始化 BPF Map 等操作。

Pod 创立

当容器运行时通过 CNI 来创立 Pod 的网络命名空间,当执行到 CNI 插件时,CNI 插件会调用 Agent API 来调配 IP 地址、创立 CiliumEndpoint,并在 Pod 的网络命名空间中加载必要的 BPF 程序。

网络策略

应用 Cilium 的 CiliumNetworkPolicy 能够灵便地定义利用的网络通信策略,例如容许或回绝特定的流量流入和流出利用。以此保障只有通过受权的流量能够拜访应用程序,提供细粒度的访问控制。

以《应用 Cilium 加强 Kubernetes 网络安全》中应用的策略为例。

apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "rule1"
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"

Cilium Agent 中运行着大量的 watcher,其中一个就是 CiliumNetworkPolicy watcher。当策略创立或者更新时,Agent 会对策略进行转换并将规定存储到 BPF Map 中。在网络通信时,BPF 程序会对网络流量进行查看并决定该当容许或者回绝拜访。

关注 ” 云原生指北 ” 公众号
(转载本站文章请注明作者和出处盛世浮生,请勿用于任何商业用途)

正文完
 0