k8s-[kube-proxy]

root
233
文章
0
评论
2021年8月13日19:03:39 评论 9980字阅读33分16秒

k8s-kube-proxy

kube-proxy组件介绍

          Kubernetes service只是把应用对外提供服务的方式做了抽象,真正的应用跑在Pod中的container里,我们的请求转到kubernetes nodes对应的nodePort上,那么nodePort上的请求是如何进一步转到提供后台服务的Pod的呢? 就是通过kube-proxy实现的:

         kube-proxy部署在k8s的每一个Node节点上,是Kubernetes的核心组件,我们创建一个 service 的时候,kube-proxy 会在iptables中追加一些规则,为我们实现路由与负载均衡的功能。在k8s1.8之前,kube-proxy默认使用的是iptables模式,通过各个node节点上的iptables规则来实现service的负载均衡,但是随着service数量的增大,iptables模式由于线性查找匹配、全量更新等特点,其性能会显著下降。从k8s的1.8版本开始,kube-proxy引入了IPVS模式,IPVS模式与iptables同样基于Netfilter,但是采用的hash表,因此当service数量达到一定规模时,hash查表的速度优势就会显现出来,从而提高service的服务性能

      service是一组pod的服务抽象,相当于一组pod的LB,负责将请求分发给对应的pod。service会为这个LB提供一个IP,一般称为cluster IP。kube-proxy的作用主要是负责service的实现,具体来说,就是实现了内部从pod到service和外部的从node port向service的访问。
1、kube-proxy其实就是管理service的访问入口,包括集群内Pod到Service的访问和集群外访问service。

2、kube-proxy管理sevice的Endpoints,该service对外暴露一个Virtual IP,也可以称为是Cluster IP, 集群内通过访问这个Cluster IP:Port就能访问到集群内对应的serivce下的Pod。

kube-proxy的作用

  • 实现pod数据包转发、
  • 将Service相关规则进行实现(iptables,ipvs)

Service的均衡是通过Kube-proxy实现的

 kube-proxy三种工作模式

Userspace方式:

         Client Pod要访问Server Pod时,它先将请求发给内核空间中的service iptables规则,由它再将请求转给监听在指定套接字上的kube-proxy的端口,kube-proxy处理完请求,并分发请求到指定Server Pod后,再将请求转发给内核空间中的service ip,由service iptables将请求转给各个节点中的Server Pod。

这个模式有很大的问题,客户端请求先进入内核空间的,又进去用户空间访问kube-proxy,由kube-proxy封装完成后再进去内核空间的iptables,再根据iptables的规则分发给各节点的用户空间的pod。由于其需要来回在用户空间和内核空间交互通信,因此效率很差。在Kubernetes 1.1版本之前,userspace是默认的代理模型。

iptables方式:

客户端IP请求时,直接请求本地内核service ip,根据iptables的规则直接将请求转发到到各pod上,因为使用iptable NAT来完成转发,也存在不可忽视的性能损耗。另外,如果集群中存上万的Service/Endpoint,那么Node上的iptables rules将会非常庞大,性能还会再打折

            iptables代理模式由Kubernetes 1.1版本引入,自1.2版本开始成为默认类型。

ipvs方式:

Kubernetes自1.9-alpha版本引入了ipvs代理模式,自1.11版本开始成为默认设置。客户端

请求时到达内核空间时,根据ipvs的规则直接分发到各pod上。kube-proxy会监视Kubernetes Service对象和Endpoints,调用netlink接口以相应地创建ipvs规则并定期与Kubernetes Service对象和Endpoints对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将被重定向到其中一个后端Pod。与iptables类似,ipvs基于netfilter 的 hook 功能,但使用哈希表作为底层数据结构并在内核空间中工作。这意味着ipvs可以更快地重定向流量,并且在同步代理规则时具有更好的性能。此外,ipvs为负载均衡算法提供了更多选项,例如:

  • rr:轮询调度
  • lc:最小连接数
  • dh:目标哈希
  • sh:源哈希
  • sed:最短期望延迟
  • nq:不排队调度

如果某个服务后端pod发生变化,标签选择器适应的pod又多一个,适应的信息会立即反映到apiserver上,而kube-proxy一定可以watch到etc中的信息变化,而将它立即转为ipvs或者iptables中的规则,这一切都是动态和实时的,删除一个pod也是同样的原理。如图:

注:

以上不论哪种,kube-proxy都通过watch的方式监控着apiserver写入etcd中关于Pod的最新状态信息,它一旦检查到一个Pod资源被删除了或新建了,它将立即将这些变化,反应再iptables 或 ipvs规则中,以便iptables和ipvs在调度Clinet Pod请求到Server Pod时,不会出现Server Pod不存在的情况。自k8s1.11以后,service默认使用ipvs规则,若ipvs没有被激活,则降级使用iptables规则.

kube-proxy生成的iptables规则分析

1、service的type类型是ClusterIp,iptables规则分析

在k8s创建的service,虽然有ip地址,但是service的ip是虚拟的,不存在物理机上的,是在iptables或者ipvs规则里的。

[root@master1 service]# kubectl get svc -l run=my-service
NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.98.63.235   <none>        80/TCP    75s
[root@master1 service]# kubectl get pods -l run=my-nginx -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP                
my-nginx-69f769d56f-6fn7b   1/1     Running   0          13m   10.244.121.22   
my-nginx-69f769d56f-xzj5l   1/1     Running   0          13m   10.244.121.21
[root@xianchaomaster1 service]# iptables -t nat -L | grep 10.98.63.235
KUBE-MARK-MASQ  tcp  -- !10.244.0.0/16        10.98.63.235         /* default/my-nginx cluster IP */ tcp dpt:http
KUBE-SVC-L65ENXXZWWSAPRCR  tcp  --  anywhere             10.98.63.235         /* default/my-nginx cluster IP */ tcp dpt:http
  • KUBE-MARK-MASQ     做标记
  • KUBE-SVC-L65ENXXZWWSAPRCR 接收转发的规则
[root@master1 service]# iptables -t nat -L | grep KUBE-SVC-L65ENXXZWWSAPRCR
KUBE-SVC-L65ENXXZWWSAPRCR  tcp  --  anywhere             10.98.63.235         /* default/my-nginx cluster IP */ tcp dpt:http
Chain KUBE-SVC-L65ENXXZWWSAPRCR (1 references)
[root@xianchaomaster1 service]# iptables -t nat -L | grep 10.244.121.22
KUBE-MARK-MASQ  all  --  10.244.121.22        anywhere             /* default/my-nginx */
DNAT       tcp  --  anywhere             anywhere             /* default/my-nginx */ tcp to:10.244.121.22:80
  • 查看pod的IP可以看到接收地址
[root@master1 service]# iptables -t nat -L | grep 10.244.121.21
KUBE-MARK-MASQ  all  --  10.244.121.21        anywhere             /* default/my-nginx */
DNAT       tcp  --  anywhere             anywhere             /* default/my-nginx */ tcp to:10.244.121.21:80

#通过上面可以看到之前创建的service,会通过kube-proxy在iptables中生成一个规则,来实现流量路由,有一系列目标为 KUBE-SVC-xxx 链的规则,每条规则都会匹配某个目标 ip 与端口。也就是说访问某个 ip:port 的请求会由 KUBE-SVC-xxx 链来处理。这个目标 IP 其实就是service ip。

2、service的type类型是nodePort,iptables规则分析

