
通过kubectl获取pod运行的node ip和镜像ID
到目标node上 执行docker exec dockerID /bin/bash -c 'cat /sys/class/net/eth0/iflink' 获取docker对应的网卡ID
docker exec dockerID /bin/bash -c 'cat /sys/class/net/eth0/iflink' 获取docker对应的网卡ID
ip link | grep ^网卡ID 获取对应的网卡名字
tcpdump -i 网卡名字
现在,你知道每个pod有自己唯一的IP地址,可以通过一个扁平的、非 NAT网络和其他pod通信。Kubernetes是如何做到这一点的?简单来说,Kubernetes不负责这块。网络是由系统管理员或者Container Network Interface(CNI)插件建立的,而非Kubernetes本身。
Kubernetes并不会要求你使用特定的网络技术,但是授权pod(或者更准确地说,其容器)不论是否运行在同一个工作节点上,可以互相通信。pod用于通信的网络必须是:pod自己认为的IP地址一定和所有其他节点认为该pod拥有的IP地址一致。
查看图 1114。当pod A连接(发送网络包)到pod B时,pod B获取到的源IP地址必须和pod A自己认为的IP地址一致。其间应该没有网络地址转换(NAT) *** 作——pod A发送到pod B的包必须保持源和目的地址不变。
这很重要,保证运行在pod内部的应用网络的简洁性,就像运行在同一个网关机上一样。pod没有NAT使得运行在其中的应用可以自己注册在其他pod中。
image
图1114 Kubernetes规定pod必须通过非NAT网络进行连接
例如,有客户端pod X和pod Y,为所有通过它们注册的pod提供通知服务。pod X连接到pod Y并且告诉pod Y,“你好,我是pod X,IP地址为1234,请把更新发送到这个IP地址”。提供服务的pod可以通过收到的IP地址连接第一个pod。
pod到节点及节点到pod通信也应用了无NAT通信。但是当pod和internet上的服务通信时,pod发送包的源IP不需要改变,因为pod的IP是私有的。向外发送包的源IP地址会被改成主机工作节点的IP地址。
构建一个像样的Kubernetes集群包含按照这些要求建立网络。有不同的方法和技术来建立,在给定场景中它们都有其优点和缺点。因此,我们不会深入探究特定的技术,会阐述跨pod网络通用的工作原理。
在 113 节,我们看到创建了pod的IP地址以及网络命名空间,由基础设施容器(暂停容器)来保存这些信息,然后pod容器就可以使用网络命名空间了。pod网络接口就是生成在基础设施容器的一些东西。让我们看一下接口是如何被创建的,以及如何连接到其他pod的接口,如图 1115 所示。
[上传失败(image-d2fcf3-1627950575030)]
图1115 同一节点上pod通过虚拟Ethernet接口对连接到同一个桥接
同节点pod通信
基础设施容器启动之前,会为容器创建一个虚拟Ethernet接口对(一个veth pair),其中一个对的接口保留在主机的命名空间中(在节点上运行ifconfig命令时可以看到vethXXX的条目),而其他的对被移入容器网络命名空间,并重命名为eth0。两个虚拟接口就像管道的两端(或者说像Ethernet电缆连接的两个网络设备)——从一端进入,另一端出来,等等。
主机网络命名空间的接口会绑定到容器运行时配置使用的网络桥接上。从网桥的地址段中取IP地址赋值给容器内的eth0 接口。应用的任何运行在容器内部的程序都会发送数据到eth0 网络接口(在容器命名空间中的那一个),数据从主机命名空间的另一个veth接口出来,然后发送给网桥。这意味着任何连接到网桥的网络接口都可以接收该数据。
如果pod A发送网络包到pod B,报文首先会经过pod A的veth对到网桥然后经过pod B的veth对。所有节点上的容器都会连接到同一个网桥,意味着它们都能够互相通信。但是要让运行在不同节点上的容器之间能够通信,这些节点的网桥需要以某种方式连接起来。
不同节点上的pod通信
有多种连接不同节点上的网桥的方式。可以通过overlay或underlay网络,或者常规的三层路由,我们会在后面看到。
跨整个集群的pod的IP地址必须是唯一的,所以跨节点的网桥必须使用非重叠地址段,防止不同节点上的pod拿到同一个IP。如图 1116 所示的例子,节点A上的网桥使用 10110/24 IP段,节点B上的网桥使用 10120/24 IP段,确保没有IP地址冲突的可能性。
图 1116 显示了通过三层网络支持跨两个节点pod通信,节点的物理网络接口也需要连接到网桥。节点 A的路由表需要被配置成图中所示,这样所有目的地为 10120/24 的报文会被路由到节点B,同时节点B的路由表需要被配置成图中所示,这样发送到 10110/24 的包会被发送到节点A。
图1116 为了让不同节点上的pod能够通信,网桥需要以某种方式连接
按照该配置,当报文从一个节点上容器发送到其他节点上的容器,报文先通过veth pair,通过网桥到节点物理适配器,然后通过网线传到其他节点的物理适配器,再通过其他节点的网桥,最终经过veth pair到达目标容器。
仅当节点连接到相同网关、之间没有任何路由时上述方案有效。否则,路由器会扔包因为它们所涉及的pod IP是私有的。当然,也可以配置路由使其在节点间能够路由报文,但是随着节点数量增加,配置会变得更困难,也更容易出错。因此,使用SDN(软件定义网络)技术可以简化问题,SDN可以让节点忽略底层网络拓扑,无论多复杂,结果就像连接到同一个网关上。从pod发出的报文会被封装,通过网络发送给运行其他pod的网络,然后被解封装、以原始格式传递给pod。
为了让连接容器到网络更加方便,启动一个项目容器网络接口(CNI)。CNI允许Kubernetes可配置使用任何CNI插件。这些插件包含
我们不会去深入探究这些插件的细节,如果想要了解更多,可以参考 >
K8S网络模型设计:扁平的可连通的网络
K8S的网络是一个极其复杂的网络,如果想要用两个简单的词来描述K8S网络,那么我觉得扁平和可连通是K8S网络最大的特点(不懂隔离性)。
何为连通呢?
二层网络的连通:如果能够直接通过MAC帧直接通信的网络便是二层连通的网络,LAN就是这种网络
比如无限WIFI网络,比如以太网
三层网络的连通:如果能够通过IP报直接通信的网络便是三层连通的网络,便是三层连通
三层网络的连通分为两个部分,第一个部分是三层网络中的每一个LAN都是二层连通的,其次需要存在能够连通的路由来保证;这里可以简单回顾下三层网络通信的流程
通过路由表确定目标ip是否在链路上
如果在链路上,通过arp协议获取对应主机的mac地址,发送mac帧到链路上;
如果不在同一个链路上,通过本地路由表发送mac帧给下一跳,然后下一跳解析mac帧,分析ip报,继续路由直到最终跳到目标网络再次通过mac帧发送到目标主机或者到达ttl消失。
假如其中任何一个步骤不满足或者出问题,三层网络就无法连通
何为扁平呢?
就是希望可以在pod内直接通过IP进行互相通信而不需要在pod内部使用***之类的东西来连接其他pod(基础架构化),具体的可以看下k8s对网络的设计与要求。
k8s在设计其网络时,就希望网络对运行在其中的pod是透明的,因此提出了以下的一些要求与原则
k8s组网要求
所有的Pods之间可以在不使用 NAT网络地址转换 的情况下相互通信
所有的Nodes之间可以在不使用NAT网络地址转换的情况下相互通信
每个Pod自己看到的自己的ip和其他Pod看到的一致
k8s网络模型设计原则
每个Pod都拥有一个独立的 IP地址,而且 假定所有 Pod 都在一个可以直接连通的、扁平的网络空间中 。
不管它们是否运行在同 一 个 Node (宿主机)中,都要求它们可以直接通过对方的 IP 进行访问。
设计这个原则的原因 是,用户不需要额外考虑如何建立 Pod 之间的连接,也不需要考虑将容器端口映射到主机端口等问题。
而要想深入了解K8S的网络,就不得不去了解Linux *** 作系统中的网络以及计算机网络协议栈和一些网络技术
其中关于计算机网络协议栈道部分上次分享已经分享过了,所以本次的主题更多是Linux *** 作系统的网络以及一些网络技术
Linux *** 作系统中的网络
首先,我们来看下基本的linux网络,如下图所示
一个APP生成socket数据,然后经过网络协议栈包装IP报文,然后封装成MAC帧,在经过网络协议栈的过程中,会存在netfilters对数据进行一定的处理,同时也会存在路由的过程,
如果在同一个物理链路内,将直接通过ARP协议获取目标IP地址的MAC地址最终发送出去;
如果不在同一个物理链路则通过路由表确定下一跳的MAC地址,封装成MAC帧发送到目标地址。
在这个过程中,会根据路由表选择对应的端口,如果是lo端口,则会将帧原封不动的返回计算机网络协议栈,然后回到监听对应端口的SOCKET里。
如果是以太网端口则走以太网端口,如果是蓝牙或者无线网端口同理。
iptables与netfilters
iptables是一个用户空间的应用程序,通过该程序可以修改一些配置文件,这些文件定义了防火墙的一些行为,netfilters是 *** 作系统内核的一部分,netfilters里有5个回调钩子会触发iptables里的规则;iptables只是Linux防火墙的管理工具而已,位于/sbin/iptables。真正实现防火墙功能的是
netfilter,它是Linux内核中实现包过滤的内部结构。
这里不具体讲述其实现的原理,仅仅列出netfilters的一些功能:
1)filter表——三个链:INPUT、FORWARD、OUTPUT
作用:过滤数据包 内核模块:iptables_filter
2)Nat表——三个链:PREROUTING、POSTROUTING、OUTPUT
作用:用于网络地址转换(IP、端口) 内核模块:iptable_nat
3)Mangle表——五个链:PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
作用:修改数据包的服务类型、TTL、并且可以配置路由实现QOS内核模块:iptable_mangle(别看这个表这么麻烦,咱们设置策略时几乎都不会用到它)
4)Raw表——两个链:OUTPUT、PREROUTING
作用:决定数据包是否被状态跟踪机制处理 内核模块:iptable_raw
虚拟网络设备 tap/tun
TUN 和 TAP 设备是 Linux 内核虚拟网络设备,纯软件实现。TUN(TUNnel)设备模拟网络层设备,处理三层报文如 IP
报文。TAP 设备模拟链路层设备,处理二层报文,比如以太网帧。TUN 用于路由,而 TAP 用于创建网桥。OS 向连接到 TUN/TAP
设备的用户空间程序发送报文;用户空间程序可像往物理口发送报文那样向 TUN/TAP 口发送报文,在这种情况下,TUN/TAP
设备发送(或注入)报文到 OS 协议栈,就像报文是从物理口收到一样。
虚拟网络设备 veth-pairs
虚拟以太网电缆。使用双向有名管道实现。常用于不同 namespace 之间的通信,即 namespace 数据穿越或容器数据穿越。
虚拟网络设备 bridge
bridge是linux自带的虚拟交换机(网桥),其可以连接多个以太网设备,拥有智能处理MAC帧的能力,流向交换机的MAC帧将智能的被传输到相应的二层链路
网络命名空间
在 Linux 中,网络名字空间可以被认为是隔离的拥有单独网络栈(网卡、路由转发表、iptables)的环境。网络名字空间经常用来隔离网络设备和服务,只有拥有同样网络名字空间的设备,才能看到彼此。
从逻辑上说,网络命名空间是网络栈的副本,有自己的网络设备、路由选择表、邻接表、Netfilter表、网络套接字、网络procfs条目、网络sysfs条目和其他网络资源。
从系统的角度来看,当通过clone()系统调用创建新进程时,传递标志CLONE_NEWNET将在新进程中创建一个全新的网络命名空间。
从用户的角度来看,我们只需使用工具ip(package is iproute2)来创建一个新的持久网络命名空间。
从系统实现来说,就是原本一个数据结构是static公共的,后来变成进程私有的,在PCB里存在一个命名空间的结构,命名空间里有着网络命名空间,网络命名空间拥有着所有跟网络相关的配置数据
默认空的网络命名空间可能只有一个未启动的lo回环网卡。
两个网络命名空间可以通过以太网揽直接连着两个网络命名空间的网卡,也可以通过以太网网桥连接。
通过以太网网桥或者以太网揽连接的两个网络命名空间只能说是在二层连通的,如果希望在三层连通,还需要给每个网络命名空间配置相应的路由表规则以及分配IP地址。
如何使用虚拟网络设备联通网络命名空间
SingleHost容器网络
none模式
本质上就是创建一个网络命名空间,里面没有路由表,也没有通过veths-pair连接任何链路,外部无法访问这个容器,容器也无法访问外部
host模式
本质上就是使用宿主机的默认网络命名空间
container模式
本质上就是将当前容器部署在另一个容器所在的网络命名空间,这样发给本地的报文最终通过回环网卡回到了本机,这是同一个网络命名空间可以互通的原因
bridge模式
桥接模式就是在这些网络命名空间通过veth-pairs连接到同一个虚拟交换机上(二层连通),同时在对应的命名空间配置对应的路由表规则,但是从中可以看到交换机另一端连的上网络协议栈。
也就是那些MAC帧都会被宿主机接收,但是宿主机接收并不一定会处理,比如并没有开启ip转发功能(工作于路由器模式还是主机模式),那么不是本地ip的报文都会被丢弃;或者说netfilters拒绝处理
这些奇怪的报文。
理论上,这些容器发送给其他容器的mac报文是会被虚拟交换机智能转发到对应的容器的,这是同一主机不同容器互相连通的原因
假如宿主机配备了相应的路由规则和防火墙规则,那么容器的报文说能够通过路由最终转发出去的,这也是容器访问互联网的原理
但是这种模式是没法运用在多主机的情况下,因为宿主机不知道其他宿主机里的虚拟网络的路由,当相关ip报到达宿主机时,这些ip报将会被宿主机交给默认路由(下一跳:路由器)
最终路由器会把相关的ip报丢失或者到达ttl最终丢失
MultiHost容器网络
路由方案
回顾docker的单机网络模型,我们发现多主机不能通行的原因就在于你只能给当前主机配置路由规则和防火墙规则,而其他主机并不知道这些ip在你的虚拟网络中,假如能够将这些路由信息同步到其他
宿主机,那么网络便会打通。比较直接的想法就是给每台宿主机配置路由规则。而路由规则要求下一跳必须在当前网络,所以假如宿主机是二层互联的,那么通过给这些宿主机同步这些路由规则便能够
实现一个扁平的连通的网络。
其中布置在每一台宿主机可以通过k8s的daemonSet实现,而这种数据的管理可以交给etcd来实现。
这类方案便是基于路由,基于这个方案的实现有基于静态路由的flannel的host-gateway,以及基于动态路由的calico(使用边际路由协议以及一堆深奥的名词的实现)。
下面来看看Flannel的host-gateway原理(每一台宿主机都相当于本机容器网络的路由器):
通过路由方案构建的网络,宿主机也能访问这些虚拟网络里的Pod
询问基德大佬得知国际化sit环境的k8s网络接口实现就是Flannel的Host-gateway,而我们的办公网络和集群网络之间的路由是搭建好的,所以我们应该可以直接通过podId访问pod里的服务
下面是sit环境的两个服务
跟踪路由发现符合猜想
其中101956和101124就是宿主机的ip,这些宿主机在一个LAN里,这些宿主机相当于虚拟网络中的路由器;
猜测我们办公网和qunhe集群在一个VLAN里(二层可达)
隧道方案
隧道方案比较典型的就是UDP和XVLAN,两者都是使用Overlay网络(覆盖网络,所谓的大二层技术);其实用隧道技术最多的是***应用
其中UDP是XVLAN的替代品(早期Linux没有支持XVLAN协议,通过tun/tap技术将流量引到用户空间然后解包生成包再发,因为发生在用户空间而且多次copy导致性能较差,所以一般不推荐,除非你的linux版本比较低没法用xvlan)
下面就简单介绍下XVLAN技术的大概原理,下图是XVLAN的报文格式,可以发现就是在高层协议的报文里塞了二层报文
其中XVLAN头里有一个关键的字段,VNID这是个24位的字段,每个虚拟的网络主机都有一个自身的VNID作为标识,理论上支持2的24次方个虚拟网络。
在docker的桥接网络里,是使用docker0网桥,在Flannel的xvlan方案里则是使用cni0作为网桥(和docker0没啥区别),主要的不同是cni网桥后面连接的是flannel1这个网络设备,应该是一个虚拟网卡
这个网卡将原始报文包装成XVLAN报文(linux高版本支持xvlan报文)
这时需要的信息有 源nodeId,目标nodeId,源vnid,源macId,目标macId,源podId,目标podId
其中目标nodeId,目标macId这两个信息是不存在的;因此需要有个方式根据目标podId获取目标nodeId以及目标macId
因此需要记录如何根据目标podId获取目标macId以及目标nodeId即可
这些数据是可以托管在某个地方的,Flannel就是将这些信息记录在etcd上
在每个node上的flannel1网络设备通过etcd来通过对方的podId获取nodeId和macId
这样最终报文就变成了一个源ip是源nodeIp,目标ip是目标nodeIp的IP报文了(两台宿主机三层可达)
原本经过虚拟网桥是直接连接网络协议栈,但在xvlan模式下,则改为连接一个flannel1,在flannel1中将对原始报文封装成overlay报文转发
udp模式类似,只是udp转发报文说通过tap连通到用户空间,用户空间对报文进行处理然后发送(因为多次内核态用户态切换且数据copy问题,性能较差,仅在不支持xvlan的低版本linux中使用)
当然xvlan是一个技术,上面只是简单介绍最简单的形式
参考:
开发内功修炼之网络篇: >
踩坑完毕,回到主线。
前面关于port的理解存在偏差,需要用实验来确认port配置的含义。
k8s官方文档对于对于这些配置项的解释还是没有很完善。下面是在其他博文中找到的解释。
已知:
从k8s集群内部的宿主机(物理机、虚拟机)可以直接访问pod的服务地址 ip:80
未知(需要测试):
1、同一局域网内,但没有加入k8s集群的其他服务器能否访问pod的服务地址 ip:80---无法访问
2、能否跳过pod直接访问容器的服务地址 ip:80---没查到ip
首先要知道容器的IP地址
可以看到上面的命令查出的结果是 - 无法看出ip,尝试进入容器查看
然后我就没辙了,不过根据linux系统的精神,所有内容都是文件,但是我google了好久也没找到ip地址到底存在哪一个文件中。然后我就怀疑是不是一定要容器开放端口,ip地址才可以用docker inspect查询,起了一个不开端口的容器,结果也是有ip的。后来问了一个底层开发的朋友,据说ip是不写文件的。
那只能先认为通过k8s启动的容器其实是没有容器ip的。
从侧面看,也很有可能k8s启动的容器确实没有ip
3、访问pod所在的主机的80端口能否返回相同的响应---无法访问
从以上的信息来看,这个port配置应该和docker中暴露端口的意思是一样的,例如下面的例子
来做一下实验:
在我们之前的pod配置文件上增加配置,如下
结果和我们之前的猜测保持一致,增加ports的配置之后,访问宿主机的ip:80也可以访问到pod的内容了。
我这里pod ip 是 101913067,宿主机是 101001237。curl 101913067 和 curl 101001237 得到的结果是一样的。正当我想再仔细看看的时候,服务器又挂了,wc,只能明天找网管重启了。
---第二天
昨天,我还想看看
1、关了这个pod之后是否就不能访问了
启动了2个pod如下,mynginx1没有配置ports,mynginx2配置了ports。
当我关了pod-mynginx2之后访问宿主机101002167应该就不能通了,结果居然是---能访问到!
大吃一惊!结果ip弄错了,宿主机不是101002167,而是101001237,犯了个低级错误。
结果如下:这回和预期的结果终于一样了。
2、宿主机上是不是本身就开启了nginx,所以恰巧就能访问
确认宿主机上没有开启nginx
3、宿主机上的端口开放情况
使用netstat查看宿主机的端口开放,居然没有发现80端口开着,好奇怪。
那如果在101001237宿主机上启动一个nginx端口开在80,结果会是什么样子呢。
我居然启动了,没有端口已被占用的报错。现在把宿主机上的nginx的index页面的内容改一下,看访问101001237:80时,到底访问的是哪一个nginx。
分别从集群内部3台服务器和集群外部1台服务器的机器取访问101001237:80,访问到的都是pod中的nginx。
会不会跟启动顺序有关,因为现在的情况是先启动了pod-nignx,后启动 宿主机-nginx,那现在将pod-nginx关闭,访问101001237:80,看是啥。
集群内部3台服务器和集群外部1台服务器访问101001237:80,结果一致,都是宿主机-nginx。
再启动pod-nginx,查看结果。
访问结果又变回pod-nginx了,4台服务器结果一致。
再去看一下宿主机-nginx的日志,有没有报错信息-----------没有错误日志
现在基本可以得出结论了:当pod和宿主机同时使用某一个端口时,不会因为冲突而报错,但是pod会优先占用端口,而与启动顺序无关。
至于为什么会这样,就不去深究了,毕竟精力有限,作为运维实施,了解到这样子的程度应该够用了。
分配原则:calico写入etcd,每个节点一个IP段
总结:pod按照calico写入etcd的网络分配IP。k8s建立pod时,在pod中写入了默认路由16925411,而这个IP并不真实存在,由于veth对二层全通,在pod发送arp路由时,calico将16925411的mac回复为host上面pod对应的veth的mac,从而完成pod造包。
Pod一般不建议设置静态IP地址,若想要实现设置静态IP,可以参考下面的方法。像亚马逊、阿里云等厂家是支持静态IP的,但如果是自己的私有云,可以参考下面的方法。这里使用的是calico网络方案,其他的网络方案,好像并不支持,更详细的 *** 作,可以看看calico的官方文档。
IP Pool资源定义
IPPool资源yaml定义
字段说明
metadata:
spec:
blockSize说明
请在 V330 版本后使用blockSize
IPv4 26和IPv6 122的默认块大小为64个地址的块。这允许将地址按组分配给在同一主机上运行的工作负载。通过对地址进行分组,主机之间以及与其他BGP对等方之间交换的路由更少。如果主机在一个块中分配所有地址,则将为其分配一个附加块。如果没有更多可用的块,则主机可以从分配给其他主机的块中获取地址。为借用的地址添加了特定的路由,这会影响路由表的大小。
将块大小从默认值增加(例如,使用24IPv4为每个块提供256个地址)意味着每个主机更少的块,并且可能会减少路由。但是,请尝试确保池中至少有与主机一样多的块。
从默认值减小块大小(例如,使用28IPv4为每个块提供16个地址)意味着每个主机有更多块,因此可能有更多路由。如果它允许块在主机之间更公平地分布,那么这将是有益的。
关于cidr和blockSize设置
比如你新增一个IPPool,cidr设置为19216900/29,在没有设置blockSize情况下,默认是/26的blockSize,这样是不允许的,19216900/29可用地址为8个,而默认blockSize为26将会把IP段分为64块,没有足够的IP,所以是无效的,所以blockSize应该等于大于子网掩码。
新创建的IPPool,可以在原有的IPPool中某一子网,比如
nodeSelector说明
以下所有的语法,都可以使用&&或||进行组合
kubernetes设置指定IP的场景及方法:
主要通过annotations指定。
基于namespace或者每个pod指定IP池
指定静态IP地址
说明:cniprojectcalicoorg/ipAddrsNoIpam:绕过IPAM分配给Pod的IPv4和/或IPv6地址的列表。任何IP冲突和路由都必须手动或由其他系统来处理。Calico仅在其IP地址属于Calico IP池内时才将路由分配到Pod。如果分配的IP地址不在Calico IP池中,则必须确保通过另一种机制来处理到该IP地址的路由。
申请浮动IP
基于node节点标签分配IP
IPPool生效优先顺序
如果将这些方法中的一种以上用于IP地址分配,则它们将具有以下优先级,其中1为最高优先级:
基于namespace指定IP池
查看当前存在的IP池
创建新的IP池
创建新的namespace,并指定IP池
创建应用测试
注意namespace设置test-ippool
为pod指定静态IP地址或地址范围
指定地址范围
创建IP地址池
创建应用测试
注意spectemplatemetadataannotations指定了使用的IPPool
Pod设置静态IP
创建应用
虽然官方说名cniprojectcalicoorg/ipAddrs:后面是IPv4或IPv6列表,实际并不支持,仅可以设置一个IP地址。所以Pod副本数超过1个是不行的。
设置的IP地址必须包含在已存在的IPPool中
根据节点标签分配IP
删除或禁用已存在的IPPool
如果不禁用或删除,创建的Pod也有可能分配到其他IPPool中的地址段
禁用IPPool
删除IPPool
给节点打上标签
创建IPPool
创建应用测试
headless不分配clusterIP
headless service可以通过解析service的DNS,返回所有Pod的地址和DNS(statefulSet部署的Pod才有DNS)
普通的service,只能通过解析service的DNS返回service的ClusterIP
statefulSet下的Pod有DNS地址,通过解析Pod的DNS可以返回Pod的IP
deployment下的Pod没有DNS
1另一个pod里 可以通过dns+[pod的端口]访问到该服务
Service的ClusterIP工作原理:一个service可能对应一组endpoints(所有pod的地址+端口),client访问ClusterIP,通过iptables或者ipvs转发到Real Server(Pod),具体 *** 作如下
从上面的结果能看到,虽然Service有2个endpoint,但是DNS查询时只会返回Service的ClusterIP地址,具体Client访问的是哪个real server,由iptables或者ipvs决定
据结果看到,dns查询会返回3个endpoint,也就是3个pod地址和DNS,通过解析pod的DNS也能返回Pod的IP
第一种:自主选择权,有时候client想自己决定使用哪个Real Server,可以通过查询DNS来获取Real Server的信息
第二种:headlessservice关联的每个endpoint(也就是Pod),都会有对应的DNS域名;这样Pod之间就可以互相访问
如上,eureka就是我们场景的StatefulSet,对应的pod就是eureka-demo-com-0,eureka-demo-com-1,eureka-demo-com-2,他们之间能互相访问,这样对于一些集群类型的应用就可以解决互相身份识别的问题了
1headless service会为关联的service分配一个域
<service name>$<namespace name>svcclusterlocal
2StatefulSet会为关联的Pod保持一个不变的Pod Name
statefulset中Pod的hostname格式为$(StatefulSet name)-$(pod序号)
3StatefulSet会为关联的Pod分配一个dnsName
$<Pod Name>$<service name>$<namespace name>svcclusterlocal
前言
skywalking是个非常不错的apm产品,但是在使用过程中有个非常蛋疼的问题,在基于es的存储情况下,es的数据一有问题,就会导致整个skywalking web ui服务不可用,然后需要agent端一个服务一个服务的停用,然后服务重新部署后好,全部走一遍。这种问题同样也会存在skywalking的版本升级迭代中。而且apm 这种过程数据是允许丢弃的,默认skywalking中关于trace的数据记录只保存了90分钟。故博主准备将skywalking的部署容器化,一键部署升级。下文是整个skywalking 容器化部署的过程。
目标:将skywalking的docker镜像运行在k8s的集群环境中提供服务
docker镜像构建
FROMregistrycn-xxxxcom/keking/jdk:18ADDapache-skywalking-apm-incubating/ /opt/apache-skywalking-apm-incubating/RUNln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo 'Asia/Shanghai' >/etc/timezone \
&& chmod +x /opt/apache-skywalking-apm-incubating/config/setApplicationEnvsh \
&& chmod +x /opt/apache-skywalking-apm-incubating/webapp/setWebAppEnvsh \
&& chmod +x /opt/apache-skywalking-apm-incubating/bin/startupsh \
&& echo "tail -fn 100 /opt/apache-skywalking-apm-incubating/logs/webapplog" >> /opt/apache-skywalking-apm-incubating/bin/startupshEXPOSE8080 10800 11800 12800CMD/opt/apache-skywalking-apm-incubating/config/setApplicationEnvsh \
&& sh /opt/apache-skywalking-apm-incubating/webapp/setWebAppEnvsh \
&& /opt/apache-skywalking-apm-incubating/bin/startupsh
在编写Dockerfile时需要考虑几个问题:skywalking中哪些配置需要动态配置(运行时设置)?怎么保证进程一直运行(skywalking 的startupsh和tomcat中 的startupsh类似)?
applicationyml
#cluster:# zookeeper:# hostPort: localhost:2181# sessionTimeout: 100000naming:jetty:#OS real network IP(binding required), for agent to find collector clusterhost:0000port:10800contextPath:/cache:# guava:caffeine:remote:gRPC:# OS real network IP(binding required), for collector nodes communicate with each other in cluster collectorN --(gRPC) --> collectorMhost:#real_hostport:11800agent_gRPC:gRPC:#os real network ip(binding required), for agent to uplink data(trace/metrics) to collector agent--(grpc)--> collectorhost:#real_hostport:11800# Set these two setting to open ssl#sslCertChainFile: $path#sslPrivateKeyFile: $path# Set your own token to active auth#authentication: xxxxxxagent_jetty:jetty:# OS real network IP(binding required), for agent to uplink data(trace/metrics) to collector through >
以上就是关于k8s使用tcpdump到对应的pod全部的内容,包括:k8s使用tcpdump到对应的pod、11.4 跨pod网络、计算机网络-k8s网络等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)