Kubernetes Service解析

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 我们都知道,在K8S集群中,每个Pod都有自己的私有IP地址,并且这些IP地址不是固定的。这意味着其不依赖IP地址而存在。例如,当我们因某种业务需求,需要对容器进行更新操作,则容器很有可能在随后的启动运行过程中被分配到其他IP地址。此外,在K8S集群外部看不到该Pod。因此,Pod若单独运行于K8S体系中,在实际的业务场景中是不现实的,故我们需要通过其他的策略去解决,那么解决方案是什么? 由此,我们引入了Serivce这个概念以解决上述问题。

     我们都知道,在K8S集群中,每个Pod都有自己的私有IP地址,并且这些IP地址不是固定的。这意味着其不依赖IP地址而存在。例如,当我们因某种业务需求,需要对容器进行更新操作,则容器很有可能在随后的启动运行过程中被分配到其他IP地址。此外,在K8S集群外部看不到该Pod。因此,Pod若单独运行于K8S体系中,在实际的业务场景中是不现实的,故我们需要通过其他的策略去解决,那么解决方案是什么? 由此,我们引入了Serivce这个概念以解决上述问题。

      如下所示,为简单的Pod配置文件定义:


apiVersion: v1
kind: Pod
metadata:
  name: k8s-activemq-pod
  labels:
    app: k8s-activemq 
spec:
  containers:
  - name: k8s-activemq-prod-container
    image: registry.docker.com/baseimg/k8s-active-mq

     K8s Service是一种抽象,定义了一组逻辑上可用的pod和策略。服务是一个REST对象,就像一个pod一样,并且具有终结点,因此只要类型支持可见性,就可以从外部访问服务。这到底是什么意思?这意味着即使服务也可以对外界隐藏。

     Service 的理念是将一组 Pod 端点划分为单一资源。我们可以配置各种方式来访问该分组。默认情况下,我们会获得稳定的集群 IP 地址,集群内部的客户端可以使用该 IP 地址与 Service 中的 Pod 通信。客户端向稳定 IP 地址发送请求,然后请求会被路由到 Service 的其中一个 Pod。

      Service 通过选择器来识别其成员 Pod。为使 Pod 成为 Service 的成员,该 Pod 必须具有选择器中指定的所有标签。标签是附加到对象的任意键值对。

     下列 Service 清单所具有的选择器指定了两种标签。selector 字段指示同时具有 app: metrics 标签和 department:engineering 标签的任何 Pod 都是该 Service 的成员。Service配置文件语法定义如下:


apiVersion: v1
kind: Service
metadata:
  name: k8s-activemq-prod-service
spec:
  selector:
    app: k8s-activemq
  ports:
    - name: http
      port: 8161
      nodePort: 32190
    - name: tcp
      port: 61616
      nodePort: 32191
  type: NodePort


为何使用 Service?

     在 Kubernetes 集群中,每个 Pod 都具有内部 IP 地址。但是,Deployment 中的 Pod 可以随时加入和退出,而且它们的 IP 地址也不是固定的。因此,直接使用 Pod IP 地址毫无意义。通过 Service,您会获得稳定的 IP 地址,该 IP 地址在 Service 的生命周期内有效,即使成员 Pod 的 IP 地址发生变化也仍然有效。

     Service 还提供负载平衡。客户端会调用单个稳定的 IP 地址,而且客户端请求在 Service 的成员 Pod 之间保持平衡。

      Service 类型

      目前,在K8S生态体系中提供了五种类型的 Service:

      1、ClusterIP(默认):内部客户端向稳定的内部 IP 地址发送请求。

      2、NodePort:客户端向使用 Service 指定的一个或多个 nodePort 值的节点的 IP 地址发送请求。

      3、LoadBalancer:客户端向网络负载平衡器的 IP 地址发送请求。

      4、ExternalName:内部客户端使用 Service 的 DNS 名称作为外部 DNS 名称的别名。          

      5、Headless:如果需要对 Pod 进行分组,同时也不需要稳定的 IP 地址,此场景下可以使用 Headless 服务。  

