Kong docker部署及简单使用

Kong使用数据库模式

1. 创建kong-net网络

$ docker network create kong-net

2. 启动PostgreSQL容器

docker run -d --name kong-database \
--network=kong-net \
-p 5432:5432 \
-e "POSTGRES_USER=kong" \
-e "POSTGRES_DB=kong" \
-e "POSTGRES_PASSWORD=kong" \
postgres:11.7

3. 运行临时Kong容器迁移数据库

docker run --rm \
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_PG_PASSWORD=kong" \
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
kong:latest kong migrations bootstrap

4. 启动Kong容器

docker run -d --name kong \
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_PG_PASSWORD=kong" \
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
-e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
-e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
-e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
-e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
-p 80:8000 \
-p 443:8443 \
-p 8001:8001 \
-p 8444:8444 \
kong:latest

5. 验证

curl -s -i http://localhost:8001/ | jq

6. dashboard

# 迁移konga数据表到pgsql
docker run --name konga --rm \
--network=kong-net \
pantsel/konga -c prepare -a postgres -u postgresql://kong:kong@kong-database:5432/kong

# 启动konga
docker run -p 1337:1337 -d \
--network=kong-net \
-e "DB_ADAPTER=postgres" \
-e "DB_HOST=kong-database" \
-e "DB_USER=kong" \
-e "DB_PASSWORD=kong" \
-e "DB_DATABASE=kong" \
-e "KONGA_HOOK_TIMEOUT=120000" \
-e "DB_PG_SCHEMA=public" \
-e "NODE_ENV=production" \
--name konga \
pantsel/konga

Kong概率术语

upstream: 是对上游服务器的抽象;

target: 代表了一个物理服务,是ip+port的抽象;

service: 是抽象层面的服务,它也可以直接映射到一个物理服务(host 指向 ip + port),也可以指向一个upstream来做到负载均衡;

route: 是路由的抽象,它负责将实际的request映射到service

默认情况下,Kong监听的端口是:8000、8001、8443、8444

8444:通过此端口,管理者可以对HTTP请求进行监控

其中8000/8443分别是用来监听来自客户端的Http和Https请求,等价于Nginx默认的80和443端口,而8001端口是默认的管理端口,可以通过HTTP Restful API来动态管理Kong的配置

Kong的简单使用

一个典型的Nginx的配置

upstream www {
	server localhost:3001 weight=100;
}

server {
    server_name www.flask.com;
	listen 80;
	location / {
		proxy_pass http://www;
	}
}

如上简单的Nginx配置,可以转换为如下的Http请求

对应的Kong配置

  1. 配置upstream
curl -X POST http://10.0.0.10:8001/upstreams --data "name=www-ups"
  1. 配置target
curl -X POST http://10.0.0.10:8001/upstreams/www-ups/targets --data "target=10.0.0.10:3001" --data "weight=100"
  1. 配置service
curl -X POST http://10.0.0.10:8001/services --data "name=www-svc" --data "host=www-ups"
  1. 配置route
curl -X POST http://10.0.0.10:8001/routes \
--data "name=www-route" \
--data "hosts[]=www.flask.com" \
--data "paths[]=/" \
--data "service.id=741dc49d-0a96-4e1d-90c3-d1948cba1175"
  1. 访问www-route(uri)
curl -s -X GET http://www.flask.com
# --url 指定kong proxy服务器的ip:port, 默认为8000端口,这里映射到虚拟机的80端口
curl -s -X GET --url 'http://10.0.0.10:80' --header 'Host: www.flask.com'

这一切都是动态的,无需手动reload nginx.conf

为Kong新增路由信息时涉及到了upstream,target,service,route等概念,便是Kong最核心的四个对象.

Kong 插件简单使用

www-svc服务添加5次/分的限流

curl -X POST http://10.0.0.10:8001/services/www-svc/plugins \
--data "name=rate-limiting" \
--data "config.minute=5"

www-svc服务添加jwt插件

