Z.S.K.'s Records

Kong学习(kong介绍)

Kong是一个Mashape开源的高性能高可用的API网关和API服务管理层,基于OpenResty,进行API管理,并提供了插件实现了API的AOP功能, 官方更是有这样的描述: Next-Generation API Platform for Multi-Cloud and Hybrid Organizations,可见kong的野心还是非常大的,也确实非常受欢迎,目前的Kong的版本为2.1.

这里简单提一下, 如果看过视频的都会发现,kong其实应该读康,而不是读空.

kong使用也有一段时间了,这里把相关的使用心得记录一下.

主要特性

kong做为API网关,总结起来有有以下特性:

  • 云原生: 与平台无关,Kong 可以从裸机运行到 Kubernetes
  • 高性能 : 背靠非阻塞通信的 nginx,性能自不用说
  • 插件机制 : 提供众多开箱即用的插件,且有易于扩展的自定义插件接口,用户可以使用 Lua 自行开发插件
  • 熔断:可以通过插件实现熔断,避免系统雪崩
  • 日志: 可以记录通过 Kong 的 HTTP,TCP,UDP 请求和响应。
  • 鉴权: 权限控制,IP 黑白名单,同样是 OpenResty 的特性
  • SSL: Setup a Specific SSL Certificate for an underlying service or API.
  • 监控: Kong 提供了实时监控插件
  • 认证: 如数支持 HMAC, JWT, Basic, OAuth 2.0 等常用协议
  • 限流:可以通过插件实现单个服务某些接口的限流,避免服务过载导致不可用
  • REST API: 通过 Rest API 进行配置管理,从繁琐的配置文件中解放
  • 健康检查:自动检查,被动检查;节点不可用同步到所有的kong节点需要 1 - 2 秒
  • 动态路由:Kong 的背后是 OpenResty+Lua,所以从 OpenResty 继承了动态路由的特性

当然,从上面这些概括可以看到:一方面,插件化的形式让kong可以很方便地提供了各种功能,对API层的管理有天然的粘合性

资源对象

当然对于一款API网关软件来说, 有一些重要的资源对象,先来熟悉一下名词:

  • Upstream

Upstream 对象表示虚拟主机名,可用于通过多个服务(目标)对传入请求进行负载均衡。例如:service.v1.xyz 为Service对象命名的上游host是service.v1.xyz对此服务的请求将代理到上游定义的目标。可以不存在upstream, 相当于没有负载均衡.

  • Target

目标IP地址/主机名,其端口表示后端服务的实例。每个上游都可以有多个target,并且可以动态添加Target。

由于上游维护Target的更改历史记录,因此无法删除或者修改Target。要禁用目标,请发布一个新的Targer weight=0,或者使用DELETE来完成相同的操作。

  • Service

顾名思义,服务实体是每个上游服务的抽象。服务的示例是数据转换微服务,计费API等。

服务的主要属性是它的URL(其中,Kong应该代理流量),其可以被设置为单个串或通过指定其protocol, host,port和path。

服务与路由相关联(服务可以有许多与之关联的路由)。路由是Kong的入口点,并定义匹配客户端请求的规则。一旦匹配路由,Kong就会将请求代理到其关联的服务。

  • Route

路由实体定义规则以匹配客户端的请求。每个Route与一个Service相关联,一个服务可能有多个与之关联的路由。与给定路由匹配的每个请求都将代理到其关联的Service上。

Service 和 Route 的组合(以及它们之间的关注点分离)提供了一种强大的路由机制,通过它可以在Kong中定义细粒度的入口点,从而使基础架构路由到不同上游服务。

  • Consumer

Consumer 对象表示服务的使用者或者用户。您可以依靠Kong作为主数据库存储,也可以将使用者列表与数据库映射,以保持Kong与现有的主数据存储之间的一致性。

  • Plugin

插件实体表示将在HTTP请求/响应生命周期期间执行的插件配置。它是如何为在Kong后面运行的服务添加功能的,例如身份验证或速率限制。

将插件配置添加到服务时,客户端向该服务发出的每个请求都将运行所述插件。如果某个特定消费者需要将插件调整为不同的值,您可以通过创建一个单独的插件实例,通过service和consumer字段指定服务和消费者 。

上述总结引用kong-introduction

说实话,在CloudNavi中的很多软件都或多或少的会引入一些名词,特别尴尬的是有些名词名字相同但是所表达的意思却完全不一样,比如上面的service,在Kubernetes也有service这个对象,但是表达的是两种不相同的事项,到后来这类东西学的越多,就越容器混淆.

详解可以参考官网admin-api

总结起来流量的走向,client –> router –> service –> [upstream] –> target, 可以使用下面的图来表示,非常清晰:

后面会重点围绕这些资源对象来测试kong的使用

API使用

kong做为一个基于openresty实现的api网关, 可以通过API直接管理对象,比如要生成以下的一段nginx配置

1
2
3
4
5
6
7
8
9
10
11
upstream hello {
server localhost:3000 weight=100;
server localhost:3001 weight=50;
}

server {
listen 80;
location /hello {
proxy_pass http://hello;
}
}

上面的nginx规则如果使用kong的api实现的话,对应以下接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 8001为kong admin的http监听端口
# 创建upstream,名字为hello
curl -X POST http://localhost:8001/upstreams --data "name=hello"

# 为upstream, 创建两个target,分别设置权重
curl -X POST http://localhost:8001/upstreams/hello/targets --data "target=localhost:3000" --data "weight=100"
curl -X POST http://localhost:8001/upstreams/hello/targets --data "target=localhost:3001" --data "weight=50"

# 创建service
curl -X POST http://localhost:8001/services --data "name=hello" --data "host=hello"
# 成功后会返回service.id
8695cc65-16c1-43b1-95a1-5d30d0a50409

# 为service创建路由
curl -X POST http://localhost:8001/routes --data "paths[]=/hello" --data "service.id=8695cc65-16c1-43b1-95a1-5d30d0a50409"

# 测试路由
curl http://localhost:8000/hello/hi

这里只是展示一下kong admin的使用,在实际使用中, 并不会直接通过api来生成对象,更多的是动态场景,要不然效率太差.

kong admin API还可以通过UI工具来直接管理, 比如最常用的konga

关于service

上面简单介绍了下kong的常用对象,做为api网关,一般都处于流量的最前端,那自然少不了路由的匹配, 因此Route这个对象还是比较好理解的。

Route匹配之后那要转到哪个服务进行响应呢? 这就是service, 但是这个service并不是真正相应请求的实体,以官方的说法,service是每个上游服务(upstream)的抽象,是个抽象的概念.

target才是真正对请求进行响应的, 在kubernetes就是部署在pods中的程序

而upstream则是个loadbalance,对多个target进行lb, 可以指定多种lb方式,健康检查机制等.

对于kong service与kubernetes service的区别, 以官方的一张图解释:

Let’s go through how Kubernetes resources are being mapped to Kong’s configuration:

  • An Ingress resource in Kubernetes defines a set of rules for proxying traffic. These rules corresponds to the concept of Route in Kong.

    kubernetes中的ingress定义了流量转发规则,这些规则对kong中的路由进行响应

  • A Service inside Kubernetes is a way to abstract an application that is running on a set of pods. This maps to two objects in Kong: Service and Upstream. The service object in Kong holds the information on the protocol to use to talk to the upstream service and various other protocol specific settings. The Upstream object defines load balancing and healthchecking behavior.

    Kubernetes内的Service是在一组Pod上运行的应用程序的方法的抽象。这映射到Kong中的两个对象:服务和上游。 Kong中的服务对象保存有关用于与上游服务进行通信的协议信息以及各种其他特定于协议的设置。上游对象定义负载平衡和运行状况检查行为

  • Pods associated with a Service in Kubernetes map as a Target belonging to the Upstream (the upstream corresponding to the Kubernetes Service) in Kong. Kong load balances across the Pods of your service. This means that all requests flowing through Kong are not directed via kube-proxy but directly to the pod.

    Kubernetes中与服务相关联的Pod映射为Kong中上游(与Kubernetes Service对应的上游)的目标。 Kong在您的服务Pod中平衡负载。这意味着所有流经Kong的请求都不会通过kube-proxy定向,而是直接定向到pod

这里有个重点是: kong中的请求到达最终的端点target并没有通过Kube-proxy,因此不存在需要遍历iptables规则,因此会对kubernetes原生的service效率会高

另一个疑问是: kong是否可以不需要service?从route匹配后直接到upstream?

kong中的service还是包含了一些信息的, 比如protocol, host, port and path等信息,如果没有这层信息, 请求从route直接到达upstream后是不知道到底是http还是https的,就相当需要把这段代码:

1
2
server {
listen 80; #

加到upstream中

1
2
3
4
upstream hello {
server localhost:3000 weight=100;
server localhost:3001 weight=50;
}

而kong又是基于nginx的,这样调整的话就与nginx的语法不相符了,因此service是有必要的.

kong还是比较强大的,比如在Kubernetes中做为ingress使用、如何集成插件化对流量进行管理等等,这里只是简单介绍了一下kong,有个整体的理解.

参考文章:

转载请注明原作者: 周淑科(https://izsk.me)

 wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?