服务概述
在Kubernetes中,服务(Service)用于将运行在一组Pod上的应用程序公开为网络服务。它不仅为这些Pod提供了一个统一的DNS名称,还实现了Pod之间的负载均衡。本文将为您介绍Kubernetes Service的基本概念以及不同类型Service的对比介绍。
基本概念
Service的类型
您可以在集群中创建指定类型的Service,不同类型Service的描述及适用场景如下:
Service类型 |
描述 |
适用场景 |
计费说明 |
---|---|---|---|
ClusterIP是默认的服务类型,从集群的服务网段中分配一个仅在集群内部可访问的虚拟IP。 |
如果只需要在集群内部进行服务间的通信,而不需要将服务暴露给集群外部,可以使用ClusterIP类型的服务。 例如,集群中部署的前端应用Pod需要访问同一集群中部署的后端数据库,此时后端数据库可以配置为ClusterIP类型,以确保仅在集群内部可访问。 |
创建该类型的Service不涉及计费 |
|
NodePort会在集群中的每个节点上开放一个端口,从而允许从集群外部通过 <NodeIP>:<NodePort> 来访问服务。 |
在业务需要临时或低流量访问的场景中,您可以通过NodePort类型服务暴露节点端口进行访问。 例如,在测试环境中,当您部署和调试一个Web应用服务时,可以使用NodePort类型。 |
创建该类型的Service不涉及计费。 若需要通过公网访问NodePort服务,您可以为节点绑定EIP。关于EIP的计费说明,请参见EIP费用组成。 |
|
LoadBalancer类型在NodePort的基础上添加了外部负载均衡器,支持将外部流量向集群内的多个Pod进行分发。Service会自动分配一个外部IP地址,允许客户端通过该IP访问服务。该类型服务不仅支持在OSI模型的第四层(传输层)处理TCP和UDP流量,还能扩展至第七层(应用层),支持HTTP和HTTPS流量的管理。 |
在云上提供应用访问时,若需提供一个稳定且易于管理的对外访问入口,可以使用LoadBalancer类型的服务。 例如生产环境中需从互联网访问的公共服务,这些服务需承受大量外部流量并确保高可用性,如Web应用和API服务等。 |
涉及负载均衡实例的费用,计费详情请参见ELB计费模式。 |
|
DNAT类型的服务可以为集群内的所有节点提供网络地址转换服务,使多个节点可以共享使用弹性IP。 |
在业务需要通过公网进行临时或低流量访问的场景中,您可以通过DNAT类型服务进行访问。DNAT类型与节点访问类型相比增强了可靠性,弹性IP无需与单个节点绑定,任何节点状态的异常不影响其访问。 |
涉及NAT网关的费用,计费详情请参见NAT网关计费模式。 涉及EIP的费用,计费详情请参见EIP费用组成。 |
|
Headless Service不会分配ClusterIP。当访问后端Pod时,服务的DNS查询会直接返回Pod的IP地址列表,客户端可以直接与特定的Pod进行通信。 |
应用需要直接与后端的具体Pod进行通信,而不是通过代理或负载均衡器。 例如,当您部署有状态应用(如ClickHouse数据库服务)时,可以使用Headless Service,使应用Pod直接访问每个ClickHouse Pod,并且能够均衡地读取数据或针对性地写入数据,从而提升数据处理效率。 |
创建该类型的Service不涉及计费 |
集群内无法访问Service的说明
upstream connect error or disconnect/reset before headers. reset reason: connection failure 或: curl: (7) Failed to connect to 192.168.10.36 port 900: Connection refused
在集群中访问ELB地址时出现无法访问的场景较为常见,这是由于Kubernetes在创建Service时,kube-proxy会把ELB的访问地址作为外部IP(即External-IP,如下方回显所示)添加到iptables或IPVS中。如果客户端从集群内部发起访问ELB地址的请求,该地址会被认为是服务的外部IP,被kube-proxy直接转发,而不再经过集群外部的ELB。
# kubectl get svc nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx LoadBalancer 10.247.76.156 123.**.**.**,192.168.0.133 80:32146/TCP 37s

