Networkpolicy的含意与现状
networkpolicy是k8s在很早就提出的一个抽象概念。它用一个对象来形容一类pod的网络出入站规定。对于networkpolicy的语义能够参考我之前的文章
networkpolicy的作用对象是pod,作用成果包含出站、入站,作用成果拓扑包含IP段、namespace、pod、端口、协定。
与以往IaaS服务场景下,针对虚拟机、网卡对象的平安组规定不同,networkpolicy是k8s原语。因而,在k8s场景下,进行网络安全规定的布局时,用networkpolicy能做到更加的灵便和自动化。举个例子:
有一套工作负载A是做相似数据库代理一类的工作,它只容许代理服务B拜访,不容许其余业务拜访。
- 在k8s场景下,如果不应用networkpolicy,咱们须要布局好A类pod的部署节点,配置相应的ACL规定,将B类pod的IP予以放行,一旦A/B类pod做了扩缩容,可能要在重新配置一份甚至多份ACL规定。
- 在k8s场景下,咱们会给A和B类别离配置label,创立好networkpolicy后限度A只放行B类pod,每当A或B扩缩容时,无需做任何额定操作。
网易数帆的networkpolicy反对
网易数帆的云计算业务的内部用户中,基于交付的openshift-sdn计划或calico计划,这些计划都能够原生地反对networkpolicy(下文会介绍)。
但云计算业务的外部用户(应用vpc或bgp CNI)大多是由PE布局治理IP白名单,限度某些网络拜访,除此之外没有做任何跨业务的网络限度(比如说:离线转码业务与领取业务是互不相干的,然而两种业务的pod彼此网络是可通信的)。因而始终没有networkpolicy的需要,而vpc、bgp等外部应用的CNI也还始终没有实现相干性能。
将来随着业务规模的扩充,相似的网络安全策略是必不可少的,因而咱们会在接下来逐渐将networkpolicy enable。
业界的networkpolicy实现
以后社区对于k8s的networkpolicy的实现,不外乎三种计划:
计划 | 依赖 | 案例 | 反对的CNI |
---|---|---|---|
基于iptables+ipset实现规定 | 容器流量须要通过宿主机的协定栈 | calico felix | calico、flannel、terway |
基于ovs流表实现规定 | 应用openvswitch | openshift-sdn | openshift-sdn |
基于ebpf hook实现规定 | 须要较高版本内核 | cilium | cilium、flannel、terway |
从下面的表格能够看出:
基于ovs流表实现的计划,典型的就是openshift-sdn,此前咱们分享过一篇openshift-sdn的详解,介绍了外面对ovs table的设计,其中有一个专门的table(tableid=21)就是用来实现networkpolicy的规定。 该计划是间接内建于openshift-sdn我的项目,根本无奈移植。 而openshift-sdn尽管代码开源,但设计上、代码逻辑上与openshift平台耦合还是比拟严密的。比如说:
- 公开的openshift-sdn部署计划须要依赖openshift-network-operator
- openshift-sdn代码中硬编码了要拜访的容器运行时为crio,不反对dockershim
- cilium是最先应用ebpf技术实现网络数据面的CNI,它力求实现大而全的容器网络,封装、加密、全面、高性能等特点包罗万象,它对于networkpolicy的反对也曾经非常欠缺。但ebpf hook的实现形式,依赖较高的内核版本,且在数据面排障时比拟吃力。ebpf技术对于网络性能的晋升很大,将来势必会越来越风行,所以值得关注。
- 基于iptables+ipset技术实现的计划,其实在几年前就比拟成熟了calico-felix、romana、kube-router等开源的网络计划都是基于此实现了反对networkpolicy。其中,felix是calico网络计划中的一个组件,官网反对在calico中enable networkpolicy,且可能与flannel配合应用。阿里云的terway便是间接套用felix实现了对networkpolicy的反对(最近还套用了cilium)。这套计划要求容器流量要进过宿主机协定栈,否则包就不会进入内核的netfilter模块,iptables规定就无奈失效。
指标
基于上述现状,咱们心愿基于现有的开源实现计划,进行兼容性调研或革新,适配网易数帆的各种网络计划,如:
- netease-vpc
- netease-bgp
- flannel
- ...
因为这些网络计划都满足felix的要求,同时felix有较为沉闷的社区和较多的适配案例,因而咱们决定基于felix,实现一套即插即用的networkpolicy addon。本文接下来将会着重介绍该计划的实现。
calico/felix的设计实现
架构
calico在部署架构上做了屡次演进,咱们以最新版本v3.17.1为准。calico的残缺架构包含了若干组件:
- calico/kube-controllers: calico控制器,用于监听一些k8s资源的变更,从而进行相应的calico资源的变更。例如依据networkpolicy对象的变更,变更相应的calicopolicy对象
- pod2daemon: 一个initcontainer,用于构建一个Unix Domain Socket,来让Felix程序与
Dikastes
(calico中反对istio的一种sidecar,详见calico的istio集成)进行加密通信. - cni plugin / ipam plugin: 规范的CNI插件,用于配置/解除网络;调配/回收网络配置
calico-node calico-node其实是一个数据面工具总成,包含了:
- felix: 治理节点上的容器网卡、路由、ACL规定;并上报节点状态
- bird/bird6: 用来建设bgp连贯, 并依据felix配置的路由,在不同节点间散发
- confd: 依据以后集群数据生成本地brid的配置
- calicoctl: calico的CLI工具。
- datastore plugin: 即calico的数据库,能够是独立的etcd,也能够以crd形式记录于所在集群的k8s中
- typha: 相似于数据库代理,能够尽量少防止有大量的连贯建设到apiserver。实用于超过100个node的集群。
官网给出了calico整体的组件架构图:
原理
在网络连通性(Networking)方面:calico的数据面是非常简单的三层路由转发。路由的学习和散发由bgp协定实现。如果k8s的上层是VPC之类的三层网络环境,则须要进行overlay,calico反对ipip封装实现overlay。
在网络安全性方面:calico思考到其Networking是依赖宿主机协定栈进行路由转发实现的,因而能够基于iptables+ipset进行流量标记、地址集布局、流量解决(放行或DROP),并且基于这些操作能够实现:
- networkpolicy的抽象概念
- calico自定义的networkpolicy,为了在openstack场景下利用而设计
- calico自定义的profile,已废除。
这里所有的iptables规定都作用在:
- pod在宿主机namespace中的veth网卡(calico中将之称为workload)
- 宿主机nodeIP所在网卡(calico中将之称为host-endpoint,实际上这部分规定不属于k8s的networkpolicy领域)。
次要包含如下几类规定:
iptables的INPUT链规定中,会先跳入
cali-INPUT
链,在cali-INPUT
链中,会判断和解决两种方向的流量:- pod拜访node(
cali-wl-to-host
)实际上这个链中只走了cali-from-wl-dispatch
链,如果是利用在openstack中,该链还会容许拜访metaserver;如果应用ipv6,该链中还会容许收回icmpv6的一系列包 - 来自node的流量(
cali-from-host-endpoint
)
- pod拜访node(
iptables的OUTPUT链中,会首先跳入
cali-OUTPUT
链,在cali-OUTPUT
链中,次要会解决:- 拜访node的流量(
cali-to-host-endpoint
)的流量
- 拜访node的流量(
iptables的FORWARD链中,会首先跳入
cali-FORWARD
链,在cali-FORWARD
链中会解决如下几种流量:- 来自node转发的流量
cali-from-hep-forward
- 从pod中收回的流量
cali-from-wl-dispatch
- 达到pod的流量
cali-to-wl-dispatch
- 达到node的转发流量
cali-to-hep-forward
- 纯正的IP段到IP段的转发流量
cali-cidr-block
- 来自node转发的流量
k8s的networkpolicy只须要关注上述流量中与pod相干的流量,因而只须要关怀:
cali-from-wl-dispatch
cali-to-wl-dispatch
这两个链的规定,对应到pod的egress和ingress networkpolicy。
1. 除了nat表,在raw和mangle表中还有对calico关注的网卡上的收发包进行初始标记的规定,和最终的判断规定。2. 在https://github.com/projectcalico/felix/blob/master/rules/static.go中能够看到残缺的动态iptables表项的设计
接着,iptables规定中还会在cali-from-wl-dispatch
和cali-to-wl-dispatch
两个链中依据收包/发包的网卡判断这是哪个pod,走到该pod的egress或ingress链中。每个pod的链中则又设置了对应networkpolicy实例规定的链,以此递归调用。
这样,pod的流量通过INPUT/OUTPUT/FORWARD等链后,递归地走了多个链,每个链都会Drop或者Return,如果把链表走一遍下来始终Return,会Return到INPUT/OUTPUT/FORWARD, 而后执行ACCEPT,也就是说这个流量满足了某个networkpolicy的规定限度。如果过程中被Drop了,就示意受某些规定限度,这个链路不通。
咱们通过一个简略的例子来形容iptables这块的链路程序。
felix实现networkpolicy的案例
假如有如下一个networkpolicy:
spec: egress: - {} ingress: - from: - podSelector: matchLabels: hyapp: client1 - from: - ipBlock: cidr: 10.16.2.0/24 except: - 10.16.2.122/32 ports: - port: 3456 protocol: TCP podSelector: matchLabels: hyapp: server
- 他作用于有
hyapp=server
的label的pod - 这类pod出方向不限度
这类pod的入站规定中只容许如下几种流量:
- 来自于有
hyapp=client1
的label的pod - 10.16.2.0/24网段中除了10.16.2.122/32以外的IP能够拜访该类pod的3456 TCP端口。
- 来自于有
咱们应用iptables -L
或iptables-save
命令来剖析机器上的iptables规定。
因为是入站规定,所以咱们能够察看iptables表中的cali-to-wl-dispatch
链。另外,该networkpolicy的作用pod只有一个,它的host侧网卡是veth-13dd25c5cb
。咱们能够看到如下的几条规定:
Chain cali-to-wl-dispatch (1 references)target prot opt source destinationcali-to-wl-dispatch-0 all -- anywhere anywhere [goto] /* cali:Ok_j0t6AwtLyoFYU */cali-tw-veth-13dd25c5cb all -- anywhere anywhere [goto] /* cali:909gC5dwdBI3E96S */DROP all -- anywhere anywhere /* cali:4M4uUxEEGrRKj1PR */ /* Unknown interface */
留神,这里有一个cali-to-wl-dispatch-0
的链,是用来做前缀映射的, 该链的规定下蕴含所有cali-tw-veth-0
这个前缀的链:
Chain cali-to-wl-dispatch-0 (1 references)target prot opt source destinationcali-tw-veth-086099497f all -- anywhere anywhere [goto] /* cali:Vt4xxuTYlCRFq62M */cali-tw-veth-0ddbc02656 all -- anywhere anywhere [goto] /* cali:7FDgBEq4y7PN7kMf */DROP all -- anywhere anywhere /* cali:up42FFMQCctN8FcW */ /* Unknown interface */
这是felix设计上用于缩小iptables规定遍历次数的一个优化伎俩。
咱们通过iptables-save |grep cali-to-wl-dispatch
命令,能够发现如下的规定:
cali-to-wl-dispatch -o veth-13dd25c5cb -m comment --comment "cali:909gC5dwdBI3E96S" -g cali-tw-veth-13dd25c5cb
意思就是:在cali-to-wl-dispatch
链中,依据pod在host侧网卡的名字,会执行cali-tw-veth-13dd25c5cb
链, 咱们再看这条链:
Chain cali-tw-veth-13dd25c5cb (1 references) target prot opt source destination1 ACCEPT all -- anywhere anywhere /* cali:RvljGbJwZ8z9q-Ee */ ctstate RELATED,ESTABLISHED2 DROP all -- anywhere anywhere /* cali:krH_zVU1BetG5Q5_ */ ctstate INVALID3 MARK all -- anywhere anywhere /* cali:Zr20J0-I__oX_Y2w */ MARK and 0xfffeffff4 MARK all -- anywhere anywhere /* cali:lxQlOdcUUS4hyf-h */ /* Start of policies */ MARK and 0xfffdffff5 cali-pi-_QW8Cu1Tr3dYs2pTUY0- all -- anywhere anywhere /* cali:d2UTZGk8zG6ol0ME */ mark match 0x0/0x200006 RETURN all -- anywhere anywhere /* cali:zyuuqgEt28kbSlc_ */ /* Return if policy accepted */ mark match 0x10000/0x100007 DROP all -- anywhere anywhere /* cali:DTh9dO0o6NsmIQSx */ /* Drop if no policies passed packet */ mark match 0x0/0x200008 cali-pri-kns.default all -- anywhere anywhere /* cali:krKqEtFijSLu5oTz */9 RETURN all -- anywhere anywhere /* cali:dgRtRf38hD2ZVmC7 */ /* Return if profile accepted */ mark match 0x10000/0x1000010 cali-pri-ksa.default.default all -- anywhere anywhere /* cali:NxmrZYbhCNLKgL6O */11 RETURN all -- anywhere anywhere /* cali:zDbjbrN6JPMZx9S1 */ /* Return if profile accepted */ mark match 0x10000/0x1000012 DROP all -- anywhere anywhere /* cali:d-mHGbHkL0VRl6I6 */ /* Drop if no profiles matched */
- 第1、2条:如果ct表中能检索到该连贯的状态,咱们间接依据状态来确定这个流量的解决形式,这样能够省略很大一部分工作。
- 第3条:先对包进行标记(将第17地位0),在本链的规定执行结束后,会判断标记是否match(判断第17位是否有被置1),不匹配(没有被置1)就DROP;
- 第4条:如果该网卡对应的pod有相干的networkpolicy,要再打一次mark,与之前的mark做与计算后目前mark应该是0xfffcffff(17、18位为0);
- 第5条:如果包mark match 0x0/0x20000(第18位为0), 执行
cali-pi-_QW8Cu1Tr3dYs2pTUY0-
链进入networkpolicy的判断。 - 第6、7条:如果networkpolicy查看通过,会对包进行mark批改, 所以查看是否mark match 0x10000/0x10000, 匹配阐明通过,间接RETURN,不再查看其余的规定;如果mark没有批改,与原先统一,视为没有任何一个networkpolicy容许该包通过,间接DROP
- 第8、9、10、11条:当没有任何相干的networkpolicy时(即第4~7条不存在)才会被执行,执行calico的profile策略,分成namespace维度和serviceaccount维度,如果在这两个策略里没有对包的mark做任何批改,就示意通过。这两个策略是calico的概念,且为了不与networkpolicy混同,曾经被弃用了。因而此处都是空的。
- 第12条:如果包没有进入 上述两个profile链,DROP。
接着看networkpolicy的链cali-pi-_QW8Cu1Tr3dYs2pTUY0-
,只有在这个链里执行Return前有将包打上mark使其match 0x10000/0x10000,就示意匹配了某个networkpolicy规定,包容许放行:
Chain cali-pi-_QW8Cu1Tr3dYs2pTUY0- (1 references)target prot opt source destinationMARK all -- anywhere anywhere /* cali:fdm8p72wShIcZesY */ match-set cali40s:9WLohU2k-3hMTr5j-HlIcA0 src MARK or 0x10000RETURN all -- anywhere anywhere /* cali:63L9N_r1RGeYN8er */ mark match 0x10000/0x10000MARK all -- anywhere anywhere /* cali:xLfB_tIU4esDK000 */ MARK xset 0x40000/0xc0000MARK all -- 10.16.2.122 anywhere /* cali:lUSV425ikXY6zWDE */ MARK and 0xfffbffffMARK tcp -- 10.16.2.0/24 anywhere /* cali:8-qnPNq_KdC2jrNT */ multiport dports 3456 mark match 0x40000/0x40000 MARK or 0x10000RETURN all -- anywhere anywhere /* cali:dr-rzJrx0I6Vqfkl */ mark match 0x10000/0x10000
- 第1、2条:如果src ip match ipset:
cali40s:9WLohU2k-3hMTr5j-HlIcA0
,将包 mark or 0x10000, 并查看是否match,match就RETUR。 咱们能够在机器上执行ipset list cali40s:9WLohU2k-3hMTr5j-HlIcA0
, 能够看到这个ipset里蕴含的就是networkpolicy中指明的、带有hyapp=client1
这个label的两个pod的ip。 - 第3、4、5、6条则是针对networkpolicy中的第二局部规定,先对包设置正向标记,而后将要隔离的src IP/IP段进行判断并做反向标记,接着判断src段是否在准入范畴,如果在,并且目标端口匹配,并且标记为正向,就再对包进行MARK or 0x10000 , 这样,最终判断match了就会Return。
- 实际上咱们能够看到,这里就算不match,这个链执行完了也还是会RETURN的,所以这个链执行的后果是通过mark返回给上一级的,这就是为什么调用该链的上一级,会在调用结束后要判断mark并确认是否ACCEPT。
至此,一个残缺的networkpolicy的实现链路就实现了。
egress规定与上述ingress规定相似。 能够参考下图:
通用的felix插件设计
如果你看了上文calico/felix的设计实现,你就会发现原理其实非常简单,这个设计齐全能够利用到任何一个“基于三层路由转发”的网络计划中。但理论利用过程中咱们还是遇到了一些问题。
问题1:networkpolicy-only
咱们晓得,较新版本的felix都是集成到calico-node组件中运行。calico-node默认状况下会实现容器网络和networkpolicy两块工作,如何部署一个只负责实现networkpolicy规定的calico-node呢?
能够参考calico官网提供的canal计划是如何适配flannel的。从canal的部署模板中咱们能够根本确认,只有部署好kube-controllers
,pod2daemon
,calico-node
并且通过环境变量管制calico-node
的CALICO_NETWORKING
环境变量为"false"
(禁止配置容器网络)即可。
问题2:网卡名映射
咱们尝试在轻舟k8s集群(应用网易云VPC作为容器网络)中尝试以这样的形式部署一套calico套件,部署后,咱们会发现calico-node的日志里定期报错,提醒:找不到cali****
的网卡,无奈配置iptables规定。 有用过calico的同学应该看得明确,cali
是calico计划在宿主机侧生成的网卡名前缀。而咱们基于网易云VPC设计的容器网络计划,会以veth-
为容器hostveth前缀。如果calico是基于前缀来找到容器网卡的,那么是否有参数能够指定前缀呢?
官网的felix配置文档中提到:能够应用InterfacePrefix
参数或FELIX_INTERFACEPREFIX
环境变量,决定felix要检索的host侧网卡前缀。一开始看到这个阐明令人欣喜万分。然而当咱们理论配置了之后,会发现,calico-node还是会报错,提醒: 找不到veth-*****
的网卡,这个网卡名超过了linux内核的常数限度(15个字符)。
咱们依照日志里打印的网卡名去找,的确找不到这个网卡,看来必须要搞清楚calico是如何给host侧的网卡进行命名的。
calico为pod的veth命名的规定实现在libcalico-go
我的项目中,存在如下的一个接口
type WorkloadEndpointConverter interface { VethNameForWorkload(namespace, podName string) string PodToWorkloadEndpoints(pod *kapiv1.Pod) ([]*model.KVPair, error)}
这个接口用用来实现pod映射到workload的,同时还能依据pod的信息,推导pod的hostveth网卡名是啥,该接口只有一种实现:defaultWorkloadEndpointConverter
, 其中VethNameForWorkload
的实现如下:
// VethNameForWorkload returns a deterministic veth name// for the given Kubernetes workload (WEP) name and namespace.func (wc defaultWorkloadEndpointConverter) VethNameForWorkload(namespace, podname string) string { // A SHA1 is always 20 bytes long, and so is sufficient for generating the // veth name and mac addr. h := sha1.New() h.Write([]byte(fmt.Sprintf("%s.%s", namespace, podname))) prefix := os.Getenv("FELIX_INTERFACEPREFIX") if prefix == "" { // Prefix is not set. Default to "cali" prefix = "cali" } else { // Prefix is set - use the first value in the list. splits := strings.Split(prefix, ",") prefix = splits[0] } log.WithField("prefix", prefix).Debugf("Using prefix to create a WorkloadEndpoint veth name") return fmt.Sprintf("%s%s", prefix, hex.EncodeToString(h.Sum(nil))[:11])}
能够看到,calico依据pod的namespace和name进行hash,而后依据FELIX_INTERFACEPREFIX
环境变量的值决定网卡名前缀,将前缀与hash的前11个字符拼凑起来。 libcalico-go
是所有calico组件的lib库,也就是说,不论是calico-cni去创立veth,还是felix去依据pod查找对应的网卡, 都是基于这个逻辑去匹配的。
显然这个代码破绽很大!calico没有对前缀做长度查看,这里要填充hash的前11位,齐全是因为默认的前缀是四个字符的cali
!
问题十分明确了,要想在本人的网络计划下无痛享受felix,就得本人实现一个WorkloadEndpointConverter
接口,并编译出定制化的calico-node镜像。
案例1: canal如何接入
从canal的部署模板中咱们就能够看得出来,canal计划中应用的CNI plugin实际上也是calico,只不过calico只负责创立veth对,配置IP和路由等工作,veth的命名交给calico来做,天然就依照calico的官网配置来命名了,理论应用过程中就能够看到,canal计划下容器在宿主机上的veth名称也是cali
前缀。
案例2:阿里云terway如何接入
阿里云的ACK应用其自研的terway来作为容器网络计划。terway中反对两种容器网卡虚拟化计划:
- veth
- ipvlan L2
veth计划下会应用felix来实现networkpolicy,而ipvlan下则应用cilium。咱们此处次要关注veth计划。
veth计划下felix是如何应用的呢?terway在部署时,间接基于社区v3.5.8版本的felix代码进行编译(编译前还往代码中退出了一个terway自定义的patch),将编译进去的felix二进制文件丢到terway的docker镜像中, daemonset里启动三个terway镜像容器,别离用于装置cni插件;运行agent;运行felix。
terway是如何实现兼容felix的呢?上文提到的网卡名的问题,它如何解决呢?
通过浏览terway的源码 ,咱们发现terway做得比拟暴力——间接复用了calico代码中的网卡命名形式,对host侧的veth进行命名,网卡前缀为硬编码的cali
。
案例3:网易云k8s如何接入
网易云的场景中,host侧网卡命名是以某个前缀加上pod的sandbox容器id来命名的(起因见下文)。因而咱们即使把前缀改成cali
或者其余长度4以内的字符串,felix也无奈基于calico的那套逻辑找到网卡。
因而咱们改写了该接口。实现了一个sandboxWorkloadEndpointConverter
, 将VethNameForWorkload
做了另一种实现:
- 依据felix参数感知自定义的网卡名前缀,这里为了防止prefix太长,导致网卡名抵触,对prefix长度进行限度,倡议不超过5个字符,至多给后缀保留10个字符(咱们已经在线上环境呈现过同一个节点的两个podsandbox容器id前9位完全相同的状况)
- 依据pod信息获取到他对应的sandbox容器ID,取其
15-len(prefix)
位作为后缀。 - 通过前缀与sandboxID后缀形成workload的网卡名。
将来咱们会尝试对这部分代码做更通用化的革新,反对多种前缀,并反对主动选用网卡命名办法。
为什么咱们要以podsandbox容器id来命名网卡?
因为理论应用过程中咱们发现,kubelet对于sandbox容器的解决并不一定是有序的,可能呈现如下场景:
- 为poda创立出sandbox1, 调用CNI ADD失败,但veth曾经创立;
- 为poda创立出sandbox2, 调用 CNI ADD胜利,间接应用了上一次创立的veth;
- 删除此前曾经失败的sandbox1,调用 CNI DEL。 将第2步创立的veth删除,导致poda的网络异样。
因而,如果kubelet调用CNI是以sandbox为粒度,那么咱们创立的资源就理当也以sandbox为粒度。
编译与构建
目前咱们将通用的felix基于calico/node的v3.17分支构建, 并将它援用的libcalico-go
fork到网易云的github organization我的项目:163yun/libcalico-go,并建设分支tag:v1.7.2-nks.1
。
这样,咱们能够间接拉取社区代码,进行编译:
cd $GOPATH/srcmkdir -p github.com/projectcalicocd github.com/projectcalicogit clone https://github.com/projectcalico/nodecd node# 批改依赖包,改为援用咱们批改过后的libcalico-gogo mod edit -replace=github.com/projectcalico/libcalico-go=github.com/163yun/libcalico-go@v1.7.2-nks.1# 编译出calico/node的docker imagemake calico/nodedocker tag calico/node:latest-amd64 $EXPECTED_IMAGE_PATH:$EXPECTED_IMAGE_TAG
编译构建过程中可能呈现一些网络起因导致编译阻塞:
- 编译过程中会在容器里进行
go build
,为了不便执行go module,所以倡议在Makefile、以及执行make时下载的长期版本Makefile.common.v***
文件中的局部地位注入环境变量:GOPROXY=https://goproxy.cn
- 编译结束后构建docker image时,会在根底镜像中下载安装多个依赖工具,可能呈现yum源无奈解析等问题,倡议在
Makefile
文件中调用docker build
的语句里追加参数--network=host
测试方法
首先咱们要筹备好网易轻舟k8s集群,并应用vpc或bgp网络计划,并额定部署felix套件(参考上图)。
咱们应用sonobuoy工具进行测试工作,该工具也能够素来进行k8s集群的conformance认证。下载该工具的二进制文件,而后执行:
sonobuoy run --e2e-focus="\[Feature:NetworkPolicy\]" --e2e-skip="" --image-pull-policy IfNotPresent
即可在以后集群里进行networkpolicy相干的e2e测试(并且测试过程创立的pod的imagePullPolicy都是IfNotPresent
)。
执行命令后能够查看集群中的pods,会看到sonobuoy的pod以及它创立进去的一些e2e相干的pod,如果有pod阻塞于ImagePullBackoff,能够尝试在pod所在节点上拉取备用镜像并批改成所需镜像:
docker pull hub.c.163.com/combk8s/conformance:v1.19.3docker tag hub.c.163.com/combk8s/conformance:v1.19.3 k8s.gcr.io/conformance:v1.19.3docker pull hub.c.163.com/combk8s/e2e-test-images/agnhost:2.20docker tag hub.c.163.com/combk8s/e2e-test-images/agnhost:2.20 k8s.gcr.io/e2e-test-images/agnhost:2.20
测试结束后,实践上所有e2e前缀的pod都会被删除,此时执行sonobuoy retrieve
命令, 会在当前目录生成一个tar.gz
文件,解压该文件,并读取plugins/e2e/results/global/e2e.log
, 就能够看到整个e2e测试的执行后果。 也能够通过plugins/e2e/sonobuoy_results.yaml
文件查看,但这个文件内容包含了未执行的用例,可读性可能不太好。
简要的e2e测试后果如下:
root@pubt2-nks-for-dev6:/home/hzhuangyang1/plugins/e2e/results/global# tail -n 10 e2e.logJUnit report was created: /tmp/results/junit_01.xml{"msg":"Test Suite completed","total":29,"completed":29,"skipped":5204,"failed":0}Ran 29 of 5233 Specs in 4847.335 secondsSUCCESS! -- 29 Passed | 0 Failed | 0 Pending | 5204 SkippedPASSGinkgo ran 1 suite in 1h20m48.75547671sTest Suite Passed
总结
本文介绍了networkpolicy的特点和劣势,并剖析了当下支流的networkpolicy实现计划——calico-felix,摸索了calico-felix通用化革新的计划和落地。随着calico-felix的引入,用户能同时享受到vpc的易扩展性和networkpolicy的灵活性。
将来咱们还将着力引入cilium实现高内核版本下、基于ebpf实现的networkpolicy,并实现networkpolicy拓扑可视化。