kubenetes 四种 Service 类型 1.K8S Service 介绍 Service 是什么?
Service 是 Kubernetes 集群中的一个资源对象,用于定义如何访问一组带有相同特征的 Pods,提供统一的访问入口 + 负载均衡。通常情况下,Service 通过 Label Selector 来确定目标 Pods,ExternalName Services 例外,关于 Service 的详细介绍,请参阅官方文档中 Service 章节 。
Kubernetes 提供了四种类型的 Service,分别用于不同的业务场景,默认的类型是 ClusterIP 。
ClusterIP
NodePort
LoadBalance
ExternalName
iptables 或者 ipvs 是 Service 的具体实现手段,为一组 Pods 提供负载均衡能力。
Pods 与 Service 的关系是:Service 通过 Pods 的 label 标签关联一组 Pods
Service 工作流程:
流程:客户端 -> NodePort/ClusterIP (iptables/ipvs负载均衡规则) -> 各节点的 Pod
1 2 3 4 5 6 7 $ kubectl get service $ kubectl get svc $ kubectl get endpoints $ kubectl get ep
2.K8S 四种 Service 资源类型 (1)ClusterIP 集群内部访问 ClusterIP 是 Kubernetes 中默认的服务类型。分配一个稳定的IP,即VIP,一个稳定的内部域名,只能在集群内部访问,再结合 k8s ingress-controller 提供对外的访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 --- apiVersion: v1 kind: Service metadata: name: nginx-test labels: app: nginx-test namespace: default spec: type: ClusterIP selector: app: nginx-test ports: - port: 80 protocol: TCP targetPort: 80
(2)NodePort 节点对外暴露应用 NodePort 在每台 K8S 节点上启用一个端口来暴露服务,可以在集群外部访问。也会分配一个稳定内部集群IP地址。访问地址:<任意NodeIP>:NodePort,默认端口范围:30000-32767
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 --- apiVersion: v1 kind: Service metadata: name: nginx-test labels: app: nginx-test namespace: default spec: type: NodePort selector: app: nginx-test ports: - port: 80 protocol: TCP targetPort: 80 nodePort: 30011
查看 service
1 2 3 4 $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16d nginx-test NodePort 10.97.37.133 <none> 80:30008/TCP 41m
(3)LoadBalance 结合云负载均衡对外暴露应用(公有云) 参考 UCloud UK8S Service
LoadBalance 是通过集群外部的负载均衡设备来暴露服务,负载均衡设备一般由云厂商提供或者使用者自行搭建。
LoadBalance 与 NodePort 类似,也会在每个节点上启用一个端口来暴露服务。区别是云负载均衡器会自动的将 node 节点添加进 RS ,省去了手动添加 Nginx upstream 的步骤。
LoadBalancer 类型的 Service 方法,借助于 Kubernetes 提供的扩展接口,云 K8S 会创建一个与该 Service 对应的负载均衡服务 LB 来承接外部流量,并路由到集群内部。但在诸如微服务等场景下,一个 Service 对应一个负载均衡器,管理成本明显过高,Ingress 因此应运而生。
实际使用需要查看各云厂商提供的文档指引。
(4)ExternalName 将服务映射到一个 DNS 域名(如example.test.ucloud.cn),DNS 域名可通过 spec.externalName 参数配置。
这种类型不常用,这里不做过多赘述。
3.Service 的两种网络代理模式 kube-proxy
Service 的底层主要有 iptables (默认) 和 ipvs 两种网络模式,决定了如何转发流量。k8s自1.8版本开始强推ipvs,之前版本默认使用iptables.
1 2 3 4 5 6 7 8 9 10 $ iptables-save | grep <SERVICE-NAME> $ ipvsadm -L -n|grep 30011 TCP 172.17.0.1:30011 rr TCP 172.25.214.192:30011 rr TCP 192.168.100.51:30011 rr
4.kubeadm 集群修改 kube-proxy 模式为 IPVS: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 $ kubectl get pods -n kube-system -o wide $ kubectl edit configmap kube-proxy -n kube-system .... mode: "ipvs" $ kubectl delete pod kube-proxy-8mmbm -n kube-system $ kubectl get pods -n kube-system -o wide $ kubectl logs kube-proxy-v7gkv -n kube-system I0419 09:14:57.480897 1 node.go:136] Successfully retrieved node IP: 192.168.99.102 I0419 09:14:57.481117 1 server_others.go:111] kube-proxy node IP is an IPv4 address (192.168.99.102), assume IPv4 operation I0419 09:14:57.681023 1 server_others.go:259] Using ipvs Proxier. E0419 09:14:57.706576 1 proxier.go:381] can't set sysctl net/ipv4/vs/conn_reuse_mode, kernel version must be at least 4.1 W0419 09:14:57.706848 1 proxier.go:434] IPVS scheduler not specified, use rr by default I0419 09:14:57.707188 1 server.go:650] Version: v1.19.0 I0419 09:14:57.707857 1 conntrack.go:52] Setting nf_conntrack_max to 131072 I0419 09:14:57.710100 1 config.go:315] Starting service config controller I0419 09:14:57.710132 1 shared_informer.go:240] Waiting for caches to sync for service config I0419 09:14:57.710181 1 config.go:224] Starting endpoint slice config controller I0419 09:14:57.710193 1 shared_informer.go:240] Waiting for caches to sync for endpoint slice config I0419 09:14:57.810381 1 shared_informer.go:247] Caches are synced for endpoint slice config I0419 09:14:57.810482 1 shared_informer.go:247] Caches are synced for service config # 最后把其他节点的 kube-proxy 杀掉让其启动重启加载新配置 $ kubectl delete pod kube-proxy-4zjr9 -n kube-system $ kubectl delete pod kube-proxy-g22bf -n kube-system
节点上安装 ipvs 命令行管理工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 $ yum install ipvsadm -y $ ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn ...... TCP 10.97.37.133:80 rr -> 10.244.36.75:80 Masq 1 0 0 -> 10.244.169.146:80 Masq 1 0 0 -> 10.244.169.147:80 Masq 1 0 0 ``` ipvs 会在宿主机上创建一张虚拟网卡 kube-ipvs0,用于接收 K8S 集群内部流量,外部流量也是通过 ipvs 匹配来转发到后端节点的 Pod 上面 ```bash $ ip addr ...... 7: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default link /ether 9e:58:50:a2:65:19 brd ff:ff:ff:ff:ff:ff inet 10.96.0.1/32 scope global kube-ipvs0 valid_lft forever preferred_lft forever inet 10.96.0.10/32 scope global kube-ipvs0 valid_lft forever preferred_lft forever inet 10.97.37.133/32 scope global kube-ipvs0 valid_lft forever preferred_lft forever
5.二进制 K8S集群修改 kube-proxy 模式为 IPVS: CoreDNS YAML文件
1 2 3 4 5 6 7 $ vim kube-proxy-config.yml ...... mode: ipvs ipvs: scheduler: "rr" $ systemctl restart kube-proxy
6.kube-proxy模式选择: kube-proxy是kubernetes中的关键组件,其主要功能是在Service和其后端Pod之间(Endpoint)进行负载均衡。kube-proxy 有三种运行模式,每种都有不同的实现技术:userspace、iptables或者IPVS。
userspace模式由于性能问题已经不推荐使用。这里主要介绍iptables和IPVS两种模式的比较及选择。
如何选择
对于集群规模较大,特别是Service数量可能超过1000的,推荐选择IPVS。(详见后续测试数据)
对于集群规模中等,Service数量不多的,推荐选择iptables。
如果客户端会出现大量并发短链接,目前建议选择iptables,原因见下方备注。
备注:在使用IPVS模式的kubernetes集群中进行滚动更新,期间如果有一个客户端在短时间内(两分钟)内发送大量短链接,客户端端口会被复用,导致node收到的来自于该客户端的请求报文网络五元组相同,触发IPVS复用Connection,有可能导致报文被转发到了一个已经销毁的Pod上,导致业务异常。
官方issue:
参考资料1 参考资料2