【kubernetes系列】kubernetes之kube-proxy的工作模式

news2024/11/24 2:52:48

概述

从kubernetes最早开始,kube-proxy到现在总共支持三种模式,在v1.8之前我们使用的是iptables 以及 userspace两种模式,iptables 模式从 v1.2 版本开始引入并作为kube-proxy 默认的操作模式。在kubernetes 1.8之后引入了ipvs模式,并且在v1.11中正式使用,其中iptables和ipvs都是内核态也就是基于netfilter,只有userspace模式是用户态。下面详细介绍下各个模式:

userspace

在k8s v1.2后就已经被淘汰了,该模式下kube-proxy会为每一个Service创建一个监听端口。发向Cluster IP的请求被Iptables规则重定向到kube-proxy监听的端口上,kube-proxy根据LB算法选择一个提供服务的Pod并和其建立连接,以将请求转发到Pod上。该模式下,Kube-proxy充当了一个四层Load balancer的角色,proxy会为每个svc随机监听一个端口,并增加一个iptables规则,从客户端到 ClusterIP:Port 的报文都会被重定向到 proxy port,kube-proxy 收到报文后,通过 Round Robin (轮询) 或者 Session Affinity分发给对应的 Pod。然而由于kube-proxy运行在userspace中,在进行转发处理时会增加两次内核和用户空间之间的数据拷贝,效率较另外两种模式低一些。如下图为userspace的工作流程。
在这里插入图片描述

iptables

iptables模式是从kubernetes1.2开始引入并在v1.12之前使用的默认模式。该模式避免了增加内核和用户空间的数据拷贝操作,提高了转发效率。在这种模式下proxy监控kubernetes对svc和ep对象的改变,直接为service后端的每个Pod创建对应的iptables规则,直接将发向Cluster IP的请求重定向到一个Pod IP。并且这种模式使用iptables来做用户态的入口,而真正提供服务的是内核的Netilter,Netfilter采用模块化设计,具有良好的可扩充性。其重要工具模块IPTables从用户态的iptables连接到内核态的Netfilter的架构中,Netfilter与IP协议栈是无缝契合的,并允许使用者对数据报进行过滤、地址转换、处理等操作。该模式下iptables由kube-proxy动态的管理,kube-proxy不再负责转发,只负责创建iptables规则。数据包的走向完全由iptables规则决定,这样的过程不存在内核态到用户态的切换,效率明显会高很多。流量的转发都是在内核态进行的,所以性能更高更加可靠。

但是随着service的增加,iptables规则会不断增加,导致内核十分繁忙。并且iptables修改了规则后必须得全部刷新才可以生效。如下图为iptables的工作流程。

在这里插入图片描述

ipvs

参考文档https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/ipvs/README.md#prerequisit
IPVS(IP Virtual Server,IP虚拟服务器)实现了传输层的负载平衡,通常称为4 LAN(四层局域网)交换,是Linux内核的一部分。IPVS在主机上运行,在真实服务器集群前面充当负载平衡器。IPVS可以将基于 TCP 和 UDP 的服务请求定向到真实服务器上。

kubernetes从1.8开始增加了IPVS支持,它也是基于netfilter实现的,但定位不同:iptables是为防火墙设计的,IPVS则专门用于高性能,IPVS相对于iptables来说效率会更加高,使用ipvs模式需要在允许proxy的节点上安装ipvsadm,ipset工具包加载ipvs的内核模块。
负载均衡,并使用高效的数据结构Hash表,允许几乎无限的规模扩张。一句话说明:ipvs使用ipset存储iptables规则,在查找时类似hash表查找,时间复杂度为O(1),而iptables时间复杂度则为O(n),使得ipvs可以轻松处理每秒 10 万次以上的转发请求。

当proxy启动的时候,proxy将验证节点上是否安装了ipvs模块。如果未安装的话将回退到iptables模式。在Kubernetes 1.12成为kube-proxy的默认代理模式。对比iptables模式在大规模Kubernetes集群有更好的扩展性和性能,支持更加复杂的负载均衡算法(如:最小负载、最少连接、加权等),支持Server的健康检查和连接重试等功能。ipvs依赖于iptables,由于ipvs 无法提供包过滤、SNAT、masquared(伪装)等功能。因此在某些场景(如Nodeport的实现)下还是要与iptables搭配使用,ipvs 将使用ipset来存储需要DROP或masquared的流量的源或目标地址,以确保 iptables 规则的数量是恒定的。假设要禁止上万个IP访问我们的服务器,则用iptables的话,就需要一条一条地添加规则,会在iptables中生成大量的规则;但是使用ipset的话,只需要将相关的IP地址(网段)加入到ipset集合中即可,这样只需要设置少量的iptables规则即可实现目标。
在这里插入图片描述

这种模式,Kube-Proxy 会监视 Kubernetes Service 对象 和 Endpoints,调用 Netlink 接口以相应地创建 IPVS 规则并定期与 Kubernetes Service 对象 和 Endpoints 对象同步 IPVS 规则,以确保 IPVS 状态与期望一致。访问服务时,流量将被重定向到其中一个后端 Pod上。

那么 ipvs 模式和 iptables 模式之间有哪些差异呢?

  • ipvs 为大型集群提供了更好的可扩展性和性能
  • ipvs 支持比 iptables 更复杂的复制均衡算法(最小负载、最少连接、加权等等)
  • ipvs 支持服务器健康检查和连接重试等功能
  • 可以动态修改ipset集合。即使iptables的规则正在使用这个集合。

kube-proxy使用ipvs模式

在每台机器上安装依赖包:

[root@k8s-m1 ~]# yum install ipvsadm ipset sysstat conntrack libseccomp -y

##所有机器选择需要开机加载的内核模块,以下是 ipvs 模式需要加载的模块并设置开机自动加载
[root@k8s-m1 ~]#  > /etc/modules-load.d/ipvs.conf   #先清空
module=(
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
br_netfilter
  )  
for kernel_module in ${module[@]};do
    /sbin/modinfo -F filename $kernel_module |& grep -qv ERROR && echo $kernel_module >> /etc/modules-load.d/ipvs.conf 
done
systemctl enable --now systemd-modules-load.service

上面用systemctl enable命令如果报错可以用systemctl status -l systemd-modules-load.service看看哪个内核模块加载不了,在/etc/modules-load.d/ipvs.conf里注释掉它再enable试试

所有机器需要设定/etc/sysctl.d/k8s.conf的系统参数。

[root@k8s-m1 ~]# cat > /etc/sysctl.d/k8s.conf  <<EOF 
# https://github.com/moby/moby/issues/31208 
# ipvsadm -l --timout
# 修复ipvs模式下长连接timeout问题 小于900即可
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 10
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
net.ipv4.ip_forward = 1
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2
# 要求iptables不对bridge的数据进行处理
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-arptables = 1
net.netfilter.nf_conntrack_max = 2310720
fs.inotify.max_user_watches=89100
fs.may_detach_mounts = 1
fs.file-max = 52706963
fs.nr_open = 52706963
vm.swappiness = 0
vm.overcommit_memory=1
vm.panic_on_oom=0
EOF

[root@k8s-m1 ~]# sysctl --system

修改Kube-proxy配置文件将mode设置为ipvs

使用kubeadm部署的k8s集群中,kube-proxy的配置文件是用configmap存放的,可以通过edit更改后重启kube-proxy的pod。

[root@k8s-m1 ~]# kubectl edit cm kube-proxy -n kube-system
 ......
    iptables:
      masqueradeAll: true
      masqueradeBit: 14
      minSyncPeriod: 0s
      syncPeriod: 30s
    ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: rr
      strictARP: false
      syncPeriod: 15s
      tcpFinTimeout: 0s
      tcpTimeout: 0s
      udpTimeout: 0s
    kind: KubeProxyConfiguration
    metricsBindAddress: ""
    mode: ipvs
    nodePortAddresses: null
    oomScoreAdj: null
......
#修改mode模式为ipvs即可

创建 ClusterIP 类型服务时,IPVS proxier 将执行以下三项操作:

  • 确保节点中存在虚拟接口,默认为 kube-ipvs0
  • 将Service IP 地址绑定到虚拟接口
  • 分别为每个Service IP 地址创建 IPVS virtual servers
## pod的yml文件
[root@k8s-m1 k8s-total]# cat nginx-deployment.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      tier: frontend
  replicas: 1
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
        - name: nginx-gateway
          image: nginx
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
          ports:
            - containerPort: 80
#svc的yml文件
[root@k8s-m1 k8s-total]# cat nginx-svc.yml 
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - port: 80
  selector:
    tier: frontend
#创建
[root@k8s-m1 k8s-total]#kubectl apply -f nginx-deployment.yml -f nginx-svc.yml
#查看svc
[root@k8s-m1 k8s-total]# kubectl get svc nginx-service
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
nginx-service   ClusterIP   10.111.157.115   <none>        80/TCP    2d12h
#查看pod
[root@k8s-m1 k8s-total]# kubectl get pod -o wide
NAME                        READY   STATUS    RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
configmap-subpath           1/1     Running   43         43h     10.244.42.136   k8s-m1   <none>           <none>
my-nginx-7ff446c4f4-2d9gz   1/1     Running   0          9m42s   10.244.42.143   k8s-m1   <none>           <none>
my-nginx-7ff446c4f4-tbtpc   1/1     Running   0          8m8s    10.244.11.12    k8s-m3   <none>           <none>

#查看ipvs转发表
[root@k8s-m1 k8s-total]# ipvsadm -Ln
TCP  10.111.157.115:80 rr
  -> 10.244.11.12:80              Masq    1      0          0         
  -> 10.244.42.143:80             Masq    1      0          0         
TCP  10.244.42.151:30080 rr
  -> 10.244.11.12:80              Masq    1      0          0         
  -> 10.244.42.143:80             Masq    1      0          0         
TCP  10.244.42.151:30119 rr
TCP  10.244.42.151:30404 rr

通过查看ipvs的转发表,发现是按照我们预想的转发。
删除 Kubernetes Service将触发删除相应的 IPVS 虚拟服务器,IPVS 物理服务器及其绑定到虚拟接口的 IP 地址。

端口映射:

IPVS 中有三种代理模式:NAT(masq),IPIP 和 DR。 只有 NAT 模式支持端口映射。 Kube-proxy 利用 NAT 模式进行端口映射。 以下示例显示 IPVS 服务端口80到Pod端口80的映射。

[root@k8s-m1 k8s-total]# ipvsadm -Ln
TCP  10.111.157.115:80 rr
  -> 10.244.11.12:80              Masq    1      0          0         
  -> 10.244.42.143:80             Masq    1      0          0       

会话关系:

IPVS 支持客户端 IP 会话关联(持久连接)。 当服务指定会话关系时,IPVS 代理将在 IPVS 虚拟服务器中设置超时值(默认为180分钟= 10800秒)。

ipvs proxier 将在以下5种情况下依赖于 iptables:

  • kube-proxy 设置 --masquerade-all = true
  • kube-proxy 设置 --cluster-cidr=<cidr>
  • Load Balancer 类型的 Service
  • NodePort 类型的 Service
  • 指定 externalIPs 的 Service

kube-proxy 配置参数 –masquerade-all=true

如果 kube-proxy 配置了–masquerade-all=true参数,则 ipvs 将伪装所有访问 Service 的 Cluster IP 的流量,此时的行为和 iptables 是一致的,由 ipvs 添加的 iptables 规则如下:

[root@k8s-m1 ~]# iptables -t nat -nL

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */

Chain KUBE-MARK-MASQ (2 references)
target     prot opt source               destination
MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x4000

Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOOP-BACK dst,dst,src

Chain KUBE-SERVICES (2 references)
target     prot opt source               destination
KUBE-MARK-MASQ  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-CLUSTER-IP dst,dst
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-CLUSTER-IP dst,dst

在 kube-proxy 启动时指定集群 CIDR

如果 kube-proxy 配置了–cluster-cidr=参数,则 ipvs 会伪装所有访问 Service Cluster IP 的外部流量,其行为和 iptables 相同,假设 kube-proxy 提供的集群 CIDR 值为:10.244.16.0/24,那么 ipvs 添加的 iptables 规则应该如下所示:

# iptables -t nat -nL

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */

Chain KUBE-MARK-MASQ (3 references)
target     prot opt source               destination
MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x4000

Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOOP-BACK dst,dst,src

Chain KUBE-SERVICES (2 references)
target     prot opt source               destination
KUBE-MARK-MASQ  all  -- !10.244.16.0/24       0.0.0.0/0            match-set KUBE-CLUSTER-IP dst,dst
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-CLUSTER-IP dst,dst

Load Balancer 类型的 Service

对于loadBalancer类型的服务,ipvs 将安装匹配 KUBE-LOAD-BALANCER 的 ipset 的 iptables 规则。特别当服务的 LoadBalancerSourceRanges 被指定或指定 externalTrafficPolicy=local 的时候,ipvs 将创建 ipset 集合KUBE-LOAD-BALANCER-LOCAL/KUBE-LOAD-BALANCER-FW/KUBE-LOAD-BALANCER-SOURCE-CIDR,并添加相应的 iptables 规则,如下所示规则:

# iptables -t nat -nL

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */

Chain KUBE-FIREWALL (1 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOAD-BALANCER-SOURCE-CIDR dst,dst,src
KUBE-MARK-DROP  all  --  0.0.0.0/0            0.0.0.0/0

Chain KUBE-LOAD-BALANCER (1 references)
target     prot opt source               destination
KUBE-FIREWALL  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOAD-BALANCER-FW dst,dst
RETURN     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOAD-BALANCER-LOCAL dst,dst
KUBE-MARK-MASQ  all  --  0.0.0.0/0            0.0.0.0/0

Chain KUBE-MARK-DROP (1 references)
target     prot opt source               destination
MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x8000

Chain KUBE-MARK-MASQ (2 references)
target     prot opt source               destination
MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x4000

Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOOP-BACK dst,dst,src

Chain KUBE-SERVICES (2 references)
target     prot opt source               destination
KUBE-LOAD-BALANCER  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOAD-BALANCER dst,dst
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOAD-BALANCER dst,dst

NodePort 类型的 Service

对于 NodePort 类型的服务,ipvs 将添加匹配KUBE-NODE-PORT-TCP/KUBE-NODE-PORT-UDP的 ipset 的iptables 规则。当指定externalTrafficPolicy=local时,ipvs 将创建 ipset 集KUBE-NODE-PORT-LOCAL-TC/KUBE-NODE-PORT-LOCAL-UDP并安装相应的 iptables 规则,如下所示:(假设服务使用 TCP 类型 nodePort)

|

# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */

Chain KUBE-MARK-MASQ (2 references)
target     prot opt source               destination
MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x4000

Chain KUBE-NODE-PORT (1 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-NODE-PORT-LOCAL-TCP dst
KUBE-MARK-MASQ  all  --  0.0.0.0/0            0.0.0.0/0

Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOOP-BACK dst,dst,src

Chain KUBE-SERVICES (2 references)
target     prot opt source               destination
KUBE-NODE-PORT  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-NODE-PORT-TCP dst

指定 externalIPs 的 Service

对于指定了externalIPs的 Service,ipvs 会安装匹配KUBE-EXTERNAL-IP ipset 集的 iptables 规则,假设我们有指定了 externalIPs 的 Service,则 iptables 规则应该如下所示:

# iptables -t nat -nL

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
KUBE-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */

Chain KUBE-MARK-MASQ (2 references)
target     prot opt source               destination
MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x4000

Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */ mark match 0x4000/0x4000
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOOP-BACK dst,dst,src

Chain KUBE-SERVICES (2 references)
target     prot opt source               destination
KUBE-MARK-MASQ  all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-EXTERNAL-IP dst,dst
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-EXTERNAL-IP dst,dst PHYSDEV match ! --physdev-is-in ADDRTYPE match src-type !LOCAL
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-EXTERNAL-IP dst,dst ADDRTYPE match dst-type LOCAL

IPVS 模式

入流量

入流量是指由集群外部访问 service 的流量。
Iptables 入流量的 chain 路径是 PREROUTING@nat -> INPUT@nat。

ClusterIP

Iptables 入流量的 chain 路径是 PREROUTING@nat -> INPUT@nat。
在 PREROUTING 阶段,流量跳转到 KUBE-SERVICES target chain:

[root@k8s-m1 ~]# iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
cali-PREROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* cali:6gwbT8clXdHdC1b1 */
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

KUBE-SERVICES chain 如下:


Chain KUBE-SERVICES (2 references)
target     prot opt source               destination         
KUBE-LOAD-BALANCER  all  --  0.0.0.0/0            0.0.0.0/0            /* Kubernetes service lb portal */ match-set KUBE-LOAD-BALANCER dst,dst
KUBE-MARK-MASQ  all  --  0.0.0.0/0            0.0.0.0/0            /* Kubernetes service cluster ip + port for masquerade purpose */ match-set KUBE-CLUSTER-IP dst,dst
KUBE-MARK-MASQ  all  --  0.0.0.0/0            0.0.0.0/0            /* Kubernetes service external ip + port for masquerade and filter purpose */ match-set KUBE-EXTERNAL-IP dst,dst
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            /* Kubernetes service external ip + port for masquerade and filter purpose */ match-set KUBE-EXTERNAL-IP dst,dst PHYSDEV match ! --physdev-is-in ADDRTYPE match src-type !LOCAL
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            /* Kubernetes service external ip + port for masquerade and filter purpose */ match-set KUBE-EXTERNAL-IP dst,dst ADDRTYPE match dst-type LOCAL
KUBE-NODE-PORT  all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-CLUSTER-IP dst,dst
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            match-set KUBE-LOAD-BALANCER dst,dst

ClusterIP service 的访问流量会交由 KUBE-MARK-MASQ处理,其匹配规则是匹配内核中名为 KUBE-CLUSTER-IP 的 ipset(将源地址不是10.244.0.0/16的IP交由KUBE-MARK-MASQ)。

下一步就是为这些包打上标记:

Chain KUBE-MARK-MASQ (4 references)
target     prot opt source               destination         
MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK or 0x4000

此时封包在 iptables 的路径已经走完,并没有后续的 DNAT 到后端 endpoint 的流程,这一步的工作交由 IPVS 来完成。(这步是仅仅给ipset list中的KUBE-CLUSTER-IP 添加了一个标签0x4000,有此标记的数据包会在KUBE-POSTROUTING chain中统一做MASQUERADE)

检查 ipvs 代理规则

用户可以使用ipvsadm工具检查 kube-proxy 是否维护正确的 ipvs 规则,比如,我们在集群中有以下一些服务:

[root@k8s-m1 k8s-total]# kubectl get svc -A
NAMESPACE                       NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                                                      AGE
default                         kubernetes                  ClusterIP      10.96.0.1        <none>          443/TCP                                                                      412d
kube-system                     kube-dns                    ClusterIP      10.96.0.10       <none>          53/UDP,53/TCP,9153/TCP                                                       412d

我们可以得到如下的一些 ipvs 代理规则:

[root@k8s-m1 k8s-total]# ipvsadm -Ln
TCP  10.96.0.1:443 rr
  -> 192.168.2.140:6443           Masq    1      0          0         
  -> 192.168.2.141:6443           Masq    1      1          0         
  -> 192.168.2.142:6443           Masq    1      1          0         
TCP  10.96.0.10:53 rr
  -> 10.244.11.58:53              Masq    1      0          0         
  -> 10.244.81.166:53             Masq    1      0          0   

出流量
出流量是指由集群内的 pod 访问 service 的流量。
Iptables 出流量的 chain 路径是 OUTPUT@nat -> POSTROUTING@nat。
OUTPUT chain 如下,与入流量情形一样,也是所有流量跳转到 KUBE-SERVICES chain:

[root@k8s-m1 k8s-total]#  iptables -L -n -t nat
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
cali-OUTPUT  all  --  0.0.0.0/0            0.0.0.0/0            /* cali:tVnHkvAo15HuiPy0 */
KUBE-SERVICES  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

而后的动作与入流量一致,不论 ClusterIP service 还是 NodePort service,都是为封包打上 0x4000 的标记。区别是至此入流量的 iptables 流程走完,而出流量还需要经过 nat 表的 POSTROUTING chain,其定义如下:

[root@k8s-m1 k8s-total]#  iptables -L -n -t nat
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
cali-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* cali:O3lYWMrLQYEMJtB5 */
KUBE-POSTROUTING  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */
MASQUERADE  all  --  172.16.0.0/16        0.0.0.0/0           
MASQUERADE  all  --  172.19.0.0/16        0.0.0.0/0           
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0                  

进一步跳转到 KUBE-POSTROUTING chain:Chain KUBE-POSTROUTING (1 references)

Chain KUBE-POSTROUTING (1 references)
target     prot opt source               destination         
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* Kubernetes endpoints dst ip:port, source ip for solving hairpin purpose */ match-set KUBE-LOOP-BACK dst,dst,src
RETURN     all  --  0.0.0.0/0            0.0.0.0/0            mark match ! 0x4000/0x4000
MARK       all  --  0.0.0.0/0            0.0.0.0/0            MARK xor 0x4000
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes service traffic requiring SNAT */

在这里,会为之前打上 0x4000 标记的出流量封包执行 MASQUERADE target,即类似于 SNAT 的一种操作,将其来源 IP 变更为 ClusterIP 或 Node ip。

被打了标记的流量处理方式

[root@k8s-m1 ~]#  iptables -L -n

Chain KUBE-FIREWALL (2 references)
target     prot opt source               destination         
DROP       all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes firewall for dropping marked packets */ mark match 0x8000/0x8000
DROP       all  -- !127.0.0.0/8          127.0.0.0/8          /* block incoming localnet connections */ ! ctstate RELATED,ESTABLISHED,DNAT

Chain KUBE-FORWARD (1 references)
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes forwarding rules */ mark match 0x4000/0x4000
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes forwarding conntrack pod source rule */ ctstate RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes forwarding conntrack pod destination rule */ ctstate RELATED,ESTABLISHED

ipset命令使用(iptables 中 match-set 匹配的就是就这里的地址 )

[root@k8s-m1 ~]# ipset list
Name: KUBE-CLUSTER-IP
Type: hash:ip,port
Revision: 5
Header: family inet hashsize 1024 maxelem 65536
Size in memory: 3192
References: 2
Number of entries: 48
Members:
10.110.139.178,tcp:15443
10.108.18.160,tcp:8443
10.110.240.216,tcp:80
10.96.246.188,tcp:80
10.110.139.178,tcp:80
10.99.232.160,tcp:9411
10.100.7.245,tcp:14250
10.103.189.79,tcp:8000
10.96.0.10,tcp:9153
10.99.242.17,tcp:80
10.98.180.236,tcp:80
10.101.138.128,tcp:16686
10.97.144.128,tcp:853
10.101.230.40,tcp:9080
10.100.7.245,tcp:14268
10.110.57.244,tcp:9080
10.111.157.115,tcp:80
10.108.18.160,tcp:8080
10.101.101.153,tcp:8000
10.96.0.1,tcp:443
10.106.45.53,tcp:15443
10.97.144.128,udp:53
10.106.45.53,tcp:443
10.106.45.53,tcp:80
10.99.172.101,tcp:5000
10.98.90.254,tcp:443
10.97.144.128,tcp:443
10.98.189.216,tcp:20001
10.110.139.178,tcp:443
10.97.144.128,tcp:15012
10.100.7.245,tcp:14267
10.96.0.10,tcp:53
10.97.144.128,tcp:15010
10.104.103.99,tcp:9090
10.111.82.238,tcp:443
10.97.144.128,tcp:15014
10.97.164.0,tcp:80
10.106.150.183,tcp:9090
10.97.154.242,tcp:8080
10.104.131.196,tcp:9411
10.99.22.164,tcp:3306
10.104.193.235,tcp:443
10.110.33.30,tcp:9080
10.110.139.178,tcp:15020
10.110.139.178,tcp:31400
10.96.0.10,udp:53
10.97.172.70,tcp:3000
10.106.73.215,tcp:443

官方文档:https://github.com/kubernetes/kubernetes/blob/master/pkg/proxy/ipvs/README.md

更多关于kubernetes的知识分享,请前往博客主页。编写过程中,难免出现差错,敬请指出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/715515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

!!!已解决: Linux操作系统登录,输入正确账号密码显示却显示:Sorry, that didn‘t work. Please try again.

&#xff01;&#xff01;&#xff01;已解决&#xff1a; Linux操作系统登录&#xff0c;明明输入密码正确却显示&#xff1a;Sorry, that didn’t work. Please try again. 先给大家复现一下我的问题&#xff1a; 为什么出现这个问题&#xff1f;&#xff1f;&#xff1f; …

知识梳理for CDGA/CDGP——第九章 ​文件和内容管理

第九章在CDGA分值占比较少&#xff0c;CDGP不考核&#xff0c;主要考点包括&#xff1a;定义、目标、原则、活动、工具、度量指标等基本概念、记住精心管理档案特点、GARP原则等。因此本章建议不需要花大量时间研究&#xff0c;熟悉历史真题&#xff0c;聚焦关键考点即可&#…

Leetcode-每日一题【1290. 二进制链表转整数】

题目 给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。 请你返回该链表所表示数字的 十进制值 。 示例 1&#xff1a; 输入&#xff1a;head [1,0,1]输出&#xff1a;5解释&#xff1a;二进制数 (101) 转化为…

没有BuildConfig

Android Gradle 插件8.0.0&#xff08;2023年4月&#xff09; 刚刚发现&#xff0c;新创建的一个Android项目&#xff0c;成功运行到手机上了&#xff0c;然后在代码中想使用一下BuildConfig这个类&#xff0c;发现没有&#xff0c;按以前的经验&#xff0c;项目刚创建时Build…

优雅码住!ChatGPT的五大开源替代方案

自去年11月发布以来&#xff0c;ChatGPT吸引了全球各行业人士的注意力和想象力。人们将它用于各种任务和应用程序&#xff0c;而且它有可能改变流行的应用程序并创建新的应用程序。 但ChatGPT也引发了微软和谷歌等科技巨头之间的人工智能竞赛&#xff0c;使得该行业在大型语言模…

Docker服务编排之Docker Compose的使用

Docker服务编排 概念&#xff1a;按照一定的业务规则批量的管理容器 微服务架构的应用系统中一般包含很多微服务&#xff0c;一个微服务中又包含很多的实例&#xff0c;每个微服务都要手动管理&#xff0c;维护的工作量很大。 拉去镜像&#xff0c;创建多个容器&#xff0c;分…

使用YOLOv5实现实时目标检测结果保存

本文将分享保存实时目标检测结果的方法&#xff0c;包括将目标信息逐帧保存到.txt文件中、逐帧输出检测结果图片、以及如何保存所有检测图片&#xff08;包括视野中无目标的帧&#xff09;。 目录 0.准备 1.目标信息保存 2.检测图片保存 3.保存所有帧 0.准备 本文以单摄像…

基于卷积变分自动编码器的3D数据处理与重建【CVAE】

在这个项目中&#xff0c;我们将学习如何使用卷积变分自动编码器 (CVAE) 来处理和重建 3D 湍流数据。 我们使用计算流体动力学 (CFD) 方法生成 3D 湍流立方体&#xff0c;每个 3D 立方体沿着三个速度分量携带物理信息&#xff08;与图像数据类似&#xff0c;被视为单独的通道&…

elk中kibana使用

1.前言 kibana是一款作为elasticsearch可视化的一款软件&#xff0c;将elasticsearch中的数据以可视化的状态展现出来&#xff0c;kibana也提供了查询、统计、修改索引等功能 2.kibana使用 索引管理 在索引管理中&#xff0c;可以看到所有索引的状态、运行状况、主分片、副本…

76-基于51单片机家庭红外人体检测震动报警系统(程序+原理图+元件清单全套资料)...

资料编号&#xff1a;076 功能介绍&#xff1a;采用51单片机作为主控CPU&#xff0c;采用红外接触传感器采集当前是否有人&#xff0c;采用震动传感器采集当前是否有震动&#xff0c;起到家庭防盗效果&#xff0c;采用按键设置当前布防/撤防状态&#xff0c;布防状态下&#xf…

Binder系列--获取ServiceManager

获取ServiceManager hongxi.zhu 2023-7-1 以SurfaceFlinger为例&#xff0c;分析客户端进程如何获取ServiceManager代理服务对象 主要流程 SurfaceFlinger中获取SM服务 frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp // publish surface flingersp<…

适合初中生用的台灯有哪些?这样的台灯最适合学生!

对于学生而言台灯主要的点就是能够护眼、缓解眼睛疲劳&#xff0c;因为学生需要长时间的学习和用眼而且可以休息放松的时间比较少&#xff0c;导致眼睛过度疲劳&#xff0c;这也是为什么这么多中小学生近视的原因。那么我们应该怎么样选好一款台灯呢&#xff1f; 要想台灯能护眼…

Linux系统之dnf包管理器的基本使用

Linux系统之dnf包管理器的基本使用 一、dnf工具介绍1. dnf工具简介2. dnf的功能 二、DNF的安装1. 检查本地操作系统版本2. 安装epel3. 检查本地yum仓库状态4. 安装dnf包 三、dnf的使用帮助1. 查看dnf版本2. 查看dnf命令的帮助信息3. dnf命令的选项解释 四、dnf命令的基本使用1.…

浅谈Unicode与UTF-8

我们都知道&#xff0c;在Golang中字符都是以UTF-8编码的形式存储&#xff0c;当我们使用range遍历字符串的时候&#xff0c;go会为我们取出一个字符(rune)而不是一个byte&#xff0c;例如以下例子&#xff0c;我们使用range迭代取出第一个字符“你”&#xff0c;并且打印输出取…

TechSmith Camtasia for Mac 2023.0.3 中文破解版 Win/Mac上强大的屏幕录像工具

Camtasia 是Win/Mac上最强大的屏幕录像工具之一&#xff0c;该软件集成了视频录制、编辑、导出等一系列功能&#xff0c;支持鼠标光标样式、草绘示意插图、冰冻区域等实用的功能&#xff0c;还具有移动客户端让你录制视频&#xff0c;然后通过无线传输到 Camtasia 中进行编辑&a…

判断数组中所有元素是否均为实数对象 numpy.isrealobj()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断数组中所有元素 是否均为实数对象 numpy.isrealobj() [太阳]选择题 请问关于以下代码的说法错误的是&#xff1f; import numpy as np a np.array([1, 2, 3]) b np.array([1, 1 2j, …

剑指 Offer 19: 正则表达式匹配

可能存在一个现象&#xff0c;就是aaab&#xff0c;然后a*ab&#xff0c;那么这样*只能代表一个a。 这道题可以使用动态规划的方式来解决。 这道题就是状态的判断&#xff1a;是否两个都为0&#xff1f;只有两个都为0才为true&#xff0c;并且判断*&#xff0c;有两个情况&…

Docker WebRTC容器部署方案

文章目录 WebRTC简介WebRTC Docker容器部署优势方案&#xff08;mpromonet/webrtc-streamer&#xff09;步骤 WebRTC简介 WebRTC&#xff08;Web Real-Time Communication&#xff09;是一种开放的实时通信技术&#xff0c;它允许浏览器之间进行音频、视频和数据的实时传输。W…

从古代八卦探究计算机的八进制

八进制&#xff0c;即八卦&#xff0c;是中国古代哲学体系中非常重要的一个概念&#xff0c;它被广泛应用于易经、道家、儒家等诸多领域。随着计算机科学的快速发展&#xff0c;人们开始思考&#xff1a;八进制是否可以应用到计算机上&#xff1f; 一、什么是八进制&#xff1…

Javaee技术目的总结

一.前节回顾 在前一节中&#xff0c;我们了解了&#xff1a; 1.将中央控制器中的Action容器&#xff0c;变成可控制! 2.针对于反射调用业务代码&#xff0c;最终页面跳转 3.jsp页面参数传递后台的代码优化字段太多有影响&#xff01; 二.项目部署前期准备工作 1.项目运行环境…