- 多实例的工作负载需要保证所有实例均可正常访问,否则可能出现概率性访问不通的情况。
- CCE Turbo集群(云原生2.0网络模型)中,仅当Service的后端对接使用主机网络(HostNetwork)的Pod时,亲和级别支持配置为节点级别。
- 表格中仅列举了可能存在访问不通的场景,其他不在表格中的场景即表示可以正常访问。
服务端发布服务类型 |
访问类型 |
客户端请求发起位置 |
容器隧道集群(IPVS) |
VPC集群(IPVS) |
容器隧道集群(IPTABLES) |
VPC集群(IPTABLES) |
---|---|---|---|---|---|---|
节点访问类型Service |
公网/私网 |
与服务Pod同节点 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
与服务Pod不同节点 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
正常访问 |
正常访问 |
||
与服务Pod同节点的其他容器 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
无法访问 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
无法访问 |
||
与服务Pod不同节点的其他容器 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
访问服务端所在节点IP+NodePort — 正常访问 访问非服务端所在节点IP+NodePort — 无法访问 |
||
独享型负载均衡类型Service |
私网 |
与服务Pod同节点 |
无法访问 |
无法访问 |
无法访问 |
无法访问 |
与服务Pod同节点的其他容器 |
无法访问 |
无法访问 |
无法访问 |
无法访问 |
||
DNAT网关类型Service |
公网 |
与服务Pod同节点 |
无法访问 |
无法访问 |
无法访问 |
无法访问 |
与服务Pod不同节点 |
无法访问 |
无法访问 |
无法访问 |
无法访问 |
||
与服务Pod同节点的其他容器 |
无法访问 |
无法访问 |
无法访问 |
无法访问 |
||
与服务Pod不同节点的其他容器 |
无法访问 |
无法访问 |
无法访问 |
无法访问 |
||
NGINX Ingress控制器插件对接独享型ELB(Local) |
私网 |
与cceaddon-nginx-ingress-controller Pod同节点 |
无法访问 |
无法访问 |
无法访问 |
无法访问 |
与cceaddon-nginx-ingress-controller Pod同节点的其他容器 |
无法访问 |
无法访问 |
无法访问 |
无法访问 |
解决这个问题通常有如下办法:
- (推荐)在集群内部访问使用Service的ClusterIP或服务域名访问。
- 将Service的externalTrafficPolicy设置为Cluster,即集群级别服务亲和。不过需要注意这会影响源地址保持。
apiVersion: v1 kind: Service metadata: annotations: kubernetes.io/elb.class: union kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}' labels: app: nginx name: nginx spec: externalTrafficPolicy: Cluster ports: - name: service0 port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer
- 使用Service的pass-through特性,使用ELB地址访问时绕过kube-proxy,先访问ELB,经过ELB再访问到负载。具体请参见LoadBalancer类型Service使用pass-through能力。
- 在CCE Standard集群中,当使用独享型负载均衡配置pass-through后,从工作负载Pod所在节点或同节点的其他容器中访问ELB的私网IP地址,会出现无法访问的问题。
- 1.15及以下老版本集群暂不支持该能力。
- IPVS网络模式下,对接同一个ELB的Service需保持pass-through设置情况一致。
- 使用节点级别(Local)的服务亲和的场景下,会自动设置kubernetes.io/elb.pass-through为onlyLocal,开启pass-through能力。
apiVersion: v1 kind: Service metadata: annotations: kubernetes.io/elb.pass-through: "true" kubernetes.io/elb.class: union kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}' labels: app: nginx name: nginx spec: externalTrafficPolicy: Local ports: - name: service0 port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer
相关文档
- 创建并使用不同类型的Service:
- 在容器场景中,访问请求会经过多个代理层,获取客户端的真实IP地址需要在服务中进行适当的配置,详情请参见不同场景下容器内获取客户端源IP。
- 如果您需要保证同一客户端的请求在会话期间始终被转发到同一后端服务器,可通过负载均衡配置会话保持,详情请参见通过负载均衡配置实现会话保持。