前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring-cloud-k8s 跨 NS 的坑

spring-cloud-k8s 跨 NS 的坑

作者头像
程序猿Damon
发布2021-11-15 11:18:14
8520
发布2021-11-15 11:18:14
举报
文章被收录于专栏:程序猿 Damon 带你进阶全栈

回顾

前面文章 (Spring Cloud Kubernetes 之实战服务注册与发现) 中,讲述了 spring-cloud-k8s 在微服务实践中,带来了多大的优势。介绍了 k8s 中资源 Service,其如何来实现服务的注册与发现。

其实在 k8s 中,Service 资源的类型比较多,有四种:

  • ExternalName:创建一个 DNS 别名指向 service name,这样可以防止 service name 发生变化,但需要配合 DNS 插件使用。
  • ClusterIP:默认的类型,用于为集群内 Pod 访问时,提供的固定访问地址,默认是自动分配地址,可使用 ClusterIP 关键字指定固定 IP。
  • NodePort:基于 ClusterIp,用于为集群外部访问 Service 后面 Pod 提供访问接入端口。
  • LoadBalancer:它是基于 NodePort。

我们一般会默认使用的类型:ClusterIP,但此时会出现一种问题,那就是此类型的 Service 被用来访问非同一 NS 下的 pods,即<servicename>.<namespace>.svc.cluster.local形式访问 pod,只能通过 servicename 直接访问同一 namespace 下的 pod。

案例

下面,我们来看案例:假设我这里有三个服务:cas-server、rest-service、diff-ns-service 等,我通过 deployment 来部署这些服务的 pod。

image.png

可以看到这些 pod 处于 不同的 namespace 下,同样的对应的 service 也是处于对应的 namespace 下:

代码语言:javascript
复制
ns-app          diff-ns-service-service   ClusterIP   10.16.178.187   <none>        2008/TCP        6h39m   app=diff-ns-service
system-server   cas-server-service        ClusterIP   10.16.134.168   <none>        2000/TCP        16d     app=cas-server
system-server   rest-service-service      ClusterIP   10.16.128.58    <none>        2001/TCP        16d     app=rest-service

这里的 Service 类型都是 ClusterIp,在前面,我们验证过基于这样的服务,我们可以利用 springcloud-k8s 来实现同一 namespace 下服务之间的注册与发现,实现负载均衡。但如果不在同一 namespace 下呢?比如这里的diff-ns-service,它与另外两个服务不在同一 namespace。此时我们通过基于 Ribbon 的负载均衡策略。这是因为我们默认了 KubernetesRibbonMode 的模式:POD,就是获取服务提供者的 pod 的 ip 和 port,该 ip 是 kubernetes 集群的内部 ip,只要服务消费者是部署在同一个 kubernetes 集群内就能通过 pod 的 ip 和服务提供者暴露的端口访问。当我们使用当modeSERVICE时,就是获取服务提供者在 k8s 中的 service 的名称和端口,使用这种模式会导致 Ribbon 的负载均衡失效,转而使用 k8s 的负载均衡。

所以,如果不使用默认的 Ribbon 来实现负载均衡,可以配置:

代码语言:javascript
复制
spring:
  cloud:
    kubernetes:
      ribbon:
        mode: SERVICE

这个前提其实还是在同一 namespace 下,但如果不在同一 NS 呢?还是设置为SERVICE模式,但里面还是用 k8s 原生的调用方式:<servicename>.<namespace>.svc.cluster.local***,假设这里需要调用 diff-ns-service,则:

代码语言:javascript
复制
ResponseEntity<String> responseEntity = new RestTemplate().exchange("http://diff-ns-service-service/getservicedetail?servicename=cas-server-service",
     HttpMethod.GET, formEntity, String.class);

访问请求该服务时,发现并未请求到:

代码语言:javascript
复制
2021-11-04 09:23:16.830:147 [http-nio2-2001-exec-2] DEBUG org.springframework.web.client.RestTemplate -HTTP GET http://diff-ns-service-service/getservicedetail?servicename=cas-server-service
2021-11-04 09:23:16.834:147 [http-nio2-2001-exec-2] DEBUG org.springframework.web.client.RestTemplate -Accept=[text/plain, application/json, application/*+json, */*]
2021-11-04 09:23:16.859:255 [http-nio2-2001-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor -Using 'text/html', given [text/html, application/xhtml+xml, image/avif, image/webp, image/apng, application/xml;q=0.9, application/signed-exchange;v=b3;q=0.9, */*;q=0.8] and supported [text/plain, */*, text/plain, */*, application/json, application/*+json, application/json, application/*+json]
2021-11-04 09:23:16.860:91 [http-nio2-2001-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor -Writing [""]

如果走 mode 为POD的 Ribbon 的负载均衡:

代码语言:javascript
复制
2021-11-04 09:34:32.188:147 [http-nio2-2001-exec-2] DEBUG org.springframework.web.client.RestTemplate -HTTP GET http://diff-ns-service-service/getservicedetail?servicename=cas-server-service
2021-11-04 09:34:32.193:147 [http-nio2-2001-exec-2] DEBUG org.springframework.web.client.RestTemplate -Accept=[text/plain, application/json, application/*+json, */*]
2021-11-04 09:34:32.261:115 [http-nio2-2001-exec-2] INFO  com.netflix.config.ChainedDynamicProperty -Flipping property: diff-ns-service-service.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2021-11-04 09:34:32.271:197 [http-nio2-2001-exec-2] INFO  com.netflix.loadbalancer.BaseLoadBalancer -Client: diff-ns-service-service instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=diff-ns-service-service,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2021-11-04 09:34:32.278:222 [http-nio2-2001-exec-2] INFO  com.netflix.loadbalancer.DynamicServerListLoadBalancer -Using serverListUpdater PollingServerListUpdater
2021-11-04 09:34:32.281:88 [http-nio2-2001-exec-2] WARN  org.springframework.cloud.kubernetes.ribbon.KubernetesEndpointsServerList -Did not find any endpoints in ribbon in namespace [system-server] for name [diff-ns-service-service] and portName [null]
2021-11-04 09:34:32.282:150 [http-nio2-2001-exec-2] INFO  com.netflix.loadbalancer.DynamicServerListLoadBalancer -DynamicServerListLoadBalancer for client diff-ns-service-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=diff-ns-service-service,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:org.springframework.cloud.kubernetes.ribbon.KubernetesEndpointsServerList@d48bf01
2021-11-04 09:34:32.308:255 [http-nio2-2001-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor -Using 'text/html', given [text/html, application/xhtml+xml, image/avif, image/webp, image/apng, application/xml;q=0.9, application/signed-exchange;v=b3;q=0.9, */*;q=0.8] and supported [text/plain, */*, text/plain, */*, application/json, application/*+json, application/json, application/*+json]
2021-11-04 09:34:32.309:91 [http-nio2-2001-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor -Writing [""]
2021-11-04 09:34:32.316:1131 [http-nio2-2001-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet -Completed 200 OK

此时,给我的感觉就是:

代码语言:javascript
复制
spring:
  cloud:
    kubernetes:
      ribbon:
        #直接走k8s的LB
        mode: SERVICE #POD走ribbon的LB
      discovery:
        all-namespaces: true

此类配置是无法进行 Service 到应用服务的访问,只能访问到 Service。同时我们看到日志:

代码语言:javascript
复制
2021-11-04 09:34:32.281:88 [http-nio2-2001-exec-2] WARN  org.springframework.cloud.kubernetes.ribbon.KubernetesEndpointsServerList -Did not find any endpoints in ribbon in namespace [system-server] for name [diff-ns-service-service] and portName [null]

上面给到的是 mode 为 POD 时,走的 Ribbon 的负载均衡后,无法找到当前 pod 对应的 NS 下的 Servcie 为 diff-ns-service-service 的服务。

代码语言:javascript
复制
2021-11-04 09:20:27.109:89 [PollingServerListUpdater-1] WARN  org.springframework.cloud.kubernetes.ribbon.KubernetesServicesServerList -Did not find any service in ribbon in namespace [system-server] for name [diff-ns-service-service] and portName [null]

同样地,当 mode 为 SERVICE 时,依然无法找到当前 pod 的对应的 NS 的 Servcie 为 diff-ns-service-service 的服务。

同样会拿不到请求返回信息,这里说明:在不同NS下,Service为ClusterIP,不管如何负载均衡,都无法访问。

解决方案

一、通过 Springcloud k8s 社区来实现跨 NS 下的服务的相互访问的简单策略
二、走 K8s 的原生的负载均衡策略

从前面的分析可以看到:虽然 spring-cloud-k8s 帮我们发现了 Service,但在底层策略时,不同的NS还是做了隔离,只能通过 k8s 原生的方式来进行服务的发现:<servicename>.<namespace>.svc.cluster.local

PS:同时,我们需要注意的是,此时基于 k8s 负载均衡,我们不能再基于 Ribbon 或其他来进行负载均衡机制了,直接通过 Http 协议来请求 k8s 的 service,实现跨 NS 的 pod 之间的互通。

开源项目

  实践项目代码开源:https://gitee.com/damon_one/microservice-k8s

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 交个朋友之猿天地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 回顾
  • 案例
  • 解决方案
    • 一、通过 Springcloud k8s 社区来实现跨 NS 下的服务的相互访问的简单策略
      • 二、走 K8s 的原生的负载均衡策略
        • 开源项目
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档