k8s教程(service篇)-概念和原理(中)

本文涉及的产品
.cn 域名,1个 12个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
应用型负载均衡 ALB,每月750个小时 15LCU
简介: k8s教程(service篇)-概念和原理

06 将Service暴露给外部集群

KubernetesService创建的ClusterIP地址是对后端Pod列表的一层抽象,对于集群外部来说并没有意义,但有许多Service是需要对集群外部提供服务的,Kubernetes提供了多种机制将Service暴露出去,供集群外部的客户端访问。

这可以通过Service资源对象的类型字段“type”进行设置。

目前Service的类型如下:

类型 描述
ClusterIP Kubernetes默认会自动设置Service的虚拟IP地址,仅可被集群内部的客户端应用访问。当然,用户也可手工指定一个ClusterIP地址,不过需要确保该IP在Kubernetes集群设置的ClusterIP地址范围内(通过kube-apiserver 服务的启动参数-service-cluster–ip-range设置),并且没有被其他Service使用
NodePort 将Service的端口号映射到每个Node的一个端口号上,这样集群中的任意Node都可以作为Service的访问入口地址,即NodeIP:NodePort
LoadBalancer 将Servicel映射到一个已存在的负载均衡器的IP地址上, 通常在公有云环境中使用
ExternalName 将Service映射为一个外部域名地址,通过externalName字段进行设置

6.1 NodePort类型

下面的例子设置Service的类型为NodePort,并且设置具体的nodePort端口号为8081:

apiVersion: v1
kind: Service
metadata:
  name: webapp
spec:
type: NodePort
ports:
- port: 8080
  targetPort: 8080
  nodePort: 8081
selector:
  app: webapp

使用kubectl create创建了Service之后,就可以通过任意一个Node的IP地址+ NodePort 8081端口号访问服务了。

另外,如果用户在Service定义中不设置具体的nodePort端口号,则Kubernetes会自动分配一个NodePort范围内的可用端口号

在默认情况下,Node的kube-proxy会在全部网卡(0.0.0.0)上绑定NodePort端口号。在很多数据中心环境中,一台主机会配置多块网卡,作用各不相同(例如:存在业务网卡和管理网卡等)。

从Kubernetes1.10版本开始,kube-proxy可以通过设置特定的IP地址将NodePort绑定到特定的网卡上,而无须绑定在全部网卡上, 其设置方式为配置启动参数 “-nodeport-addresses”,指定需要绑定的网卡IP地址,多个地址之间使用逗号分隔。

例如:仅在10.0.0.0192.168.18.0对应的网卡上绑定NodePort端口号,对其他IP地址对应的网卡不会进行绑定,配置如下:

--nodeport-addresses=10.0.0.0/8,192.168.18.0/24

6.2 LoadBalancer类型

通常在公有云环境中设置Service的类型为 “LoadBalancer‘” ,可以将Service映射到公有云提供的某个负载均衡器的IP地址上,客户端通过负载均衡器的IPService的端口号就可以访问到具体的服务,无须再通过kube-proxy提供的负载均衡机制进行流量转发。公有云提供的LoadBalancer可以直接将流量转发到后端Pod上,而负载分发机制依赖于公有云服务商的具体实现。

举例:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
type: LoadBalancer
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
  clusterIP: 10.0.171.239

在服务创建成功之后,云服务商会在Service的定义中补充LoadBalancerIP 地址(status字段):

status:
  loadBalancer:
    ingress:
    - ip:192.0.2.127

6.3 ExternalName类型

ExternalName类型的服务用于将集群外的服务定义为Kubernetes的集群的Service,并且通过externalName字段指定外部服务的地址,可以使用域名或IP格式,集群内的客户端应用通过访问这个Service就能访问外部服务了

这种类型的Service没有后端Pod,所以无须设置Label Selector。例如:

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

