服务
公开在一组上运行的应用程序的抽象方法豆荚作为一个网络服务。使用Kubernetes,您不需要修改应用程序来使用不熟悉的服务发现机制。Kubernetes为Pods提供了它们自己的IP地址和一组Pods的单个DNS名称,并可以在它们之间进行负载平衡。
动机
Kubernetes豆荚的创建和销毁,以匹配集群的状态。豆荚是非永久资源。如果你使用部署要运行你的应用程序,它可以动态创建和销毁吊舱。
每个Pod都有自己的IP地址,但是在部署中,一瞬间运行的Pod集可能与稍后运行该应用程序的Pod集不同。
这导致一个问题:如果一些豆荚(称之为“后端”)提供了功能其他豆荚(称之为“前端”)在您的集群,前端如何发现和跟踪IP地址连接,所以,前端可以使用后端负载的一部分?
输入服务.
服务资源
在Kubernetes中,服务是一种抽象,它定义了一组pod的逻辑集合和访问它们的策略(有时这种模式被称为微服务)。服务的目标Pods集通常由选择器.要了解定义服务端点的其他方法,请参见服务没有选择器.
例如,考虑使用3个副本运行的无状态图像处理后端。这些副本是可替换的前端并不关心他们使用哪个后端。虽然组成后端集的实际pod可能会发生变化,但前端客户端不需要知道这一点,也不需要跟踪后端集。
服务抽象支持这种分离。
进行服务发现
如果您能够在应用程序中使用Kubernetes api进行服务发现,则可以查询API服务器对于端点,只要服务中的pod集发生更改,就会更新。
对于非本机应用程序,Kubernetes提供了在应用程序和后端pod之间放置网络端口或负载平衡器的方法。
定义一个服务
Kubernetes中的Service是一个REST对象,类似于Pod。与所有REST对象一样,您可以帖子
API服务器的服务定义,以创建新实例。服务对象的名称必须是有效的RFC 1035标签名称.
例如,假设您有一组Pods,其中每个Pods侦听TCP端口9376并包含一个标签应用= MyApp
:
apiVersion:v1友善的:服务元数据:的名字:我的服务规范:选择器:应用程序:MyApp港口:-协议:TCP港口:80发送:9376
该规范创建了一个名为“my-service”的新服务对象,它以任何Pod上的TCP端口9376为目标应用= MyApp
标签。
Kubernetes为该服务分配一个IP地址(有时称为“集群IP”),由服务代理使用(参见虚拟ip和服务代理下)。
Service选择器的控制器不断扫描与它的选择器匹配的Pods,然后将任何更新发布到同样名为“my-service”的端点对象。
注意:服务可以映射任何传入的港口
到一个发送
.为方便起见,默认情况下发送
设置为与港口
字段。
Pods中的端口定义有名称,您可以在发送
服务的属性。即使服务中使用单一配置的名称混合使用pod,通过不同的端口号使用相同的网络协议,这也可以工作。这为部署和演进您的服务提供了很大的灵活性。例如,您可以在后台软件的下一个版本中更改Pods公开的端口号,而不会破坏客户端。
服务的默认协议是TCP;你也可以用其他的支持的协议.
由于许多服务需要公开多个端口,Kubernetes支持服务对象上的多个端口定义。每个端口定义可以具有相同的协议
,或者另一个。
服务,而不选择器
服务通常抽象对Kubernetes Pods的访问,但它们也可以抽象其他类型的后端。例如:
- 您希望在生产环境中有一个外部数据库集群,但在您的测试环境中,您将使用自己的数据库。
- 您希望将您的服务指向另一个名称空间或者在另一个集群上。
- 您正在将工作负载迁移到Kubernetes。在评估该方法时,您只在Kubernetes中运行部分后端。
在任何这些场景中,您都可以定义服务没有就象一个豆荚里的选择器。例如:
apiVersion:v1友善的:服务元数据:的名字:我的服务规范:港口:-协议:TCP港口:80发送:9376
由于此服务没有选择器,因此不会自动创建相应的Endpoints对象。通过手动添加Endpoints对象,可以手动将服务映射到其运行的网络地址和端口:
apiVersion:v1友善的:端点元数据:的名字:我的服务子集:-地址:-知识产权:192.0.2.42港口:-港口:9376
端点对象的名称必须是有效的DNS子域名.
注意:端点IPs不得是:loopback (IPv4为127.0.0.0/8,IPv6为::1/128),或link-local (IPv4为169.254.0.0/16和224.0.0.0/24,IPv6为fe80::/64)。
端点IP地址不能是其他Kubernetes服务的集群IP地址,因为kube-proxy不支持虚拟ip作为目的地。
访问没有选择器的服务的工作原理与访问有选择器的服务的工作原理相同。在上面的例子中,流量被路由到YAML中定义的单个端点:192.0.2.42:9376
(TCP)。
ExternalName服务是服务的一种特殊情况,它没有选择器,而是使用DNS名称。有关更多信息,请参见ExternalName小节。
在能力端点
如果一个endpoint资源有超过1000个端点,那么Kubernetes v1.22(或更高版本)集群会用注释来标注端点endpoints.kubernetes。io /产能过剩:截断
.该注释表明受影响的endpoint对象超出了容量,并且端点控制器将端点的数量截断为1000。
EndpointSlices
Kubernetes v1.21[稳定]
EndpointSlices是一种API资源,可以为端点提供更可伸缩的替代方案。尽管在概念上与endpoint非常相似,但EndpointSlices允许跨多个资源分布网络端点。默认情况下,当EndpointSlice达到100个端点时,它被认为是“满的”,在这一点上,将创建额外的EndpointSlices来存储任何额外的端点。
EndpointSlice提供了其他属性和功能,详细描述见EndpointSlices.
应用协议
Kubernetes v1.20(稳定)
的appProtocol
字段提供为每个服务端口指定应用程序协议的方法。该字段的值由相应的endpoint和EndpointSlice对象反映。
该字段遵循标准的Kubernetes标签语法。值应该是IANA标准服务名称或以域名为前缀的名称,例如mycompany.com/my-custom-protocol
.
虚拟ip和服务代理
Kubernetes集群中的每个节点运行一个kube-proxy
.kube-proxy
负责实现一种形式的虚拟IP服务
类型不是ExternalName
.
为什么不使用轮询DNS?
经常会出现的一个问题是,为什么Kubernetes依赖代理将入站流量转发到后端。那其他方法呢?例如,是否有可能配置具有多个A值(或IPv6的AAAA)的DNS记录,并依赖于轮循名称解析?
使用服务代理有以下几个原因:
- DNS实现不尊重记录ttl的历史很长,并且在名称查找结果应该过期之后缓存它们。
- 有些应用只做一次DNS查询,并无限期地缓存结果。
- 即使应用程序和库进行了适当的重新解析,DNS记录上的低或零ttl可能会给DNS带来高负载,从而变得难以管理。
在本页的后面,您可以了解各种kube-proxy实现的工作。总之,您应该注意,当运行时kube-proxy
,内核级规则可能会被修改(例如,可能会创建iptables规则),但在某些情况下,直到重新引导后才会清理这些规则。因此,运行kube-proxy只能由管理员来完成,管理员必须了解在计算机上使用低级别、特权网络代理服务的后果。虽然kube-proxy
可执行的支持清理
函数,该函数不是官方特性,因此只能按原样使用。
配置
注意,kube-proxy以不同的模式启动,这是由它的配置决定的。
- kube-proxy的配置是通过ConfigMap完成的,而kube-proxy的ConfigMap有效地废弃了几乎所有kube-proxy标志的行为。
- kube-proxy的ConfigMap不支持实时重新加载配置。
- kube-proxy的ConfigMap参数不能在启动时全部进行验证和验证。例如,如果您的操作系统不允许您运行iptables命令,那么标准内核kube-proxy实现将无法工作。同样地,如果你的操作系统不支持
netsh
,它将不会在Windows用户空间模式下运行。
用户空间代理模式
在此(遗留)模式中,kube-proxy将监视Kubernetes控制面,以查看服务和端点对象的添加和删除。对于每个服务,它在本地节点上打开一个端口(随机选择的)。任何到这个“代理端口”的连接都被代理到服务的一个后端pod(通过端点报告)。kube-proxy花SessionAffinity
在决定使用哪个后端Pod时考虑服务的设置。
最后,用户空间代理安装iptables规则来捕获到服务的流量clusterIP
(是虚拟的)和港口
.这些规则将流量重定向到代理后端Pod的代理端口。
默认情况下,kube-proxy在用户空间模式下通过轮询算法选择后端。
iptables
代理模式
在此模式中,kube-proxy将监视Kubernetes控制面,以查看服务和端点对象的添加和删除。对于每个服务,它安装iptables规则,这些规则捕获到服务的流量clusterIP
和港口
,并将该流量重定向到服务的一个后端集。对于每个Endpoint对象,它安装选择后端Pod的iptables规则。
默认情况下,kube-proxy在iptables模式下随机选择一个后端。
使用iptables处理流量具有较低的系统开销,因为流量是由Linux netfilter处理的,不需要在用户空间和内核空间之间进行切换。这种方法也可能更可靠。
如果kube-proxy以iptables模式运行,并且选择的第一个Pod没有响应,则连接失败。这与用户空间模式不同:在这种情况下,kube-proxy将检测到与第一个Pod的连接失败,并将自动重试不同的后端Pod。
你可以使用Pod准备调查来验证后端pod是否正常工作,以便kube-proxy在iptables模式下只看到测试结果为健康的后端。这样做意味着您可以避免通过kube-proxy将流量发送到已知已经失败的Pod。
ipv代理模式
Kubernetes v1.11(稳定)
在ipv
模式,kube-proxy监视Kubernetes服务和端点,调用netlink
接口创建相应的IPVS规则,并定期与Kubernetes Services和endpoint同步IPVS规则。该控制循环确保IPVS状态与期望的状态匹配。当访问一个服务时,IPVS将流量导向一个后端pod。
IPVS代理模式基于netfilter钩子函数,类似于iptables模式,但使用哈希表作为底层数据结构,工作在内核空间。这意味着在IPVS模式下的kube-proxy比在iptables模式下的kube-proxy重定向流量的延迟更低,在同步代理规则时性能更好。与其他代理模式相比,IPVS模式支持更高的网络流量吞吐量。
IPVS提供了更多的选项来平衡后端pod的流量;这些都是:
rr
:循环信用证
:最小连接数(打开连接的最小数目)dh
:目标哈希上海
来源:哈希sed
:最短预期延迟nq
:永远不要队列
注意:如果要以IPVS模式运行kube-proxy,在启动kube-proxy之前,必须使节点上的IPVS可用。
当kube-proxy以IPVS代理模式启动时,将验证IPVS内核模块是否可用。如果未检测到IPVS内核模块,kube-proxy将恢复为iptables代理模式运行。
在这些代理模型中,服务的IP:Port绑定的流量被代理到适当的后端,而客户机不知道关于Kubernetes、Services或Pods的任何信息。
如果希望确保每次都将来自特定客户机的连接传递到相同的Pod,可以通过设置根据客户机的IP地址选择会话关联service.spec.sessionAffinity
为“ClientIP”(默认为“None”)。您还可以通过“setting”设置会话保持的最大时间service.spec.sessionAffinityConfig.clientIP.timeoutSeconds
适当。(默认值是10800,计算出来是3小时)。
多口服务
对于某些服务,您需要公开多个端口。Kubernetes允许您在一个Service对象上配置多个端口定义。当为一个服务使用多个端口时,您必须给出所有端口的名称,以确保它们没有歧义。例如:
apiVersion:v1友善的:服务元数据:的名字:我的服务规范:选择器:应用程序:MyApp港口:-的名字:http协议:TCP港口:80发送:9376-的名字:https协议:TCP港口:443发送:9377
注意:与Kubernetes的名字一般情况下,端口名称只能包含小写字母和数字字符
-
.端口名也必须以字母数字字符开始和结束。例如,名称
123年,美国广播公司
和网状物
是有效的,但123年_abc
和网
不是。
选择自己的IP地址
您可以指定您自己的集群IP地址作为服务
创建请求。要做到这一点,设置.spec.clusterIP
字段。例如,如果您已经有一个希望重用的现有DNS条目,或者为特定的IP地址配置了遗留系统,并且很难重新配置。
中选择的IP地址必须是有效的IPv4或IPv6地址service-cluster-ip-range
API服务器配置的CIDR范围。如果尝试使用无效的clusterIP地址值创建服务,API服务器将返回一个422 HTTP状态代码,以表明存在问题。
交通政策
外部交通政策
您可以设置spec.externalTrafficPolicy
字段来控制如何路由来自外部源的流量。有效值为集群
和当地的
.将字段设置为集群
将外部流量路由到所有准备好的端点当地的
只路由到准备好的节点本地端点。如果流策略为当地的
并且没有节点本地端点,kube-proxy不会转发相关服务的任何流量。
注意:功能状态:Kubernetes v1.22[α]
如果您启用
ProxyTerminatingEndpoints
功能门ProxyTerminatingEndpoints
对于kube-proxy, kube-proxy检查节点是否有本地端点以及是否将所有本地端点标记为终止。如果有本地端点和所有其中的终止,则kube-proxy忽略的任何外部流量策略当地的
.相反,虽然节点本地端点仍然作为所有终止点,但kube-proxy将该服务的流量转发到其他健康的端点,就像外部流量策略被设置为这样集群
.这种用于终止端点的转发行为的存在是为了允许外部负载平衡器优雅地排出由其支持的连接NodePort
即使健康检查节点端口开始失效,也不会影响业务。否则,从节点仍在负载均衡器的节点池到pod终止期间流量正在被丢弃之间的时间可能会导致流量丢失。
内部交通政策
Kubernetes v1.22(β)
您可以设置spec.internalTrafficPolicy
字段,以控制来自内部源的流量如何路由。有效的值集群
和当地的
.将字段设置为集群
将内部通信路由到所有准备好的端点当地的
只路由到准备好的节点本地端点。如果流策略为当地的
并且没有节点本地端点,流量被kube-proxy丢弃。
发现服务
Kubernetes支持查找服务环境变量和DNS的两种主要模式。
环境变量
当Pod在Node上运行时,kubelet会为每个活动的Service添加一组环境变量。它同时支持码头工人连接兼容的变量(见makeLinkVariables)和简单的{SVCNAME} _SERVICE_HOST
和{SVCNAME} _SERVICE_PORT
变量,其中服务名是大写的,破折号被转换为下划线。
例如,服务redis-master
,暴露TCP端口6379,并已分配集群IP地址10.0.0.11,产生以下环境变量:
REDIS_MASTER_SERVICE_HOST=10.0.0.11REDIS_MASTER_SERVICE_PORT=6379REDIS_MASTER_PORT=tcp://10.0.0.11:6379REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379REDIS_MASTER_PORT_6379_TCP_PROTO=tcpREDIS_MASTER_PORT_6379_TCP_PORT=6379REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11
注意:当您有一个Pod需要访问服务,并且您正在使用环境变量方法将端口和集群IP发布到客户端Pod时,必须创建该服务之前客户端pod就出现了。否则,这些客户机pod将无法填充它们的环境变量。
如果您只使用DNS来发现服务的集群IP,则无需担心这个排序问题。
DNS
您可以(而且几乎总是应该)使用附加组件.
一个集群感知的DNS服务器,如CoreDNS,监视Kubernetes API的新服务,并为每个服务创建一组DNS记录。如果在整个集群中启用了DNS,那么所有pod都应该能够根据它们的DNS名称自动解析服务。
例如,如果您有一个服务调用我的服务
在Kubernetes名称空间中my-ns
,由控制平面和DNS Service共同作用创建DNS记录my-service.my-ns
. 豆荚my-ns
名称空间应该能够通过执行名称查找来查找服务我的服务
(my-service.my-ns
也可以)。
其他名称空间中的Pods必须将名称限定为my-service.my-ns
.这些名称将解析为为服务分配的集群IP。
Kubernetes还支持命名端口的DNS SRV (Service)记录。如果my-service.my-ns
服务有一个名为http
协议设置为TCP
,你可以做一个DNS SRV查询_http._tcp.my-service.my-ns
发现的端口号http
,以及IP地址。
Kubernetes DNS服务器是唯一的访问方式ExternalName
服务。你可以找到更多关于ExternalName
决议DNS pod和服务.
无头服务
有时您不需要负载平衡和单个服务IP。在这种情况下,您可以通过显式指定创建所谓的“headless”服务“没有”
为集群IP (.spec.clusterIP
).
您可以使用无头服务与其他服务发现机制进行接口,而无需绑定到Kubernetes的实现。
无头的服务
,集群IP不分配,kube-proxy不处理这些服务,平台不为它们进行负载均衡或代理。如何自动配置DNS取决于服务是否定义了选择器:
与选择器
对于定义选择器的headless服务,端点控制器创建端点
并修改DNS配置以返回直接指向的A记录(IP地址)豆荚
支持服务
.
没有选择器
对于没有定义选择器的headless服务,端点控制器不会创建端点
记录。然而,DNS系统查找和配置:
- CNAME记录
ExternalName
-类型服务。 - A记录任何
端点
与服务共享一个名称,用于所有其他类型。
发布服务(ServiceTypes)
对于应用程序的某些部分(例如前端),您可能希望将服务公开到集群之外的外部IP地址。
KubernetesServiceTypes
允许您指定您想要的服务类型。默认值是ClusterIP
.
类型
价值观及其行为是:
ClusterIP
:在集群内部IP上暴露服务。选择此值将使服务只能从集群内部访问。这是默认值ServiceType
.NodePort
:暴露每个节点的IP上的服务在一个静态端口(NodePort
).一个ClusterIP
服务,其中NodePort
自动创建服务路线。你可以联系NodePort
服务,从集群外部,通过请求< NodeIP >: < NodePort >
.loadbalance
:使用云提供商的负载均衡器向外部公开服务。NodePort
和ClusterIP
外部负载均衡器路由的服务会自动创建。ExternalName
:将服务映射到externalName
字段(如。foo.bar.example.com
),返回aCNAME
记录其值。没有建立任何形式的代理。注意:你需要kube-dns
版本1.7或CoreDNS版本0.0.8或更高版本以使用ExternalName
类型。
你也可以用入口公开您的服务。入口不是服务类型,但它充当集群的入口点。它允许您将路由规则合并到单个资源中,因为它可以在相同的IP地址下公开多个服务。
类型NodePort
如果你设置类型
字段NodePort
, Kubernetes控制平面从指定的范围分配端口——service-node-port-range
标志(默认值:30000 - 32767)。每个节点将该端口(每个节点上的端口号相同)代理到您的服务中。您的服务在其.spec.ports [*] .nodePort
字段。
如果想指定代理端口的特定IP,可以设置——nodeport-addresses
kube-proxy或等效的标志nodePortAddresses
场的kube-proxy配置文件到特定的IP块。
该标志接受以逗号分隔的IP块列表(例如:10.0.0.0/8
,192.0.2.0/25
)来指定kube-proxy应该认为是该节点本地的IP地址范围。
例如,如果您使用——nodeport-addresses = 127.0.0.0/8
标志时,kube-proxy只为NodePort Services选择loopback接口。的默认值——nodeport-addresses
是一个空列表。这意味着,Kube代理应该考虑所有可用的NoDePoT网络接口。(这也与早期的Kubernetes版本兼容)。
如果需要指定的端口号,可以在节点端口
字段。控制平面要么为您分配该端口,要么报告API事务失败。这意味着您需要自己处理可能的端口冲突。您还必须使用一个有效的端口号,该端口号必须在为NodePort配置的范围内。
使用NodePort可以自由设置自己的负载平衡解决方案,配置Kubernetes不完全支持的环境,甚至可以直接公开一个或多个节点的ip。
注意,此服务可见为< NodeIP >: spec.ports [*] .nodePort
和.spec.clusterIP: spec.ports [*] .port
.如果——nodeport-addresses
kube-proxy或kube-proxy配置文件中等效字段的标志被设置,< NodeIP >
将被过滤的节点IP。
例如:
apiVersion:v1友善的:服务元数据:的名字:我的服务规范:类型:NodePort选择器:应用程序:MyApp港口:#默认情况下,为方便起见,' targetPort '设置为与' port '字段相同的值。-港口:80发送:80#可选字段#默认情况下,为了方便,Kubernetes控制平面将从一个范围分配端口(默认:30000-32767)节点端口:30007
类型loadbalance
在支持外部负载均衡器的云提供商上,设置类型
字段loadbalance
为您的服务提供一个负载平衡器。负载平衡器的实际创建是异步进行的,有关已供应的平衡器的信息发布在服务的.status.loadBalancer
字段。例如:
apiVersion:v1友善的:服务元数据:的名字:我的服务规范:选择器:应用程序:MyApp港口:-协议:TCP港口:80发送:9376clusterIP:10.0.171.239类型:loadbalance状态:loadbalance:入口:-知识产权:192.0.2.127
来自外部负载均衡器的流量指向后端pod。云提供商决定如何实现负载平衡。
一些云提供商允许您指定loadBalancerIP
.在这些情况下,使用用户指定的方式创建负载平衡器loadBalancerIP
.如果loadBalancerIP
字段不指定时,loadBalancer将设置一个临时IP地址。如果你指定loadBalancerIP
但是你的云服务提供商不支持这个特性loadbalancerIP
您设置的字段将被忽略。
注意:在Azure,如果您想使用用户指定的公共类型
loadBalancerIP
,首先需要创建静态类型的公网IP地址资源。该公有IP资源应与集群中其他自动创建的资源在同一个资源组中。例如,MC_myResourceGroup_myAKSCluster_eastus
.指定分配的IP地址为loadBalancerIP。确保您已经更新了云提供商配置文件中的securityGroupName。有关故障排除的信息
CreatingLoadBalancerFailed
许可问题请参见,在Azure Kubernetes Service (AKS)负载均衡器中使用静态IP地址或在高级网络的AKS集群上创建loadbalancerfailed.
混合协议类型的负载均衡器
Kubernetes v1.20(α)
默认情况下,对于LoadBalancer type of Services,当定义了多个端口时,所有端口必须具有相同的协议,且该协议必须是云提供商支持的协议。
如果特征门MixedProtocolLBService
在kube-apiserver中启用,当定义了多个端口时,允许使用不同的协议。
注意:可用于LoadBalancer类型的服务的协议集仍然由云提供商定义。
禁用负载均衡器NodePort分配
Kubernetes v1.20(α)
从v1.20开始,您可以通过设置该字段来禁用Service Type=LoadBalancer的节点端口分配spec.allocateLoadBalancerNodePorts
来假
.这应该只用于将流量直接路由到pod的负载均衡器实现,而不是使用节点端口。默认情况下,spec.allocateLoadBalancerNodePorts
是真正的
LoadBalancer服务类型将继续分配节点端口。如果spec.allocateLoadBalancerNodePorts
被设置为假
对于已分配节点端口的服务,这些节点端口不会被自动回收。必须显式地删除nodePorts
entry在每个服务端口中删除这些节点端口。您必须启用ServiceLBNodePortControl
功能门使用此领域。
指定负载平衡器实现的类
Kubernetes v1.22(β)
spec.loadBalancerClass
允许您使用云提供商默认之外的负载平衡器实现。此特性可从v1.21获得,您必须启用ServiceLoadBalancerClass
功能门在v1.21中使用该字段,并且功能门从v1.22开始默认启用。默认情况下,spec.loadBalancerClass
是零
和一个loadbalance
类型的服务使用云提供商的默认负载均衡器实现,如果集群配置了使用——云提供商
组件标记。如果spec.loadBalancerClass
,则假定与指定类匹配的负载平衡器实现正在监视Services。任何默认的负载均衡器实现(例如,云提供商提供的负载均衡器)都会忽略设置了此字段的服务。spec.loadBalancerClass
可以在类型为的服务上设置loadbalance
只有。一旦设置,就不能更改。的价值spec.loadBalancerClass
必须是标签样式的标识符,带有可选前缀,如“internal-vip
”或“example.com/internal-vip
".无前缀的名称保留给最终用户。
内部负载平衡器
在混合环境中,有时需要在相同(虚拟)网络地址块内路由来自服务的流量。
在跨界DNS环境中,您将需要两个服务来将外部和内部流量路由到您的端点。
要设置一个内部负载平衡器,根据您使用的云服务提供商,向您的服务添加以下注释之一。
选择其中一个选项卡。
[...]元数据:的名字:我的服务注释:cloud.google.com/load-balancer-type:“内部”[...]
[...]元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / aws-load-balancer-internal:“真正的”[...]
[...]元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / azure-load-balancer-internal:“真正的”[...]
[...]元数据:的名字:我的服务注释:service.www.amasoeur.com / ibm-load-balancer-cloud-provider-ip-type:“私人”[...]
[...]元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / openstack-internal-load-balancer:“真正的”[...]
[...]元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / cce-load-balancer-internal-vpc:“真正的”[...]
[...]元数据:注释:service.www.amasoeur.com / qcloud-loadbalancer-internal-subnetid:subnet-xxxxx[...]
[...]元数据:注释:service.beta.www.amasoeur.com / alibaba-cloud-loadbalancer-address-type:“内部网”[...]
AWS上的TLS支持
为了在AWS上运行的集群上获得部分TLS / SSL支持,您可以添加三个注释到loadbalance
服务:
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / aws-load-balancer-ssl-cert:arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012
第一个指定要使用的证书的ARN。它可以是上传到IAM的第三方颁发者的证书,也可以是在AWS证书管理器中创建的证书。
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com/aws-load-balancer-backend-protocol:ssl (https http | | | tcp)
第二个注释指定Pod使用哪个协议。对于HTTPS和SSL, ELB希望Pod使用证书通过加密连接进行身份验证。
HTTP和HTTPS选择第7层代理:ELB终止与用户的连接,解析报头,并注入X-Forwarded-For
在转发请求时,带有用户IP地址的报头(Pods仅在其连接的另一端看到ELB的IP地址)。
TCP和SSL选择第4层代理:ELB转发流量而不修改头。
在混合使用环境中,某些端口是安全的,而其他端口是未加密的,您可以使用以下注释:
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com/aws-load-balancer-backend-protocol:httpservice.beta.www.amasoeur.com / aws-load-balancer-ssl-ports:“443、8443”
在上面的例子中,如果服务包含三个端口,80
,443
,8443
,然后443
和8443
将使用SSL证书,但是80
将被代理HTTP。
从Kubernetes v1.9开始就可以使用了预定义AWS SSL策略为您的服务使用HTTPS或SSL监听器。要查看哪些策略可用,可以使用aws
命令行工具:
Aws elb description -load-balance -policies——查询'PolicyDescriptions[].PolicyName'
然后您可以使用“service.beta.www.amasoeur.com / aws-load-balancer-ssl-negotiation-policy
“注释;例如:
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / aws-load-balancer-ssl-negotiation-policy:“ELBSecurityPolicy-TLS-1-2-2017-01”
AWS上的代理协议支持
要启用代理协议支持AWS上运行的集群,您可以使用以下服务注释:
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / aws-load-balancer-proxy-protocol:“*”
从1.3.0版本开始,该注释的使用适用于由ELB代理的所有端口,不能进行其他配置。
AWS上的ELB访问日志
AWS上有一些注释用于管理ELB Services的访问日志。
注释service.beta.www.amasoeur.com / aws-load-balancer-access-log-enabled
控制是否启用访问日志。
注释service.beta.www.amasoeur.com / aws-load-balancer-access-log-emit-interval
以分钟为单位控制发布访问日志的时间间隔。您可以指定5分钟或60分钟的间隔。
注释service.beta.www.amasoeur.com / aws-load-balancer-access-log-s3-bucket-name
存储负载均衡器访问日志的Amazon S3桶名。
注释service.beta.www.amasoeur.com / aws-load-balancer-access-log-s3-bucket-prefix
指定为Amazon S3桶创建的逻辑层次结构。
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / aws-load-balancer-access-log-enabled:“真正的”#是否启用负载均衡器的访问日志service.beta.www.amasoeur.com / aws-load-balancer-access-log-emit-interval:“60”#发布访问日志的时间间隔。您可以指定5或60(分钟)的间隔。service.beta.www.amasoeur.com / aws-load-balancer-access-log-s3-bucket-name:“我的桶”#存储访问日志的Amazon S3桶名service.beta.www.amasoeur.com / aws-load-balancer-access-log-s3-bucket-prefix:“my-bucket-prefix /刺激”#您为Amazon S3 bucket创建的逻辑层次结构,例如' my-bucket-prefix/prod '
AWS连接排水
经典elb的连接消耗可以通过注释来管理service.beta.www.amasoeur.com / aws-load-balancer-connection-draining-enabled
设置为的值“真正的”
.注释service.beta.www.amasoeur.com / aws-load-balancer-connection-draining-timeout
还可以用于设置最大时间(以秒为单位),以便在注销实例之前保持现有连接打开。
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / aws-load-balancer-connection-draining-enabled:“真正的”service.beta.www.amasoeur.com / aws-load-balancer-connection-draining-timeout:“60”
其他ELB注释
下面描述了用于管理Classic Elastic负载均衡器的其他注释。
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / aws-load-balancer-connection-idle-timeout:“60”#负载平衡器关闭连接之前,允许连接处于空闲状态(未通过连接发送数据)的时间(以秒为单位)service.beta.www.amasoeur.com/aws-load-balancer-cross-zone-load-Balanced-enabled:“真正的”#负载均衡器是否启用跨区域负载均衡service.beta.www.amasoeur.com / aws-load-balancer-additional-resource-tags:“环境=刺激,所有者= devops”以逗号分隔的键值对列表,将被记录为# ELB中的附加标签。service.beta.www.amasoeur.com / aws-load-balancer-healthcheck-healthy-threshold:""后端需要连续成功的运行状况检查次数对交通来说是健康的默认值为2,必须在2到10之间service.beta.www.amasoeur.com / aws-load-balancer-healthcheck-unhealthy-threshold:“3”后端所需的不成功的运行状况检查次数#被认为对交通有害。默认为6,必须在2到10之间service.beta.www.amasoeur.com / aws-load-balancer-healthcheck-interval:“20”对象的健康检查之间的大约间隔(以秒为单位)#个体实例。默认值是10,必须在5到300之间service.beta.www.amasoeur.com / aws-load-balancer-healthcheck-timeout:“5”#没有响应意味着失败的时间,以秒为单位#健康检查。该值必须小于service.beta.www.amasoeur.com/aws-load-balancer-healthcheck-interval#价值。默认为5,必须在2到60之间service.beta.www.amasoeur.com / aws-load-balancer-security-groups:“sg-53fae93f”要在创建的ELB上配置的现有安全组列表。与注释# service.beta.kubernetes。io/aws-load-balancer-extra-security-groups,这将替换之前分配给ELB的所有其他安全组,并覆盖创建为这个ELB唯一生成的安全组的#。#此列表中的第一个安全组ID用作源,允许进入的流量进入目标工作节点(服务流量和健康检查)。#如果多个elb配置了相同的安全组ID,则只会有一个permit行添加到工作节点安全组中,即如果您删除了任何一个#,它将删除单个允许行并阻止共享相同安全组ID的所有elb的访问。#如果使用不当,可能会导致跨服务中断service.beta.www.amasoeur.com / aws-load-balancer-extra-security-groups:“sg-53fae93f sg-42efd82e”#要添加到创建的ELB的其他安全组的列表,这将保留唯一生成的安全组,这将确保每个ELB#具有唯一的安全组ID和匹配的允许行,允许流量到目标工作节点(服务流量和健康检查)。这里定义的安全组可以在服务之间共享。service.beta.www.amasoeur.com / aws-load-balancer-target-node-labels:“ingress-gw gw-name =公共api”,使用逗号分隔的键值对列表#选择负载均衡器的目标节点
在AWS上支持网络负载均衡器
Kubernetes v1.15[测试版]
要在AWS上使用网络负载均衡器,请使用注释service.beta.www.amasoeur.com / aws-load-balancer-type
将值设置为nlb
.
元数据:的名字:我的服务注释:service.beta.www.amasoeur.com / aws-load-balancer-type:“nlb”
注意:NLB只适用于特定的实例类;看到AWS的德赢是不是大平台文档支持的实例类型列表的弹性负载均衡。
与传统的弹性负载均衡器不同,网络负载均衡器(NLBs)将客户端的IP地址转发给节点。如果一个服务的.spec.externalTrafficPolicy
被设置为集群
,客户端的IP地址没有传播到终端Pods。
通过设置.spec.externalTrafficPolicy
来当地的
,客户端IP地址被传播到终端Pods,但这可能导致流量分布不均匀。对于特定的LoadBalancer服务,没有任何pod的节点将无法通过自动分配的NLB目标组的健康检查.spec.healthCheckNodePort
并且不接收任何流量。
为了实现均匀的流量,可以使用DaemonSet或指定豆荚anti-affinity不在同一节点上定位。
您也可以使用NLB服务内部负载均衡器注释。
为了使客户端流量能够到达NLB后面的实例,Node安全组被修改为以下IP规则:
规则 | 协议 | 端口(年代) | IpRange (s) | IpRange描述 |
---|---|---|---|---|
健康检查 | TCP | NodePort (s) (.spec.healthCheckNodePort 为.spec.externalTrafficPolicy=当地的 ) |
子网CIDR | www.amasoeur.com /规则/ nlb /健康= < loadBalancerName > |
客户端流量 | TCP | NodePort (s) | .spec.loadBalancerSourceRanges (默认为0.0.0.0/0 ) |
www.amasoeur.com /规则/ nlb /客户= < loadBalancerName > |
MTU发现 | ICMP | 3、4 | .spec.loadBalancerSourceRanges (默认为0.0.0.0/0 ) |
www.amasoeur.com /规则/ nlb / mtu = < loadBalancerName > |
为了限制哪个客户端IP可以访问网络负载均衡器,指定loadBalancerSourceRanges
.
规范:loadBalancerSourceRanges:-“143.231.0.0/16”
注意:如果.spec.loadBalancerSourceRanges
, Kubernetes允许从0.0.0.0/0
到节点安全组。如果节点具有公共IP地址,请注意,非NLB流量也可以到达这些修改过的安全组中的所有实例。
腾讯Kubernetes Engine (TKE)上的其他CLB注释
TKE上还有其他用于管理云负载平衡器的注释,如下所示。
元数据:的名字:我的服务注释:使用指定的节点绑定loadbalancerservice.www.amasoeur.com / qcloud-loadbalancer-backends-label:输入(value1, value2)#已存在的负载均衡器IDservice.www.amasoeur.com / tke-existed-lbid: lb-6swtxxxx#自定义LB参数,暂不支持修改LB类型service.www.amasoeur.com / service.extensiveParameters:""#自定义LB侦听器参数service.www.amasoeur.com / service.listenerParameters:""指定负载均衡器的类型;#有效值:classic(经典云负载均衡器)或application(应用云负载均衡器)service.www.amasoeur.com / loadbalance-type:xxxxx#指定公网带宽计费方法;#有效值:traffic_postaid_by_hour(话单流量)和bandwidth_postaid_by_hour(话单带宽)。service.www.amasoeur.com / qcloud-loadbalancer-internet-charge-type:xxxxxx#指定带宽值,取值范围为[1,2000]Mbps。service.www.amasoeur.com / qcloud-loadbalancer-internet-max-bandwidth-out:“10”#设置此注释后,LoadBalancer将仅注册节点#pod在其上运行时,否则将注册所有节点。service.www.amasoeur.com / local-svc-only-bind-node-with-pod:真正的
类型ExternalName
类型为ExternalName的服务将服务映射到DNS名称,而不是典型的选择器,例如我的服务
或卡珊德拉
.属性指定这些服务spec.externalName
参数。
例如,此服务定义映射我的服务
服务于戳
名称空间my.database.example.com
:
apiVersion:v1友善的:服务元数据:的名字:我的服务名称空间:戳规范:类型:ExternalNameexternalName:my.database.example.com
注意:ExternalName接受IPv4地址字符串,但接受由数字组成的DNS名称,而不是IP地址。CoreDNS或ingress nginx不会解析与IPv4地址相似的外部名称,因为ExternalName旨在指定规范DNS名称。要硬编码IP地址,请考虑使用无头服务.
查找主机时my-service.prod.svc.cluster.local
时,集群DNS服务返回aCNAME
用值记录my.database.example.com
.访问我的服务
其工作方式与其他服务相同,但有一个关键区别,即重定向发生在DNS级别,而不是通过代理或转发。如果您以后决定将数据库移动到集群中,您可以启动它的pod,添加适当的选择器或端点,并更改服务类型
.
警告:对于一些常见的协议,包括HTTP和HTTPS,您可能会遇到使用ExternalName的麻烦。如果使用ExternalName,那么集群内客户机使用的主机名与ExternalName引用的名称不同。
对于使用主机名的协议,这种差异可能会导致错误或意外的响应。HTTP请求将有一个
主持人:
源服务器不识别的报头;TLS服务器将无法提供与客户机连接到的主机名匹配的证书。
注意:这部分是感谢Kubernetes提示-第一部分博客从阿伦Komljen.
外部“诱导多能性”
如果有路由到一个或多个群集节点的外部IP,则可以在这些节点上公开Kubernetes服务externalIPs
.在服务端口上使用外部IP(作为目标IP)进入集群的流量将被路由到一个服务端点。externalIPs
不是由Kubernetes管理的,而是由集群管理员负责。
在服务规范中,externalIPs
可以与任何ServiceTypes
.在下面的例子中,我的服务
"可由客户访问"80.11.12.10:80
" (externalIP:端口
)
apiVersion:v1友善的:服务元数据:的名字:我的服务规范:选择器:应用程序:MyApp港口:-的名字:http协议:TCP港口:80发送:9376externalIPs:-80.11.12.10
缺点
为vip使用用户空间代理可以在中小型规模下工作,但不能扩展到具有数千个服务的非常大的集群。的门户网站的原始设计方案对此有更多的细节。
使用用户空间代理会掩盖访问服务的数据包的源IP地址。这使得某些类型的网络过滤(防火墙)变得不可能。iptables代理模式在集群源IP中并不模糊,但它仍然会影响通过负载平衡器或节点端口访问的客户端。
的类型
字段被设计成嵌套功能——每一层都添加到前一层。这并不是所有云提供商都严格要求的(例如谷歌计算引擎不需要分配一个NodePort
为了使loadbalance
工作,但AWS可以),但当前的API需要它。
虚拟IP实现
对于希望使用Services的许多人来说,前面的信息应该足够了。然而,在幕后有很多事情值得我们去理解。
避免碰撞
Kubernetes的主要哲学之一是,你不应该暴露在可能导致你的行动失败的情况下,而不是你自己的错误。对于服务资源的设计,这意味着如果您的选择可能与他人的选择相冲突,则不要求您选择自己的端口号。这是一个孤立的失败。
为了允许您为您的服务选择端口号,我们必须确保没有两个服务发生冲突。Kubernetes通过为每个服务分配自己的IP地址来实现这一点。
为了确保每个服务接收到唯一的IP,内部分配器会自动更新中的全局分配映射etcd在创建每个服务之前。Services必须在注册表中存在映射对象,才能获得IP地址分配,否则创建将失败,并显示无法分配IP地址的消息。
在控制平面中,后台控制器负责创建该映射(需要支持从使用内存锁定的旧版本Kubernetes迁移)。Kubernetes还使用控制器检查无效分配(例如由于管理员干预),并清理已分配的任何服务不再使用的IP地址。
服务IP地址
与实际路由到固定目的地的Pod IP地址不同,服务IP实际上不是由单个主机响应的。相反,kube-proxy使用iptables (Linux中的包处理逻辑)来定义虚拟根据需要透明重定向的IP地址。当客户端连接到VIP时,它们的流量将自动传输到适当的端点。服务的环境变量和DNS实际上是根据服务的虚拟IP地址(和端口)填充的。
kube proxy支持三种代理模式用户空间、iptables和ipv,每种模式的操作略有不同。
用户空间
以上面描述的图像处理应用程序为例。创建后端Service时,Kubernetes master会分配一个虚拟IP地址,例如10.0.0.1。假设服务端口为1234,则集群中的所有kube-proxy实例都将观察该服务。当代理看到一个新的服务时,它会打开一个新的随机端口,从虚拟IP地址建立一个iptables重定向到这个新端口,并开始在该端口上接受连接。
当客户端连接到服务的虚拟IP地址时,iptables规则将起作用,并将包重定向到代理的自己的端口。“服务代理”选择一个后端,并开始代理从客户端到后端的流量。
这意味着服务所有者可以选择他们想要的任何端口,而不会有冲突的风险。客户端可以连接到IP和端口,而不知道他们实际访问的是哪个pod。
iptables
同样,考虑上面描述的图像处理应用程序。创建后端服务时,Kubernetes控制平面会分配一个虚拟IP地址,例如10.0.0.1。假设服务端口为1234,则集群中的所有kube-proxy实例都将观察该服务。当代理看到一个新的服务时,它会安装一系列iptables规则,这些规则从虚拟IP地址重定向到每个服务规则。每个服务规则链接到每个端点规则,这些规则将流量(使用目的NAT)重定向到后端。
当客户端连接到服务的虚拟IP地址时,iptables规则开始生效。选择后端(基于会话关联或随机),并将包重定向到后端。与用户空间代理不同的是,数据包永远不会复制到用户空间,kube代理不需要运行虚拟IP地址才能工作,节点可以看到来自未更改的客户端IP地址的流量。
当流量通过节点端口或负载均衡器进入时,执行相同的基本流,不过在这些情况下,客户端IP确实会发生改变。
ipv
iptables操作在大型集群(如10,000个服务)中显著降低。IPVS是基于内核哈希表的负载均衡设计。因此,通过基于ipv4的kube-proxy可以实现大量服务的性能一致性。同时,基于ipv4的kube-proxy具有更复杂的负载均衡算法(最小conns、局部、加权、持久)。
API对象
服务是Kubernetes REST API中的顶级资源。你可以在下面找到更多关于API对象的细节:服务API对象.
支持的协议
TCP
您可以将TCP用于任何类型的服务,它是默认的网络协议。
UDP
你可以为大多数服务使用UDP。对于type=LoadBalancer Services, UDP支持依赖于提供此功能的云提供商。
SCTP
Kubernetes v1.20(稳定)
当使用支持SCTP流量的网络插件时,您可以为大多数服务使用SCTP。对于type=LoadBalancer Services, SCTP支持取决于提供此功能的云提供商。(最不)。
警告
支持多主机SCTP关联
警告:多主机SCTP关联的支持要求CNI插件能够支持为Pod分配多个接口和IP地址。
多主机SCTP关联的NAT需要相应的内核模块中的特殊逻辑。
窗户
注意:基于Windows的节点不支持SCTP。
用户空间kube-proxy
警告:kube-proxy在用户空间模式下不支持对SCTP关联的管理。
HTTP
如果您的云提供商支持它,您可以使用LoadBalancer模式下的服务来设置外部HTTP / HTTPS反向代理,并转发到服务的端点。
注意:你也可以用入口代替Service来公开HTTP/HTTPS服务。
代理协议
如果您的云提供商支持它,您可以使用LoadBalancer模式下的Service在Kubernetes本身之外配置负载均衡器,它将转发以代理协议.
负载平衡器将发送一个描述传入连接的初始序列,类似于这个示例
代理TCP4 192.0.2.202 10.0.42.7 12345 7\r\n
然后是来自客户端的数据。
接下来是什么
- 读将应用程序与服务连接
- 读到入口
- 读到EndpointSlices