收集整理,转载自深入理解kubernetes(k8s)网络原理之二-service原理

深入理解k8s网路原理之-POD连接主机中主要介绍了POD与主机及POD访问外网的原理。

Linux网络基础知识

netfilter

netfileter子系统5个关键扩展点:

  • PREROUTING,数据包刚到达时会经过这个点,通常用来完成DNAT的功能。
  • INPUT,数据包要进入本机的传输层时会经过这个点,通常用来完成防火墙入站检测。
  • FORWARD,数据包要通过本机转发时会经过这个点,通常用来完成防火墙转发过滤。
  • OUTPUT,从本机的数据包要出去的时候会经过这个点,通常用来做DNAT和防火墙出站检测。
  • POSTROUTING,数据包离开本机前会经过这个点,通常用来做SNAT。

netfilter
1、 主机的应用程序接收外部的数据包会经过的点: PREROUTING -> INPUT

2、 主机的应用程序发送数据包到外部经过的点: OUTPUT -> POSTROUTING

3、 主机的POD发送的数据包去外部或者去主机的另外一个POD: PREROUTING -> FORWARD -> POSTROUTING

主机上运行的POD虽然也是主机上的一个进程,但是POD发送数据包出去的流程去和主机的其他进程不一样,由于POD在新的NS中,所以他的发包流程适合主机收到另一台主机的数据然后转发的流程是一样的。

4、注意图中的IPIsLocal?的判断,如果数据包的目标IP是本机IP,则往INPUT点走,否则查看net.ipv4.ip_forward是否为1,是则往FORWARD走,0则丢弃。

iptables 基础知识

iptables 初识别

iptables -A INPUT -t filter -s 192.168.1.10 -j DROP
意思是指不允许来源为192.168.1.10ip访问本机的服务。

命令详解:

  • -A 是指后面加一条规则,其他为
    • -I 是前面加一条规则,优先级更高
    • -D 删除规则
    • -N 新增加链
    • -F 清除链上的所有规则或者所有链
    • -X 删除一条用户的自定义链
    • -P 更改链的默认策略
    • -L 真是指定链上的规则
  • 防火墙规则一般制工作在INPUT/OUTPUT/FORWARD三个扩展点
  • -t 指定当前命令操作所属的表,主要有:
    • filter 表,主要用于拦截或者房型,不修改包,如果不指定,则默认为filter
    • nat 表,用于修改ip包的源/目的地址
    • mangle 表,用于给数据包打标记
    • raw 表,#TODO
    • security 表, #TODO
  • -s 数据包的匹配规则,规则可以一个或者多个,多个是与的效果,这里 -s 是匹配来源的的意思,其他的还有
    • -d 匹配目标地址
    • –sport 匹配来源端口
    • –dport 匹配目标端口
    • -p tcp 匹配协议类型
  • -j DROP是执行的动作,这里是跳转到(jumpDROP 链,iptables 有几个预定义的链:
    • DROP 丢弃进入该链的包
    • ACCEPT 接收进入该链的包
    • RETURN 返回上一级链
    • SNAT 源地址转换,要指定转换后的源地址
    • DNAT 目标地址转换,要指定转换后目标地址
    • MASQUEREDE 对进入该链的包进行源地址转换,与SNAT 类似,但不用指定具体的转换后的源地址,会自动应用网卡的地址作为原地址,通常都用这条链完成SNAT
      进阶示例:
      — 把本机应用发往10.96.0.100的数据包的目标地址转换为10.244.3.10上,注意使要影响本机应用,
1
iptables -A OUTPUT -t nat -d 10.96.0.100 -j DNAT --to-distination 10.244.3.10
  • 上面的规则支队本机的应用程序发送的流量有影响, 对于本机的POD发出的流量乜有影响,如果要影响本机的POD,还要加一条,规则都一样,只是工作在PREROUTING链.
1
iptables -A RPEROTING -t nat -d 10.96.0.100 -j DNAT --to-distination 10.244.3.10
  • 对本机发送的数据包中来源ip 为172.20.1.10 的数据包进行源地址伪装,注意修改源地址只有个一个点可以用,就是POSTROUTING,下面的规则就是配置POD上外网时使用的:
1
iptabels -A POSTROUTING -t NAT -S 172.20.1.10 -j MASQUEREDE
  • 允许来源IP为192.168.6.166并访问本机的TCP80 端口
1
iptables -A  INPUT -t filter -s 192.168.8.166 -p tcp --dport 80 -j ACCEPT

iptables 上的规则创建会有一些限制,如无法在POSTROUTING链上创建DNAT的规则,因为饿在POSTROUTING之前,数据包要进行路由判决,内核会根据当前的目的地选择一个最合适的出口,而POSTROUTING链的规则是在路由判决后发生,在这里修改数据包的目的地会造成数据包不可到达的后果。

K8SService 设计

主要考虑如下两个原因:

  • pod 的特性是快速创建销毁,所以podip是不固定的,要让调用方有个固定依赖,所以需要一个VIP来代表服务
  • 一般来说为了追求应用的高可用,一个应用会部署多个POD,这时需要一个VIP充当多个pod的流量负载

service 几种类型的使用场景

  • clusterIP: 只能在集群的节点和pod中访问,解决的就是集群内应用间的相互访问的问题
  • nodeport: 通过节点的地址和端口将pod暴露到集群外,让集群外的应用能够访问集群内的应用,设置服务类型为nodeport时,是在clusterIP的基础上再给节点开个端口转发,所以nodeport的服务也会有一个clusterIP
  • loadBalancer: 因为使用nodeport方式时,需要在应用的调用方写死一个集群节点的IP,此方式并非为高可用方式,这个时候使用第三方负载均衡器的方式,转发到多个节点的nodeportloadBanlancer是在nodeport的基础上再创建一个lb,所以也会先分配一个clusterIP,再创建节点的端口转发。
  • headless: 应用多个副本彼此间相互访问,比如要部署到mysql的主从,从的副本想要找主的副本:
  • externalName: 相当于coredns里面的cname记录

iptables 模式下,clusterIP都是ping不通的,这是因为 kube-proxy 在实现时之根据ip+端口+协议精确匹配才转发,这才导致clusterIP不能ping

hairpin flow场景: pod通过clusterIP访问自己

推荐一篇万字长文iptables长文详解