在本例中设置的服务名为my-service,所在namespace为prod,客户端访问服务地址my-service.prod.svc.cluster.local时,系统将自动指向外部域名my.database.example.com

07 Service支持的网络协议

目前Service支持的网络协议如下.

类型 描述
TCP Service的默认网络协议,可用于所有类型的Service
UDP 可用于大多数类型的Service,LoadBalancer类型取决于云服务商对UDP的支持
HTTP 取决于云服务商是否支持HTTP和实现机制
PROXY 取决于云服务商是否支持HTTP和实现机制
SCTP 从Kubernetes1.12版本引入,到1.19版本时达到Beta阶段,默认启用,如需关闭该特性,则需要设置kube-apiserver的启动参数–feature- gates=-SCTPSupport=-false进行关闭

Kubernetes从1.17版本开始,可以为Service和Endpoint资源对象设置一个新的段"AppProtocol",用于标识后端服务在某个端口号上提供的应用层协议类型,例如HTTP、HTTPS、SSL、DNS等。

要使用AppProtocol,需要设置kube-apiserver的启动参数--feature-gates=ServiceAppProtocol=true进行开启,然后在Service或Endpoint的定义中设置AppProtocol字段指定应用层协议的类型,例如:

apiVersion: v1
kind: Service
metadata: 
  name: webapp 
spec:
  ports:
  - port: 8080
    targetPort: 8080
    AppProtocol: HTTP
  selector:
    app: webapp

08 Kubernetes的服务发现机制

服务发现机制指客户端应用在一个Kubernetes集群中如何获知后端服务的访问地址,一共有两种方式,下面来讲讲。

8.1 环境变量方式

在一个Pod运行起来的时候,系统会自动为其容器运行环境注入所有集群中有效Service的信息。

Service的相关信息包括服务IP、服务端口号、各端口号相关的协议等,通过{SVCNAME_SERVICE_HOST}{SVCNAME_SERVICE_PORT}格式进行设置。

其中,SVCNAME的命名规则为:将Servicename字符串转换为全大写字母,将中横线“”替换为下画线 “_”,以webapp服务为例:

apiVersion: v1
kind: Service
metadata:
  name: webapp
spec: 
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
  selector:
    app: webapp

在一个新创建的Pod(客户端应用)中,可以看到系统自动设置的环境变量如下:

WEBAPP_SERVICE_HOST=169.169.81.175
WEBAPP_SERVICE_PORT=8080
WEBAPP_P0RT=tcp://169.169.81.175:8080
WEBAPP_P0RT_8080_TCP=tcp://169.169.81.175:8080
WEBAPP_PORT_8080_TCP_PROTO=tcp
WEBAPP_PORT_8080_TCP_PORT=8080
WEBAPP_PORT_8080_TCP_ADDR=169.169.81.175

然后,客户端应用就能够根据Service相关环境变量的命名规则,从环境变量中获取需要访问的目标服务的地址了,例如:

curl http://{WEBAPP_SERVICE_HOST}:${WEBAPP_SERVICE_HOST}

8.2 DNS方式

Service在Kubernetes系统中遵循DNS命名规范,Service的DNS域名表示方法 为<servicename>.<namespace>.svc.<clusterdomain>,其中:

  • servicename:为服务的名称;
  • namespace:为其所在namespace的名称;
  • clusterdomain:为Kubernetes集群设置的域名后缀(例如cluster.local),服务名称的命名规则遵循RFC 1123规范的要求。

另外,Service定义中的端口号如果设置了名称(name),则该端口号也会拥

有一个DNS域名,在DNS服务器中以SRV记录的格式保存:_<portname>._<protocol>.<servicename>.<namespace>.svc. <clusterdomain>,其值为端口号的数值。

ServiceDNS域名形式进行访问时,就需要在Kubernetes集群中存在一个DNS服务器来完成域名到ClusterIP地址的解析工作了,经过多年的发展,目前由