[root@master1 service]# kubectl get pods -l  run=my-nginx-nodeport
NAME                                 READY   STATUS    RESTARTS   AGE
my-nginx-nodeport-649c945f85-l2hj6   1/1     Running   0          21m
my-nginx-nodeport-649c945f85-zr47r   1/1     Running   0          21m
[root@master1 service]# kubectl get svc -l run=my-nginx-nodeport
NAME                TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
my-nginx-nodeport   NodePort   10.104.251.190   <none>        80:30380/TCP   22m
[root@master1 service]# iptables -t nat -S | grep 30380
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/my-nginx-nodeport" -m tcp --dport 30380 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/my-nginx-nodeport" -m tcp --dport 30380 -j KUBE-SVC-J5QV2XWG4FEBPH3Q
[root@xianchaomaster1 service]# iptables -t nat -S | grep KUBE-SVC-J5QV2XWG4FEBPH3Q
-N KUBE-SVC-J5QV2XWG4FEBPH3Q
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/my-nginx-nodeport" -m tcp --dport 30380 -j KUBE-SVC-J5QV2XWG4FEBPH3Q
-A KUBE-SERVICES -d 10.104.251.190/32 -p tcp -m comment --comment "default/my-nginx-nodeport cluster IP" -m tcp --dport 80 -j KUBE-SVC-J5QV2XWG4FEBPH3Q
-A KUBE-SVC-J5QV2XWG4FEBPH3Q -m comment --comment "default/my-nginx-nodeport" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XRUO23GXY67LXLQN
-A KUBE-SVC-J5QV2XWG4FEBPH3Q -m comment --comment "default/my-nginx-nodeport" -j KUBE-SEP-IIBDPNPJZXXASELC
[root@xianchaomaster1 service]# iptables -t nat -S | grep KUBE-SEP-XRUO23GXY67LXLQN
-N KUBE-SEP-XRUO23GXY67LXLQN
-A KUBE-SEP-XRUO23GXY67LXLQN -s 10.244.102.90/32 -m comment --comment "default/my-nginx-nodeport" -j KUBE-MARK-MASQ
-A KUBE-SEP-XRUO23GXY67LXLQN -p tcp -m comment --comment "default/my-nginx-nodeport" -m tcp -j DNAT --to-destination 10.244.102.90:80
-A KUBE-SVC-J5QV2XWG4FEBPH3Q -m comment --comment "default/my-nginx-nodeport" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-XRUO23GXY67LXLQN
[root@xianchaomaster1 service]# iptables -t nat -S | grep KUBE-SEP-IIBDPNPJZXXASELC
-N KUBE-SEP-IIBDPNPJZXXASELC
-A KUBE-SEP-IIBDPNPJZXXASELC -s 10.244.121.23/32 -m comment --comment "default/my-nginx-nodeport" -j KUBE-MARK-MASQ
-A KUBE-SEP-IIBDPNPJZXXASELC -p tcp -m comment --comment "default/my-nginx-nodeport" -m tcp -j DNAT --to-destination 10.244.121.23:80
-A KUBE-SVC-J5QV2XWG4FEBPH3Q -m comment --comment "default/my-nginx-nodeport" -j KUBE-SEP-IIBDPNPJZXXASELC

 

修改kube-proxy配置文件的方法

[root@master01 ~]# kubectl get cm -n kube-system
NAME                                 DATA   AGE
calico-config                        4      132d
coredns                              1      133d
extension-apiserver-authentication   6      133d
kube-proxy                           2      133d
kubeadm-config                       2      133d
kubelet-config-1.18                  1      133d
[root@master01 ~]# kubectl edit cm -n kube-system kube-proxy

 

 

ServiceIP为什么无法ping通

因为没有具体的设备进行响应,他只是提供一个包过滤防火墙,也就是四层的功能

查看iptables的转发表

[root@master01 ~]# iptables-save |grep 30202
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/web:" -m tcp --dport 30202 -j KUBE-MARK-MASQ
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/web:" -m tcp --dport 30202 -j KUBE-SVC-BIJGBSD4RZCCZX5R
[root@master01 ~]# iptables-save |grep KUBE-SVC-BIJGBSD4RZCCZX5R
:KUBE-SVC-BIJGBSD4RZCCZX5R - [0:0]
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/web:" -m tcp --dport 30202 -j KUBE-SVC-BIJGBSD4RZCCZX5R
-A KUBE-SERVICES -d 10.102.52.147/32 -p tcp -m comment --comment "default/web: cluster IP" -m tcp --dport 80 -j KUBE-SVC-BIJGBSD4RZCCZX5R
-A KUBE-SVC-BIJGBSD4RZCCZX5R -m comment --comment "default/web:" -j KUBE-SEP-2K47U5U2G7Z3MFI7

可以看到为Service创建的转发规则

 

启用IPvs:

[root@master01 ~]# lsmod|grep ip_vs

#开机启动模块
[root@master01 ~]# cat>>/etc/rc.local <<x
> modprobe -- ip_vs
> modprobe -- ip_vs_rr
> modprobe -- ip_vs_wrr
> modprobe -- ip_vs_sh
> modprobe -- nf_conntrack_ipv4
> x

因为使用的kubeadm部署的,所以修改kube-proxy的配置文件,需要修改configmap

[root@master01 ~]# kubectl get cm -n kube-system
NAME                                 DATA   AGE
calico-config                        4      11d
coredns                              1      11d
extension-apiserver-authentication   6      11d
kube-proxy                           2      11d
kubeadm-config                       2      11d
kubelet-config-1.18                  1      11d

 

进行修改,找到“mode”默认是iptabls

