摘要

当业务量发生变化时,需要对上游服务进行扩缩容,或者因服务器硬件故障需要更换服务器。如果网关是通过配置来维护上游服务信息,在微服务架构模式下,其带来的维护成本可想而知。再者因不能及时更新这些信息,也会对业务带来一定的影响,还有人为误操作带来的影响也不可忽视,所以网关非常必要通过服务注册中心动态获取最新的服务实例信息。架构图如下所示:

  1. 服务启动时将自身的一些信息,比如服务名、IP、端口等信息上报到注册中心;各个服务与注册中心使用一定机制(例如心跳)通信,如果注册中心与服务长时间无法通信,就会注销该实例;当服务下线时,会删除注册中心的实例信息;
  2. 网关会准实时地从注册中心获取服务实例信息;
  3. 当用户通过网关请求服务时,网关从注册中心获取的实例列表中选择一个进行代理;

常见的注册中心:Eureka, Etcd, Consul, Nacos, Zookeeper 等

如何扩展注册中心?

基本步骤

APISIX 要扩展注册中心其实是件非常容易的事情,其基本步骤如下:

  1. 在 apisix/discovery/ 目录中添加注册中心客户端的实现;
  2. 实现用于初始化的 _M.init_worker() 函数以及用于获取服务实例节点列表的 _M.nodes(service_name) 函数;
  3. 将注册中心数据转换为 APISIX 格式的数据;

集成nacos

https://www.bookstack.cn/read/apisix-2.13-zh/275fbdd662ec08a9.md

discovery:
nacos:
host:
- "http://192.168.xx.xx:8848"
prefix: "/nacos/v1"
fetch_interval: 1
weight: 1
timeout:
connect: 2000
send: 2000
read: 5000

集成kubernetes

https://www.bookstack.cn/read/apisix-2.13-zh/a586728927b44a68.md

https://apisix.apache.org/zh/docs/apisix/next/discovery/kubernetes/

discovery:
kubernetes:
service:
schema: https
host: 192.168.60.146
port: "6443" #这里有一个比较坑的地方,port 必须是字符串,否则会导致 APISIX 启动报错:
client:
token: |-
ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNkltWTNNRVpCUTJSa2FHSnNkMVpsYjIwMWNFODVTMVpLUjE5TFFVTlhZVEo0ZWs5UlpFMXJiakZtV0RRaWZRLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZVzFsYzNCaFkyVWlPaUpoY0dsemFYZ2lMQ0pyZFdKbGNtNWxkR1Z6TG1sdkwzTmxjblpwWTJWaFkyTnZkVzUwTDNObFkzSmxkQzV1WVcxbElqb2laR1ZtWVhWc2RDMTBiMnRsYmkxa2F6WTJlaUlzSW10MVltVnlibVYwWlhNdWFXOHZjMlZ5ZG1salpXRmpZMjkxYm5RdmMyVnlkbWxqWlMxaFkyTnZkVzUwTG01aGJXVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpYSjJhV05sTFdGalkyOTFiblF1ZFdsa0lqb2lOemxpTnpnd00yWXRPR1poWXkwMFlXRTVMVGsxWWpjdFlXSmhORFEwWVdNNE4yRXhJaXdpYzNWaUlqb2ljM2x6ZEdWdE9uTmxjblpwWTJWaFkyTnZkVzUwT21Gd2FYTnBlRHBrWldaaGRXeDBJbjAuT3hWUTh2d2w0ZnZaLThZbTk1anlNcTNxTFBPTDhjaGZxdlZKQy10WXhLb3J5X2Fma3dzcU5WZ1RONWZuYlhmLW53MlNHWmpJdV9MbnhhbGxiQmhGT0l6UkI3QTY5QkpsYkpfTTNTNHNXcjdhN1EzaF9xTUZsc0pQQ2VhSG1NV3doZUR2dnZfOHFoV2dfN3MtRGk4OHp6QWpva1dOMlZIM3FBRXU5dWpmeVRlUTJXRzZYTVJyWWM1Y0pwN2F2WjBrNUo0V05yMHdTRHpYRkFsQUtUOHV4NUJWSlg0VEl6eXdjZDdTdWtkR3FrbmVtUnc3Q0lDWmR0bnZxZ1lXWnJpRFdwaVBSYklDLUFISFgtY3RrREtBV19TdFhvNFRLSTcxTlRYTzdVd0wtMWV4eXM0VnBETEZ6TkdhVDBUOWVRM1llTktfRUxRQy0zZWJGOEItRjFDRU5n
match:
- default
- ^my-[a-z]+$

获取serviceaccount账号的token的方法

apisix的k8s服务发现配置

1 为了让 APISIX 能查询和监听 Kubernetes 的 Endpoints 资源变动,我们需要创建一个 ServiceAccount:

kind: ServiceAccount
apiVersion: v1
metadata:
name: apisix-test
namespace: default

2 以及一个具有集群级查询和监听 Endpoints 资源权限的 ClusterRole:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: apisix-test
rules:
- apiGroups: [ "" ]
resources: [ endpoints ]
verbs: [ get,list,watch ]

3 再将这个 ServiceAccount 和 ClusterRole 关联起来:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: apisix-test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: apisix-test
subjects:
- kind: ServiceAccount
name: apisix-test
namespace: default

4 然后我们需要获取这个 ServiceAccount 的 token 值,如果 Kubernetes 是 v1.24 之前的版本,可以通过下面的方法获取 token 值:

$ kubectl get secrets | grep apisix-test
$ kubectl get secret apisix-test-token-89hcm -o jsonpath={.data.token} | base64 -d

5 Kubernetes 从 v1.24 版本开始,不能再通过 kubectl get secret 获取 token 了,需要手动建立secret来生成token:

# 集群执行这个yaml
apiVersion: v1
kind: Secret
metadata:
name: apisix-test-kubeapi
namespace: default
annotations:
kubernetes.io/service-account.name: "apisix-test"
type: kubernetes.io/service-account-token
data: # 然后执行
kubectl get secret apisix-test-kubeapi -n default -o jsonpath={".data.token"} | base64 -d

6 我们在 APISIX 的配置文件 config.yaml 中添加如下内容( 将上面生成的 token 填写到 token 字段 ):

discovery:
kubernetes:
service:
schema: https
host: 127.0.0.1
port: "6443"
client:
token: ...

上面服务发现,我选择kubernetes时,并没有成功,而我直接在节点节,使用<服务名>.<命令空间>,这种方式反而是支持的,配置如下

clusterrole相关操作

kubectl describe  serviceaccount  <sa-name>
kubectl describe clusterrole <clusterrole-name>
kubectl describe clusterrolebinding <clusterrolebinding-name>
kubectl get rolebindings,clusterrolebindings --all-namespaces | grep apisix-test

添加上游服务

说明: service_name 必须满足格式:[namespace]/[name]:[portName]

  • namespace: Endpoints 所在的命名空间
  • name: Endpoints 的资源名
  • portName: Endpoints 定义包含的 ports.name 值,如果 Endpoints 没有定义 ports.name,请依次使用 targetPort, port 代替。设置了 ports.name 的情况下,不能使用后两者。

    返回值: 以如下 Endpoints 为例:
apiVersion: v1
kind: Endpoints
metadata:
name: plat-dev
namespace: default
subsets:
- addresses:
- ip: "10.5.10.109"
- ip: "10.5.10.110"
ports:
- port: 3306
name: port

这里有一个比较坑的地方,port 必须是字符串,否则会导致 APISIX 启动报错 invalid discovery kubernetes configuration: object matches none of the required

问题与解决

  • k8s token错误
2024/05/17 03:01:07 [error] 54#54: *114 [lua] informer_factory.lua:295: list failed, kind: Endpoints, reason: Unauthorized, message : {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}

检查token值

  • k8s serviceaccount账号无权限
2024/05/17 03:01:07 [error] 54#54: *114 [lua] informer_factory.lua:295: list failed, kind: Endpoints, reason: Forbidden, message : {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Forbidden","code":403}

检查serviceaccount绑定的clusterrole是否有endpoint权限

  • 上游服务未找到
2024/05/17 03:05:22 [error] 52#52: *623 [lua] init.lua:400: nodes(): get unexpected upstream service_name: cms.default.svc.cluster.local, client: 192.168.60.136, server: _, request: "GET /k8s/products HTTP/1.1", host: "test-apisix.pkulaw.com"

2024/05/17 03:05:22 [error] 52#52: *623 [lua] init.lua:545: handle_upstream(): failed to set upstream: no valid upstream node: nil, client: 192.168.60.136, server: _, request: "GET /k8s/products HTTP/1.1", host: "test-apisix.pkulaw.com"

因为apisix中获取到的是k8s服务的endpoints地址【由service指向的pod的真实地址】,这个地址对k8s集群外是不公开的,如图

大功告成!

参考:https://www.aneasystone.com/archives/2023/03/apisix-service-discovery.html

