沃趣技术干货丨cilium cni 流程分析

/01

cni注册流程

cilium启动时,会在主机:/etc/cni/net.d目录下生成配置,containerd会定期扫描目录下的文件,当发现有配置时,表示cni已经完成初始化。

/02

cni 调用流程分析

pod创建到cni调用流程如下:

wechat-1761807949265.png

在调用cni时,基于CNI规范,将传入如下参数:

type CmdArgs struct { ContainerID string  // 容器ID Netns       string  // 网络命名空间 IfName      string  // 网卡名称 Args        string  // cni 扩展参数 Path        string  // CNIPATH 路径 StdinData   []byte  // 其它自定义参数:来自 /etc/cni/net.d下的配置文件数据}

样例如下:

&skel.CmdArgs{ContainerID:"26e73994457474ab3520a9b2f9ada2600378ac58280934aaf8d1bd2ec2abd089",Netns:"/var/run/netns/cni-bf264779-8c1d-7d7f-9d6d-7a29c3a3d243",IfName:"eth0",Args:"IgnoreUnknown=1;K8S_POD_NAMESPACE=default;K8S_POD_NAME=nettest-qmfnz;K8S_POD_INFRA_CONTAINER_ID=26e73994457474ab3520a9b2f9ada2600378ac58280934aaf8d1bd2ec2abd089;K8S_POD_UID=45602948-01f7-4062-b786-6d381bc2afd5",Path:"/opt/cni/bin"}

1、整体流程图

wechat-1761807951578.png

上面的流程,忽略了些特定场景才会用到的功能:

下面将针对调用cilium-agent的三个接口:申请IP,创建endpoint,释放IP深入分析。

2、ip申请流程

在PostIpam函数中,可明确看到,ip申请调用的是POST /ipam接口,请求参数为pod名称与namespace。

在cilium-agent中,相关的定义入口如下:

o.handlers["POST"]["/ipam"] = ipam.NewPostIpam(o.context, o.IpamPostIpamHandler)restAPI.IpamPostIpamHandler = NewPostIPAMHandler(d)

收到请求后,将基于family:ip类型,owner:pod信息,从内存中申请ip。

在申请时,needSyncUpstream是设置成true的,表示在申请完ip后,需要将ip信息更新到cilium-node中,用于信息持久化。

ip的分配相对比较简单。在启动时,cilium会加载所有已分配的ip信息到内存中,使用bigint按位标志使用的ip情况,分配时,只需要取未分配的标志就可以。这里不做深入展开。

重点在于如何完成内存的初始化与在分配完成后,如何保证ip分配信息完成上报。

ip内存初始化

由于ipam支持很多种,这里分析两种典型:crd和cluster-pool。crd需要将相关信息保存在cilium-node中,cluster-pool为纯内存操作。

在NewIPAM中定义的ipam初始化流程

1、cluster-pool初始化流程

newHostScopeAllocator比较简单,只是初始化结构体

2、crd初始化流程

newCRDAllocator相比cluster-pool场景,多传入了一个参数:k8sEventReg,这就是重点所在。

相关初始化都在newNodeStore中:

wechat-1761807953913.png

3、restore流程

在allocator初始化后,cilium将加载本机已分配的ip信息:

restoreCiliumHostIPs 加载cilium-host的ip信息

restoreOldEndpoints 加载本机在支持的endpoint信息:扫描/var/run/cilium/state/下的endpoint信息,并加载到内存中

AnnotateNode 更新node annotation信息。默认未开启,可通过AnnotateK8sNode开关控制。开启后会将节点子网,cilium内部ip信息记录在node上

调用RestoreFinished,crd模式下,为关闭store.restoreFinished。从上面2.1.2可知,会触发一次refreshTrigger

到此,crd初始化与restore流程结束。

crd与cluster-pool都需要经过restore流程,但唯一的区别在于crd需要在初始化时,等待node完成加载,且crd多了一个refreshTrigger。

crd时,加载了两遍,因为crd的更新是异步的,极端情况crd不存在,而本地存在。本地是最完整信息。而初始化store与trigger也是为了后续运行作为准备。

refreshTrigger ip信息上报

在初始化trigger时,注册了refreshNodeTrigger回调函数。在收到事件时,就调用该函数

在回调函数失败时,通过调用n.refreshTrigger.TriggerWithReason("retry after error")保证继续再重试。

刷新就是每次调用:n.refreshNode(),将本地内存中的分配信息更新到ciliumNode中。

3、endpoint创建流程

在cni流程最后,会调用endpoointCreate,用于触发endpoint创建:

// Specify that endpoint must be regenerated synchronously. See GH-4409. ep.SyncBuildEndpoint = true// EndpointCreate creates a new endpointfunc (c *Client) EndpointCreate(ep *models.EndpointChangeRequest) error { id := pkgEndpointID.NewCiliumID(ep.ID) params := endpoint.NewPutEndpointIDParams().WithID(id).WithEndpoint(ep).WithTimeout(api.ClientTimeout) _, err := c.Endpoint.PutEndpointID(params) return Hint(err)}

而在server端,注册的处理函数如下:

o.handlers["PUT"]["/endpoint/{id}"] = endpoint.NewPutEndpointID(o.context, o.EndpointPutEndpointIDHandler)restAPI.EndpointPutEndpointIDHandler = NewPutEndpointIDHandler(d)

endpoint创建处理流程如下:

wechat-1761807956198.png

m.requests[podName] = &endpointCreationRequest{ cancel:   cancel, endpoint: ep, started:  time.Now(),}2. eventQueue为cilium的整个内部消息事件队列,而ep的流程也使用了。后续将单独分析eventQueue的管理流程:epEvent := eventqueue.NewEvent(&EndpointRegenerationEvent{        regenContext: regenContext,        ep:           e,    })/03

cni 卸载流程

卸载流程比较简单,流程图如下:

wechat-1761807958461.png

在cni卸载中,调用了cilium的endpoint删除接口,用于清理endpoint相关资源:

o.handlers["DELETE"]["/endpoint/{id}"] = endpoint.NewDeleteEndpointID(o.context, o.EndpointDeleteEndpointIDHandler)restAPI.EndpointDeleteEndpointIDHandler = NewDeleteEndpointIDHandler(d)

在endpoint清理流程中,主要是两个资源回收:

清理endpointCreations中的资源m.requests[podName]。回收可能残留的endpoint管理器。按cilium注释中说明:Cancel any ongoing endpoint creation,由于cni中加载ebpf为异步,且可能存在之前未完成的cni流程,在这里统一进行清理。

调用d.ipam.ReleaseIP回收ip

本期作者丨沃趣科技产品研发部

版权作品,未经许可禁止转载

往期作品快速浏览:

wechat-1761807960823.png
wechat-1761807963188.png
wechat-1761807965531.png