CoreDNS作为Kubernetes集群的默认DNS服务器提供域名解析服务。

webapp服务为例,将其端口号命名为“http”:

apiversion: v1
kind: Service
metadata:
  name: webapp
spec:
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080
    name: http
  selector:
    app: webapp

解析名为 “http” 端口的DNS SRV记录

_http._tcp.webapp.default.svc.cluster.local'”,可以查询到其端口号的值为8080

09 Headless Service的概念和应用

在某些应用场景中,客户端应用不需要通过Kubernetes内置Service实现的负载均衡功能,或者需要自行完成对服务后端各实例的服务发现机制,或者需要自行实现负载均衡功能,此时可以通过创建一种特殊的名为 Headless‘”的服务来实现。

Headless Service的概念是这种服务没有入口访问地址(无ClusterIP地址), kube-proy不会为其创建负载转发规则,而服务名(DNS域名)的解析机制取决于该Headless Service是否设置了Label Selector

9.1 已设置Label Selector

如果Headless Service设置了Label Selector,Kubernetes则将根据Label Selector查询后端Pod列表,自动创建Endpoint列表,将服务名(DNS域名)的解析机制设置为当客户端访问该服务名时,得到的是全部Endpoint列表(而不是一个确定的IP地址)

以下面的Headless Service为例,其设置了Label Selector:

apiversion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
  clusterIP: None
  selector:
    app: nginx

使用kubectl create命令创建完之后,可以查看该Headless Service的详细信息,可以看到后端的Endpoint列表:

nslookup工具Headless Service名称尝试域名解析,将会看到DNS系统返回的全部EndpointIP地址,例如:

当客户端通过DNS服务名 “nginx”(或其FQDN全限定域名"nginx.<namespace>.svc.cluster.local“)和服务端口号访问该Headless服务(URL=nginx:80)时,将得到Service后端Endpoint列表"10.0.95.12:80,10.0.9513:80,10.0.95.14:80”,然后由客户端程序自行决定如何操作,例如:通过轮询机制访问各个Endpoint

9.2 没设置Label Selector

如果Ieadless Service没有设置Label Selector,则Kubernetes将不会自动创建对应的Endpoint列表。

DNS系统会根据下列条件尝试对该服务名设置DNS记录:

  • 如果Servicel的类型为ExternalName,则对服务名的访问将直接被DNS系统转换为Service设置的外部名称(externalName);
  • 如果系统中存在与Service同名的Endpoint定义,则服务名将被解析为Endpoint定义中的列表,适用于非ExternalName类型的Service。

10 端点分片和服务拓扑

Service的后端是一组Endpoint列表,为客户端应用提供了极大的便利。

问题:随着集群规模的扩大及Service数量的增加,特别是Service后端Endpoint数量的增加,kube-proxy需要维护的负载分发规则(例如iptables规则侧或 ipvs规则)的数量也会急剧增加,导致后续对Service后端Endpoint的添加、删除 等更新操作的成本急剧上升。

举例:假设在Kubernetes集群中有10000个Endpoint运行在大约5000个Node上,则对单个Pod的更新将需要总计约5GB的数据传输,这不仅对集群内的网络带宽浪费巨大,而且对Master的冲击非常大,会影响Kubernetes集群的整体性能,在Deployment不断进行滚动升级操作的情况下尤为突出。

解决方式:使用端点分片(Endpoint Slices)机制。

  • EndpointSlice通过对Endpoint进行分片管理来实现降低Master和各Node之间的网络传输数据量及提高整体性能的目标。对于Deployment的滚动升级,可以实现仅更新部分Node上的Endpoint信息,Master与Node之间的数据传输量可以减少100倍左右,能够大大提高管理效率。

EndpointSlice根据Endpoint 所在Node的拓扑信息进行分片管理,如图所示

Endpoint Slices要实现的第2个目标是为基于Node拓扑的服务路由提供支持,这需要与服务拓扑(Service Topology)机制共同实现

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
3月前
|
Kubernetes 容器
K8S的Service的LoadBanlance之Metallb解决方案
本文介绍了如何在Kubernetes中使用MetalLB来实现Service的LoadBalancer功能,包括MetalLB的部署、配置、以及通过创建地址池和部署服务来测试MetalLB的过程。
164 1
K8S的Service的LoadBanlance之Metallb解决方案
|
13天前
|
关系型数据库 MySQL Docker
《docker高级篇(大厂进阶):5.Docker-compose容器编排》包括是什么能干嘛去哪下、Compose核心概念、Compose使用三个步骤、Compose常用命令、Compose编排微服务
《docker高级篇(大厂进阶):5.Docker-compose容器编排》包括是什么能干嘛去哪下、Compose核心概念、Compose使用三个步骤、Compose常用命令、Compose编排微服务
75 24
|
15天前
|
关系型数据库 MySQL Docker
《docker高级篇(大厂进阶):5.Docker-compose容器编排》包括是什么能干嘛去哪下、Compose核心概念、Compose使用三个步骤、Compose常用命令、Compose编排微服务
《docker高级篇(大厂进阶):5.Docker-compose容器编排》包括是什么能干嘛去哪下、Compose核心概念、Compose使用三个步骤、Compose常用命令、Compose编排微服务
94 6
|
2月前
|
Kubernetes 持续交付 微服务
深入浅出:理解 Kubernetes 核心概念
Kubernetes 是一个由 Google 开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它已成为微服务架构下的行业标准。本文深入浅出地介绍了 Kubernetes 的核心概念和组件,包括 Master 和 Node 组件、Pod、Service、Deployment 等,并提供了基本操作示例和实战应用,帮助你更好地管理和利用容器环境。
|
1月前
|
存储 Kubernetes 调度
K8S中的核心概念
【10月更文挑战第26天】云原生环境下的安全问题易被忽视,导致潜在风险。应用层渗透测试和漏洞扫描是检测安全的关键,尤其是对于CVE漏洞的修复。然而,常见误解认为安全由外部防护处理且不易引入问题。
|
4月前
|
Kubernetes 网络安全 容器
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
|
1天前
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。
|
3天前
|
Kubernetes 网络协议 应用服务中间件
Kubernetes Ingress:灵活的集群外部网络访问的利器
《Kubernetes Ingress:集群外部访问的利器-打造灵活的集群网络》介绍了如何通过Ingress实现Kubernetes集群的外部访问。前提条件是已拥有Kubernetes集群并安装了kubectl工具。文章详细讲解了Ingress的基本组成(Ingress Controller和资源对象),选择合适的版本,以及具体的安装步骤,如下载配置文件、部署Nginx Ingress Controller等。此外,还提供了常见问题的解决方案,例如镜像下载失败的应对措施。最后,通过部署示例应用展示了Ingress的实际使用方法。
18 2
|
15天前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
本文源自2024云栖大会苏雅诗的演讲,探讨了K8s集群业务为何需要灾备及其重要性。文中强调了集群与业务高可用配置对稳定性的重要性,并指出人为误操作等风险,建议实施周期性和特定情况下的灾备措施。针对容器化业务,提出了灾备的新特性与需求,包括工作负载为核心、云资源信息的备份,以及有状态应用的数据保护。介绍了ACK推出的备份中心解决方案,支持命名空间、标签、资源类型等维度的备份,并具备存储卷数据保护功能,能够满足GitOps流程企业的特定需求。此外,还详细描述了备份中心的使用流程、控制台展示、灾备难点及解决方案等内容,展示了备份中心如何有效应对K8s集群资源和存储卷数据的灾备挑战。
|
1月前
|
Kubernetes 监控 Cloud Native
Kubernetes集群的高可用性与伸缩性实践
Kubernetes集群的高可用性与伸缩性实践
73 1