news 2026/9/14 22:39:41

Cilium Azure IPAM 详解:基于 CRD 与 Azure 私有 IP 的集群级地址分配

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cilium Azure IPAM 详解:基于 CRD 与 Azure 私有 IP 的集群级地址分配

Cilium Azure IPAM 详解:基于 CRD 与 Azure 私有 IP 的集群级地址分配

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

Azure IPAM 是 Cilium 面向非 AKS 自管理集群(运行在 Azure 虚拟机 VM 或虚拟机规模集 VMSS 上)提供的 IP 分配方案,它基于 Azure 私有 IP 地址进行 Pod 地址管理。本文将从整体架构、配置方式、分配/释放算法、Azure 权限模型、故障排查与指标观测六个维度,完整讲解 Cilium 如何在 Azure 云环境中落地 IPAM,并结合仓库源码给出底层实现依据,帮助读者在自建 Azure 集群中正确启用并运维 Azure IPAM。

适用场景与部署形态

Azure IPAM 分配器面向在 Azure 云中运行的 Cilium 部署,基于 Azure 私有 IP 地址。

在 AKS 上运行 Cilium 时,官方推荐以下两种方式,而非本文所述的 Azure IPAM:

  • Azure CNI Powered by Cilium:AKS 完全托管 Cilium 的部署与配置,集群以--network-dataplane cilium创建,IP 分配由 AKS 自身的控制器通过 delegated IPAM 处理。
  • Bring Your Own CNI(BYOCNI):集群以--network-plugin=none创建,由管理员通过 Helm 或 cilium-cli 自行管理 Cilium,可使用任意 Cilium IPAM 后端。

架构上,Azure IPAM 的关键设计是保证只有单个 operator 与 Azure API 通信,从而避免大规模集群中的 API 限流问题;同时通过预分配水位(pre-allocation watermark)在节点上维持一定数量的空闲 IP,使得新 Pod 调度时无需即时请求 Azure API。

架构:CRD-backed 分配器

Azure IPAM 构建在 CRD-backed 分配器之上,其核心交互如下图所示。

整体工作流程分为两侧:

  • Cilium Agent(节点侧):每个节点上的 Cilium 首次启动时,会创建与节点同名的ciliumnodes.cilium.io自定义资源。Agent 获取 Kubernetesv1.Node资源并提取.Spec.ProviderID字段,以此推导出 Azure 实例 ID。Azure 分配参数作为 Agent 配置选项提供,并同步写入该自定义资源。Agent 从 CiliumNode 的spec.ipam.available中取用 IP 分配给 Pod,并将已用 IP 上报到status.ipam.used
  • Cilium Operator(集群侧):Operator 监听新的ciliumnodes.cilium.io自定义资源并自动接管 IPAM 管理。它扫描 Azure 实例上已存在的网卡及其关联 IP,通过spec.ipam.available字段将其发布为可用地址;随后持续监控status.ipam.used中的已用地址,按 IP 预分配水位(watermark)追加分配更多 IP,保证节点上始终有可用地址。

ProviderID 前缀与地址上限等常量定义在 pkg/azure/types/types.go 中:ProviderPrefix = "azure://"用于识别 k8s ProviderID 代表 Azure 资源,InterfaceAddressLimit = 256是单张网卡可关联的最大地址数。Azure 规范字段AzureSpec(含interface-name)会被嵌入v2.CiliumNode自定义资源,而AzureStatus.Interfaces则承载节点网卡状态。

启用 Azure IPAM

启用 Azure IPAM 需要同时在 Agent 与 Operator 上开启:

  • --ipam=azure运行 Cilium Agent 和 Operator,或在 ConfigMap 中设置ipam: azure。该选项会在节点 Agent 与 Operator 中同时启用 Azure IPAM 分配。
  • 大多数场景下,建议在 Agent 首次于节点启动时自动创建ciliumnodes.cilium.io自定义资源:指定--auto-create-cilium-node-resource选项,或在 ConfigMap 中设置auto-create-cilium-node-resource: "true"
  • 通常也建议在 Operator 上通过--enable-metrics开启指标。Prometheus 与 Grafana 面板的安装方式参见 observability/grafana.rst。