ClusterIP

      通过集群的内部 IP 暴露服务,选择该值,服务只能够在集群内部可以访问,这也是默认的 ServiceType。简要拓扑如下:

     如上图所示,ClusterIP类型的Service就是在K8S节点上创建一个满足Service IP地址的Iptables或Ipvs规则。这种类型的Service的IP地址一定是我们在初始化集群时,指定的Service网络中的地址,这意味着这种类型的Service不能被集群外部客户端所访问,仅能在集群节点上访问。

      以下为 ClusterIP 类型的 Service 的实例配置:


apiVersion: v1
kind: Service
metadata:
  name: springboot-demo-service
spec:
  selector:
    app: metrics
    department: sales
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080


NodePort

      NodePort 类型是 ClusterIP 类型的扩展。因此,NodePort 类型的 Service 具有集群 IP 地址。通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 :,可以从集群的外部访问一个 NodePort 服务。简要拓扑如下:

      如上图所示,NodePort类型的Service,是建构在ClusterIP的基础上做的扩展,主要解决了集群外部客户端访问问题。在上图拓扑中,我们可以看到NodePort类型Service在创建时,它会为每个节点上创建一条DNAT规则,外部客户端访问集群任意节点的指定端口,都会被DNAT到对应的Service上,从而实现访问集群内部Pod。对于集群内部客户端的访问它还是通过ClusterIP进行的,NodePort类型Service与ClusterIP类型Service唯一不同的是:NodePort类型Service能够被外部客户端所访问,在集群每个节点上都有对应的DNAT规则。

       以下是 NodePort 类型的 Service 的实例配置:


apiVersion: v1
kind: Service
metadata:
  name: springboot-demo-service
spec:
  selector:
    app: metrics
    department: sales
  type: NodePort
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080


LoadBalancer

       LoadBalancer 类型是 NodePort 类型的扩展。因此,LoadBalancer 类型的 Service 具有集群 IP 地址以及一个或多个 NodePort 值。简要拓扑如下:

      如上图所示,LoadBalancer主要基于云提供商的负载均衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。LoadBalancer这种类型的Service是在NodePort的基础上做的扩展,这种类型Service只能在底层是云环境的K8S上创建,如果底层是非云环境,这种类型无法实现,只能手动搭建反向代理进行对NodePort类型的Service进行反代;它主要解决NodePort类型Service被集群外部访问时的端口映射以及负载。

      以下是 LoadBalancer类型的 Service 的实例配置:


apiVersion: v1
kind: Service
metadata:
  name: springboot-demo-service
spec:
  selector:
    app: metrics
    department: engineering
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080


ExternalName

     ExternalName 类型的 Service 为外部 DNS 名称提供内部别名。内部客户端使用内部 DNS 名称发出请求,然后请求会被重定向到外部名称。简要拓扑如下:

      如上图所示,ExternalName这种类型Service主要用来解决对应Service引用集群外部的服务。我们知道对于Service来说,它就是一条Iptables或Ipvs规则,对于后端引用的资源是什么,取决于对应Endpoint关联的是什么资源的Ip地址和端口。如果我们需要在集群中使用集群外部的服务,我们就可以创建ExternalName类型的Service,指定后端关联外部某个服务端ip地址或域名即可。它的工作流程如上图所示,在集群内部客户端访问对应Service时,首先要去Ccore-DNS上查询对应域名的Ip地址,然后再根据Dns返回的Ip地址去连接对应的服务,使用这种类型Service的前提是对应的Coredns能够连接到外部网络解析对应的域名。

      以下是 ExternalName类型的 Service 的实例配置:


apiVersion: v1
kind: Service
metadata:
  name: springboot-demo-service
spec:
  type: ExternalName
  externalName: example.com

      ExternalName Service 类型与其他 Service 类型完全不同。事实上,ExternalName 类型的 Service 不符合本主题开头提出的 Service 定义。ExternalName 类型的 Service 不与一组 Pod 相关联,也没有稳定的 IP 地址。相反,ExternalName 类型的 Service 从内部 DNS 名称映射到外部 DNS 名称。  

Headless

      在某些场景中,我们有时候不需要负载均衡,以及单独的 Service IP,可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建 Headless Service。我们可以使用 Headless Service 与其他服务发现机制进行接口,而不必与 Kubernetes 的实现捆绑在一起。

      对 Headless Service 而言,并不会分配 Cluster IP,Kube-Proxy 不会处理它们,而且平台也不会为它们进行负载均衡和路由。DNS 如何实现自动配置,依赖于 Service 是否定义了 selector。其简要拓扑如下:

       以下是 Headless Service类型的 Service 的实例配置:


apiVersion: v1
kind: Service
metadata:
  name: gateway-test
  labels:
    app: gateway_test
spec:
  ports:
  - port: 433
    name: gateway_api
  # clusterIP 设置为 None
  clusterIP: None
  selector:
    app: gateway_test

      Headless Services 主要有以下应用场景:

      1、自主选择权,有时候 client 想自己来决定使用哪个Real Server,可以通过查询DNS来获取 Real Server 的信息。

     2、Headless Service 的对应的每一个 Endpoints,即每一个Pod,都会有对应的DNS域名,这样Pod之间就可以互相访问。

      至此,K8S生态体系中的五种类型的 Service简要介绍完成。具体,可以依据当前项目实际场景进行规划与选择。


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
2月前
|
Kubernetes 容器
K8S的Service的LoadBanlance之Metallb解决方案
本文介绍了如何在Kubernetes中使用MetalLB来实现Service的LoadBalancer功能,包括MetalLB的部署、配置、以及通过创建地址池和部署服务来测试MetalLB的过程。
97 1
K8S的Service的LoadBanlance之Metallb解决方案
|
3月前
|
Kubernetes API 调度
Kubernetes 架构解析:理解其核心组件
【8月更文第29天】Kubernetes(简称 K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。它提供了一个可移植、可扩展的环境来运行分布式系统。本文将深入探讨 Kubernetes 的架构设计,包括其核心组件如何协同工作以实现这些功能。
277 0
|
12天前
|
存储 Kubernetes 监控
深度解析Kubernetes在微服务架构中的应用与优化
【10月更文挑战第18天】深度解析Kubernetes在微服务架构中的应用与优化
49 0
|
3月前
|
Kubernetes 网络安全 容器
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
|
3月前
|
Kubernetes 负载均衡 网络协议
在K8S中,Service的类型有哪几种,请说⼀下他们的用途?
在K8S中,Service的类型有哪几种,请说⼀下他们的用途?
|
3月前
【Azure 应用服务】App Service 配置 Application Settings 访问Storage Account得到 could not be resolved: '*.file.core.windows.net'的报错。没有解析成对应中国区 Storage Account地址 *.file.core.chinacloudapi.cn
【Azure 应用服务】App Service 配置 Application Settings 访问Storage Account得到 could not be resolved: '*.file.core.windows.net'的报错。没有解析成对应中国区 Storage Account地址 *.file.core.chinacloudapi.cn
|
3月前
|
网络协议 微服务
【Azure 微服务】基于已经存在的虚拟网络(VNET)及子网创建新的Service Fabric并且为所有节点配置自定义DNS服务
【Azure 微服务】基于已经存在的虚拟网络(VNET)及子网创建新的Service Fabric并且为所有节点配置自定义DNS服务
|
3月前
|
Kubernetes 负载均衡 网络协议
在K8S中,Service的类型有哪些?
在K8S中,Service的类型有哪些?
|
3月前
|
Kubernetes API 容器
在K8S中,Service的Nodeport端口范围?
在K8S中,Service的Nodeport端口范围?
KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(五)
KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(五)
249 0
KUBERNETES04_Service服务ClusterIP、NodePort方式、Ingress域名访问、路径重写、限流操作(五)