curl -X POST http://10.0.0.10:8001/services/www-svc/plugins \
--data "name=jwt"

代理缓存插件

curl -i -X POST http://10.0.0.10:8001/plugins \
--data name=proxy-cache \
--data config.content_type="application/json" \
--data config.cache_ttl=30 \
--data config.strategy=memory

验证代理缓存

# 注意响应的内容格式必须是json格式的才有效果
curl -i -X GET --url 'http://10.0.0.10:80' --header 'Host: demo1.flask.com'
X-Cache-Status: Miss
X-Cache-Status: Hit

设置秘钥认证插件

curl -X POST http://10.0.0.10:8001/routes/demo1/plugins \
--data name=key-auth
curl -i -X GET --url 'http://10.0.0.10:80' --header 'Host: demo1.flask.com'
# 返回{"message":"No API key found in request"}

创建消费者
curl -i -X POST -d "username=consumer&custom_id=consumer" http://10.0.0.10:8001/consumers/

创建消费者秘钥
curl -i -X POST http://10.0.0.10:8001/consumers/consumer/key-auth -d 'key=apikey'

验证秘钥
curl -i -X GET --url 'http://10.0.0.10:80' --header 'Host: demo1.flask.com' -H 'apikey:apikey'

禁用插件
curl -s  -X GET http://10.0.0.10:8001/routes/demo1/plugins | jq '.data[].id'
curl -X PATCH http://10.0.0.10:8001/routes/demo1/plugins/81554ece-ef5b-42c5-91c4-9e0bf9e29920 \
 --data "enabled=false"

同理,插件也可以安装在route之上

获取www-svc的所有路由名称和routeId,带上cookie和 authorization
curl -s -b "io=rCMjxICHRJ6zv2PTAAAF" -H 'authorization: Bearer eyJhbGciOiJIUzI1NiJ9.MQ.Lu-KcR4aCeuT9hi1K474zV3s4VaopLDCcf4nZvH6DQo' http://10.0.0.10:1337/kong/services/741dc49d-0a96-4e1d-90c3-d1948cba1175/routes |jq '.data[].name, .data[].id'

curl -X POST http://10.0.0.10:8001/routes/{routeId}/plugins \
--data "name=jwt"

curl -X POST http://10.0.0.10:8001/routes/c3ea95c1-7a56-4fad-847e-f77de918bf26/plugins \
--data "name=rate-limiting" \
--data "config.second=5"

Base Auth访问

curl -s -H 'Authorization: Basic dGVzdDp0ZXN0' --url 'http://10.0.0.10:80'  --header 'Host: hello.flask.com'

Kong不添加Upstream,直接使用services访问

#添加services
curl -i -X POST \
--url http://10.0.0.10:8001/services/ \
--data 'name=svc-demo1' \
--data 'url=http://httpbin.org/ip'

#添加routes
curl -i -X POST \
--url http://10.0.0.10:8001/services/svc-demo1/routes \
--data 'name=demo1' \
--data 'hosts[]=demo1.flask.com'

#访问测试
curl -i -X GET \
--url http://10.0.0.10:80/ \
--header 'Host: demo1.flask.com'

Kong OAuth2验证

1.1 使用Kong的管理API端口8001添加一个名称为book的服务

curl -s -X POST \
--url http://localhost:8001/services/ \
--data 'name=book' \
--data 'url=http://10.0.0.10:3002/v1/books' | jq

1.2 给book服务添加一个路由 /v1/books

# paths[]的值必须与book服务中的/v1/books一致,使book服务暴露出来以供用户访问,book服务没必要添加多个路由

curl -s -X POST \
--url http://localhost:8001/services/book/routes \
--data 'name=v1' \
--data 'hosts[]=book.com' \
--data 'paths[]=/v1/books' | jq

1.3 通过Kong在80端口暴露出来的服务地址获取所有的书籍

curl -s -X GET \
--url http://localhost:80/v1/books \
--header 'Host: book.com' | jq

# 获取book服务的描述信息
curl -s http://localhost:8001/services/book | jq
# 获取book服务使用的插件
curl -s http://localhost:8001/services/book/plugins | jq

1.4 为book服务启动OAuth2.0 Authentication插件,并激活简化模式授权

curl -s -X POST \
--url http://localhost:8001/services/book/plugins \
--data "name=oauth2" \
--data "config.scopes=email,phone" \
--data "config.mandatory_scope=true" \
--data "config.enable_implicit_grant=true" | jq

# 获取oauth2插件的provision_key,待会发请求需要
curl -s http://localhost:8001/services/book/plugins | jq '.data[].config.provision_key' | sed 's/"//g'

provision_key: SBUm1zCs5ropHZcCL5iUwoIz2bQW3ZWG

1.5 添加一个username为laowang消费者

# custom_id参数可以省略,此参数是一个自定义的唯一标识,它作用是把消费者老王映射到另外一个数据库上
curl -s -X POST \
--url http://localhost:8001/consumers/  \
--data "username=laowang" | jq

1.6 为消费者老王创建一个名为Book App的应用

# redirect_uri参数定义发送code和state的回调地址
参数{client_id}和{client_secret}可自定义,省略时由系统随机生成

curl -s -X POST \
--url http://localhost:8001/consumers/laowang/oauth2/ \
--data "name=Book App" \
--data "redirect_uris=http://getkong.org" | jq

1.7 根据client_id查询消费者的应用程序信息

# 获取 laowang 的client_id
curl -s http://localhost:8001/consumers/laowang | jq '.id'
client_id: dfdd8230-ce2e-4378-b42a-de73ae846ada

# 记录下消费者老王下的OAuth2的client_secret和client_id
curl -s -X GET \
--url http://localhost:8001/oauth2 \
--data "client_id=dfdd8230-ce2e-4378-b42a-de73ae846ada" | jq 

# laowang的oauth2信息
client_secret: HnBL9tbsARkS6wUu5cpFsSgfhA3tGJ85
client_id: 3mYuLCNoCrY6hnoDjb7Bc3LZcmGkl6iU

1.8 测试请求 /v1/books 接口

# 通过Kong的proxy端口暴露出来的服务地址读一条书籍记录,实际上是通过Kong在转发我的请求,不管是读1条记录还读所有书籍记录,我们都无权获得数据

curl -s -X GET \
--url http://localhost:80/v1/books \
--header 'Host: book.com' | jq

#响应
{
  "error_description": "The access token is missing",
  "error": "invalid_request"
}

1.9 生成访问令牌

# 所有步骤在浏览器中完成,简化模式下令牌对访问者是可见的,且客户端不需要认证。
客户端将发送由参数{client_id},{response_type},
{scope},{provision_key},{authenticated_userid},{state}构成的POST请求直接获得访问令牌
{state}客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值
{scope}表示申请的权限范围
{authenticated_userid}已授予权限的终端登录用户userid

curl -s -X POST \
--url https://localhost:443/v1/books/oauth2/authorize \
--header 'Host: book.com' \
--data "client_id=3mYuLCNoCrY6hnoDjb7Bc3LZcmGkl6iU" \ #laowang的oauth2的client_id
--data "response_type=token" \
--data "scope=email,phone" \
--data "provision_key=SBUm1zCs5ropHZcCL5iUwoIz2bQW3ZWG" \
--data "authenticated_userid=1206" \
--data "state=xyz" --insecure | jq

# 响应
{
  "redirect_uri": "http://getkong.org#access_token=a3z6QvuqdhMgz6G9RrAmLqcfCY85s8fK&expires_in=7200&state=xyz&token_type=bearer"
}

1.10 使用令牌访问book接口

curl -s -X GET \
--url https://localhost:443/v1/books \
--header "Authorization: Bearer a3z6QvuqdhMgz6G9RrAmLqcfCY85s8fK" \
--header 'Host: book.com' --insecure | jq
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章