cilium-without-Kubernetes调研
概述
根据公司目前部署的 Kubernetes 集群的模式(见下图的k8s-master部分),kube-apiserver 的进程是通过二进制在独立的节点上部署,节点上不会部署 kubelet,也不会有 kube-proxy 等进程,因此是无法识别类似 Service 这样的负载均衡的流量手段。
之前有考虑过能否在 k8s-master 的节点上部署 cilium-agent 来实现在 k8s-master 也能识别类似 Service 这样的负载均衡方式(见下面问号部分),下面是实验和过程的结果。
cilium-docker
cilium-docker 是 Cilium 官方在 v1.9 的版本最后一次提到 Cilium without Kubernetes 了,详情可以参考 Is it possible to run Cilium without Kubernetes? #13072。鉴于目前 Cilium 已经发展到 v1.14 的版本了,代码变化很大,官方也已经不推荐这种方式来使用 Cilium 了。
Without Kubernetes
从 issue 中,可以看到跟我们有类似的问题,参考 Cilium Operator panics when starting without Kubernetes #24767,从官方的回复来说,如果不在 Kubernetes 的节点上运行 cilium-agent,可能很难去获取所有节点、网络策略等信息的同步,从官方文档,我们也可以大概了解到相关的限制 Apiserver outside of cluster。
测试验证
因为之前分析过 cilium-agent 的启动流程,从 DaemonSet 的角度分析了 cilium-agent 的 Pod 需要经过几个 init-container 的流程才可以正常启动,详细可以参考之前的文章。所以按照之前的分析,我们完全可以在物理机或者一个 cilium-agent 的镜像启动的容器内尝试启动 cilium-agent,并且通过远程 debug 分析 cilium-agent 启动与 Kubernetes 的关联,进一步确认 cilium-agent 能否在非 Kubernetes 的环境下启动和运行。
通过下面的脚本,在某个节点上,通过 docker 启动一个 cilium-agent 的容器,并且执行一些必要的脚本。
|
|
最后,通过 dlv,在容器内启动 cilium-agent,并且在本地进行远程 debug。
|
|
默认情况下,cilium-agent 走到这里就会陷入循环,循环超时之后,然后报错退出,主要原因是 cilium-agent 需要获取当前节点的信息,而这个信息是通过 Kubernetes 的 API 获取的,因为节点没有部署 kubelet,或者说节点不属于正常的 Kubernetes 集群内的节点,因此这个循环是没法获得节点的信息的。
从上面看,如果想在非 Kubernetes 节点部署 cilium-agent,不改配置或者代码是无法达成的,即使我们将 IPv4NodeAddr 设置成节点的 IP,而不是默认的 auto,因为本身这个 IP 没有注册到 Kubernetes 集群,实际上也会报错。
总结
cilium-agent 需要拿到 Node 的信息来构建 Host Endpoint 等资源,而 Node 的信息会从 Kubernetes 里获取,而且从源码以及 issue 上看,在不修改代码的情况下,没有配置可以绕开这个逻辑,同时需要考虑到,如果修改这个逻辑,需要更多的时间来完善测试和验证才可能把 cilium-agent 部署到 k8s-master 这个节点上,否则出现任何问题,都可能会是灾难级别的网络问题,需要谨慎考虑。
另外还需要考虑到当前集群的 k8s-master 节点的内核版本普遍较低,未来需要考虑升级节点的内核版本,以及考虑将部署的架构进行调整,按照新的版本,将 Kubernetes 的组件通过 static pod 这样的方式进行部署和维护,这样就不需要在 cilium without Kubernetes 上折腾太多时间。
参考资料
- Is it possible to run Cilium without Kubernetes? #13072
- Cilium Operator panics when starting without Kubernetes #24767
- Apiserver outside of cluster