cilium
weight: 52
title: 基于eBPF 的网络Cilium
date: “2022-05-21T00:00:00+08:00”
type: book
本节将带你了解什么是
Cilium 是什么?
基于微服务的应用程序分为小型独立服务,这些服务使用
注:
eBPF
扩展的柏克莱封包过滤器(extented Berkeley Packet Filter,缩写
eBPF ) ,是 类Unix 系统上 数据链路层 的一种原始接口,提供原始链路层 封包 的收发,除此之外,如果网卡驱动支持 洪泛 模式,那么它可以让网卡处于此种模式,这样可以收到 网络 上的所有包,不管他们的目的地是不是所在 主机。参考 维基百科 和eBPF 简史及BPF、eBPF、XDP 和Bpfilter 的区别。
Hubble 是什么?
通过建立在
特性
以下是
基于身份的安全性
卓越的性能
传统防火墙仅根据
专为扩展而设计
为什么选择Cilium 和Hubble ?
现代数据中心应用程序的开发已经转向面向服务的体系结构(SOA
这种向高度动态的微服务的转变过程,给确保微服务之间的连接方面提出了挑战和机遇。传统的
另一个挑战是提供准确的可视性,因为传统系统使用
利用
功能概述
透明的保护API
能够保护现代应用程序协议,如
- 允许所有带有方法
GET
和路径/public/.*
的HTTP 请求。拒绝所有其他请求。 - 允许
service1
在Kafka topic 上生成topic1
,service2
消费topic1
。拒绝所有其他Kafka 消息。 - 要求
HTTP 标头X-Token: [0-9]+
出现在所有REST 调用中。
详情请参考
基于身份来保护服务间通信
现代分布式应用程序依赖于诸如容器之类的技术来促进敏捷性并按需扩展。这将导致在短时间内启动大量应用容器。典型的容器防火墙通过过滤源
为了避免受到规模限制,
安全访问外部服务
基于标签的安全性是集群内部访问控制的首选工具。为了保护对外部服务的访问,支持入口(ingress)和出口(egress)的传统基于
简单网络
一个简单的扁平第
支持以下多节点网络模型:
-
Overlay:基于封装的虚拟网络产生所有主机。目前
VXLAN 和Geneve 已经完成,但可以启用Linux 支持的所有封装格式。何时使用此模式:此模式具有最小的基础架构和集成要求。它几乎适用于任何网络基础架构,唯一的要求是主机之间可以通过
IP 连接。 -
本机路由:使用
Linux 主机的常规路由表。网络必须能够路由应用程序容器的IP 地址。何时使用此模式:此模式适用于高级用户,需要了解底层网络基础结构。此模式适用于:
- 本地
IPv6 网络 - 与云网络路由器配合使用
- 如果您已经在运行路由守护进程
- 本地
负载均衡
应用程序容器和外部服务之间的流量的分布式负载均衡。负载均衡使用
注意:负载均衡需要启用连接跟踪。这是默认值。
监控和故障排除
可视性和故障排查是任何分布式系统运行的基础。虽然我们喜欢用 tcpdump
和 ping
,它们很好用,但我们努力为故障排除提供更好的工具。包括以下工具:
- 使用元数据进行事件监控:当数据包被丢弃时,该工具不仅仅报告数据包的源
IP 和目标IP ,该工具还提供发送方和接收方的完整标签信息等。 - 策略决策跟踪:为什么丢弃数据包或拒绝请求。策略跟踪框架允许跟踪运行工作负载和基于任意标签定义的策略决策过程。
- 通过
Prometheus 导出指标:通过Prometheus 导出关键指标,以便与现有仪表板集成。
集成
- 网络插件集成:CNI、libnetwork
- 容器运行时:containerd
- Kubernetes:NetworkPolicy、Label、Ingress、Service
- 日志记录:syslog、fluentd
概念
- 策略身份,
Label 列表<=> 服务身份标识 - 全局的服务
ID ,与VIP 相关联(可选) - 封装的
VTEP (Vxlan Tunnel End Point)映射(可选)
为了简单起见,
组成
下图是
管理员通过
Cilium Agent
- 暴露
API 给运维和安全团队,可以配置容器间的通信策略。还可以通过这些API 获取网络监控数据。 - 收集容器的元数据,例如
Pod 的Label ,可用于Cilium 安全策略里的Endpoint 识别,这个跟Kubernetes 中的service 里的Endpoint 类似。 - 与容器管理平台的网络插件交互,实现
IPAM 的功能,用于给容器分配IP 地址,该功能与 flannel、calico 网络插件类似。 - 将其有关容器标识和地址的知识与已配置的安全性和可视性策略相结合,生成高效的
BPF 程序,用于控制容器的网络转发和安全行为。 - 使用
clang/LLVM 将BPF 程序编译为字节码,在容器的虚拟以太网设备中的所有数据包上执行,并将它们传递给Linux 内核。
命令行工具
cilium
命令使用方式如下。
Usage:
cilium [command]
Available Commands:
bpf 直接访问本地 BPF map
cleanup 重置 agent 状态
completion bash 自动补全
config Cilium 配置选项
debuginfo 从 agent 请求可用的调试信息
endpoint 管理 endpoint
identity 管理安全身份
kvstore 直接访问 kvstore
map 访问 BPF map
monitor 显示 BPF 程序事件
node 管理集群节点
policy 管理安全策略
prefilter 管理 XDP CIDR filter
service 管理 service & loadbalancer
status 显示 daemon 的状态
version 打印版本信息
详细使用情况请参考 Cilium Command Cheatsheet。
策略控制示例
使用docker inspect
来查询使用
"Networks": {
"cilium-net": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"a08e52d13a38"
],
"NetworkID": "c4cc3ac444f3c494beb1355e4a9c4bc474d9a84288ceb2030513e8406cdf4e9b",
"EndpointID": "2e3e4486525c20fc516d0a9d1c52f84edf9a000f3068803780e23b4c6a1ca3ed",
"Gateway": "",
"IPAddress": "10.15.125.240",
"IPPrefixLen": 32,
"IPv6Gateway": "f00d::a0f:0:0:1",
"GlobalIPv6Address": "f00d::a0f:0:0:ed50",
"GlobalIPv6PrefixLen": 128,
"MacAddress": "",
"DriverOpts": null
}
}
- NetworkID:每个网络平面的唯一标识
- EndpointID:每个容器
/Pod 的在网络中的唯一标识
在
策略使用id=app2
标签的容器可以使用id=app1
标签的容器。
[
{
"labels": [{ "key": "name", "value": "l3-rule" }],
"endpointSelector": { "matchLabels": { "id": "app1" } },
"ingress": [
{
"fromEndpoints": [{ "matchLabels": { "id": "app2" } }],
"toPorts": [
{
"ports": [{ "port": "80", "protocol": "TCP" }]
}
]
}
]
}
]
将该配置保存成cilium policy import
命令即可应用到
如图所示,此时 id
标签为其他值的容器就无法访问 id=app1
容器,策略配置中的 toPorts
中还可以配置method
path
,实现更细粒度的访问策略控制。