赞
踩
k8s Service详解(概念、原理、流量分析、代码) - sucre_tan - 博客园
补充说明:
kubernetes中kube-proxy的工作原理是什么 - 云计算 - 亿速云
Kubernetes中的负载均衡原理————以iptables模式为例 | CITAHub技术团队
kube-proxy其实就是管理service的访问入口,包括集群内Pod到Service的访问和集群外访问service。
kube-proxy管理sevice的Endpoints,该service对外暴露一个Virtual IP,也成为Cluster IP, 集群内通过访问这个Cluster IP:Port
就能访问到集群内对应的serivce下的Pod。
service是通过Selector选择的一组Pods的服务抽象,其实就是一个微服务,提供了服务的LB和反向代理的能力,而kube-proxy的主要作用就是负责service的实现。
service另外一个重要作用是,一个服务后端的Pods可能会随着生存灭亡而发生IP的改变,service的出现,给服务提供了一个固定的IP,而无视后端Endpoint的变化。
k8s提供了两种方式进行服务发现:
环境变量: 当你创建一个Pod的时候,kubelet会在该Pod中注入集群内所有Service的相关环境变量。需要注意的是,要想一个Pod中注入某个Service的环境变量,则必须Service要先比该Pod创建。这一点,几乎使得这种方式进行服务发现不可用。
比如,一个ServiceName为redis-master的Service,对应的ClusterIP:Port为10.0.0.11:6379,则其对应的环境变量为:
REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11
DNS:这也是k8s官方强烈推荐的方式。可以通过cluster add-on的方式轻松的创建KubeDNS来对集群内的Service进行服务发现。更多关于KubeDNS的内容,请查看:Kubernetes DNS Service技术研究 - 爱码网 。
k8s原生的,一个Service的ServiceType决定了其发布服务的方式。
ClusterIP:在集群内发布服务,这是k8s默认的ServiceType。通过集群内的ClusterIP在内部发布服务,只能够在集群内部访问服务。
ExternalName:用于集群内不同命名空间内的服务通过名称可直接访问,以及将在k8s集群外部的服务引入到k8s集群内通过服务名称访问场景。需要借助KubeDNS(version >= 1.7)的支持,就是用KubeDNS将该service和ExternalName做一个Map,KubeDNS返回一个CNAME记录。
ExternalName的用途(业务场景),有两个:
(1)将k8s集群内在某个namespace内的服务暴露到另外一个namespace内,实现两个不同的namespace之间的不同pod可以通过name的形式访问。假如集群内有两个服务服务a和b,a服务访问b服务。若两个服务都定义在同一个namespaceA下,则a可以通过b的名称http://b/访问b服务,k8s会将http://b/转为http://b.namespaceA.svc.cluster.local/ svc.cluster.local 是整个k8s集群的域),若将b定义在namespaceB访问,则A无法直接通过b的名称http://b/访问服务b,因为b的namespace不是namespaceA。若想仍然通过http://b访问,可以在namespaceA下定义一个type为ExternalName的服务b,其externalName属性的值为b.namespaceB.svc.cluster.local即可,相当于在namespaceA下为定义在namespaceB下的服务b建了一个链接,连接名为b。namespaceA下的ExternalName服务b定义如下:
apiVersion: v1
kind: Service
metadata:
name: b
namespace: namespaceA
spec:
type: ExternalName
externalName: b.namespaceB.svc.cluster.local
(2)将k8s集群外的服务引入到k8s内部,供内部的pod访问,就像使用集群内的服务一样使用外部服务,利用ExternalName的Service访问的外部服务地址必须是域名,不支持IP地址。举例参见下方k8s集群内部与外部之间互联互通#通过ExternalName Service访问域名方式的外部服务
NodePort
需要借助真实存在的ip,是一个公共的ip,任何人都可以访问,而ClusterIP
可以理解成不对外开放,仅限于集群内的节点之间特定的一个范围。LoadBalancer: 也是用来对集群外暴露k8s内部的Service。使用云提供商的负载局衡器,可以路由到 NodePort 服务和 ClusterIP 服务,这个需要结合具体的云厂商进行操作。所有通往指定的端口的流量都会被转发到对应的服务。它没有过滤条件,没有路由等。这意味着你几乎可以发送任何种类的流量到该服务,像 HTTP,TCP,UDP,Websocket,gRPC 或其它任意种类。这个方式的最大缺点是每一个用 LoadBalancer 暴露的服务都会有它自己的 IP 地址,每个用到的 LoadBalancer 都需要付费,这将是非常昂贵的。
k8s借助kube-proxy实现负载均衡。
kube-proxy实现了三种代理模式:
以上三种方式,都是利用客户端的OS的网络内核(iptables规则)拦截到ClusterIP:ClusterPort的请求,因此是客户端实现的负载均衡。
userspace是在用户空间,通过kube-proxy来实现service的代理服务,其原理如下如图所示:
这种方式完全利用内核iptables来实现service的代理和LB。是v1.2及之后版本默认模式,其原理图如下所示:
说明:
iptables最初也不是为了负载均衡而设计,而纯粹是为了防火墙而设计。为了解决iptables模式下的性能问题,kube-proxy引入了一个更适合负载均衡场景且有更高效数据结构(散列表)的模块——ipvs。
k8s网络原理-ipvs - 简书
kube-proxy ipvs模式原理分析 - 墨天轮
说明:
通过创建kube-ipvs0 dummy网卡并绑定service ip,使得从外部进来的流量在PREROUTING后的路由决策中发往INPUT,从而能到达ipvs模块。
ipvs模式下通过维护ipvs规则和ipset两种高效的数据结构,使得iptables规则不再随着service数量增加而增加,这也是ipvs模式在大规模场景下比iptables模式性能更优越的原因。
外部访问service ip的链路为:PREROUTING->route->INPUT->ipvs(DNAT)->OUTPUT->route->POSTROUTING
。
宿主机上访问service ip的链路为:OUTPUT->ipvs(DNAT)->OUTPUT->route->POSTROUTING
。
ipvs只做了DNAT,部分场景下仍需要iptables做SNAT。
可通过NodePort、LoadBalancer和Ingeress方式,从k8s集群外部访问k8s内部的服务。
区别参见:K8S ClusterIP、 NodePort、LoadBalancer和Ingress 区别 - 王叫兽 - 博客园
参见:【k8s学习】ExternalName Service介绍以及Endpoints+Headless Service介绍 - 简书
有以下几种方式:
apiVersion: v1
kind: Service
metadata:
name: baidu-service
namespace: namespaceA
spec:
type: ExternalName
externalName: www.baidu.com
#Service定义,可以是Headless Service,也可以是普通的Service。
#注意这里没有pod选择器,因此它不知道往哪里转发流量。
#因此需手动创建一个将从此服务接收流量的 Endpoints 对象(见下方Endpoints定义)
apiVersion: v1
kind: Service
metadata:
name: games
spec:
#clusterIP: None表示headless service
#clusterIP: None
type: ClusterIP
ports:
- port: 80
targetPort: 8091
#EndPoints定义,接收上方Service转发的流量(name要与Service的name相同)
#并将流量转发到真正的外部服务192.168.3.175:8091上
#若相同的外部服务有多个ip:port,则可以都定义在subsets中
#k8s会在所有服务地址之间进行流量的负载平衡
apiVersion: v1
kind: Endpoints
metadata:
name: games
subsets:
- addresses:
- ip: 192.168.3.175
ports:
- port: 8091
client Pod访问服务的处理过程如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。