[root@master01 ~]# kubectl edit cm kube-proxy -n kube-system
    ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      strictARP: false
      syncPeriod: 0s
      tcpFinTimeout: 0s
      tcpTimeout: 0s
      udpTimeout: 0s
    kind: KubeProxyConfiguration
    metricsBindAddress: ""
    mode: "ipvs"
    nodePortAddresses: null
    oomScoreAdj: null

 

修改完成后,还不能直接就使用到ipvs,还需要重新构建一下ipvs

[root@master01 ~]# kubectl get pod -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-59877c7fb4-qncr7   1/1     Running   2          11d
calico-node-p79hh                          1/1     Running   4          11d
calico-node-qh997                          1/1     Running   3          11d
calico-node-r7mfk                          1/1     Running   2          11d
coredns-66bff467f8-4sbx4                   1/1     Running   3          11d
coredns-66bff467f8-8xwlm                   1/1     Running   3          11d
etcd-master01                              1/1     Running   2          11d
kube-apiserver-master01                    1/1     Running   5          11d
kube-controller-manager-master01           1/1     Running   5          11d
kube-proxy-dltmj                           1/1     Running   2          11d
kube-proxy-tdcj2                           1/1     Running   4          11d
kube-proxy-vn2vv                           1/1     Running   3          11d
kube-scheduler-master01                    1/1     Running   5          11d

把node2节点的kube-proxy修改为ipvs模式

[root@master01 ~]# kubectl get pod -n kube-system -o wide
kube-proxy-dltmj                           1/1     Running   2          11d   192.168.1.5     master01   <none>           <none>
kube-proxy-tdcj2                           1/1     Running   4          11d   192.168.1.7     node02     <none>           <none>
kube-proxy-vn2vv                           1/1     Running   3          11d   192.168.1.6     node01     <none>           <none>
[root@master01 ~]# kubectl delete pod kube-proxy-tdcj2 -n kube-system
pod "kube-proxy-tdcj2" deleted

进行验证node proxy是否改为ipvs模式,下载ipvsadm工具

[root@master01 ~]# yum install -y ipvsadm
[root@node02 ~]# yum -y install ipvsadm

进行查看

[root@node02 ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  172.17.0.1:30001 rr
  -> 10.244.241.78:8443           Masq    1      0          0         
TCP  192.168.1.7:30001 rr
  -> 10.244.241.78:8443           Masq    1      0          0         
TCP  192.168.122.1:30001 rr
  -> 10.244.241.78:8443           Masq    1      0          0         
TCP  10.96.0.1:443 rr
  -> 192.168.1.5:6443             Masq    1      0          0         
TCP  10.96.0.10:53 rr
  -> 10.244.241.73:53             Masq    1      0          0         
  -> 10.244.241.75:53             Masq    1      0          0         
TCP  10.96.0.10:9153 rr
  -> 10.244.241.73:9153           Masq    1      0          0         
  -> 10.244.241.75:9153           Masq    1      0          0         
TCP  10.100.25.41:8000 rr
  -> 10.244.241.76:8000           Masq    1      0          0

而master的proxy没有修改为ipvs所以没有的

[root@master01 ~]# ipvsadm -L -n
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

可以看一下网卡,ipvs生成一个虚拟网卡

9: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN 
    link/ether ca:6c:f5:71:9c:24 brd ff:ff:ff:ff:ff:ff
    inet 10.96.0.10/32 brd 10.96.0.10 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.100.25.41/32 brd 10.100.25.41 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.103.95.133/32 brd 10.103.95.133 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.96.0.1/32 brd 10.96.0.1 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.102.52.147/32 brd 10.102.52.147 scope global kube-ipvs0
       valid_lft forever preferred_lft forever

在应用比较多的时候,切换ipvs比iptables数据包转发效果更好一些

 

继续阅读
weinxin
我的微信
这是我的微信扫一扫
  • 文本由 发表于 2021年8月13日19:03:39
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
k8s-Service Account Kubernetes

k8s-Service Account

k8s-Service Account的授权管理 Service Account也是一种账号,是给运行在Pod里的进程提供了必要的身份证明。需要在Pod定义中指明引用的Service Account,...
k8s-RBAC Kubernetes

k8s-RBAC

k8s-RBAC认证授权策略 RBAC介绍 在Kubernetes中,所有资源对象都是通过API进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现...
k8s-Secret Kubernetes

k8s-Secret

配置管理中心Secret Secret是什么? Configmap一般是用来存放明文数据的,如配置文件,对于一些敏感数据,如密码、私钥等数据时,要用secret类型 Secret解决了密码、token...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: