K8S生态之服务发现解析

简介: 当前,云原生生态已经成为全球各大厂商以及企业尤其是互联网企业技术选型、场景推广的一个重要参考标准。云原生所代表的技术已经逐渐成为大家的共识,从一个虚无缥缈的概念逐渐演化成众多参与者的下一个技术战略储备。自然而言,承载业务需求的应用架构就会提及到微服务生态体系,以及其中最重要的分布式协作模式——“Service Discovery”,即:服务发现。

    当前,云原生生态已经成为全球各大厂商以及企业尤其是互联网企业技术选型、场景推广的一个重要参考标准。云原生所代表的技术已经逐渐成为大家的共识,从一个虚无缥缈的概念逐渐演化成众多参与者的下一个技术战略储备。自然而言,承载业务需求的应用架构就会提及到微服务生态体系,以及其中最重要的分布式协作模式——“Service Discovery”,即:服务发现。

    在微服务体系架构中,我们通常所说的“服务发现”,指的是广义层面的描述,其主要包含两个最核心的模块:服务注册与服务发现。那么什么是“服务注册”、“服务发现”呢?        通常来讲,服务注册,指的是将提供某个服务的模块信息(通常是这个服务的 IP 和 Port )注册到某个公共的组件上去,例如: 微服务生态中的 Zookeeper、Eureka 以及 Consul 等等组件。其语法可描述为:NameServer—>register(newServer)。

    而对于服务发现,其指的是新注册的这个服务模块能够及时的被其他调用者所发现。无论其操作状态为服务新增还是服务删减都能够实现自动发现。其语法可描述为:NameServer—>getAllServer()。


    针对上述概念的解析,其具体场景表现为:服务 X 调用服务 Y 时,需要通过服务发现模块找到服务 Y 的 IP 和 Port 列表,而服务 Y 的实例在启动时需要把提供服务的 IP 和 Port 注册到服务注册中心。一个典型的服务发现结构如下所示:

   基于上述结构图,针对每一个 Service (如 X、Y、、、)包含多个实例,每一个实例包含对应的IP 和 Port,以方便对方调用。逻辑上还是 Serivce X -> Service Y -> Service WV,但是 Proxy 或者 Service 帮助我们隐藏了细节,因此,基于应用服务角度,从 Service X 至 Service Y,我们能看到只不过是一个完整的服务,而非其他主机资源。

    其实,从本质上讲,在微服务生态的发展历程中,其终极目标无非是为了将业务组件与非业务组件进行完全分离,使得每一个微服务能够独立且完整,其具体的实现细节将会被封装或隐藏掉,对客户端无感知。作为 Service Mesh 目前最流行的产品,Istio 使用了基于 Virtual Service 与 Destination Rule 来解决了服务注册与发现的问题,正在一步步朝向最终目标前进。

服务注册

   截止目前,基于微服务生态体系流行的注册中心比较多,无论其基于何种语言,比较常见的有 Zookeeper、Ectd、Consul、Eureka 、Nacos 以及 Coredns 组件等。服务注册通常有三种:自注册、主动注册以及第三方注册。具体如下所示:

   1、自注册,指的是服务提供方在启动服务过程中通过将提供服务的 IP 和Port 发送到注册中心,并通过心跳方式维持健康状态。当服务下线时,自己把相应的数据删除。目前,典型场景就是基于使用 Eureka 客户端发布微服务。

   2、主动注册,与第三方注册方式比较类似,主动注册方式是指注册中心和调度或发布系统路由互通,主动同步最新的服务 IP 列表信息。典型的场景为基于 Kubernetes 生态体系中,Coredns 订阅 Api Server 数据。

   3、第三方注册,第三方注册是指存在一个第三方的系统或平台专门负责在服务启动或停止过程中向注册中心增加或删除服务数据。典型的场景例如基于 Devops 系统或容器调度系统主动调注册中心接口注册服务。

   接下来,我们再解析下“服务发现”相关架构体系,具体可参考如下内容。

服务发现

   在真正发起服务调用前,调用方需要从注册中心拿到相应服务可用的 IP 和 Port 列表,即服务发现。服务发现从对应用的侵入性上可以分为两大类:

   1、SDK-Based 这类的服务发现方式,需要调用方依赖相应的 SDK ,显式调用 SDK 代码才可以实现服务调用,即对业务有侵入性,典型例子如 Eureka、Zookeeper 等。

   2、DNS-Based DNS 本身是一种域名解析系统,可以满足简单的服务发现场景,如双方约定好端口、序列化协议等等。但是,这远远不能满足真正的微服务场景需求。近几年,基于 DNS 的服务发现渐渐被业界提及并进一步推广与落地。

   以上为站在微服务角度针对“服务发现”原理机制及场景进行解析,接下来,我们将基于容器生态并对其进行补充。

   在 Kubernetes 生态中,我们通常借助 “Service” 概念-对象来实现服务之间的互访,具体为在一组提供服务的 Pod 之前创建一个稳定的网络端点,并为这些 Pod 进行负载分配。具体如下所示:

    基于上图所述,右侧的 Pod 可能会因为容器服务的伸缩、更新、故障等相关场景,其数量将会发生变动,而 Service 会实时对这些变动进行跟踪、监测。与此同时 Service 的名称、IP 和 Port 却不会因为 Pod 的任意变动而产生变化。从本质上讲,我们可以将 Kubernetes Service 抽象为 Front-end (前端)和 Back-end(后端)两个核心部分。针对 Front-end 部分,其稳定可靠,名称、IP 和 Port 在 Service 的整个生命周期中都不会改变,因此,意味着无需担心客户端 DNS 缓存超时等问题。针对 Back-end 部分,其包括一组符合标签选择条件的 Pod,其属性为动态更新,Pod 往往会因为各种客观原因进行动态调整。因此,在实际的业务场景下,需要借助负载均衡机制来维持服务访问的无感性。基于上述的解析,我们以 Node Port Services 为例,简要描述请求从群集外部访问服务的最基本方法。节点端口是保留在群集中每个节点上的端口,可通过该端口访问服务。具体如下图所示:


   在 Kubernetes 1.12 以及后续的版本,为了满足服务注册及发现这一需要,每个 Kubernetes 集群都会在 Kube-System 命名空间中用 Pod 的形式运行一个 DNS 服务,通常称之为集群 DNS。集群 DNS 基于 CoreDNS,以 Kubernetes 原生应用的形式运行。其所实现的注册流程,具体如下所示:

    1、向 API Server 用 POST 方式提交一个新的 Service 定义

    2、此请求需要经过认证、鉴权以及其它的准入策略检查过程之后才会放行

    3、Service 得到一个 ClusterIP(虚拟 IP 地址),并保存到集群数据仓库

    4、在集群范围内传播 Service 配置

    5、集群 DNS 服务得知该 Service 的创建,据此创建必要的 DNS A 记录。

    从某种意义上来说,CoreDNS 实现了一个控制器,会对 API Server 进行监听,一旦发现有新建的 Service 对象,就创建一个从 Service 名称映射到 ClusterIP 的域名记录。这样 Service 就不必自行向 DNS 进行注册,CoreDNS 控制器会关注新创建的 Service 对象,并实现后续的 DNS 过程。通常,DNS 中注册的名称为 metadata.name,而 ClusterIP 则由 Kubernetes 自行分配。基于上述配置,当 Service 对象注册到集群 DNS 之中后,其就能够被运行在集群中的其它 Pod 发现。

    当 Service 的前端创建成功并注册成功后,Service 对象依据 Label Selector 标签列表把流量分发至后端的 Pod 列表中,因此,只有符合列表条件的 Pod 才能够获取到前端服务的请求,具体可参考如下示意图:

    基于上述结构图,在实际的业务场景中,Kubernetes 会自动为每个 Service 创建 Endpoints 对象。Endpoints 对象的职责就是保存一个符合 Service 标签选择器标准的 Pod 列表,这些 Pod 将接收来自 Service 的流量。

    通常,针对 Kubernetes 集群中某两个相互互访的应用,例如:web-x 和 web-y。要使用服务发现功能,每个 Pod 都需要知道集群 DNS 的位置才能正确使用它。因此每个 Pod 中的每个容器的 /etc/resolv.conf 文件都被配置为使用集群 DNS 进行解析。因此,如果 web-x 中的 Pod 想要连接到 web-y 中的 Pod(前提条件:web-x 知道目标服务的名称),就得向 DNS 服务器发起对域名 web-y-svc 的查询并获取web-y-svc 的 ClusterIP(VIP)。此时,将会往此 IP 发送流量请求,由于 ClusterIP 所在的网络被称为 Service Network ,因为没有路由,所有容器把发现这种地址的流量都发送到了缺省网关(名为 CBR0 的网桥)。这些流量会被转发给 Pod 所在节点的网卡上,基于此场景,节点的内核修改了数据包 Header 中的目标 IP,使其转向健康的 Pod。

   基于上述所述,在实际的容器环境中,我们在创建新的 Service 对象时,会得到一个被称为 ClusterIP 的虚拟 IP。服务名及其 ClusterIP 被自动注册到集群 DNS 中,并且会创建相关的 Endpoints 对象用于保存符合标签条件的健康 Pod 的列表,Service 对象会向列表中的 Pod 转发流量。与此同时集群中所有节点都会配置相应的 Iptables/IPVS 规则,监听目标为 ClusterIP 的流量并转发给真实的 Pod IP。与此同时,若此 Pod 基于 Service 访问其他的 Pod ,先进行 Core DNS 查询请求,将 Service 名称解析为 ClusterIP,然后将流量发送给位于 Service 网络的 ClusterIP 上,再次,基于缺省网关进行流量转发以及内核的调整,最终使得流量分发至可路由的扁平的叠加网络中的健康 Pod 列表之上。

   综上所述,基于容器 K8S 生态中“服务发现“机制的相关解析,本文到此为止,大家有任何问题或建议,可以随时留言、沟通。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
8月前
|
缓存 Kubernetes Docker
GitLab Runner 全面解析:Kubernetes 环境下的应用
GitLab Runner 是 GitLab CI/CD 的核心组件,负责执行由 `.gitlab-ci.yml` 定义的任务。它支持多种执行方式(如 Shell、Docker、Kubernetes),可在不同环境中运行作业。本文详细介绍了 GitLab Runner 的基本概念、功能特点及使用方法,重点探讨了流水线缓存(以 Python 项目为例)和构建镜像的应用,特别是在 Kubernetes 环境中的配置与优化。通过合理配置缓存和镜像构建,能够显著提升 CI/CD 流水线的效率和可靠性,助力开发团队实现持续集成与交付的目标。
|
8月前
|
Kubernetes 网络协议 Nacos
OpenAI 宕机思考丨Kubernetes 复杂度带来的服务发现系统的风险和应对措施
Kubernetes 体系基于 DNS 的服务发现为开发者提供了很大的便利,但其高度复杂的架构往往带来更高的稳定性风险。以 Nacos 为代表的独立服务发现系统架构简单,在 Kubernetes 中选择独立服务发现系统可以帮助增强业务可靠性、可伸缩性、性能及可维护性,对于规模大、增长快、稳定性要求高的业务来说是一个较理想的服务发现方案。希望大家都能找到适合自己业务的服务发现系统。
279 85
|
10月前
|
Kubernetes 监控 API
深入解析Kubernetes及其在生产环境中的最佳实践
深入解析Kubernetes及其在生产环境中的最佳实践
530 93
|
Kubernetes API 调度
Kubernetes 架构解析:理解其核心组件
【8月更文第29天】Kubernetes(简称 K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。它提供了一个可移植、可扩展的环境来运行分布式系统。本文将深入探讨 Kubernetes 的架构设计,包括其核心组件如何协同工作以实现这些功能。
814 2
|
8月前
|
Kubernetes Linux 虚拟化
入门级容器技术解析:Docker和K8s的区别与关系
本文介绍了容器技术的发展历程及其重要组成部分Docker和Kubernetes。从传统物理机到虚拟机,再到容器化,每一步都旨在更高效地利用服务器资源并简化应用部署。容器技术通过隔离环境、减少依赖冲突和提高可移植性,解决了传统部署方式中的诸多问题。Docker作为容器化平台,专注于创建和管理容器;而Kubernetes则是一个强大的容器编排系统,用于自动化部署、扩展和管理容器化应用。两者相辅相成,共同推动了现代云原生应用的快速发展。
2223 11
|
10月前
|
负载均衡 Java 持续交付
深入解析微服务架构中的服务发现与负载均衡
深入解析微服务架构中的服务发现与负载均衡
486 7
|
10月前
|
运维 Kubernetes Cloud Native
Kubernetes云原生架构深度解析与实践指南####
本文深入探讨了Kubernetes作为领先的云原生应用编排平台,其设计理念、核心组件及高级特性。通过剖析Kubernetes的工作原理,结合具体案例分析,为读者呈现如何在实际项目中高效部署、管理和扩展容器化应用的策略与技巧。文章还涵盖了服务发现、负载均衡、配置管理、自动化伸缩等关键议题,旨在帮助开发者和运维人员掌握利用Kubernetes构建健壮、可伸缩的云原生生态系统的能力。 ####
|
10月前
|
存储 Kubernetes 调度
深度解析Kubernetes中的Pod生命周期管理
深度解析Kubernetes中的Pod生命周期管理
|
11月前
|
存储 Kubernetes 监控
深度解析Kubernetes在微服务架构中的应用与优化
【10月更文挑战第18天】深度解析Kubernetes在微服务架构中的应用与优化
386 0
|
负载均衡 Kubernetes 算法
K8s服务发现与负载均衡的技术探索
【7月更文挑战第15天】K8s通过Service资源对象和kube-proxy组件实现了高效、灵活的服务发现和负载均衡机制。通过合理选择Service类型、优化kube-proxy配置以及使用Ingress进行高级路由,可以确保应用在K8s集群中高效、可靠地运行。随着云原生技术的不断发展,K8s的服务发现和负载均衡机制也将不断完善和优化,为更多场景提供强大的支持。

推荐镜像

更多
  • DNS