在 Helm 部署场景下,上述选项由 install/kubernetes/cilium/templates/cilium-configmap.yaml 自动生成:当azure.enabled为 true 时,模板会设置enable-endpoint-routes: "true"auto-create-cilium-node-resource: "true"azure-use-primary-address,并在配置了azure.nodeSpec.azureInterfaceName时写入azure-interface-name;若设置azure.userAssignedIdentityID则会写入azure-user-assigned-identity-id

Operator 的作用域:订阅、资源组、身份

Operator 通过三段上下文与 Azure 交互,每段都可以从 Azure Instance Metadata Service(IMDS)自动探测,或通过--azure-*系列 operator 参数 显式指定:

  • 订阅(--azure-subscription-id:所有 Azure SDK 客户端都绑定到单一订阅。未设置时,Operator 通过 IMDS 探测其所在节点的订阅。对应的 IMDS 路径为instance/compute/subscriptionId,见 pkg/azure/metadata/metadata.go。
  • 资源组(--azure-resource-group:用于限定按资源组维度的 API 调用,如列出网卡、VMSS 与 Public IP Prefix。该值必须是集群节点所在的资源组。未设置时通过 IMDS 探测节点自身的资源组(路径instance/compute/resourceGroupName),但仅当 Operator Pod 与集群其余节点处于同一资源组时结果才正确。当 worker VM/VMSS 位于不同资源组时(例如自管理集群将控制面与工作节点池拆分到多个资源组),必须显式设置该参数。
  • VNet / 子网资源组:Operator 在运行时从每张网卡的子网 ID 推导 VNet 与子网所属资源组,无对应参数。当 VNet 位于共享网络资源组时,Operator 的身份需要在该资源组拥有读权限。

这些选项的定义位于 operator/option/config.go:azure-subscription-idazure-resource-groupazure-user-assigned-identity-idazure-use-primary-address。其中azure-use-primary-address决定是否将网卡的 primary IP 暴露进可分配池:在 pkg/azure/ipam/instances.go 中该值被镜像为InstancesManager.usePrimary字段,用于在计算网卡可用地址时预留 primary IP 占用的槽位。

认证方式

Operator 使用 Azure Identity SDK 认证,支持两种模式:

  • 默认凭据链(不设置任何参数):当--azure-user-assigned-identity-id为空时,Operator 调用DefaultAzureCredential,依次尝试:环境变量、工作负载身份(projected token)、系统分配托管身份、Azure CLI。这是 AKS 集群配合 Azure AD Workload Identity 的推荐路径。
  • 用户分配托管身份(--azure-user-assigned-identity-id:设置后 Operator 以指定的用户分配托管身份认证。该值必须是身份的client ID(UUID),而非完整的 Azure 资源 ID(/subscriptions/.../userAssignedIdentities/...)。client ID 可在 Azure 门户的身份概览页查看,或通过az identity show -g <resource-group> -n <name> --query clientId -o tsv获取。

自定义 Azure IPAM 配置:Helm 与 CNI ConfigMap

自定义 Azure IPAM 配置可以通过 Helm 或自定义 CNI 配置 ConfigMap 定义。若同一字段同时配置了 Helm 与自定义 CNI,自定义 CNI 优先于 Helm 配置。

通过 Helm 配置

可使用--set或 Helm value 文件指定。下面的示例将 Cilium 配置为:使用eth0网卡进行 Pod IP 分配;最小分配 IP 数设为 10:

helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \ --set azure.enabled=true \ --set azure.nodeSpec.azureInterfaceName=eth0 \ --set ipam.nodeSpec.ipamMinAllocate=10

完整的可用选项见 install/kubernetes/cilium/values.yaml 中的azureipam配置节(azure.enabledazure.nodeSpec.azureInterfaceNameazure.usePrimaryAddressazure.resourceGroupazure.subscriptionIDazure.userAssignedIdentityID等),以及 Helm 参考文档的azure.nodeSpecipam.nodeSpec章节。

通过 CNI 配置 ConfigMap

创建cni-config.yaml,基于以下模板并填写interface-name字段:

apiVersion: v1 kind: ConfigMap metadata: name: cni-configuration namespace: kube-system data: cni-config: |- { "cniVersion":"0.3.1", "name":"cilium", "plugins": [ { "cniVersion":"0.3.1", "type":"cilium-cni", "azure": { "interface-name":"eth0" } } ] }

部署该 ConfigMap:

kubectl apply -f cni-config.yaml

然后按前述方式部署 Cilium,并附加以下 Helm 参数使其使用自定义 CNI 配置:

--set cni.customConf=true \ --set cni.configMap=cni-configuration

azure段在 CNI 配置中的承载结构见 plugins/cilium-cni/types/types.go:CNI 配置中azureJSON 字段直接映射到azureTypes.AzureSpec,其测试用例 types_test.go 验证了azure.interface-name从 CNI 配置读取并解析为AzureSpec{InterfaceName: "eth1"}的行为。

Azure 分配参数

以下参数用于控制 IP 分配,它们对应 pkg/ipam/types/types.go 中IPAMSpec的字段(min-allocatepre-allocatemax-above-watermark)与AzureSpecinterface-name

参数说明
spec.ipam.min-allocate节点首次启动时必须分配的最少 IP 数,定义必须可用的最小地址基数。达到该水位后,由 PreAllocate 与 MaxAboveWatermark 逻辑继续分配。未指定时不要求最小 IP 数(+kubebuilder:validation:Minimum=0)。
spec.ipam.pre-allocate任何时刻必须保持可用的 IP 地址数量,即无需 Operator 介入即可立即分配的地址缓冲。未指定时默认值为8
spec.azure.interface-name用于 IP 分配的网卡名称。

pre-allocate默认值 8 定义在 pkg/defaults/defaults.go(IPAMPreAllocation = 8),并在 operator/pkg/ipam/nodemanager/node.go 的getPreAllocate()中应用:当Spec.IPAM.PreAllocate为 0 时回退到该默认值。同样地,pkg/azure/ipam/node.go 的GetMinimumAllocatableIPv4()也返回defaults.IPAMPreAllocation

运维细节:缓存、水位与分配算法

网卡、子网与虚拟网络缓存

Operator 在缓存中维护与 Azure 订阅关联的所有 ScaleSets、实例、网卡、虚拟网络与子网。缓存每分钟更新一次,或在完成一次 IP 分配后更新;由分配触发的更新最多每秒执行一次。全量同步与单实例增量同步的实现见 pkg/azure/ipam/instances.go:Resync()执行全量同步(先一次性拉取所有网卡,再只针对实际使用的子网 ID 做定向查询,避免无谓的 Azure API 调用),InstanceSync()则对单个实例做增量同步,并将 Azure API 的 404 响应视为实例已不存在,与临时同步失败区分开。

发布可用 IP

缓存更新后,Operator 会更新所有代表节点的 CiliumNode 自定义资源,发布新变为可用的 IP。该过程中会扫描所有网卡上的全部可用 IP:所有发现的 IP 加入spec.ipam.available,每张网卡也加入status.azure.interfaces。若此次更新导致自定义资源发生变化,则通过 Kubernetes API 的Update()和/或UpdateStatus()方法更新资源。状态填充逻辑位于 pkg/azure/ipam/node.go 的PopulateStatusFields():为保证未变化节点的比较结果稳定、跳过重复的状态写入,它对网卡与地址按 ID、IP 排序后再写入Status.Azure.Interfaces

IP 赤字与过剩的判定

Operator 持续监控所有节点,在两种时机检测可用 IP 赤字:CiliumNode 自定义资源被更新时;以及常规间隔(每分钟一次)全量扫描所有节点时。

赤字计算:

spec.ipam.pre-allocate - (len(spec.ipam.available) - len(status.ipam.used))

过剩计算:

(len(spec.ipam.available) - len(status.ipam.used)) - (spec.ipam.pre-allocate + spec.ipam.max-above-watermark)

检测到赤字后,节点被加入需要分配 IP 的队列。通过间隔扫描发现赤字时,节点的分配顺序按其赤字严重程度排列,赤字最大的节点排在分配队列最前;需要释放 IP 的节点排在需要分配的节点之后。分配队列按需处理,但最多每秒处理一次

IP 分配

为存在地址赤字的节点执行分配时,Operator 首先查看该节点(由 CiliumNode 资源代表)已挂载的网卡,然后选择满足以下条件的第一张网卡:

  • 网卡已关联的地址中存在未使用的,或网卡关联地址数小于 Azure 允许的单卡最大地址数(256);
  • 网卡关联的子网仍有可分配的 IP。

单次分配多少 IP 由以下公式决定:

min(AvailableOnSubnet, min(AvailableOnInterface, NeededAddresses + spec.ipam.max-above-watermark))

这意味着单次分配周期分配的 IP 数可能小于满足spec.ipam.pre-allocate所需的量。在 pkg/azure/ipam/node.go 的PrepareIPAllocation()中,候选网卡还需要匹配spec.azure.interface-name(若指定)并通过isAvailableInterface()检查:availableOnInterface = max(256 - len(iface.Addresses), 0)(未启用 primary 地址时上限减一),同时通过FirstSubnetWithAvailableAddresses()确认子网有空闲地址。随后AllocateIPs()依据网卡所属是独立 VM 还是 VMSS,分别调用AssignPrivateIpAddressesVMAssignPrivateIpAddressesVMSS完成实际分配。

静态公网 IP 分配

节点可以从打有标签的 Azure Public IP Prefix 获得静态公网 IP:

  1. 在与节点相同的资源组中创建并标记 Public IP Prefix:

    $ az network public-ip prefix create \ --resource-group $RESOURCE_GROUP \ --name $PREFIX_NAME \ --length 28 \ --tags prefix-tag-key=prefix-tag-value
  2. 在 CNI 配置中设置ipam.static-ip-tags

    { "ipam": { "static-ip-tags": { "prefix-tag-key": "prefix-tag-value" } } }

Operator 会从第一个具有剩余容量且匹配标签的 Prefix 分配公网 IP,并将 Prefix ID 存储在 CiliumNode 的status.ipam.assigned-static-ip中。源码层面的实现为 pkg/azure/ipam/node.go 的AllocateStaticIP(),同样按 VM 与 VMSS 分支调用AssignPublicIPAddressesVM/AssignPublicIPAddressesVMSS

IP 释放

为存在 IP 过剩的节点执行释放时,Operator 扫描节点挂载的网卡,单卡可释放的 IP 数由以下公式决定:

min(FreeOnInterface, (TotalFreeIPs - spec.ipam.pre-allocate - spec.ipam.max-above-watermark))

从源码结构看,Azure 网卡不支持 prefix delegation(IsPrefixDelegated()返回 false、ReleaseIPPrefixes()为空操作),因此释放逻辑围绕单个 IP 展开。

节点终止

当节点或实例终止时,Kubernetes apiserver 发送节点删除事件,Operator 捕获该事件后删除对应的ciliumnodes.cilium.io自定义资源。对应地,实例增量同步中 Azure API 返回 404 时会被转换为nodemanager.ErrInstanceNotFound,供上层据此清理本地实例缓存(pkg/azure/ipam/instances.go)。

Masquerading

Masquerading 可通过 eBPF ip-masq-agent 或设置--ipv4-native-routing-cidr支持。

所需权限(Azure RBAC)

Operator 使用的身份(托管身份、服务主体或工作负载身份联合)需要按拓扑在两个或三个作用域上拥有 Azure RBAC 权限:

  • 节点资源组:授予 VMSS 的读权限,以及向节点 NIC 附加 IP 配置所需的写权限。在 VMSS 上是对 VMSS 实例的 VM model 的写操作,在独立 VM 上是对网络接口本身的写操作(具体见下方Actions拆分)。即通过--azure-resource-group传入的资源组(Operator 与节点同置时也可从 IMDS 自动探测)。
  • VNet / 子网资源组:授予 VNet 与子网的读权限,以及附加新私有 IP 时使用的subnets/join/action。通常与节点资源组相同,也可能是独立的网络资源组。
  • 订阅(可选):仅当希望通过单一角色分配让 VNet 发现跨多个资源组工作时才需要。List调用按 RBAC 过滤,因此订阅级 Reader 并非必需,将相同 Actions 限定到各相关资源组即可。

自定义角色的最小Actions

所有部署共用的权限:

Microsoft.Network/networkInterfaces/read Microsoft.Network/virtualNetworks/read Microsoft.Network/virtualNetworks/subnets/read Microsoft.Network/virtualNetworks/subnets/join/action Microsoft.Compute/virtualMachineScaleSets/read

VMSS 集群额外添加:

Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read Microsoft.Compute/virtualMachineScaleSets/virtualMachines/write

独立 VM 集群额外添加:

Microsoft.Network/networkInterfaces/write

使用 Public IP Prefix 的静态公网 IP 分配时,额外添加:

Microsoft.Network/publicIPPrefixes/read Microsoft.Network/publicIPPrefixes/join/action Microsoft.Compute/virtualMachines/read

两点重要说明:

  • Microsoft.Compute/virtualMachineScaleSets/virtualMachines/write是较宽泛的权限,它授权对实例 VM model 的任何 PATCH,而不仅是 NIC 变更,但对 VMSS 拓扑是必需的:在 VMSS 上,每实例的 NIC 配置属于实例模型本身(Properties.NetworkProfileConfiguration),不存在只允许编辑 NIC 块的更窄 RBAC 动作。Operator 仅使用该权限增删已有 NIC 上的 IP 配置,不会发起 VMSS 实例生命周期操作。独立 VM 部署没有此问题,因为 NIC 是一等资源,通过Microsoft.Network/networkInterfaces/write编辑。
  • 节点资源组不是AKS 集群的资源组。单个资源组可容纳多个 AKS 集群,但每个 AKS 集群会把所有资源归入一个自动托管的次级资源组。

故障排查

  • AuthorizationFailedonMicrosoft.Network/virtualNetworks/read:Operator 的身份对拥有 VNet 的资源组没有读权限。需要添加限定到 VNet 资源组(可能与节点资源组不同)的角色分配。
  • spec.ipam.available一直为空且不发生任何分配--azure-resource-group指向了错误的资源组。请核对该值匹配实际包含 VM 或 VMSS 的资源组,而不是 Operator 自身所在的资源组,也不是 AKS 集群资源组。
  • ManagedIdentityCredential authentication failed--azure-user-assigned-identity-id被设置为完整的资源 ID(/subscriptions/.../userAssignedIdentities/<name>)。请改为传入身份的 client ID(UUID)。

指标观测

开启 Operator 的--enable-metrics后,可通过 IPAM 相关指标观测分配行为。完整指标表见 observability/metrics.rst 的 IPAM 一节(这些指标仅在启用 AWS、AlibabaCloud 或 Azure IPAM 插件时全部启用),核心指标包括:

指标标签说明
ipam_ip_allocation_opssubnet_idIP 分配操作次数。
ipam_ip_release_opssubnet_idIP 释放操作次数。
ipam_allocation_duration_secondstype,status,subnet_idIP 或网卡分配延迟。
ipam_release_duration_secondstype,status,subnet_idIP 或网卡释放延迟。
ipam_nodescategory按类别(totalin-deficitat-capacity)统计的节点数。
ipam_resync_total与外部 IPAM API 的同步操作次数。
ipam_api_duration_secondsoperation,response_code与外部 IPAM API 交互的耗时。
ipam_api_rate_limit_duration_secondsoperation访问外部 IPAM API 时被限流的耗时。
ipam_available_ipstarget_node节点上可用 IP 数(已考虑插件特定的 NIC/地址上限)。
ipam_used_ipstarget_node节点当前已用 IP 数。
ipam_needed_ipstarget_node满足节点分配所需的 IP 数。

其中ipam_nodesin-deficitat-capacity类别由 operator/pkg/ipam/nodemanager/node_manager.go 在每次节点统计后通过metricsAPI.SetNodes(...)更新,可用于快速判断集群中是否存在 IP 分配赤字节点。结合 Grafana 面板(参见 observability/grafana.rst),可以直观监控各节点的可用/已用 IP 水位、分配与释放延迟以及 Azure API 的限流情况,为大规模集群的 IP 容量规划提供依据。

【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 22:38:39

Anolis OS 23.4全面支持RISC-V架构的技术解析

1. 项目概述&#xff1a;Anolis OS 23.4的技术突破龙蜥社区最新发布的Anolis OS 23.4版本&#xff0c;标志着国产操作系统在RISC-V生态支持上的重大进展。这个版本最引人注目的特性是完整支持RVA23 RISC-V架构规范&#xff0c;这意味着开发者现在可以在Anolis OS上构建和运行符…

作者头像 李华
网站建设 2026/9/14 22:38:04

知识图谱增强RAG-从Cypher到企业问答

知识图谱 RAG&#xff1a;让大模型读懂实体关系&#xff0c;而非只搜关键词摘要&#xff1a;本文基于 DeepLearning.AI《RAG 的知识图谱》课程实践&#xff0c;系统讲解如何用 Neo4j 知识图谱增强 RAG&#xff1a;从图建模基础&#xff08;节点/关系/属性/标签&#xff09;、S…

作者头像 李华
网站建设 2026/9/14 22:36:49

CD3ε抗体在T细胞研究与免疫治疗中的关键作用

1. CD3ε抗体在T细胞研究中的核心地位CD3ε抗体作为免疫学研究的重要工具&#xff0c;其价值在于能够特异性识别T细胞表面的CD3ε分子。CD3ε是T细胞受体&#xff08;TCR&#xff09;复合物的关键组成部分&#xff0c;与CD3γ、CD3δ和CD3ζ共同构成TCR-CD3复合物。这个复合物在…

作者头像 李华
网站建设 2026/9/14 22:35:48

ArcGIS脚本工具开发全流程与实战技巧

1. ArcGIS脚本工具入门指南作为一名GIS工程师&#xff0c;我使用ArcGIS脚本工具已有8年时间。脚本工具是ArcGIS平台中最高效的自动化解决方案&#xff0c;它允许我们将Python脚本封装成标准的GP工具&#xff0c;实现批量化、流程化的地理数据处理。不同于直接运行Python脚本&am…

作者头像 李华
网站建设 2026/9/14 22:35:37

光热电站N-k安全约束优化调度MATLAB实现

1. 项目背景与核心挑战在可再生能源占比不断提升的现代电力系统中&#xff0c;光热电站&#xff08;Concentrated Solar Power, CSP&#xff09;因其独特的储热能力和灵活调节特性&#xff0c;正成为解决风电、光伏波动性问题的关键技术手段。然而&#xff0c;当我们将光热电站…

作者头像 李华