27、资源对象-Service【IPVS代理模式】

发布时间 2023-03-23 12:03:36作者: 小粉优化大师

1、基础知识

1.1、知识点回顾

1.2、关键点

ipvs会在每个节点上创建一个名为kube-ipvs0的虚拟接口,并将集群所有Service对象的ClusterIP和ExternalIP都配置在该接口;
 - 所以每增加一个ClusterIP 或者 EternalIP,就相当于为 kube-ipvs0 关联了一个地址罢了。

kube-proxy为每个service生成一个虚拟服务器( IPVS Virtual Server)的定义。

1.3、基本流程

所以当前节点接收到外部流量后,如果该数据包是交给当前节点上的clusterIP,则会直接将数据包交
给kube-ipvs0,而这个接口是内核虚拟出来的,而kube-proxy定义的VS直接关联到kube-ipvs0上。
如果是本地节点pod发送的请求,基本上属于本地通信,效率是非常高的。
默认情况下,这里的ipvs使用的是nat转发模型,而且支持更多的后端调度算法。仅仅在涉及到源地址转换的场景中,会涉及到极少量的iptables规则(应该不会超过20条)

2、环境准备

# 有安装kube-proxy的主机,都需要安装
yum install ipset ipvsadm -y

#加载模块到内核
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack

# 在/etc/modules-load.d/k8s.conf中加入ipvs相关模块,使其开机自动加载到内核。
cat >> /etc/modules-load.d/k8s.conf << 'EOF'
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF

3、模式解析

3.1、从哪里修改代理模式

对于k8s来说,默认情况下,支持的规则是 iptables,我们可以通过多种方式对我们的代理模式进行更改,
因为这些规则都是基于kube-proxy来定制的,所以,我们如果要更改代理模式的话,就需要调整kubeproxy的属性。

3.2、查看kube-proxy的所有属性信息

master1 ~]# kubectl -n kube-system get configmaps 
NAME                                 DATA   AGE
coredns                              1      6d13h
extension-apiserver-authentication   6      6d13h
kube-flannel-cfg                     2      6d13h
kube-proxy                           2      6d13h
kube-root-ca.crt                     1      6d13h
kubeadm-config                       1      6d13h
kubelet-config                       1      6d13h


master1 ~]# kubectl -n kube-system describe configmap kube-proxy 
...
iptables:
  localhostNodePorts: null
  masqueradeAll: false           # 这个属性打开的话,会对所有的请求都进行源地址转换
  masqueradeBit: null
  minSyncPeriod: 0s
  syncPeriod: 0s
ipvs:                            # 调度算法,默认是randomrobin
  excludeCIDRs: null
  minSyncPeriod: 0s
  scheduler: ""
  strictARP: false
  syncPeriod: 0s
  tcpFinTimeout: 0s
  tcpTimeout: 0s
  udpTimeout: 0s
kind: KubeProxyConfiguration
metricsBindAddress: ""
mode: ""    # 默认没有指定,就是使用 iptables 规则
...

3.3、kube-proxy修改ipvs代理模式的方法

3.3.1、方法1:资源清单的修改方法

# 初始化集群的时候配置好
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
  SupportIPVSProxyMode: true
mode: ipvs

3.3.2、方法2:configmap修改方法

master1 ~]# kubectl -n kube-system get cm | grep proxy
kube-proxy                           2      6d15h

# 修改模式mode ipvs
master1 ~]# kubectl -n kube-system edit configmap kube-proxy
apiVersion: v1
data:
  config.conf: |-
...
    kind: KubeProxyConfiguration
    metricsBindAddress: ""
    mode: "ipvs"

# 通过标签批量删除pod
master1 ~]# kubectl -n kube-system delete pod -l k8s-app=kube-proxy

# 重新启动成功
master1 ~]# kubectl -n kube-system get pods | grep proxy
kube-proxy-bwvs4                  1/1     Running   0               41s
kube-proxy-cmbgp                  1/1     Running   0               41s
kube-proxy-kdxbd                  1/1     Running   0               41s
kube-proxy-mkgjg                  1/1     Running   0               41s
kube-proxy-vrljp                  1/1     Running   0               40s


# 随机抽一个pod查看日志
master1 ~]# kubectl -n kube-system logs -f kube-proxy-bwvs4
...
I0323 03:24:40.713799       1 proxier.go:462] "IPVS scheduler not specified, use rr by default" # 默认使用rr调试模式
...

# 在master或node查看LVS的调度情况
[root@node1 ~]# ipvsadm -Ln
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.4.29:8000             Masq    1      0          0         
TCP  172.17.0.1:30443 rr
  -> 10.244.4.8:8443              Masq    1      0          0  

4、实践

4.1、实践1-验证IPVS是否成功

4.1.1、定义资源配置清单

cat > service-ipvs.yml<<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: nginx-test
  labels:
    app: my-nginx
spec:

  containers:
  - name: nginx
    image: 192.168.10.33:80/k8s/my_nginx:v1
---
kind: Service
apiVersion: v1
metadata:
  name: service-test1
spec:
  type: NodePort
  selector:
    app: my-nginx
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30089
EOF

4.1.2、应用资清配置清单

master1 ]# kubectl apply -f service-ipvs.yml 
pod/nginx-test created
service/service-test1 created

master1 service]# kubectl get pods -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx-test   1/1     Running   0          87s   10.244.3.214   node1   <none>           <none>

master1 ]# kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service-test1   NodePort    10.106.71.137   <none>        80:30089/TCP   9s

4.1.3、查看ipvsadm规则

master1 ]# ipvsadm -Ln 
TCP  10.106.71.137:80 rr # 集群的IP地址
  -> 10.244.3.214:80              Masq    1      0          0 # pod的IP地址

4.1.4、查看iptables规则

# 查看ipvsadm规则
node1 ~]# iptables -t nat -S KUBE-NODE-PORT
-N KUBE-NODE-PORT
-A KUBE-NODE-PORT -p tcp -m comment --comment "Kubernetes nodeport TCP port for masquerade purpose" -m set --match-set KUBE-NODE-PORT-TCP dst -j KUBE-MARK-MASQ

node2 ~]# iptables -t nat -S KUBE-NODE-PORT
-N KUBE-NODE-PORT
-A KUBE-NODE-PORT -p tcp -m comment --comment "Kubernetes nodeport TCP port for masquerade purpose" -m set --match-set KUBE-NODE-PORT-TCP dst -j KUBE-MARK-MASQ

总结:
    所有的规则自动转换成 ipvsadm了,iptables规则没有生成了。