apisix~集成服务发现注册中心的更多相关文章

  1. Spring Cloud Consul使用——服务注册与发现(注册中心)

    整理自该文章 一.Consul 服务端接下来我们开发 Consul 的服务端,创建一个 spring-cloud-consul-producer 项目 1.添加依赖包 <dependencies ...

  2. 【微服务】之二:从零开始,轻松搞定SpringCloud微服务系列--注册中心(一)

    微服务体系,有效解决项目庞大.互相依赖的问题.目前SpringCloud体系有强大的一整套针对微服务的解决方案.本文中,重点对微服务体系中的服务发现注册中心进行详细说明.本篇中的注册中心,采用Netf ...

  3. 为 Eureka 服务注册中心实现安全控制

    上一篇Eureka 实现微服务注册发现讲了用 Eureka 实现单体版的服务注册与发现.因为本篇是在上一篇的基础上的一点扩充,所以读此篇之前要保证看了上一篇. Eureka 如果不加安全控制,会存在下 ...

  4. Dubbo源代码实现三:注册中心Registry

    我们知道,对于服务治理框架来说,服务通信(RPC)和服务管理两部分必不可少,而服务管理又分为服务注册.服务发现和服务人工介入,我们来看看Dubbo框架的结构图(来源网络): 图中可以看出,服务提供者P ...

  5. 没使用Spring Cloud的版本管理导致Eureka服务无法注册到Eureka服务注册中心

    创建了一个Eureka Server的服务注册集群(两个Eureka服务),都能相互注册,写了一个Eureka客户端服务无法注册到服务发现注册中心 注册中心1: 注册中心2: 服务正常: pom依赖文 ...

  6. 【十次方微服务后台开发】Day02:加密与JWT鉴权、微服务注册中心、配置中心、熔断器、网关、消息总线、部署与持续集成、容器管理与监控Rancher、influxDB、grafana

    一.密码加密与微服务鉴权JWT 1.BCrypt密码加密 Spring Security 提供了BCryptPasswordEncoder类,实现Spring的PasswordEncoder接口使用B ...

  7. 手把手教你将Eureka升级Nacos注册中心

    由于原有SpringCloud体系版本比较老,最初的注册中心使用的Eureka后期官方无升级方案,配置中心无法在线管理配置,还有实时上下线的问题,因此需要将原有系统的Eureka服务升级Nacos注册 ...

  8. 借助 APISIX Ingress,实现与注册中心的无缝集成

    作者张晋涛,API7.ai 云原生技术专家,Apache APISIX PMC 成员,Apache APISIX Ingress Controller 项目维护者. 原文链接 云原生场景下是否需要服务 ...

  9. SpringCloud-服务注册与发现(注册中心)

    SpringCloud-服务注册与发现(注册中心) 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 注:作者使用IDEA + Gradle 注:需要有一定的java&& ...

  10. springcloud之服务注册与发现(zookeeper注册中心)-Finchley.SR2版

    新年第一篇博文,接着和大家分享springcloud相关内容:本次主要内容是使用cloud结合zookeeper作为注册中心来搭建服务调用,前面几篇文章有涉及到另外的eureka作为注册中心,有兴趣的 ...

随机推荐

  1. 深入理解 Java 多线程、Lambda 表达式及线程安全最佳实践

    Java 线程 线程使程序能够通过同时执行多个任务而更有效地运行. 线程可用于在不中断主程序的情况下在后台执行复杂的任务. 创建线程 有两种创建线程的方式. 扩展Thread类 可以通过扩展Threa ...

  2. Git分支教程:详解分支创建、合并、删除等操作

    Git是一种强大的分布式版本控制系统,它的分支功能使得团队协作和代码管理变得更加灵活和高效.分支可以让开发人员在不影响主线开发的情况下进行并行开发和实验性工作.本篇博客将详解Git分支的创建.合并.删 ...

  3. Git 07 IDEA基本使用

    IDEA 是目前最流行的 Java 集成开发环境,我们一般使用 Git 都是在 IDEA 上操作. 这里以 2021.3.2 版 IDEA 为例. 克隆项目 1.复制 Gitee 上的项目地址 2.点 ...

  4. 【课程汇总】Hello HarmonyOS系列课程,手把手带你零基础入门

    HarmonyOS是面向未来.面向全场景的新一代智能终端操作系统,为不同设备的智能化.互联与协同提供了统一的语言,给人们带来简洁.流畅.连续.安全可靠的全场景交互体验. 初识HarmonyOS的开发者 ...

  5. js es6系列——map函数

    正文 map,必要解释就是map不是地图的意思,而是映射的意思. 这里就简单的介绍了这个map了. array.map(callback,[ thisObject]); 看下这个案例后,我们发现了就发 ...

  6. allure常用

    overview:概述页面:categories:分类目录:suites:按套件和类分组的已执行测试的标准结构:graphs:图表:timeline:时间线:behaviors:可根据epic.fea ...

  7. dom4j 通用解析器,解析成List<Map<String,Object>>

    import java.io.InputStream; import java.util.Iterator; import java.util.LinkedHashMap; import java.u ...

  8. 力扣467(java)-环绕字符串中唯一的子字符串(中等)

    题目: 把字符串 s 看作是 "abcdefghijklmnopqrstuvwxyz" 的无限环绕字符串,所以 s 看起来是这样的: "...zabcdefghijklm ...

  9. HarmonyOS NEXT应用开发之MpChart图表实现案例

    介绍 MpChart是一个包含各种类型图表的图表库,主要用于业务数据汇总,例如销售数据走势图,股价走势图等场景中使用,方便开发者快速实现图表UI.本示例主要介绍如何使用三方库MpChart实现柱状图U ...

  10. 冬奥幕后故事:从低碳火炬到AI裁判,十四年后中国科技再上场

    ​北京冬奥会开幕后,一个段子在社交媒体上流传甚广:"夏奥开幕式和冬奥开幕式就差半年,这半年人类科技进步真大啊." ​ 文|张婧怡 封面来源|北京日报客户端 冬奥季终于到来. 2月4 ...