Kubernetes-网络缺点排查实战之旅 (kubernetes与docker的关系)
在开发Kata/remote-hypervisor(也称为peer-pods)打算时,我遇到了一个疑问,即KubeespodIP在上班节点上不可访问。在本博客中,我将形容Kubernetes网络缺点排查环节,宿愿对读者有协助。
译自AHands-onKubernetesNetworkTroubleshootingJourney。
Kata远程治理程序(peer-pods)打算经过在AWS或MicrosoftAzure等基础设备环境中经常使用本机基础设备治理API(如在AWS上创立KataVM时经常使用AWSAPI,在Azure上创立时经常使用MicrosoftAzureAPI),实如今任何基础设备环境中创立KataVM。CNCF隐秘容器名目标cloud-api-adaptor子名目成功了Kata远程治理程序。
如下图所示,在peer-pods打算中,pod(Kata)虚构机在Kubernetes(K8s)上班节点外部运转,经过VXLAN隧道从上班节点访问podIP。经常使用隧道可以确保pod联网继续反常上班,无需对CNI网络做任何扭转。
当经常使用Kata容器时,Kubernetespod在虚构机内运转,因此咱们将运转pod的虚构机称为KataVM或pod虚构机。
疑问
podIP10.132.2.46,它位于pod虚构机上(IP:192.168.10.201),从上班节点虚构机(IP:192.168.10.163)不可访问。
以下是我环境中的虚构机具体消息——上班节点虚构机和pod(Kata)虚构机。经常使用的KubernetesCNI是OVN-Kubernetes。
+===========================+================+================+|VM称号|IP地址|备注|+===========================+================+================+|ocp-412-ovn-worker-1|192.168.10.163|上班节点虚构机|+---------------------------+----------------+----------------+|podvm--priv-8b726648|192.168.10.201|Pod虚构机|+---------------------------+----------------+----------------+
最繁难的处置打算就是请网络专家来处置这个疑问。但是,在我的状况下,因为其余紧迫疑问,专家不可间接介入处置。此外,peer-pods网络拓扑结构还比拟新,触及多个网络栈——KubernetesCNI、Kata网络和VXLAN隧道,使得基本要素难以查明且十分耗时。
因此,我将这种状况视为提高我的Kubernetes网络技艺的时机。在一些网络外围专家的指点下,我开局自行调试。
在后续章节中,我将经过我的方法带您逐渐了解调试环节和找到疑问基本要素。我宿愿这个环节能对Kubernetes网络疑问缺点扫除有所协助。
缺点排查-第一阶段
在上层面上,我采取的方法蕴含以下两个步骤:
让咱们从上班节点虚构机pingIP:10.132.2.46,并跟踪网络栈中的流量:
[root@ocp-412-worker-1core]#ping10.132.2.46
Linux会参考路由表来确定发送数据包的目标地。
[root@ocp-412-worker-1core]#iprouteget10.132.2.4610.132.2.46devovn-k8s-mp0src10.132.2.2uid0
因此,到podIP的路由是经过设备ovn-k8s-mp0
让咱们失掉上班节点网络具体消息,并检索无关ovn-k8s-mp0设备的消息。
[root@ocp-412-ovn-worker-1core]#iprdefaultvia192.168.10.1devbr-exprotodhcpsrc192.168.10.163metric4810.132.0.0/14via10.132.2.1devovn-k8s-mp010.132.2.0/23devovn-k8s-mp0protokernelscopelinksrc10.132.2.2169.254.169.0/29devbr-exprotokernelscopelinksrc169.254.169.2169.254.169.1devbr-exsrc192.168.10.163mtu1400169.254.169.3via10.132.2.1devovn-k8s-mp0172.30.0.0/16via169.254.169.4devbr-exmtu1400192.168.10.0/24devbr-exprotokernelscopelinksrc192.168.10.163metric48[root@ocp-412-ovn-worker-1core]#ipa[snip]2:ens3:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscfq_codelmasterovs-systemstateUPgroupdefaultqlen1000link/ether52:54:00:f9:70:58brdff:ff:ff:ff:ff:ff3:ovs-system:<BROADCAST,MULTICAST>mtu1500qdiscnoopstateDOWNgroupdefaultqlen1000link/ether32:7c:7a:20:6e:5abrdff:ff:ff:ff:ff:ff4:genev_sys_6081:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu65000qdiscnoqueuemasterovs-systemstateUNKNOWNgroupdefaultqlen1000link/ether3a:9c:a8:4e:15:0cbrdff:ff:ff:ff:ff:ffinet6fe80::389c:a8ff:fe4e:150c/64scopelinkvalid_lftforeverpreferred_lftforever5:br-int:<BROADCAST,MULTICAST>mtu1400qdiscnoopstateDOWNgroupdefaultqlen1000link/etherd2:b6:67:15:ef:06brdff:ff:ff:ff:ff:ff6:ovn-k8s-mp0:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1400qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000link/etheree:cb:ed:8e:f9:e0brdff:ff:ff:ff:ff:ffinet10.132.2.2/23brd10.132.3.255scopeglobalovn-k8s-mp0valid_lftforeverpreferred_lftforeverinet6fe80::eccb:edff:fe8e:f9e0/64scopelinkvalid_lftforeverpreferred_lftforever8:br-ex:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000link/ether52:54:00:f9:70:58brdff:ff:ff:ff:ff:ffinet192.168.10.163/24brd192.168.10.255scopeglobaldynamicnoprefixroutebr-exvalid_lft2266secpreferred_lft2266secinet169.254.169.2/29brd169.254.169.7scopeglobalbr-exvalid_lftforeverpreferred_lftforeverinet6fe80::17f3:957b:5e8d:a4a6/64scopelinknoprefixroutevalid_lftforeverpreferred_lftforever[snip]
从上述输入可以看出,ovn-k8s-mp0接口的IP是10.132.2.2/23
让咱们失掉ovn-k8s-mp0接口的设备具体消息。
如下输入所示,这个接口是一个OVS实体。
[root@ocp-412-ovn-worker-1core]#ip-dlishdevovn-k8s-mp06:ovn-k8s-mp0:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1400qdiscnoqueuestateUNKNOWNmodeDEFAULTgroupdefaultqlen1000link/etheree:cb:ed:8e:f9:e0brdff:ff:ff:ff:ff:ffpromiscuity1minmtu68maxmtu65535openvswitchaddrgenmodeeui64numtxqueues1numrxqueues1gso_max_size65536gso_max_segs65535
ovn-k8s-mp0是一个OVS桥吗?
从上方的命令输入可以分明看到,ovn-k8s-mp0不是一个OVS桥。上班节点上存在的只要两个桥:br-ex和br-int
[root@ocp-412-ovn-worker-1core]#ovs-vsctllist-brbr-exbr-int
所以ovn-k8s-mp0是一个OVS端口。咱们须要找出领有这个端口的OVS桥。
从上方的命令输入可以分明看到,ovn-k8s-mp0不是桥br-ex的OVS端口。
[root@ocp-412-ovn-worker-1core]#ovs-ofctldump-portsbr-exovn-k8s-mp0ovs-ofctl:br-ex:unknownport`ovn-k8s-mp0`
从上方的命令输入可以分明看到,ovn-k8s-mp0是一个OVS桥br-int的端口。
[root@ocp-412-ovn-worker-1core]#ovs-ofctldump-portsbr-intovn-k8s-mp0OFPST_PORTreply(xid=0x4):1portsport"ovn-k8s-mp0":rxpkts=1798208,bytes=665641420,drop=2,errs=0,frame=0,over=0,crc=0txpkts=2614471,bytes=1357528110,drop=0,errs=0,coll=0
总结一下,ovn-k8s-mp0是一个br-int**OVS桥上的端口。它也持有桥的IP,即**10.132.2.2/23
如今,让咱们失掉pod的网络性能具体消息。
必定知道pod网络命名空间能力确定pod网络具体消息。上方的命令经过IP找到pod网络命名空间。
[root@ocp-412-ovn-worker-1core]#POD_IP=10.132.2.46;fornsin$(ipnetnsls|cut-f1-d"");doipnetnsexec$nsipa|grep-q$POD_IP;status=$?;[$status-eq0]&&echo"podnamespace:$ns";donepodnamespace:c16c7a01-1bc5-474a-9eb6-15474b5fbf04
一旦知道了pod网络命名空间,就可以找到pod的网络性能具体消息,如下所示。
[root@ocp-412-ovn-worker-1core]#NS=c16c7a01–1bc5–474a-9eb6–15474b5fbf04[root@ocp-412-ovn-worker-1core]#ipnetnsexec$NSipa1:lo:<LOOPBACK,UP,LOWER_UP>mtu65536qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000link/loopback00:00:00:00:00:00brd00:00:00:00:00:00inet127.0.0.1/8scopehostlovalid_lftforeverpreferred_lftforeverinet6::1/128scopehostvalid_lftforeverpreferred_lftforever2:eth0@if4256:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1400qdiscnoqueuestateUPgroupdefaultqlen1000link/ether0a:58:0a:84:02:2ebrdff:ff:ff:ff:ff:fflink-netns59e250f6–0491–4ff4-bb22-baa3bca249f6inet10.132.2.46/23brd10.132.3.255scopeglobaleth0valid_lftforeverpreferred_lftforeverinet6fe80::858:aff:fe84:22e/64scopelinkvalid_lftforeverpreferred_lftforever4257:vxlan1@if4257:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000link/etherca:40:81:86:fa:73brdff:ff:ff:ff:ff:fflink-netns59e250f6–0491–4ff4-bb22-baa3bca249f6inet6fe80::c840:81ff:fe86:fa73/64scopelinkvalid_lftforeverpreferred_lftforever[root@ocp-412-ovn-worker-1core]#ipnetnsexec$NSiprdefaultvia10.132.2.1deveth010.132.2.0/23deveth0protokernelscopelinksrc10.132.2.46
所以eth0@if4256是pod的主网络接口。
让咱们失掉eth0设备的具体消息。
从上方的输入可以看出,pod网络命名空间中的eth0设备是一个veth设备。
[root@ocp-412-ovn-worker-1core]#ipnetnsexec$NSip-dlishdeveth0link/ether0a:58:0a:84:02:2ebrdff:ff:ff:ff:ff:fflink-netns59e250f6–0491–4ff4-bb22-baa3bca249f6vethaddrgenmodeeui64numtxqueues8numrxqueues8gso_max_size65536gso_max_segs65535tso_max_size524280tso_max_segs65535gro_max_size65536
妇孺皆知veth设备以对的方式上班;一端在init(或root)命名空间中,另一端在(pod)网络命名空间中。
让咱们在init命名空间中找到pod对应的veth设备对。
[root@ocp-412-ovn-worker-1core]#ipa|grep-A1^42564256:8b7266486ea2861@if2:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1400qdiscnoqueuemasterovs-systemstateUPgroupdefaultlink/etherde:fb:3e:87:0f:d6brdff:ff:ff:ff:ff:fflink-netnsc16c7a01–1bc5–474a-9eb6–15474b5fbf04
所以,8b7266486ea2861@if2是init命名空间中的podveth设备端点。这个veth对衔接了init和pod网络命名空间。
让咱们找出veth设备端点的具体消息。
[root@ocp-412-ovn-worker-1core]#ip-dlishdev8b7266486ea28614256:8b7266486ea2861@if2:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1400qdiscnoqueuemasterovs-systemstateUPmodeDEFAULTgroupdefaultlink/etherde:fb:3e:87:0f:d6brdff:ff:ff:ff:ff:fflink-netnsc16c7a01–1bc5–474a-9eb6–15474b5fbf04promiscuity1minmtu68maxmtu65535vethopenvswitch_slaveaddrgenmodeeui64numtxqueues4numrxqueues4gso_max_size65536gso_max_segs65535
所以8b7266486ea2861@if2是一个OVS实体。转储OVS替换机具体消息将提供哪个OVS桥领有此端口的具体消息。
如下输入所示,桥br-int领有这个端口。
留意,经常使用ovs-vsctl命令是之前ovs-ofctldump-ports<bridge><port>命令的另一种选用。这是为了展现不同的命令可以协助探求网络拓扑结构。
[root@ocp-412-ovn-worker-1core]#ovs-vsctlshow[snap]Bridgebr-intfl_mode:secure>[root@ocp-412-ovn-worker-1core]#ipnetnsexec$NSip-dlishdevvxlan14257:vxlan1@if4257:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscnoqueuestateUNKNOWNmodeDEFAULTgroupdefaultqlen1000link/etherca:40:81:86:fa:73brdff:ff:ff:ff:ff:fflink-netns59e250f6–0491–4ff4-bb22-baa3bca249f6promiscuity0minmtu68maxmtu65535vxlanid555005remote192.168.10.201srcport00dstport4789nolearningttlautoageing300udpcsumnoudp6zerocsumtxnoudp6zerocsumrxaddrgenmodeeui64numtxqueues1numrxqueues1gso_max_size65536gso_max_segs65535
一个显现的疑问是数据包如何从eth0接口发送到vxlan1接口。
这是经过在网络命名空间中设置Linux流量控制(TC)在eth0和vxlan1之间镜像流量来成功的。这是从Kata容器的设计中已知的。但是,我以为在缺点扫除网络疑问时审核TC性能是一种好的通常。
上方的输入显示了我环境中pod网络命名空间中设备性能的TC过滤器。
[root@ocp-412-ovn-worker-1core]#ipnetnsexec$NStcfiltershowdeveth0rootfilterparentffff:protocolallpref49152u32chain0filterparentffff:protocolallpref49152u32chain0fh800:htdivisor1filterparentffff:protocolallpref49152u32chain0fh800::800order2048keyht800bkt0terminalflowidnot_in_hwmatch00000000/00000000at0actionorder1:mirred(EgressRedirecttodevicevxlan1)stolenindex1ref1bind1[root@ocp-412-ovn-worker-1core]#ipnetnsexec$NStcfiltershowdevvxlan1rootfilterparentffff:protocolallpref49152u32chain0filterparentffff:protocolallpref49152u32chain0fh800:htdivisor1filterparentffff:protocolallpref49152u32chain0fh800::800order2048keyht800bkt0terminalflowidnot_in_hwmatch00000000/00000000at0actionorder1:mirred(EgressRedirecttodeviceeth0)stolenindex2ref1bind1
eth0的进口被重定向到了vxlan1,而vxlan1的进口被重定向到了eth0
有了一切这些细节,就可以为参考和进一步剖析绘制上班节点网络拓扑图。拓扑结构如下图所示。
如今,让咱们把重点转到pod虚构机上。
请留意,pod虚构机的设计是经常使用一个名为po的固定pod网络命名空间。
以下输入显示了pod虚构机的网络性能:
ubuntu@podvm-nginx-priv-8b726648:/home/ubuntu#ipa1:lo:<LOOPBACK,UP,LOWER_UP>mtu65536qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000link/loopback00:00:00:00:00:00brd00:00:00:00:00:00inet127.0.0.1/8scopehostlovalid_lftforeverpreferred_lftforeverinet6::1/128scopehostvalid_lftforeverpreferred_lftforever2:ens2:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscfq_codelstateUPgroupdefaultqlen1000link/ether52:54:00:e1:58:67brdff:ff:ff:ff:ff:ffinet192.168.10.201/24brd192.168.10.255scopeglobaldynamicens2valid_lft2902secpreferred_lft2902secinet6fe80::5054:ff:fee1:5867/64scopelinkvalid_lftforeverpreferred_lftforeverroot@podvm-nginx-priv-8b726648:/home/ubuntu#iprdefaultvia192.168.10.1devens2protodhcpsrc192.168.10.201metric100192.168.10.0/24devens2protokernelscopelinksrc192.168.10.201192.168.10.1devens2protodhcpscopelinksrc192.168.10.201metric100root@podvm-nginx-priv-8b726648:/home/ubuntu#iptables-S-PINPUTACCEPT-PFORWARDACCEPT-POUTPUTACCEPT
以下输入显示了podns网络命名空间内的网络性能。
root@podvm-nginx-priv-8b726648:/home/ubuntu#ipnetnsexecpodnsipa1:lo:<LOOPBACK,UP,LOWER_UP>mtu65536qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000link/loopback00:00:00:00:00:00brd00:00:00:00:00:00inet127.0.0.1/8scopehostlovalid_lftforeverpreferred_lftforeverinet6::1/128scopehostvalid_lftforeverpreferred_lftforever3:vxlan0@if3:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1400qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000link/ether7e:e5:f7:e6:f5:1abrdff:ff:ff:ff:ff:fflink-netnsid0inet10.132.2.46/23brd10.132.3.255scopeglobalvxlan0valid_lftforeverpreferred_lftforeverinet6fe80::7ce5:f7ff:fee6:f51a/64scopelinkvalid_lftforeverpreferred_lftforeverroot@podvm-nginx-priv-8b726648:/home/ubuntu#ipnetnsexecpodnsiprdefaultvia10.132.2.1devvxlan010.132.2.0/23devvxlan0protokernelscopelinksrc10.132.2.46root@podvm-nginx-36590ccc:/home/ubuntu#ipnetnsexecpodnsip-dlishvxlan03:vxlan0@if3:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1400qdiscnoqueuestateUNKNOWNmodeDEFAULTgroupdefaultqlen1000link/ether7e:e5:f7:e6:f5:1abrdff:ff:ff:ff:ff:fflink-netnsid0promiscuity0minmtu68maxmtu65535vxlanid555005remote192.168.10.163srcport00dstport4789nolearningttlautoageing300udpcsumnoudp6zerocsumtxnoudp6zerocsumrxaddrgenmodeeui64numtxqueues1numrxqueues1gso_max_size65536gso_max_segs65535root@podvm-nginx-priv-8b726648:/home/ubuntu#ipnetnsexecpodnsiptables-S-PINPUTACCEPT-PFORWARDACCEPT-POUTPUTACCEPT
vxlan隧道设置看起来反常。它显示了远程端点IP192.168.10.163,这是上班节点虚构机的IP。
此外,pod虚构机中没有防火墙规定。
但是,你没有看到像在上班节点上一样的veth对。如今,显现的一个疑问是,没有veth对,init和podns网络命名空间之间如何启动通讯。请留意,物理设备在init(root)命名空间中,vxlan设备在podns网络命名空间中。
感谢StefanoBrivio指出了使这种状况出现的Linux内核提交。
commitf01ec1c017dead42092997a2b8684fcab4cbf126Author:NicolasDichtel<nicolas.dichtel@6wind.com>Date:ThuApr2410:02:492014+0200vxlan:addx-netnssupportThispatchallowstoswitchthenetnswhenpacketisencapsulatedordecapsulated.Thevxlansocketisopennedintothei/onetns,ieintothenetnswhereencapsulatedpacketsarereceived.Thesocketlookupisdoneintothisnetnstofindthecorrespondingvxlantunnel.Afterdecapsulation,thepacketisinjectingintothecorrespondinginterfacewhichmaystandtoanothernetns.Whenoneofthetwonetnsisremoved,thetunnelisdestroyed.Configurationexample:ipnetnsaddnetns1ipnetnsexecnetns1iplinksetloupiplinkaddvxlan10typevxlanid10group239.0.0.10deveth0dstport0iplinksetvxlan10netnsnetns1ipnetnsexecnetns1ipaddradd192.168.0.249/24broadcast192.168.0.255devvxlan10ipnetnsexecnetns1iplinksetvxlan10up
这也有一个StackOverflow主题对此启动了解释。
这些细节为咱们提供了对pod虚构机网络拓扑的良好概述,如下图所示。
让咱们在vxlan0接口上运转tcpdump,看ICMP恳求能否从上班节点接纳。
如下输入所示,ICMP恳求已接纳,但没有照应。
root@podvm-nginx-priv-8b726648:/home/ubuntu#ipnetnsexecpodnstcpdump-ivxlan0-s0-n-vvtcpdump:listeningonvxlan0,link-typeEN10MB(Ethernet),capturesize262144bytes[snip]10.132.2.2>10.132.2.46:ICMPechorequest,id20,seq1,length6410:34:17.389643IP(tos0x0,ttl64,id27606,offset0,flags[DF],protoICMP(1),length84)10.132.2.2>10.132.2.46:ICMPechorequest,id20,seq2,length6410:34:18.413682IP(tos0x0,ttl64,id27631,offset0,flags[DF],protoICMP(1),length84)10.132.2.2>10.132.2.46:ICMPechorequest,id20,seq3,length6410:34:19.002837IP(tos0x0,ttl1,id28098,offset0,flags[DF],protoUDP(17),length69)[snip]
如今,让咱们总结一下状况。
经过这个练习,你对上班节点和pod虚构机的网络拓扑有了很好的了解,隧道的设置看起来也没有疑问。你也看到ICMP数据包被pod虚构机接纳,没有软件防火墙阻止数据包。那么下一步该做什么?
继续浏览以了解下一步该做什么:-)
缺点排查-第二阶段
我经常使用wireshark剖析了来自上班反常(惯例Kata)设置的tcpdump捕捉。Wireshark图形界面可以繁难地理解经过tcpdump捕捉的网络跟踪。
在跟踪中没有观察到ARP恳求和照应。但是,上班节点上的ARP表被填充,ARP表经常使用pod网络命名空间中的eth0设备的(在上班节点上),而不是pod虚构机上的podns命名空间中的vxlan0设备的MAC。
?(10.132.2.46)at0a:58:0a:84:02:2e[ether]onovn-k8s-mp0
0a:58:0a:84:02:2e是上班节点上pod网络命名空间中eth0接口的MAC,而7e:e5:f7:e6:f5:1a是pod虚构机上podns命名空间中的vxlan0接口的MAC。
这是疑问的要素-从上班节点不可访问podIP。ARP条目应指向pod虚构机上podns命名空间中的vxlan0设备的MAC(即7e:e5:f7:e6:f5:1a)。
处置打算
StefanoBrivio的一个小技巧处置了这个疑问。在pod虚构机的vxlan0接口上经常使用与上班节点上pod的eth0接口相反的MAC地址可以处置衔接疑问。
ipnetnsexecpodnsiplinksetvxlan0downipnetnsexecpodnsiplinksetdevvxlan0address0a:58:0a:84:02:2eipnetnsexecpodnsiplinksetvxlan0up
最终的网络拓扑结构如下所示。
图片
论断
调试Kubernetes集群中的网络疑问并非易事。但是,经过明白的方法、专家的协助和地下可用的资料,找到基本要素和修复疑问是或许的。在这个环节中取得乐趣并把握常识。
我宿愿这篇文章对你有协助。
以下是在我的缺点扫除练习中十分有用的参考资料列表:
kubernetes 集群中 cilium 的实践及其网络通信解析
Cilium是一个基于 eBPF 和 XDP 的高性能容器网络方案的开源项目,目标是为微服务环境提供网络、负载均衡、安全功能,主要定位是容器平台。
Why Cilium ?
现在应用程序服务的发展已从单体结构转变为微服务架构,微服务间的的通信通常使用轻量级的 http 协议。微服务应用往往是经常性更新变化的,在持续交付体系中为了应对负载的变化通常会横向扩缩容,应用容器实例也会随着应用的更新而被创建或销毁。
这种高频率的更新对微服务间的网络可靠连接带来了挑战:
Cilium 通过利用 BPF 具有能够透明的注入网络安全策略并实施的功能,区别于传统的 IP 地址标识的方式,Cilium 是基于 service / pod /container 标识来实现的,并且可以在应用层实现 L7 Policy 网络过滤。总之,Cilium 通过解藕 IP 地址,不仅可以在高频变化的微服务环境中应用简单的网络安全策略,还能在支持 L3/L4 基础上通过对 http 层进行操作来提供更强大的网络安全隔离。BPF 的使用使 Cilium 甚至可以在大规模环境中以高度可扩展的方式解决这些挑战问题。
Cilium 的主要功能特性 :
此处使用外部的 etcd 的部署方式,外部 etcd 安装 cilium 在较大的运行环境中能够提供更好的性能。
Requirements
安装 helm 3
挂载 BPF 文件系统
在 kubernetes 集群所有 node 上挂载 bpf 文件系统
kubernetes 配置
cilium 安装
当使用外部 etcd 作为 cilium 的 k-v 存储,etcd 的 IP 地址需要在 cilium 的 configmap 中配置。
使用 helm 安装 cilium
安装 cilium 连接测试用例
此用例将会部署一系列的 deployment,它们会使用多种路径来相互访问,连接路径包括带或者不带服务负载均衡和各种网络策略的组合。
部署的 podName 表示连接方式,readiness/liveness 探针则可指示连接是否成功。
安装 hubble
hubble 是一个用于云原生工作负载的完全分布式网络和安全可视化平台。它建立在 Cilium 和 eBPF 的基础上,以完全透明的方式深入了解服务以及网络基础结构的通信和行为。
hubble 对前面安装的测试用例监控信息
cilium 在 kubernetes 集群中安装好后,此处我们来探究一下在不同 node 上 pod 间的 vxlan 通信方式。
cilium 安装完后,cilium agent 会在 node 上创建cilium_net与cilium_host一对 veth pair 及用于跨宿主机通信的cilium_vxlan ,然后在cilium_host上配置其管理的 CIDR IP 作为网关。
如上图示中,通过抓包分析 Container A 与 Container B 之前的通信路径。
Container A ping Container B(以下称 Container A -> CA , Container B -> CB)
进入 Node01 上 CA 内 (10.244.1.154),ping CB ip 地址 10.224.6.11
进入 Node01 上 cilium agent 容器内,查看 CA 容器作为 cilium endpoint 的信息
CA 容器 ping 出的 icmp 包将会经过网卡 lxc8b528e748ff4 (lxcxxA) 路由到cilium_host网关,路由方式与传统的通过 Linux bridge 这样的二层设备转发不一样,cilium 在每个容器相关联的虚拟网卡上都附加了 bpf 程序,通过连接到 TC ( traffic control ) 入口钩子的 bpf 程序将所有网络流量路由到主机端虚拟设备上,由此 cilium 便可以监视和执行有关进出节点的所有流量的策略,例如 pod 内的 networkPolicy 、L7 policy、加密等规则。
CA 容器内的流量要跨宿主机节点路由到 CB 容器,则需要cilium_vxlanVTEP 设备对流量包进行封装转发到 Node02 上。bpf 程序会查询 tunnel 规则并将流量发送给cilium_vxlan ,在 cilium agent 容器内可查看到 bpf 的 tunnel 规则
在 Node01 上对cilium_vxlan抓包,可看到 CA 容器对 icmp 包经过了cilium_vxlan
再对 Node01 上的 eth0 抓包,可看到cilium_vxlan已将 CA 的流量进行 vxlan 封包,src ip 改为本机 node ip 192.168.66.226, dst ip 改为 192.168.66.221
到 Node02 上对 eth0 抓包,可看到 CA 容器的流量包已到 Node02 上
对cilium_vxlan抓包即可看到 CA 容器过来对流量包已被解封
至此,CA 容器对流量已到达 cilium 创建的虚拟网卡。
我们知道 Linux 内核本质上是事件驱动的(the Linux Kernel is fundamentally event-driven), cilium 创建的虚拟网卡接收到流量包将会触发连接到 TC ( traffic control ) ingress 钩子的 bpf 程序,对流量包进行相关策略对处理。
查看 cilium 官方给出的 ingress/egress datapath,可大致验证上述 cilium 的网络通信路径。
首先是egress datapath ,图中橙黄色标签为 cilium component,有 cilium 在宿主机上创建的 bpf 程序(对应着红色标签的 kernel bpf 钩子),若使用 L7 Policy 则还有 cilium 创建的 iptables 规则。流量从某个容器 endpoint 通过容器上的 veth pair 网卡 lxcxxx 出发,即会触发 bpf_sockops.c / bpf_redir.c bpf 程序,若使用了 L7 Policy 则进入用户空间进行 L7 层的数据处理,若没有使能 L7 Policy 则将触发 TC egress 钩子,bpf_lxc 对数据进行处理(若使能 L3 加密,则触发其他 bpf 钩子),数据最终被路由到cilium_hos t 网关处,再根据 overlay 模式(vxlan 等)将数据发送出去。
在 ciliumingress datapath中,数据流量进入主机网络设备上,cilium 可根据相关配置,对数据流量进行预处理(prefilter/L3 加解密/ 负载均衡/ L7 Policy 处理)或直接路由到cilium_host触发相应到 bpf 程序,再到最终的 endpoint 处。
[k8s系列六]K8S网络补充之DNS
前面两章介绍了service和ingress,service有Cluster IP和Node Port两种类型: 但实际上,集群内部一般不直接用Cluster IP,而是用service名作为域名,通过Core DNS组件做一次域名解析后得到cluster IP。 跨集群一般也不用nodePort,而是走Ingress ,或者loadbalance service。 DNS(Domain Name System) 用于将域名解析成IP地址,例如 Kubernetes 早期的 DNS 组件叫 KubeDNS。 CNCF 社区后来引入了更加成熟的开源项目 CoreDNS 替换了 KubeDNS。 所以我们现在提到 KubeDNS,其实默认指代的是 CoreDNS 项目。 集群中的每一个 Service(包括 DNS 服务本身)都将被分配一个 DNS name。 格式为:<service_name>.<namespace>.<cluster_domain>。 cluster_domain默认为。 每一个Pod创建时,都会在Pod的/etc/文件中,自动加入kube-dns service的domain name与相对应的IP地址。 因此Pods可以透过名为kube-dns的service组件,找到正在运行的kube-dns。 根据附录1创建dnsutils pod,并按照DNS格式,尝试解析kube-dns(kube-system命名空间)和whoami-clusterip(default命名空间)。 然后查看pod的域名解析文件/etc/中的内容,最后尝试在通过域名+端口号访问whoami-clusterip服务。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。