Skip to content


k8s_安装6_ipvs

安装六 ipvs

kube-proxy修改为ipvs模式
IPVS是Linux内核实现的四层负载均衡
kube-proxy三种模式中,现在使用的就是只有 iptables 模式 或者 ipvs 模式,不管哪种,这两个模式都是依赖 node 节点上的 iptables 规则
kube-proxy 的功能是将 svc 上的请求转发的 pod 上,无论是 iptables 模式还是 ipvs 模式,这个功能都是通过 iptables 链来完成的,iptables -t nat -L,可以打印出 kube-proxy 相关的链

查看当前模式

通过 kubectl 命令查看 kube-proxy 的配置

kubectl get configmap kube-proxy -n kube-system -o yaml | grep mode
    mode: ""
#空表示iptables

#查看日志
kubectl get pods -n kube-system -o wide| grep proxy
kube-proxy-58mfp                             1/1     Running   0             6d3h   192.168.244.5   node01.k8s.local     <none>           <none>
kube-proxy-z9tpc                             1/1     Running   0             6d3h   192.168.244.4   master01.k8s.local   <none>           <none>

kubectl logs kube-proxy-z9tpc -n kube-system 
1011 03:20:57.180789       1 server_others.go:69] "Using iptables proxy"

#查看端口
netstat -lntp 
tcp        0      0 127.0.0.1:10257         0.0.0.0:*               LISTEN      8204/kube-controlle 
tcp        0      0 127.0.0.1:10249         0.0.0.0:*               LISTEN      22903/kube-proxy 

将kube_proxy 切换为ipvs

kube-proxy默认监听的地址是127.0.0.1:10249,想要修改监听的端口
把metricsBindAddress这段修改成 metricsBindAddress: "0.0.0.0:10249"
ipvs修改mode: "ipvs"

#在master节点,修改编辑kube-proxy 这个configmap文件,修改模式为ipvs,同时改监听ip为全部:
    metricsBindAddress: ""
    mode: ""

kubectl edit configmaps kube-proxy -n kube-system

    kind: KubeProxyConfiguration
    logging:
      flushFrequency: 0
      options:
        json:
          infoBufferSize: "0"
      verbosity: 0
    metricsBindAddress: "0.0.0.0:10249"
    mode: "ipvs"
    nodePortAddresses: null
    oomScoreAdj: null
    portRange: ""

重启kube-proxy

# 我们发现修改kube-proxy 这个configmap文件后,查看pod的日志,发现ipvs模式并没有立即生效,所以我们需要删除kube-proxy的pod,这些pod是
# 由DaemonSet控制,删除之后DaemonSet会重新在每个节点创建的

#kubectl get pods -n kube-system | grep kube-proxy |awk '{print $1}' | xargs kubectl delete pods -n kube-system
kubectl  delete pods -n kube-system -l k8s-app=kube-proxy
pod "kube-proxy-58mfp" deleted
pod "kube-proxy-z9tpc" deleted

kubectl get pods -n kube-system -o wide| grep proxy       
kube-proxy-pgr2j                             1/1     Running   0             3s     192.168.244.4   master01.k8s.local   <none>           <none>
kube-proxy-xgmqz                             1/1     Running   0             3s     192.168.244.5   node01.k8s.local     <none>           <none>
kubectl logs kube-proxy-pgr2j -n kube-system 
I1017 07:21:40.118590       1 server_others.go:218] "Using ipvs Proxier"
I1017 07:21:40.118809       1 server_others.go:421] "Detect-local-mode set to ClusterCIDR, but no cluster CIDR for family" ipFamily="IPv6"

kubectl logs kube-proxy-xgmqz -n kube-system 
I1017 07:21:39.951567       1 server_others.go:218] "Using ipvs Proxier"
I1017 07:21:39.951590       1 server_others.go:421] "Detect-local-mode set to ClusterCIDR, but no cluster CIDR for family" ipFamily="IPv6"

#curl请求内部确认
curl 127.0.0.1:10249/proxyMode
ipvs

#查看端口
ss  -antulp |grep :10249
tcp    LISTEN     0      4096   [::]:10249              [::]:*                   users:(("kube-proxy",pid=5764,fd=10))

外部访问测试

http://192.168.244.4:10249/proxyMode
ipvs

查看当前ipvs转发规则

ipvsadm

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  node02.k8s.local:30080 rr
  -> node01.k8s.local:http        Masq    1      0          0         
  -> node02.k8s.local:http        Masq    1      0          0         
TCP  node02.k8s.local:30443 rr
  -> node01.k8s.local:https       Masq    1      0          0         
  -> node02.k8s.local:https       Masq    1      0          0         
TCP  node02.k8s.local:30801 rr
  -> 10.244.2.9:irdmi             Masq    1      0          0         
TCP  node02.k8s.local:32080 rr
  -> 10.244.2.24:8089             Masq    1      0          0         
TCP  node02.k8s.local:https rr
  -> master01.k8s.local:sun-sr-ht Masq    1      4          0         
TCP  node02.k8s.local:domain rr
  -> 10.244.0.10:domain           Masq    1      0          0         
  -> 10.244.0.11:domain           Masq    1      0          0         
TCP  node02.k8s.local:9153 rr
  -> 10.244.0.10:9153             Masq    1      0          0         
  -> 10.244.0.11:9153             Masq    1      0          0         
TCP  node02.k8s.local:irdmi rr
  -> 10.244.2.9:irdmi             Masq    1      0          0         
TCP  node02.k8s.local:31080 rr
  -> 10.244.2.24:8089             Masq    1      0          0         
TCP  node02.k8s.local:cslistener rr
  -> 10.244.2.8:cslistener        Masq    1      0          0         
TCP  node02.k8s.local:http rr
  -> node01.k8s.local:http        Masq    1      0          0         
  -> node02.k8s.local:http        Masq    1      0          0         
TCP  node02.k8s.local:https rr
  -> node01.k8s.local:https       Masq    1      0          0         
  -> node02.k8s.local:https       Masq    1      0          0         
TCP  node02.k8s.local:https rr
  -> node01.k8s.local:pcsync-http Masq    1      0          0         
  -> node02.k8s.local:pcsync-http Masq    1      0          0         
TCP  node02.k8s.local:irdmi rr
  -> 10.244.2.10:irdmi            Masq    1      0          0         
TCP  node02.k8s.local:31080 rr
  -> 10.244.1.93:http             Masq    1      0          0         
TCP  node02.k8s.local:30080 rr
  -> node01.k8s.local:http        Masq    1      0          0         
  -> node02.k8s.local:http        Masq    1      0          0         
TCP  node02.k8s.local:30443 rr
  -> node01.k8s.local:https       Masq    1      0          0         
  -> node02.k8s.local:https       Masq    1      0          0         
TCP  node02.k8s.local:30801 rr
  -> 10.244.2.9:irdmi             Masq    1      0          0         
TCP  node02.k8s.local:32080 rr
  -> 10.244.2.24:8089             Masq    1      0          0         
TCP  node02.k8s.local:30080 rr
  -> node01.k8s.local:http        Masq    1      0          0         
  -> node02.k8s.local:http        Masq    1      0          0         
TCP  node02.k8s.local:30443 rr
  -> node01.k8s.local:https       Masq    1      0          0         
  -> node02.k8s.local:https       Masq    1      0          0         
TCP  node02.k8s.local:30801 rr
  -> 10.244.2.9:irdmi             Masq    1      0          0         
TCP  node02.k8s.local:32080 rr
  -> 10.244.2.24:8089             Masq    1      0          0         
UDP  node02.k8s.local:domain rr
  -> 10.244.0.10:domain           Masq    1      0          0         
  -> 10.244.0.11:domain           Masq    1      0          0  

IPVS支持三种负载均衡模式

Direct Routing(简称DR),Tunneling(也称ipip模式)和NAT(也称Masq模式)

DR

IPVS的DR模式是最广泛的IPVS模式,它工作在L2,即通过Mac地址做LB,而非IP地址。在DR模式下,回程报文不会经过IPVS director 而是直接返回给客户端。因此,DR在带来高性能的同时,对网络也有一定的限制,及要求IPVS的director 和客户端在同一个局域网。另外,比较遗憾的是,DR不支持端口映射,无法支持kubernetes service的所有场景。

TUNNELING

IPVS的Tunneling模式就是用IP包封装IP包,因此也称ipip模式。Tunneling模式下的报文不经过IPVS director,而是直接回复给客户端。Tunneling模式统一不支持端口映射,因此很难被用在kubernetes的service场景中。

NAT

IPVS的NAT模式支持端口映射,回程报文需要经过IPVS director,因此也称Masq(伪装)模式。 kubernetes在用IPVS实现Service时用的正式NAT模式。 当使用NAT模式时,需要注意对报文进行一次SNAT,这也是kubernetes使用IPVS实现Service的微妙之处。

IPVS的八种调度算法

rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq

  1. 轮叫调度 rr
    这种算法是最简单的,就是按依次循环的方式将请求调度到不同的服务器上,该算法最大的特点就是简单。轮询算法假设所有的服务器处理请求的能力都是一样的,调度器会将所有的请求平均分配给每个真实服务器,不管后端 RS 配置和处理能力,非常均衡地分发下去。

  2. 加权轮叫 wrr
    这种算法比 rr 的算法多了一个权重的概念,可以给 RS 设置权重,权重越高,那么分发的请求数越多,权重的取值范围 0 – 100。主要是对rr算法的一种优化和补充, LVS 会考虑每台服务器的性能,并给每台服务器添加要给权值,如果服务器A的权值为1,服务器B的权值为2,则调度到服务器B的请求会是服务器A的2倍。权值越高的服务器,处理的请求越多。

  3. 最少链接 lc
    这个算法会根据后端 RS 的连接数来决定把请求分发给谁,比如 RS1 连接数比 RS2 连接数少,那么请求就优先发给 RS1

  4. 加权最少链接 wlc
    这个算法比 lc 多了一个权重的概念。

  5. 基于局部性的最少连接调度算法 lblc
    这个算法是请求数据包的目标 IP 地址的一种调度算法,该算法先根据请求的目标 IP 地址寻找最近的该目标 IP 地址所有使用的服务器,如果这台服务器依然可用,并且有能力处理该请求,调度器会尽量选择相同的服务器,否则会继续选择其它可行的服务器

  6. 复杂的基于局部性最少的连接算法 lblcr
    记录的不是要给目标 IP 与一台服务器之间的连接记录,它会维护一个目标 IP 到一组服务器之间的映射关系,防止单点服务器负载过高。

  7. 目标地址散列调度算法 dh
    该算法是根据目标 IP 地址通过散列函数将目标 IP 与服务器建立映射关系,出现服务器不可用或负载过高的情况下,发往该目标 IP 的请求会固定发给该服务器。

  8. 源地址散列调度算法 sh
    与目标地址散列调度算法类似,但它是根据源地址散列算法进行静态分配固定的服务器资源。

kube-proxy IPVS参数

在运行基于IPVS的kube-proxy时,需要注意以下参数:

  • -proxy-mode:除了现有的userspace和iptables模式,IPVS模式通过–proxymode=ipvs进行配置。
  • -ipvs-scheduler:用来指定ipvs负载均衡算法,如果不配置则默认使用round-robin(rr)算法。
  • -cleanup-ipvs:类似于–cleanup-iptables参数。如果设置为true,则清除在IPVS模式下创建的IPVS规则;
  • -ipvs-sync-period:表示kube-proxy刷新IPVS规则的最大间隔时间,例如5秒。1分钟等,要求大于0;
  • -ipvs-min-sync-period:表示kube-proxy刷新IPVS规则最小时间间隔,例如5秒,1分钟等,要求大于0
  • -ipvs-exclude-cidrs:用于清除IPVS规则时告知kube-proxy不要清理该参数配置的网段的IPVS规则。因为我们无法区别某条IPVS规则到底是kube-proxy创建的,还是其他用户进程的,配置该参数是为了避免删除用户自己的IPVS规则。

一旦创建一个Service和Endpoint,IPVS模式的kube-proxy会做以下三件事:

  • 1)确保一块dummy网卡(kube-ipvs0)存在,为什么要创建dummy网卡?因为IPVS的netfilter钩子挂载INPUT链,我们需要把Service的访问绑定在dummy网卡上让内核“觉得”虚IP就是本机IP,进而进入INPUT链。
  • 2)把Service的访问IP绑定在dummy网卡上
  • 3)通过socket调用,创建IPVS的virtual server和real server,分别对应kubernetes的Service和Endpoint。

PVS模式中的iptables和ipset
IPVS用于流量转发,它无法处理kube-proxy中的其他问题,例如包过滤、SNAT等。具体来说,IPVS模式的kube-proxy将在以下4中情况依赖iptables

kube-proxy 配置启动参数masquerade-all=true,即集群中所有经过Kube-proxy的包都将做一次SNAT
kube-proxy 启动参数指定集群IP地址范围
支持Load Balance 类型的服务,用于配置白名单
支持NodePort类型的服务,用于在包跨节点前配置MASQUERADE,类似于上文提到的iptables模式

Posted in 安装k8s/kubernetes.

Tagged with , , .


No Responses (yet)

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.



Some HTML is OK

or, reply to this post via trackback.