使用Cilium/eBPF实现大规模云原生网络和安全
大家读完觉得有帮助记得关注和点赞!!!
目录
抽象
1 Trip.com 云基础设施
1.1 分层架构
1.2 更多细节
2 纤毛在 Trip.com
2.1 推出时间表
2.2 自定义
2.3 优化和调整
2.3.1 解耦安装
2.3.2 避免重试/重启风暴
2.3.3 稳定性优先
2.3.4 规划规模
2.3.5 性能调优
2.3.6 可观察性和警报
2.3.7 其他选项
2.4 多集群解决方案
2.4.1 集群网格
2.4.2 KVStoreMesh
3 高级故障排除技巧
3.1 使用delve/dlv
3.2 使用bpftrace
3.2.1 使用绝对路径
2.3.2 带 PID/proc/
3.3 操作 BPF 映射bpftool
3.4 使用 API 操作 kvstore 内容etcdctl
4 总结
抽象
Trip.com 年,我们将第一个 Cilium 节点(裸机)投入生产 在 2019 年。从那时起,我们几乎所有的 Kubernetes 集群 - 都是本地的 公共云中的裸机和自我管理的集群 - 已切换到 Cilium。
现在有 ~10K 个节点,~300K Pod 在 Kubernetes 上运行, Cilium 为我们的关键业务服务提供支持,例如酒店 搜索引擎、金融/支付服务、内存数据库、数据存储 服务,其中涵盖了延迟方面的广泛要求, 吞吐量等
根据我们 4 年的经验,观众将学习 Cilium 的云原生网络和安全性,包括:
- 如何使用 CiliumNetworkPolicy 进行 L3/L4 访问控制,包括将安全模型扩展到 BM/VM 实例;
- 我们名为 KVStoreMesh 的新多集群解决方案作为 ClusterMesh 的替代方案,以及我们如何使其与社区兼容以便轻松升级;
- 大规模构建稳定性,例如管理控制平面和多集群中断,以及我们因此对 Cilium 所做的改进。
1 Trip.com 云基础设施
1.1 分层架构
Trip.com 云团队负责公司在全球的基础设施,如下所示:
- 在底部,我们有数据中心和几个公共云供应商;
- 底部上方是我们用于 BM、VM 和容器的编排系统;
- 再上一层是内部开发的持续交付平台 (CI/CD);
- 顶部是我们的业务服务和相应的中间件;
- 在垂直方向上,我们在不同级别都有安全和管理工具。
云范围是图中所示的框。
1.2 更多细节
有关我们基础设施的更多具体信息:
- 我们的大部分工作负载现在都在 Kubernetes 上运行,我们有 3 个大型 集群和几个小型集群,具有总节点和 pod;
~10k
~300k
- 大多数 Kubernetes 节点都是刀片服务器;哪
- 使用内部维护的
4.19/5.10
内核运行; - 对于主机间网络,我们将 BGP 用于本地集群和 ENI 适用于云上的自建集群。
2 纤毛在 Trip.com
2.1 推出时间表
以下是我们推出流程的简单时间表:
- 我们从 2018 年开始研究云原生网络解决方案 [9],当然,Cilium 胜出;
- 我们的第一个纤毛节点于 2019 年投入生产 [10];
- 从那时起,我们的各种业务和基础设施服务开始透明地迁移到 Cilium。
2021 年,随着大多数在线业务已经在 Cilium 中, 我们启动了一个基于 Cilium 网络策略的安全项目 [8]。
我们使用的功能:
- 服务负载均衡 (eBPF/XDP)
- CiliumNetworkPolicy (CNP)
- eBPF 主机路由
- eBPF 带宽管理器
- 哈勃(部分)
- Rsyslog 驱动程序
- 性能提升选项,如 sockops、eBPF 重定向
- …
2.2 自定义
首先,此处显示了两个 Kubernetes 集群,
我们基于上述拓扑的一些自定义:
- 使用 docker-compose 部署 cilium 以去除 kubernetes 依赖 [1];
- 为每个代理分配一个用于 Kubernetes 身份验证的专用证书,而不是所有代理共享的 seviceaccount;
- 我们已经帮助完善了 Cilium 的 rsyslog 驱动程序,并已将所有代理日志发送到 ClickHouse 进行故障排除;
- 添加了一些补丁来促进业务迁移,但这并不是那么通用,所以我们没有将它们上游化;
- 使用 BIRD 作为 BGP 代理,而不是建议的 kube-router,我们已经为 Cilium 文档贡献了 BGP+Cilium 指南;
- 我们开发了一种新的多集群解决方案,称为 KVStoreMesh [4]。更多关于这个 lader 的信息。
2.3 优化和调整
现在是优化和调整部分。
2.3.1 解耦安装
刚才说的,我们做的第一件事就是解耦 Cilium 从 Kubernetes 部署/安装:没有 daemonset,没有 configmap。所有 代理所需的配置位于节点上。
这使得代理受 Kubernetes 中断的影响较小,但更重要的是,每个代理现在在配置和升级方面都是完全独立的。
2.3.2 避免重试/重启风暴
第二个考虑因素是避免重试风暴和突发启动, 因为请求将激增两个数量级甚至更高 当发生中断时,这很容易崩溃或卡住中央组件 如 Kubernetes apiserver/etcd 和 kvstore 一样。
我们使用内部开发的重启回退 (jitter+backoff) 机制来避免此类情况。 抖动窗口是根据 Cluster Scale 计算的。 如
- 对于具有 1000 个节点的集群,抖动窗口可能是 20 分钟,在此期间,每个代理只能启动一次,然后退出。
- 对于具有 5000 个节点的集群,抖动窗口可能为 60 分钟。
- 退避机制作为 bash 脚本实现(所有状态都保存在本地文件中),使用 在 docker-compose 中作为 “pre-start hook” 时,Cilium 代码没有变化。
此外,我们还为每个代理分配了一个不同的证书(每个代理都有一个 专用用户名,但属于公共用户组),这将启用 Kubernetes 使用 APF(API 优先级和公平性)对 Cilium 代理执行速率限制。也没有更改 Cilium 代码来实现这一点。
如果您想了解有关 Kubernetes AuthN/AuthZ 模型的更多信息,请参阅我们之前的博客 [2,3]。
2.3.3 稳定性优先
Trip.com 7x24 小时在全球范围内提供在线预订服务,因此随时 在任何一天,业务服务中断都会导致 公司。因此,我们不能冒险让网络等基础服务通过简单的 “快速故障” 规则自行重启,而倾向于必要的人工干预和决策。
当失败出现时,我们希望像 Cilium 这样的服务能更有耐心,只是 在那里等待并保持当前业务不中断,让系统开发人员和 维护者决定做什么;快速失败和自动重试 在这种情况下,让事情变得更糟。
一些特定选项(带有示例配置)来调整此行为:
--allocator-list-timeout=3h
--kvstore-lease-ttl=86400s
--k8s-syn-timeout=600s
--k8s-heartbeat-timeout=60s
请参阅 Cilium 文档或源代码以找出每个选项的内容 确切的含义,并根据您的需要自定义它们。
2.3.4 规划规模
根据您的集群规模,某些内容需要提前规划。 例如,身份相关标签 () 直接确定 集群中的最大 pod:一组标签映射到 在 Cilium 中只有一个身份,所以在它的设计中,所有具有相同标签的 Pod 都共享相同的身份。 但是,如果你的 Bean 太细粒度(不幸的是,这是默认的 case),这可能会导致每个 Pod 都有不同的身份,在最坏的情况下,你的集群规模为 上限为 64K
pod,因为表示身份 替换为整数。有关更多信息,请参阅 [8]。--labels
--labels=<labels>
16bit
此外,还有一些参数需要根据 您的工作负载吞吐量,例如 Identity Allocation Mode、Connection Tracking Table。
选项:
--cluster-id
/--cluster-name
:避免多集群场景中的身份冲突;--labels=<labellist>
Identity Relevent 标签-
--identity-allocation-mode
和 kvstore 基准测试(如果使用 kvstore 模式)我们使用模式,并在大型集群的专用刀片服务器上运行 kvstore (cilium etcd)。
kvstore
--bpf-ct-*
--api-rate-limit
- 用于减少可观测性数据量的 Monitor 聚合选项
2.3.5 性能调优
Cilium 包含许多高性能选项,例如 sockops 和 BPF 主机 routing,当然,所有这些功能都需要特定的内核版本 支持。
--socops-enable
--bpf-lb-sock-hostns-only
- …
此外,禁用一些调试级别选项也是必要的:
--disable-cnp-status-updates
- …
2.3.6 可观察性和警报
我们要讨论的最后一个方面是可观测性。
- 度量
- 伐木
- 描图
除了来自 Cilium agent/operator 的指标数据外,我们还 还收集了所有代理/操作员日志(日志记录数据)并发送 到 ClickHouse 进行分析,这样,我们就可以对异常指标进行告警,以及 错误/警告日志、
此外,跟踪也很有帮助,稍后会详细介绍。
2.3.7 其他选项
--enable-hubble
--keep-config
--log-drivers
--policy-audit-mode
2.4 多集群解决方案
现在我们来看一下多集群问题。
由于历史原因,我们的业务部署在不同的 数据中心和 Kubernetes 集群。 因此,存在没有 L4/L7 边界网关的集群间通信。 这对访问控制来说是一个问题,因为 Cilium 身份是一个集群范围的对象。
2.4.1 集群网格
这个问题的社区解决方案是 ClusterMesh,如下所示,
ClusterMesh 要求每个 agent 连接到所有集群中的每个 kvstore, 有效地产生点对点网格。虽然这个解决方案是直接的 向前,它遇到了稳定性和可扩展性问题,尤其是对于大型 集群。
简而言之,当单个集群宕机时,故障很快就会传播到所有集群 网格中的其他集群, 最终,所有集群可能会同时崩溃,如下所示:
从本质上讲,这是因为 ClusterMesh 中的集群耦合得太紧密了。
2.4.2 KVStoreMesh
我们解决这个问题的概念非常简单: 从所有远程 KVSache 中提取元数据,并在筛选后推送到本地 KVSares。
三集群案例更清楚地显示了这个概念:只涉及 kvstores,
在 ClusterMesh 中,代理从远程 kvstores 获取远程元数据;在 KVStoreMesh 中,它们从本地获取。
感谢 cilium 的良好设计,这只需要对代理和操作符 [4] 进行一些改进和/或错误修复,我们已经 他们中的一些人被上游。kvstoremesh-operator 是新引入的,目前在内部维护; 我们也会在下一个版本投入更多精力将其上游化。
此外,我们还开发了一个简单的解决方案,让 Cilium 注意我们的遗留工作负载,例如 OpenStack 中的虚拟机, the-solultion 称为 CiliumExeternalResource。请看我们之前的 博客 [8] 如果你感兴趣的话。
3 高级故障排除技巧
现在让我们回到一些方便的东西。
第一个是调试。
3.1 使用delve/dlv
Delve 是一个好朋友,我们的 docker-compose 方式使调试更加容易。 由于每个代理程序都是独立部署的,因此命令可以 在节点上执行以启动/停止/重新配置代理。
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#999988"><em># Start cilium-agent agent container with entrypoint `sleep 10d`, then enter the container</em></span>
<span style="color:#000000"><strong>(</strong></span>node<span style="color:#000000"><strong>)</strong></span> <span style="color:#008080">$ </span>docker <span style="color:#0086b3">exec</span> <span style="color:#000080">-it</span> cilium-agent bash<span style="color:#000000"><strong>(</strong></span>cilium-agent ctn<span style="color:#000000"><strong>)</strong></span> <span style="color:#008080">$ </span>dlv <span style="color:#0086b3">exec</span> /usr/bin/cilium-agent <span style="color:#000080">--</span> <span style="color:#000080">--config-dir</span><span style="color:#000000"><strong>=</strong></span>/tmp/cilium/config-map
Type <span style="color:#dd1144">'help'</span> <span style="color:#000000"><strong>for </strong></span>list of commands.
<span style="color:#000000"><strong>(</strong></span>dlv<span style="color:#000000"><strong>)</strong></span><span style="color:#000000"><strong>(</strong></span>dlv<span style="color:#000000"><strong>)</strong></span> <span style="color:#0086b3">break </span>github.com/cilium/cilium/pkg/endpoint.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>Endpoint<span style="color:#000000"><strong>)</strong></span>.regenerateBPF
Breakpoint 3 <span style="color:#0086b3">set </span>at 0x1e84a3b <span style="color:#000000"><strong>for </strong></span>github.com/cilium/cilium/pkg/endpoint.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>Endpoint<span style="color:#000000"><strong>)</strong></span>.regenerateBPF<span style="color:#000000"><strong>()</strong></span> /go/src/github.com/cilium/cilium/pkg/endpoint/bpf.go:591
<span style="color:#000000"><strong>(</strong></span>dlv<span style="color:#000000"><strong>)</strong></span> <span style="color:#0086b3">break </span>github.com/cilium/cilium/pkg/endpoint/bpf.go:1387
Breakpoint 4 <span style="color:#0086b3">set </span>at 0x1e8c27b <span style="color:#000000"><strong>for </strong></span>github.com/cilium/cilium/pkg/endpoint.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>Endpoint<span style="color:#000000"><strong>)</strong></span>.syncPolicyMapWithDump<span style="color:#000000"><strong>()</strong></span> /go/src/github.com/cilium/cilium/pkg/endpoint/bpf.go:1387
<span style="color:#000000"><strong>(</strong></span>dlv<span style="color:#000000"><strong>)</strong></span> <span style="color:#000000"><strong>continue</strong></span>
...<span style="color:#000000"><strong>(</strong></span>dlv<span style="color:#000000"><strong>)</strong></span> clear 1
Breakpoint 1 cleared at 0x1e84a3b <span style="color:#000000"><strong>for </strong></span>github.com/cilium/cilium/pkg/endpoint.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>Endpoint<span style="color:#000000"><strong>)</strong></span>.regenerateBPF<span style="color:#000000"><strong>()</strong></span> /go/src/github.com/cilium/cilium/pkg/endpoint/bpf.go:591
<span style="color:#000000"><strong>(</strong></span>dlv<span style="color:#000000"><strong>)</strong></span> clear 2
Breakpoint 2 cleared at 0x1e8c27b <span style="color:#000000"><strong>for </strong></span>github.com/cilium/cilium/pkg/endpoint.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>Endpoint<span style="color:#000000"><strong>)</strong></span>.syncPolicyMapWithDump<span style="color:#000000"><strong>()</strong></span> /go/src/github.com/cilium/cilium/pkg/endpoint/bpf.go:1387
</code></span></span></span>
我们以这种方式跟踪了几个 bug。
3.2 使用bpftrace
另一个有用的工具是用于实时跟踪的 bpftrace。
但请注意,跟踪容器进程存在一些差异。 您需要在节点上找到 cilium-agent 二进制文件的 PID 命名空间或绝对路径。
3.2.1 使用绝对路径
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#999988"><em># Check cilium-agent container</em></span>
<span style="color:#008080">$ </span>docker ps | <span style="color:#0086b3">grep </span>cilium-agent
0eb2e76384b3 cilium:20220516 <span style="color:#dd1144">"/usr/bin/cilium-agent ..."</span> 4 hours ago Up 4 hours cilium-agent<span style="color:#999988"><em># Find the merged path for cilium-agent container</em></span>
<span style="color:#008080">$ </span>docker inspect <span style="color:#000080">--format</span> <span style="color:#dd1144">"{{.GraphDriver.Data.MergedDir}}"</span> 0eb2e76384b3
/var/lib/docker/overlay2/0a26c6/merged <span style="color:#999988"><em># 0a26c6.. is shortened for better viewing</em></span>
<span style="color:#999988"><em># The object file we are going to trace</em></span>
<span style="color:#008080">$ </span><span style="color:#0086b3">ls</span> <span style="color:#000080">-ahl</span> /var/lib/docker/overlay2/0a26c6/merged/usr/bin/cilium-agent
/var/lib/docker/overlay2/0a26c6/merged/usr/bin/cilium-agent <span style="color:#999988"><em># absolute path</em></span><span style="color:#999988"><em># Or you can find it bruteforcelly if there are no performance (e.g. IO spikes) concerns:</em></span>
<span style="color:#008080">$ </span>find /var/lib/docker/overlay2/ <span style="color:#000080">-name</span> cilium-agent
/var/lib/docker/overlay2/0a26c6/merged/usr/bin/cilium-agent <span style="color:#999988"><em># absolute path</em></span>
</code></span></span></span>
无论如何,在找到目标文件并检出其中的符号后,
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>nm /var/lib/docker/overlay2/0a26c6/merged/usr/bin/cilium-agent
0000000001d3e940 T type..hash.github.com/cilium/cilium/pkg/k8s.ServiceID
0000000001f32300 T type..hash.github.com/cilium/cilium/pkg/node/types.Identity
0000000001d05620 T type..hash.github.com/cilium/cilium/pkg/policy/api.FQDNSelector
0000000001d05e80 T type..hash.github.com/cilium/cilium/pkg/policy.PortProto
...
</code></span></span></span>
您可以像下面这样启动用户空间探测,打印您希望看到的内容:
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>bpftrace <span style="color:#000080">-e</span> <span style="color:#dd1144">\</span><span style="color:#dd1144">'uprobe:/var/lib/docker/overlay2/0a26c6/merged/usr/bin/cilium-agent:"github.com/cilium/cilium/pkg/endpoint.(*Endpoint).regenerateBPF" {printf("%s\n", ustack);}'</span>
Attaching 1 probe...github.com/cilium/cilium/pkg/endpoint.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>Endpoint<span style="color:#000000"><strong>)</strong></span>.regenerateBPF+0github.com/cilium/cilium/pkg/endpoint.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>EndpointRegenerationEvent<span style="color:#000000"><strong>)</strong></span>.Handle+1180github.com/cilium/cilium/pkg/eventqueue.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>EventQueue<span style="color:#000000"><strong>)</strong></span>.run.func1+363sync.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>Once<span style="color:#000000"><strong>)</strong></span>.doSlow+236github.com/cilium/cilium/pkg/eventqueue.<span style="color:#000000"><strong>(</strong></span><span style="color:#000000"><strong>*</strong></span>EventQueue<span style="color:#000000"><strong>)</strong></span>.run+101runtime.goexit+1
</code></span></span></span>
2.3.2 带 PID/proc/<PID>
更方便、更简洁的方法是找到 PID 命名空间并将其传递给 ,这将使命令更短:bpftrace
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span><span style="color:#0086b3">sudo </span>docker inspect <span style="color:#000080">-f</span> <span style="color:#dd1144">'{{.State.Pid}}'</span> cilium-agent
109997
<span style="color:#008080">$ </span>bpftrace <span style="color:#000080">-e</span> <span style="color:#dd1144">'uprobe:/proc/109997/root/usr/bin/cilium-agent:"github.com/cilium/cilium/pkg/endpoint.(*Endpoint).regenerate" {printf("%s\n", ustack); }'</span>
</code></span></span></span>
或
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>bpftrace <span style="color:#000080">-p</span> 109997 <span style="color:#000080">-e</span> <span style="color:#dd1144">'uprobe:/usr/bin/cilium-agent:"github.com/cilium/cilium/pkg/endpoint.(*Endpoint).regenerate" {printf("%s\n", ustack); }'</span>
</code></span></span></span>
3.3 操作 BPF 映射bpftool
现在考虑一个具体问题:如何确定 CNP 是否真的生效?有几种方法:
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>kubectl get cnp <span style="color:#000080">-n</span> <ns> <cnp> <span style="color:#000080">-o</span> yaml <span style="color:#999988"><em># spec & status in k8s</em></span>
<span style="color:#008080">$ </span>cilium endpoint get <ep <span style="color:#0086b3">id</span><span style="color:#000000"><strong>></strong></span> <span style="color:#999988"><em># spec & status in cilium userspace</em></span>
<span style="color:#008080">$ </span>cilium bpf policy get <ep <span style="color:#0086b3">id</span><span style="color:#000000"><strong>></strong></span> <span style="color:#999988"><em># summary of kernel bpf policy status</em></span>
</code></span></span></span>
- 查询 Kubernetes?不,这太高了;
- 查看终端节点状态?不,这是一个用户空间状态,仍然太高级别了;
- 使用 cilium 命令检查 bpf 策略?嗯,这确实是一个总结 的 BPF 策略,但摘要代码本身也可能有 bug;
最底层的策略状态是内核中的 BPF 策略映射,我们可以通过 bpftool 查看它:
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>bpftool map dump pinned cilium_policy_00794 <span style="color:#999988"><em># REAL & ULTIMATE policies in the kernel!</em></span>
</code></span></span></span>
但是要使用此工具,您首先需要熟悉一些 Cilium 数据结构。 比如,IP 地址如何对应一个身份,以及如何组合 身份、端口、协议、流量方向在 BPF 策略映射中形成一个键。
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#999988"><em># Get the corresponding identity of an (client) IP address</em></span>
<span style="color:#008080">$ </span>cilium bpf ipcache get 10.2.6.113
10.2.6.113 maps to identity 298951 0 0.0.0.0<span style="color:#999988"><em># Convert a numeric identity to its hex representation</em></span>
<span style="color:#008080">$ </span><span style="color:#0086b3">printf</span> <span style="color:#dd1144">'%08x'</span> 298951
00048fc7<span style="color:#999988"><em># Search if there exists any policy related to this identity</em></span>
<span style="color:#999988"><em>#</em></span>
<span style="color:#999988"><em># Key format: identity(4B) + port(2B) + proto(1B) + direction(1B)</em></span>
<span style="color:#999988"><em># For endpoint 794's TCP/80 ingress, check if allow traffic from identity 298951</em></span>
<span style="color:#008080">$ </span>bpftool map dump pinned cilium_policy_00794 | <span style="color:#0086b3">grep</span> <span style="color:#dd1144">"c7 8f 04 00"</span> <span style="color:#000080">-B</span> 1 <span style="color:#000080">-A</span> 3
key:
c7 8f 04 00 00 50 06 00 <span style="color:#999988"><em># 4B identity + 2B port(80) + 1B L4Proto(TCP) + direction(ingress)</em></span>
value:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
</code></span></span></span>
键和值数据结构:
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#999988"><em>// PolicyKey represents a key in the BPF policy map for an endpoint. It must</em></span>
<span style="color:#999988"><em>// match the layout of policy_key in bpf/lib/common.h.</em></span>
<span style="color:#999988"><em>// +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapKey</em></span>
<span style="color:#000000"><strong>type</strong></span> PolicyKey <span style="color:#000000"><strong>struct</strong></span> {Identity <span style="color:#445588"><strong>uint32</strong></span> <span style="color:#dd1144">`align:"sec_label"`</span>DestPort <span style="color:#445588"><strong>uint16</strong></span> <span style="color:#dd1144">`align:"dport"`</span> <span style="color:#999988"><em>// In network byte-order</em></span>Nexthdr <span style="color:#445588"><strong>uint8</strong></span> <span style="color:#dd1144">`align:"protocol"`</span>TrafficDirection <span style="color:#445588"><strong>uint8</strong></span> <span style="color:#dd1144">`align:"egress"`</span>
}<span style="color:#999988"><em>// PolicyEntry represents an entry in the BPF policy map for an endpoint. It must</em></span>
<span style="color:#999988"><em>// match the layout of policy_entry in bpf/lib/common.h.</em></span>
<span style="color:#999988"><em>// +k8s:deepcopy-gen:interfaces=github.com/cilium/cilium/pkg/bpf.MapValue</em></span>
<span style="color:#000000"><strong>type</strong></span> PolicyEntry <span style="color:#000000"><strong>struct</strong></span> {ProxyPort <span style="color:#445588"><strong>uint16</strong></span> <span style="color:#dd1144">`align:"proxy_port"`</span> <span style="color:#999988"><em>// In network byte-order</em></span>Flags <span style="color:#445588"><strong>uint8</strong></span> <span style="color:#dd1144">`align:"deny"`</span>Pad0 <span style="color:#445588"><strong>uint8</strong></span> <span style="color:#dd1144">`align:"pad0"`</span>Pad1 <span style="color:#445588"><strong>uint16</strong></span> <span style="color:#dd1144">`align:"pad1"`</span>Pad2 <span style="color:#445588"><strong>uint16</strong></span> <span style="color:#dd1144">`align:"pad2"`</span>Packets <span style="color:#445588"><strong>uint64</strong></span> <span style="color:#dd1144">`align:"packets"`</span>Bytes <span style="color:#445588"><strong>uint64</strong></span> <span style="color:#dd1144">`align:"bytes"`</span>
}<span style="color:#999988"><em>// pkg/maps/policymap/policymap.go</em></span><span style="color:#999988"><em>// Allow pushes an entry into the PolicyMap to allow traffic in the given</em></span>
<span style="color:#999988"><em>// `trafficDirection` for identity `id` with destination port `dport` over</em></span>
<span style="color:#999988"><em>// protocol `proto`. It is assumed that `dport` and `proxyPort` are in host byte-order.</em></span>
<span style="color:#000000"><strong>func</strong></span> (pm <span style="color:#000000"><strong>*</strong></span>PolicyMap) Allow(id <span style="color:#445588"><strong>uint32</strong></span>, dport <span style="color:#445588"><strong>uint16</strong></span>, proto u8proto<span style="color:#000000"><strong>.</strong></span>U8proto, trafficDirection trafficdirection<span style="color:#000000"><strong>.</strong></span>TrafficDirection, proxyPort <span style="color:#445588"><strong>uint16</strong></span>) <span style="color:#445588"><strong>error</strong></span> {key <span style="color:#000000"><strong>:=</strong></span> newKey(id, dport, proto, trafficDirection)pef <span style="color:#000000"><strong>:=</strong></span> NewPolicyEntryFlag(<span style="color:#000000"><strong>&</strong></span>PolicyEntryFlagParam{})entry <span style="color:#000000"><strong>:=</strong></span> newEntry(proxyPort, pef)<span style="color:#000000"><strong>return</strong></span> pm<span style="color:#000000"><strong>.</strong></span>Update(<span style="color:#000000"><strong>&</strong></span>key, <span style="color:#000000"><strong>&</strong></span>entry)
}
</code></span></span></span>
bpftool
在紧急情况下也会来救援,例如当 流量被拒绝,但您的 Kubernetes 或 Cilium 代理无法准备就绪, 只需插入一个 allow-any
规则,如下所示:
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#999988"><em># Add an allow-any rule in emergency cases</em></span>
<span style="color:#008080">$ </span>bpftool map update pinned <map> <span style="color:#dd1144">\</span>key hex 00 00 00 00 00 00 00 00 <span style="color:#dd1144">\</span>value hex 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 noexist
</code></span></span></span>
3.4 使用 API 操作 kvstore 内容etcdctl
我们要分享的最后一个技能是操作 kvstore 内容。
同样,这需要对 Cilium 数据模型有深入的了解。 例如,将以下三个条目插入 kvstore 中,
<span style="color:#333333"><span style="background-color:#f8f8f8"><span style="background-color:#f6f8fa"><code><span style="color:#008080">$ </span>etcdctl put <span style="color:#dd1144">"cilium/state/identities/v1/id/15614229"</span> <span style="color:#dd1144">\</span><span style="color:#dd1144">'k8s:app=app1;k8s:io.cilium.k8s.policy.cluster=cluster1;k8s:io.cilium.k8s.policy.serviceaccount=default;k8s:io.kubernetes.pod.namespace=ns1;'</span><span style="color:#008080">$ </span>etcdctl put <span style="color:#dd1144">'k8s:app=app1;k8s:io.cilium.k8s.policy.cluster=cluster1;k8s:io.cilium.k8s.policy.serviceaccount=default;k8s:io.kubernetes.pod.namespace=ns1;/10.3.9.10'</span> <span style="color:#dd1144">\</span>15614229<span style="color:#008080">$ </span>etcdctl put <span style="color:#dd1144">"cilium/state/ip/v1/cluster1/10.3.192.65"</span> <span style="color:#dd1144">\</span><span style="color:#dd1144">'{"IP":"10.3.192.65","Mask":null,"HostIP":"10.3.9.10","ID":15614299,"Key":0,"Metadata":"cilium-global:cluster1:node1:2404","K8sNamespace":"ns1","K8sPodName":"pod1"}'</span>
</code></span></span></span>
所有 cilium-agents 都会收到通知,在 Kubernetes 、 namespace 中创建了一个 pod,其中包含 PoIP、NodeIP、NodeName、pod 标签和 条目中的身份信息。cluster1
default
从本质上讲,这就是我们在 CER 解决方案中将 VM、BM 和非纤毛 pod 注入 Cilium 世界的方式(有关详细信息,请参阅我们之前的帖子 [8]); 它也是 Cilium 网络策略的基础。
警告:操纵 kvstores 和 BPF 映射是危险的, 因此,我们不建议在生产环境中执行这些操作 环境中,除非您知道自己在做什么。
4 总结
我们从 1.4 开始一直在使用 Cilium,现在已经一路升级到 1.10(2022.11 更新)。 它支持我们的业务和基础设施关键服务。 凭借 4 年的经验,我们相信它不仅为大规模生产做好了准备, 而且在性能、功能、社区等方面也是最佳候选人之一。1.11
最后,我想特别感谢 Andre、Denial、Joe、Martynas、Paul、Quentin、Thomas 以及所有 Cilium 的家伙。社区非常好,过去帮了我们很多。
相关文章:
使用Cilium/eBPF实现大规模云原生网络和安全
大家读完觉得有帮助记得关注和点赞!!! 目录 抽象 1 Trip.com 云基础设施 1.1 分层架构 1.2 更多细节 2 纤毛在 Trip.com 2.1 推出时间表 2.2 自定义 2.3 优化和调整 2.3.1 解耦安装 2.3.2 避免重试/重启风暴 2.3.3 稳定性优先 2…...
SQL美化器优化
文章目录 1.目录2.代码 1.目录 2.代码 package com.sunxiansheng.mybatis.plus.inteceptor;import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.*; import org.apache.ibatis.plugin.*; import org.apache.ibatis.reflection.*…...
网络基础1 http1.0 1.1 http/2的演进史
http1.0 1.1 http/2的演进史😎 (连接复用 队头阻塞 服务器推送 2进制分帧) 概述 我们主要关注的是应用层 传输层 http协议发展历史 http的报文结构:起始行 Header Body http的典型特征 http存在的典型问题 Keep Alive机制 chun…...
MySQL不使用子查询的原因
MySQL不使用子查询的原因及优化案例 目录 MySQL不使用子查询的原因及优化案例 目录不推荐使用子查询和JOIN的原因解决方案优化案例 案例1:查询所有有库存的商品信息案例2:使用EXISTS优化子查询案例3:使用JOIN代替子查询案例4:优化…...
网络编程(1)
网络编程概述 Java是 Internet 上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。 Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在 Java 的本机安装系统里&#…...
Jaeger UI使用、采集应用API排除特定路径
Jaeger使用 注: Jaeger服务端版本为:jaegertracing/all-in-one-1.6.0 OpenTracing版本为:0.33.0,最后一个版本,停留在May 06, 2019。最好升级到OpenTelemetry。 Jaeger客户端版本为:jaeger-client-1.3.2。…...
【python:文件->统计飞鸟集单词个数】
主函数.py fopen("飞鸟集.txt",r,encoding"UTF-8")#只读方式打开 contentf.read()# 提取全文,将文件内容字符串对象返回给content dccontent.split("\n")#对字符串调用分割符切割 print(dc) f.close() # 统计单词频率 ofnumcontent.count("…...
解决SpringBoot无法使用JDK8问题
解决SpringBoot无法使用JDK8问题 现状解决方案 现状 使用idea创建springboot项目无法选择java8。原因是23年11月的spring更新后就明确了不在支持java8版本的项目创建,但是目前为止很多公司开发还在用java8,导致会有问题的产生。 解决方案 使用idea创…...
论文导读 | 数据库系统中基于机器学习的基数估计方法
背景 基数估计任务是在一个查询执行之前预测其基数,基于代价的查询优化器(Cost Based Optimizer)将枚举所有可能的执行计划,并利用估计的基数选出期望执行代价最小的计划,从而完成查询优化的任务。 然而,…...
Shader->LinearGradient线性渐变着色器详解
XML文件 <com.example.myapplication.MyViewxmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_gravity"center"android:layout_height"400dp"/>自定义View代码 c…...
Unity打包+摄像机组件
转换场景 使用程序集:using UnityEngine.SceneManagement; 切换场景相关代码:SceneManager.LoadScene(1);//括号内可放入场景名称,场景索引等 //Application.LoadLevel(""); 老版本Unity加载场景方法 打包相关 Bundle Identi…...
Git 命令代码管理详解
一、Git 初相识:版本控制的神器 在当今的软件开发领域,版本控制如同基石般重要,而 Git 无疑是其中最耀眼的明珠。它由 Linus Torvalds 在 2005 年创造,最初是为了更好地管理 Linux 内核源代码。随着时间的推移,Git 凭借…...
游戏引擎学习第78天
Blackboard: Position ! Collision “网格” 昨天想到的一个点,可能本来就应该想到,但有时反而不立即思考这些问题也能带来一些好处。节目是周期性的,每天不需要全程关注,通常只是在晚上思考,因此有时我们可能不能那么…...
Centos9-SSH免密登录配置-修改22端口-关闭密码登录-提高安全性
Centos9-SSH免密登录配置-修改22端口-关闭密码登录 生成秘钥对将公钥信息存进authorized_keys测试登录查询访问记录、比对指纹更换22访问端口关闭账号密码登录生成秘钥对 生成密钥对,指定 备注 和 文件目录命令执行后,默认两次回车,不设置秘钥使用密码ssh-keygen -t rsa -b …...
汇总统计数据--SQL中聚集函数的使用
目录 1、为什么需要汇总数据 2、聚集函数 (1)AVG函数 (2)COUNT函数 (3)MAX和MIN函数 (4)SUM函数 3、聚集不同值--DISTINCT 4、组合聚集函数 5、小结 博主用的是mysql8 DBMS…...
pdf提取文本,表格以及转图片:spire.pdf
文章目录 🐒个人主页:信计2102罗铠威🏅JavaEE系列专栏📖前言:🎀 1. pdfbox1.1导入pdfbox 的maven依赖1.1 提取文本1.2 提取文本表格(可自行加入逻辑处理)1.3 pdf转换成图片代码&…...
【C#学习笔记】C#中委托
概述 C#的委托是一种类型安全的函数指针,用于引用方法,委托允许方法作为参数传递,或者将方法赋值给委托变量,并通过委托调用方法。 委托类型:委托定义了方法的的签名([方法的参数类型和返回值]࿰…...
C#的Task
优先使用Task.Run,除非有定制化需求才用Task.Factory.StartNew Task.Factory.StartNew的TaskScheduler参数颠覆你的认知: var cnt 0;var cancelToken new CancellationTokenSource();await Task.Factory.StartNew(() > {cnt;Debug.WriteLine($&quo…...
企业全文搜索-搜索权限,非侵入文档同步,权限同步 ,扩展字段
简介 企业全文搜索帮助员工高效快速定位所需的信息和资源,搜索权限控制是必须的,原因有二,首先,企业文档,包括公文,流程,技术文档等,带有敏感信息,搜索返回带片段,可能带出敏感信息;其次,若没有权限,用户搜索出来的文档可能不能阅读原文,体验非常差。onesearch有…...
Linux电源管理——CPUidle Framework
目录 前言 一、CPU idle 二、cpuidle framework 相关概念 三、cpuidle core 数据结构 3.1、cpuidle_state 3.2、cpuidle_driver 3.3、cpuidle_device 3.4、cpuidle_governor 四、cpuidle driver初始化流程 4.1、cpuidle driver 初始化方式 4.2、drv->states[0]的初…...
【黑灰产】假钱包推广套路
假钱包推广产业链研究 市面上钱包的主要推广方式: 1,竞价(搜索引擎),误导客户为真正官方钱包从而完成下载使用 优点:精准,客户大 缺点:竞价户容易挂,投资大 2࿰…...
联想java开发面试题及参考答案
IP 协议是哪一层的? IP 协议(Internet Protocol)属于网络层协议。 网络层主要负责将数据从源节点传输到目标节点,它在整个网络通信体系中起到了承上启下的关键作用。在分层网络模型中,下层(如数据链路层)为网络层提供物理链路的连接和帧传输服务。数据链路层关注的是在相…...
C# 继承(接口)
接口 如果一个类派生与一个接口,它就会执行某些函数。并不是所有的面向对象语言都支持接口。 熟悉COM的开发人员应注意,尽管在概念上C#接口类似于COM接口,但他们是不筒的,底层的结构不筒。比如,C#接口并不派生于IUnko…...
FPGA的 基本结构(Xilinx 公司Virtex-II 系列FPGA )
以Xilinx 公司Virtex-II 系列FPGA 为例,其基本结构由下图所示。它是主要由两大部分组成:可编程输入/输出(Programmable I/Os)部分和内部可配置(Configurable Logic)部分。 可编程输入/输出(I/Os…...
妙用编辑器:把EverEdit打造成一个编程学习小环境
1 妙用编辑器:把EverEdit打造成一个编程学习小环境 1.1 应用场景 最近在学习Python语言,由于只是学习和练习,代码规模很小,不想惊动PyCharm、VSCode、WingIDE这些重型武器,只想轻快的敲些代码,记事本虽好&…...
ELK日志分析实战宝典之ElasticSearch从入门到服务器部署与应用
目录 ELK工作原理展示图 一、ElasticSearch介绍(数据搜索和分析) 1.1、特点 1.2、数据组织方式 1.3、特点和优势 1.3.1、分布式架构 1.3.2、强大的搜索功能 1.3.3、数据处理与分析 1.3.4、多数据类型支持 1.3.5、易用性与生态系统 1.3.6、高性…...
【学习笔记】理解深度学习和机器学习的数学基础:数值计算
深度学习作为人工智能领域的一个重要分支,其算法的实现和优化离不开数值计算。数值计算在深度学习中扮演着至关重要的角色,它涉及到如何在计算机上高效、准确地解决数学问题。本文将介绍深度学习中数值计算的一些关键概念和挑战,以及如何应对…...
【Java回顾】Day5 并发基础|并发关键字|JUC全局观|JUC原子类
JUC全称java.util.concurrent 处理并发的工具包(线程管理、同步、协调) 一.并发基础 多线程要解决什么问题?本质是什么? CPU、内存、I/O的速度是有极大差异的,为了合理利用CPU的高性能,平衡三者的速度差异,解决办法…...
VSCODE使用Echarts组件库(不是vue)
第一步打开Echarts官网 Examples - Apache ECharts 第二步随便点击一个图形点击我圈的按钮 第三步...
DNS解析域名简记
域名通常是由: 权威域名.顶级域名.根域名组成的。 从左往右,级别依次升高,这和外国人从小范围到大范围的说话习惯相关。(我们自己是更习惯先说大范围再说小范围,如XX省XX市XX区XX路) DNS解析域名时,会先查…...
选择器css
1.a标签选择 // 选中所具有herf 的元素 [herf] {color: skyblue; } // 选中所具有herfhttps://fanyi.youdao.com/ 的元素 [herf$"youdao.com"] {color:pink; } // 按此顺序书写 link visited hover active // 未访问状态 a:link {color:orange } // 访问状态 a…...
9.4 visualStudio 2022 配置 cuda 和 torch (c++)
一、配置torch 1.Libtorch下载 该内容看了【Libtorch 一】libtorchwin10环境配置_vsixtorch-CSDN博客的博客,作为笔记用。我自己搭建后可以正常运行。 下载地址为windows系统下各种LibTorch下载地址_libtorch 百度云-CSDN博客 下载解压后的目录为: 2.vs…...
ASP.NET Core 实现微服务 -- Polly 服务降级熔断
在我们实施微服务之后,服务间的调用变的异常频繁。多个服务之间可能是互相依赖的关系。某个服务出现故障或者是服务间的网络出现故障都会造成服务调用的失败,进而影响到某个业务服务处理失败。某一个服务调用失败轻则造成当前相关业务无法处理࿱…...
2_CSS3 背景 --[CSS3 进阶之路]
CSS3 中的背景属性提供了许多强大的功能来增强网页设计,包括但不限于多背景图像、渐变、背景大小控制等。以下是一些关键的 CSS3 背景属性及其用法示例。 1. 多重背景图像 CSS3 允许你为一个元素设置多个背景图像。这些图像按照它们在 background-image 属性中定义…...
于交错的路径间:分支结构与逻辑判断的思维协奏
大家好啊,我是小象٩(๑ω๑)۶ 我的博客:Xiao Xiangζั͡ޓއއ 很高兴见到大家,希望能够和大家一起交流学习,共同进步。* 这一节内容很多,文章字数达到了史无前例的一万一,我们要来学习分支与循环结构中…...
升级 CentOS 7.x 系统内核到 4.4 版本
问题描述 在 CentOS 7.x 系统中,默认内核版本是 3.10.x,这个版本可能会带来一些与 Docker 和 Kubernetes 兼容性的问题,导致系统性能不稳定或功能异常。为了提高系统的稳定性和兼容性,建议升级到更高版本的内核,例如 …...
MySQL数据导出导入
一、数据导出 1.导出全库备份到本地的目录 mysqldump -u$USER -p$PASSWD -h127.0.0.1 -P3306 --routines--default-character-setutf8 --lock-all-tables --add-drop-database -A >db.all.sql 2.导出指定库到本地的目录(例如mysql库) mysqldump -u$USER -p$PASSWD -h127.…...
【机器学习:八、逻辑回归】
逻辑回归(Logistic Regression) 1. 逻辑回归的引出 在现实世界中,许多问题都涉及到分类任务。例如: 判断一封邮件是否为垃圾邮件;预测某人是否会患某种疾病;确定图片中是否包含某种特定物体。 这些问题…...
uniapp使用sm4加密
安装:npm install sm-crypto --save 1、在utils下新建crypto.js文件 // sm4 加密 export function encryption(params) {const SM4 require("sm-crypto").sm4const key 0123456789abcdeffedcba9876543212; // 提供的密钥const iv fedcba9876543210012…...
【STM32-学习笔记-1-】GPIO
文章目录 GPIOⅠ、GPIO函数Ⅱ、GPIO_InitTypeDef结构体参数①、GPIO_Mode②、GPIO_Pin③、GPIO_Speed GPIO Ⅰ、GPIO函数 // 将指定的GPIO端口寄存器重置为默认值 void GPIO_DeInit(GPIO_TypeDef* GPIOx);// 将GPIO的备用功能寄存器重置为默认值 void GPIO_AFIODeInit(void);…...
C#中的运算符和类--06
目录 一.运算符 1.赋值运算符 2.算数运算符 3.关系运算符 4.逻辑运算符 5.位运算符 6.三元运算符 7.空合并运算符 8.其他运算符 二.类 1.普通类 2.静态类 3.抽象类 4.密封类 5.部分类 6.泛型类 7.嵌套类 8.记录类 9.接口 一.运算符 1.赋值运算符 定义:赋值…...
【微服务】面试 2、服务雪崩
服务雪崩概念 主要内容:在微服务项目中,微服务间存在远程调用。若某一服务(如服务 d)出现故障,调用它的服务(如服务 a)会失败。若调用方持续向故障服务发起请求,由于服务连接数有限且…...
“深入浅出”系列之QT:(6)如何在一个项目中调用另一个项目
在Qt中,如果想在一个项目中调用另一个项目,这通常意味着想要在一个CMake构建的项目中集成或依赖另一个CMake构建的项目。 1.子模块或子目录方式: 如果另一个项目可以作为一个子模块或子目录包含在当前项目中,可以使用add_sub…...
计算机网络—地址与子网(IPv4)相关知识总结
前言 为了更加清楚的了解该相关知识,下面是发现的一些宝藏博主的博客。 彻底搞懂网络地址、广播地址、主机地址、网关、子网掩码、网络号、主机号 - lipga - 博客园 IP地址(分类)、子网掩码、网络号、主机号、子网号_网络号,主机号,子网号…...
计算机网络 (36)TCP可靠传输的实现
前言 TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP通过多种机制实现可靠传输,这些机制主要包括连接管理、序列号和确认应答机制、重传机制、流量控制、拥塞控制等。 一、连接管理 TCP使用三次握手࿰…...
SQL从入门到实战-2
高级语句 窗口函数 排序窗口函数 例题二十九 select yr,party,votes, rank() over (PARTITION BY yr ORDER BY votes desc) as pson from ge where constituency S14000021 order by party,yr 偏移分析函数 例题三十 select name,date_format(whn,%Y-%m-%d) data, confi…...
基于python的网页表格数据下载--转excel
基于 Python 的网页表格数据爬取与下载:以维基百科为例 目录 基于 Python 的网页表格数据爬取与下载:以维基百科为例1. 背景介绍2. 工具与环境3. 操作步骤1. 获取网页内容2. 定位表格元素3. 表格变身 Pandas DataFrame4. 检查数据,收工!5. 进阶玩法与优化6. 完整代码4. 结果…...
用户界面的UML建模13
􀂄 Concrete Presentation Model 包中所包含的是,在Environment 包中与表示层框架模式中的《apm》类相对应的那些类。 8 结论 本文使用了一个图书馆系统的案例,来论述了关于用户界面的建模。通过使用统一建模语言来对应用系统进行建模&…...
[Python学习日记-75] 计算机基础与网络
[Python学习日记-75] 计算机基础与网络 简介 计算机基础 什么是网络编程 计算机网络 简介 本篇主要介绍的计算机基础是浓缩的,这是因为我们主要学习的是 Python,而 Python 主要是为了开发应用程序的,并不会用它来开发操作系统和嵌入式程序…...
【机器学习:六、特征工程】
1. 特征工程背景意义 在机器学习中,特征工程是模型成功的关键之一。无论算法多么先进,其性能都很大程度上依赖于输入数据的质量。特征工程是指对原始数据进行处理,以创建更适合算法的特征的过程。这一过程在以下方面具有重要意义:…...