Примечания по использованию Kong API Gateway

Микросервисы
Примечания по использованию Kong API Gateway

задний план

Kong — это шлюз с открытым исходным кодом, основанный на OpenResty, который настраивает информацию, связанную с API, на postgresql или cassandra. Расширьте функциональность платформы шлюза с помощью модулей расширения lua.

В этой статье записано конкретное использование автором шлюза Kong. Включая развертывание Kong, использование компонентов Kong и использование подключаемых модулей Kong. Для другого контента, связанного с Kong, вы можете проверить его на официальном сайте.

Обратите внимание на публичный аккаунт WeChat: военная мразь

Ответьте на ключевое слово «конг», чтобы получить тестовый код.

Развертывание Конга

Существует множество способов развертывания Kong, вот процесс развертывания на основе Docker.

развертывание postgresql

Docker развертывает Postgresql9.6

  • Создать сеть
docker network create kong-net
  • запустить базу данных
docker run -d --name kong-database \
--network=kong-net \
-p 5432:5432 \
-e "POSTGRES_USER=mykong" \
-e "POSTGRES_DB=mykong" \
-e "POSTGRES_PASSWORD=mykong" \
postgres:9.6

База данных отличается высокой доступностью, и ее можно использовать в качестве резервного копирования двух систем в горячем режиме. У автора нет реальных потребностей Ниже приведены некоторые из собранных данных, которые не были реализованы.

Потоковая репликация + решение с горячим резервированием на двух серверах

развернуть конг

База данных, необходимая для создания конга Имя пользователя, пароль, база данных и т. д., указанные при создании базы данных, необходимо использовать с параметрами, имеющими префикс KONG_.Описание других переменных среды

docker run --rm \
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_PG_USER=mykong" \
-e "KONG_PG_PASSWORD=mykong" \
-e "KONG_PG_DATABASE=mykong" \
kong:2.0.1 kong migrations bootstrap

Используйте последнюю версию конга 2.0.1

Узел 1: 172.17.23.14

docker run -d --name kong  \
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_PG_USER=mykong" \
-e "KONG_PG_PASSWORD=mykong" \
-e "KONG_PG_DATABASE=mykong" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
-e "KONG_ADMIN_LISTEN_SSL=0.0.0.0:8444" \
-e "KONG_PROXY_ACCESS_LOG=/usr/local/kong/logs/proxy_access.log"     \
-e "KONG_ADMIN_ACCESS_LOG=/usr/local/kong/logs/admin_access.log"     \
-e "KONG_PROXY_ERROR_LOG=/usr/local/kong/logs/proxy_error.log"     \
-e "KONG_ADMIN_ERROR_LOG=/usr/local/kong/logs/admin_error.log" \
-e "KONG_TRUSTED_IPS=0.0.0.0/0,::/0"     \ # 使用IP-restriction插件时,保证真实IP地址的传递
-e "KONG_REAL_IP_HEADER=X-Forwarded-For" \ # 使用IP-restriction插件时,保证真实IP地址的传递
-p 8000:8000 \
-p 8443:8443 \
-p 8001:8001 \
-p 8444:8444 \
kong:2.0.1

Узел 2: 172.17.23.17

docker run -d --name kong  \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=172.17.23.14" \
-e "KONG_PG_USER=mykong" \
-e "KONG_PG_PASSWORD=mykong" \
-e "KONG_PG_DATABASE=mykong" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
-e "KONG_ADMIN_LISTEN_SSL=0.0.0.0:8444" \
-e "KONG_PROXY_ACCESS_LOG=/usr/local/kong/logs/proxy_access.log"     \
-e "KONG_ADMIN_ACCESS_LOG=/usr/local/kong/logs/admin_access.log"     \
-e "KONG_PROXY_ERROR_LOG=/usr/local/kong/logs/proxy_error.log"     \
-e "KONG_ADMIN_ERROR_LOG=/usr/local/kong/logs/admin_error.log" \
-e "KONG_TRUSTED_IPS=0.0.0.0/0,::/0"     \ # 使用IP-restriction插件时,保证真实IP地址的传递
-e "KONG_REAL_IP_HEADER=X-Forwarded-For" \ # 使用IP-restriction插件时,保证真实IP地址的传递
-p 8000:8000 \
-p 8443:8443 \
-p 8001:8001 \
-p 8444:8444 \
kong:2.0.1

Настроить NGINX

После развертывания кластера Kong для балансировки нагрузки используется NGINX.Чтобы повысить доступность и предотвратить отказ службы в кластере, NGINX включает проверки работоспособности служб.

Сам NGINX имеет пассивную проверку, которая настроена следующим образом:

upstream kong_cluster{
    server 172.17.23.14:80  max_fails=1 fail_timeout=10s;
}

server {
    listen 80;
    server_name example.com; 
    location / {
      proxy_pass         http://kong_cluster;
    }
}

А вот активную проверку здоровья я использую здесь.

Активная проверка работоспособности требует установки стороннего плагина, здесь используется сторонний модуль, разработанный Taobao, модуль upstream_check и требуется перекомпиляция NGINX.

У меня уже есть nginx1.10 в самой моей ОС. Поэтому я должен перекомпилировать и скомпилировать в него трехсторонний модуль.использованная литература

# git clone http://github.com/yaoweibin/nginx_upstream_check_module
  • Перезагрузите NGINX1.16.1
# 下载NGINX  1.16.1
wget http://nginx.org/download/nginx-1.16.1.tar.gz
## 因为我的操作系统中本身已经安装了nginx,所以我要重新安装,查看原来安装的命令,并把扩展的check模块编译到nginx中
# 查看原安装的命令
nginx -V 
# ubuntu系统下,安装nginx依赖包
# zlib依赖包
sudo apt-get install zlib1g-dev
# openssl依赖包
sudo apt-get install openssl libssl-dev
# 安装pcre依赖包
sudo apt-get install libpcre3 libpcre3-dev
# 安装 libxml2/libxslt
sudo apt-get install libxslt1-dev
sudo apt-get install libxml2-dev
# 安装GD依赖包
sudo apt-get install libgd-dev
# 安装 GeoIP依赖包
sudo apt-get install libgeoip-dev
# 重新安装下载的nginx1.16.1
tar zxvf nginx-1.16.1.tar.gz
cd nginx-1.16.1
# 下载三方模块并打补丁  根据nginx版本选定补丁
patch -p1 < /root/install/nginx_upstream_check_module/check_1.16.1+.patch
# 补丁打完之后,安装nginx
./configure \
--with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' \
--with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' \
--prefix=/usr/share/nginx \
--conf-path=/etc/nginx/nginx.conf \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log \
--lock-path=/var/lock/nginx.lock \
--pid-path=/run/nginx.pid \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--http-scgi-temp-path=/var/lib/nginx/scgi \
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
--with-debug \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_addition_module \
--with-http_dav_module \
--with-http_geoip_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_image_filter_module \
--with-http_v2_module \
--with-http_sub_module \
--with-http_xslt_module \
--with-stream \
--with-stream_ssl_module \
--with-mail \
--with-mail_ssl_module \
--with-threads \
--with-pcre \
--add-module=/root/install/nginx_upstream_check_module
# 编译安装
make
# 如果是已经安装过了,只需要make
# 然后将生成nginx拷贝到原来的目录
cp objs/nginx /usr/sbin/nginx

Развернуть nginx

# 配置https
upstream kong_cluster{
    # 最简单的轮询方式
    server 172.17.23.17:8000;
    server 172.17.23.14:8000;
    
    # 配置三方模块主动检查健康状态,检查TCP,只要确保Kong服务没有断掉即可,实际的服务健康检查使用Kong插件检查
    # 其他配置参考 http://tengine.taobao.org/document_cn/http_upstream_check_cn.html
    check interval=3000 rise=2 fall=3 timeout=1000 type=tcp;
}

server {
    listen 443 ssl;
    server_name example.com; # 更换自己的域名信息

    ssl_certificate   cert/214533299050973.pem;  # 更换成自己的证书信息
    ssl_certificate_key  cert/214533299050973.key; # 更换成自己的证书信息
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    # https 因为安全原因,需要禁用 gzip
    # 但是在一些场景下,不需要禁用
    # gzip off;
    gzip on;
    # 设置允许压缩的页面最小字节数
    gzip_min_length 1000;
    gzip_buffers 4 16k;
    gzip_http_version 1.1;
    # 1~9,默认为1,数值越大,压缩率越高,CPU占用越多,时间越久
    gzip_comp_level 3;
    gzip_vary on;
    # 禁用对 IE 6 使用 gzip 压缩
    gzip_disable "MSIE [1-6]\.";
    gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/javascript "application/javascript; charset=utf-8" application/xml application/xml+rss application/json "application/json; charset=utf-8" font/ttf font/otf image/svg+xml;

    # 设置最大允许的POST数据量,如果提交的文件超过这个值,会出现413错误
    client_max_body_size 20m;
    keepalive_timeout 15;

    # 不显示 nginx 的版本号
    server_tokens off;

    # 设置请求头的长度大小
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;


    ## Individual nginx logs
    access_log  /var/log/nginx/kong_access.log;
    error_log   /var/log/nginx/kong_error.log;

    location ^~ /robots.txt {
        expires 30d;
        # add_header Content-Type text/plain;
        return 200 "User-Agent:  *\nDisallow:  /";
    }

    location ~ /(\w+) {
        # websocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 真实地址传递,IP限制插件使用
        proxy_pass http://kong_cluster;
        expires -1;
    }

    # 主页返回 404
    location = / {
        return 404;
    }
}

server {
   listen 80;
   server_name  example.com; # 更换自己的域名信息
   #告诉浏览器有效期内只准用 https 访问
   add_header Strict-Transport-Security max-age=15768000;
   #永久重定向到 https 站点
   return 301 https://$server_name$request_uri;
}

Перезапустите NGINX

systemctl restart nginx

Настройте API для Kong

Описание общих компонентов в Kong

  • Service
    Service是定义的服务,通过Kong转发后根据请求的协议,host,method,path匹配到实际的服务地址。
    
    Service可以与Route进行关联,一个Service可以有很多Route, Route匹配后就会转发到Service,
    处理过程中也会通过Plugin的处理,增加或者减少一些相应的Header或者其他信息
    
    Service可以是一个实际的地址,也可以是Kong内部提供的Upstream组件关联,由Upstream将请求转发到实际的服务。
  • Маршрут:
    Route就是路由,实际就是我们通过定义一些规则来匹配客户端的请求,每个路由都会关联一个Service,
    并且Service可以关联多个Route,当匹配到客户端的请求时,每个请求都会被代理到其配置的Service中
    
    Route作为客户端的入口,通过将Route和Service的松耦合,可以通过hosts path等规则的配置,最终让请求转发到不同的Service。
    
    例如,我们规定api.example.com 和 api.service.com的登录请求都能够代理到123.11.11.11:8000端口上,那我们可以通过hosts和path来路由
    
    首先,创建一个Service s1,其相应的host和port以及协议为http://123.11.11.11:8000
    然后,创建一个Route,关联的Service为s1,其hosts为[api.service.com, api.example.com],path为login
    最后,将域名api.example.com和api.service.com的请求转到到我们的Kong集群上,也就是我们上面一节中通过Nginx配置的请求地址
    那么,当我们请求api.example.com/login和api.service.com/login时,其通过Route匹配,然后转发到Service,最终将会请求我们自己的服务。
 
  • Upstream
    这是指您自己的API /服务位于Kong后面,客户端请求被转发到该服务器。
    
    相当于Kong提供了一个负载的功能,基于Nginx的虚拟主机的方式做的负载功能
    
    当我们部署集群时,一个单独的地址不足以满足我们的时候,我们可以使用Kong的upstream来进行设置
    
    首先在service中指定host的时候,可以指定为我们的upstream定义的hostname
    
    我们在创建upstream时指定名字,然后指定solts(暂时不确定具体作用),upstream可以进行健康检查等系列操作。这里先不开启(还没有研究)
    
    然后我们可以再创建target类型,将target绑定到upstream上,那么基本上我们部署集群时,也可以使用
  • Target
    target 就是在upstream进行负载均衡的终端,当我们部署集群时,需要将每个节点作为一个target,并设置负载的权重,当然也可以通过upstream的设置对target进行健康检查。
    当我们使用upstream时,整个路线是 Route >> Service >> Upstream >> Target 
  • Consumer
    Consumer 可以代表一个服务,可以代表一个用户,也可以代表消费者,可以根据我们自己的需求来定义
    
    可以将一个Consumer对应到实际应用中的一个用户,也可以只是作为一个Service的请求消费者
    
    Consumer具体可以在Plugin使用时再做深入了解
  • Plugin
    在请求被代理到上游API之前或之后执行Kong内的动作的插件。
    
    例如,请求之前的Authentication或者是请求限流插件的使用
    
    Plugin可以和Service绑定,也可以和Route以及Consumer进行关联,也可以是全局的插件。

    常用的限流插件,IP限制插件等。
    

Конг использует

В основном используют 4 компонента Service, Route, Upstream и Target

Target настраивает сервисный узел, но связывает его с восходящим потоком.

Восходящий поток может выполнять балансировку нагрузки и проверку работоспособности на цели.Установив имя, которое будет связано со службой, служба перенаправит его соответствующему восходящему потоку, когда он будет соответствовать запросу.

Сервис устанавливает различные сервисы в зависимости от бизнеса. Сервис и маршрут связаны для получения фактического запроса, сопоставления запроса по протоколу, хосту, порту и пути и перенаправления сопоставленного запроса в восходящий поток.

Маршрут является фактической точкой входа в Конг. В основном в соответствии с протоколами, хостами, методами, настройками путей, сопоставлением запроса и пересылкой запроса в соответствующую службу.

Создаем Service, Route, Upstream и Target по очереди в таком порядке

Настройка службы

Сервис также имеет некоторые другие параметры, которые можно настроить в соответствии с конкретными потребностями.Информация на официальном сайте

  • добавить команду
curl -i -X POST \
--url http://localhost:8001/services/ \
--data 'name=example-service' \
--data 'protocol=http' \
--data 'host=api.example.service'
    
# host属性在创建Upstream时使用
  • Добавить результат
{
    "host": "api.example.service",
    "created_at": 1582626079,
    "connect_timeout": 60000,
    "id": "71b28160-15fc-4215-a68f-d0b607e9cb9f",
    "protocol": "http",
    "name": "example-service",
    "read_timeout": 60000,
    "port": 80,
    "path": null,
    "updated_at": 1582626079,
    "retries": 5,
    "write_timeout": 60000,
    "tags": null,
    "client_certificate": null
}
  • Изменить команду
curl -i -X PATCH \
--url http://localhost:8001/services/71b28160-15fc-4215-a68f-d0b607e9cb9f/ \
--data 'name=test-kong' \
--data 'protocol=http'  \
--data 'host=test.kong.service'
  • Изменить результаты
{
    "host": "test.kong.service",
    "created_at": 1582626079,
    "connect_timeout": 60000,
    "id": "71b28160-15fc-4215-a68f-d0b607e9cb9f",
    "protocol": "http",
    "name": "test-kong",
    "read_timeout": 60000,
    "port": 80,
    "path": null,
    "updated_at": 1582626120,
    "retries": 5,
    "write_timeout": 60000,
    "tags": null,
    "client_certificate": null
}

Настроить маршрут

Маршрут также имеет некоторые другие параметры, которые можно настроить в соответствии с конкретными потребностями.Информация на официальном сайте

  • добавить команду

При фактическом использовании измените хосты на фактическое доменное имя.

curl -i -X POST \
--url http://localhost:8001/routes/ \
--data 'protocols[]=http' \
--data 'protocols[]=https' \
--data 'methods[]=GET' \
--data 'methods[]=POST' \
--data 'methods[]=DELETE' \
--data 'methods[]=PUT' \
--data 'hosts[]=api.example.com' \
--data 'paths[]=/v1/test_kong' \
--data 'strip_path=false' \ # 此属性代表是否清除原有的path,默认是清除,如果不需要清除需要再添加的时候指定为false
--data 'service.id=71b28160-15fc-4215-a68f-d0b607e9cb9f'
  • Добавить результат
{
    "id": "c156de0e-4b08-43a3-bc2d-3f0cf5d5d00a",
    "path_handling": "v0",
    "paths": ["\/v1\/test_kong"],
    "destinations": null,
    "headers": null,
    "protocols": ["http", "https"],
    "methods": ["GET", "POST", "DELETE", "PUT"],
    "snis": null,
    "service": {
        "id": "71b28160-15fc-4215-a68f-d0b607e9cb9f"
    },
    "name": null,
    "strip_path": false,
    "preserve_host": false,
    "regex_priority": 0,
    "updated_at": 1582627872,
    "sources": null,
    "hosts": ["api.example.com"],
    "https_redirect_status_code": 426,
    "tags": null,
    "created_at": 1582627872
}

Настроить восходящий поток

  • добавить команду

Здесь настраиваются только активные проверки

curl -i -X POST \
--url http://localhost:8001/upstreams/ \
--data 'name=test.kong.service'  \
--data 'algorithm=round-robin' \
--data 'healthchecks.active.type=http' \
--data 'healthchecks.active.http_path=/' \
--data 'healthchecks.active.timeout=2' \
--data 'healthchecks.active.healthy.successes=3' \
--data 'healthchecks.active.healthy.interval=10' \
--data 'healthchecks.active.unhealthy.interval=10' \
--data 'healthchecks.active.unhealthy.http_failures=3'
  • Добавить результат
{
    "created_at": 1582626649,
    "hash_on": "none",
    "id": "1d3638c6-d5a0-4bb5-907b-015c8daf7861",
    "algorithm": "round-robin",
    "name": "test.kong.service",
    "tags": null,
    "hash_fallback_header": null,
    "hash_fallback": "none",
    "hash_on_cookie": null,
    "host_header": null,
    "hash_on_cookie_path": "\/",
    "healthchecks": {
        "threshold": 0,
        "active": {
            "unhealthy": {
                "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505],
                "tcp_failures": 0,
                "timeouts": 0,
                "http_failures": 3,
                "interval": 10
            },
            "type": "http",
            "http_path": "\/",
            "timeout": 2,
            "healthy": {
                "successes": 3,
                "interval": 10,
                "http_statuses": [200, 302]
            },
            "https_sni": null,
            "https_verify_certificate": true,
            "concurrency": 10
        },
        "passive": {
            "unhealthy": {
                "http_failures": 0,
                "http_statuses": [429, 500, 503],
                "tcp_failures": 0,
                "timeouts": 0
            },
            "healthy": {
                "http_statuses": [200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308],
                "successes": 0
            },
            "type": "http"
        }
    },
    "hash_on_header": null,
    "slots": 10000
}

настроить цель

  • добавить команду
curl -i -X POST \
--url http://localhost:8001/upstreams/1d3638c6-d5a0-4bb5-907b-015c8daf7861/targets \
--data 'target=172.17.23.14:38001'
    
curl -i -X POST \
    --url http://localhost:8001/upstreams/1d3638c6-d5a0-4bb5-907b-015c8daf7861/targets \
    --data 'target=172.17.23.14:38002'

  • Добавить результат
{
    "created_at": 1582627463.954,
    "upstream": {
        "id": "1d3638c6-d5a0-4bb5-907b-015c8daf7861"
    },
    "id": "66c83e7d-f006-43da-990b-d493a966fc66",
    "target": "172.17.23.14:38001",
    "weight": 100
}

{
    "created_at": 1582627517.872,
    "upstream": {
        "id": "1d3638c6-d5a0-4bb5-907b-015c8daf7861"
    },
    "id": "d9940f44-30ad-437a-aaab-836dfaf27b93",
    "target": "172.17.23.14:38002",
    "weight": 100
}
Проверьте, возможна ли настройка конга
  • Проверить настроенные запросы
curl -X GET https://example.com/v1/test_kong

{"code": 200, "message": "test kong get success"}

curl -X POST https://example.com/v1/test_kong

{"code": 200, "message": "test post get success"}

curl -X DELETE https://example.com/v1/test_kong

{"code": 200, "message": "test kong delete success"}

curl -X PUT https://example.com/v1/test_kong

{"code": 200, "message": "test kong put success"}

  • Проверьте настроенные проверки работоспособности

Наблюдение за конфигурацией службы постоянно проверяется

[I 200225 19:03:10 web:2246] 200 GET / (172.17.23.14) 0.88ms
[I 200225 19:03:20 web:2246] 200 GET / (172.17.23.17) 1.34ms
[I 200225 19:03:20 web:2246] 200 GET / (172.17.23.14) 0.67ms
[I 200225 19:03:30 web:2246] 200 GET / (172.17.23.14) 0.88ms
[I 200225 19:03:30 web:2246] 200 GET / (172.17.23.17) 1.02ms
[I 200225 19:03:40 web:2246] 200 GET / (172.17.23.14) 0.88ms
[I 200225 19:03:40 web:2246] 200 GET / (172.17.23.17) 1.15ms

Kong плагин использует

Область применения плагина, от мала до велика, может быть Route, Service, Consumer, Global.

Вы можете использовать некоторые плагины в соответствии с вашими потребностями, такие как выполнение некоторых текущих операций ограничения, белый список IP-адресов и черный список IP-адресов и т. д.

Ниже приведены подключаемые модули, доступные для версии с открытым исходным кодом, официально предоставленной Kong.

Плагин ограничения скорости

Плагин ограничения тока, который ограничивает количество обращений в течение заданного времени, которое может быть в секундах, минутах, часах, днях и т. д. Плагин может быть установлен в Сервисе, Маршруте или глобально.Если Потребитель включен, время ограничения будет рассчитываться в соответствии с Потребителем, в противном случае в соответствии с IP-адресом клиента.

Добавить плагин для данной службы

curl -X POST http://localhost:8001/services/71b28160-15fc-4215-a68f-d0b607e9cb9f/plugins \
    --data "name=rate-limiting"  \
    --data "config.second=2" \
    --data "config.hour=10000" \
    --data "config.policy=local" \
    --data "config.limit_by=ip"

Добавить результат

{
    "created_at": 1582637075,
    "config": {
        "minute": null,
        "policy": "local",
        "month": null,
        "redis_timeout": 2000,
        "limit_by": "consumer",
        "hide_client_headers": false,
        "second": 5,
        "day": null,
        "redis_password": null,
        "year": null,
        "redis_database": 0,
        "hour": 10000,
        "redis_port": 6379,
        "redis_host": null,
        "fault_tolerant": true
    },
    "id": "9f8d08c9-4bdf-4912-b4dd-f96b32e38019",
    "service": {
        "id": "71b28160-15fc-4215-a68f-d0b607e9cb9f"
    },
    "enabled": true,
    "protocols": ["grpc", "grpcs", "http", "https"],
    "name": "rate-limiting",
    "consumer": null,
    "route": null,
    "tags": null
}

Тестовый эффект

def test_rate_limiting():
    url = "https://example.com/v1/test_kong"
    def _request(idx):
        print("request {} start by : {}".format(idx, datetime.datetime.now()))
        print("request {} result >>>".format(idx))
        resp = requests.get(url)
        print("request {} status_code {} ".format(idx, resp.status_code))
        print("request {} json {} ".format(idx, resp.json()))
        print("request {} result <<<".format(idx))
        print("request {} end by : {}".format(idx, datetime.datetime.now()))

    for i in range(0, 8):
        t = threading.Thread(target=_request, args=(i, ))
        t.start()

Результаты

request 3 status_code 200
request 3 json {'message': 'test kong get success', 'code': 200}
request 3 result <<<
request 3 end by : 2020-02-25 21:45:18.566325
request 6 status_code 429
request 6 json {'message': 'API rate limit exceeded'}
request 5 status_code 429
IP Restriction

Ограничение IP-адреса заключается в перехвате и защите некоторых запросов в соответствии с IP-адресом клиента путем установки белого и черного списка IP-адресов.Из исходного кода плагина вы можете видеть, что его принцип работы заключается в том, что переменная binary_remote_addr NGINX и установленный черный список и белый список Для ограничения сначала смотрите в черный список, а потом смотрите в белый список, а значит приоритет белого списка выше.Если задать IP в черном и белом списках одновременно, то к этому IP можно будет обращаться .

Плагин ограничения IP-адресов может действовать на сервисе, маршруте, потребителе или глобально. Теперь применим его к сервису

curl -X POST http://localhost:8001/services/71b28160-15fc-4215-a68f-d0b607e9cb9f/plugins \
--data "name=ip-restriction" \
--data "config.whitelist=172.17.23.14" \
--data "config.whitelist=172.17.23.17"

Добавить результат

{
    "created_at": 1582980903,
    "config": {
        "whitelist": ["172.17.23.14", "172.17.23.17"],
        "blacklist": null
    },
    "id": "c0364fe4-2d43-451e-9330-b45964cf1483",
    "service": {
        "id": "71b28160-15fc-4215-a68f-d0b607e9cb9f"
    },
    "enabled": true,
    "protocols": ["grpc", "grpcs", "http", "https"],
    "name": "ip-restriction",
    "consumer": null,
    "route": null,
    "tags": null
}

Результаты теста

{"message":"Your IP address is not allowed"}
Zipkin

Zipkin — это распределенная система отслеживания. Целью нашего пользовательского плагина является мониторинг времени, затрачиваемого нашим API, особенно для отслеживания соответствующего потребления производительности на основе этих результатов.

Итак, мы сначала развернем сервис Zipkin и установим его напрямую с помощью Docker.

Для получения конкретной информации о zipkin см.Официальный сайт

Развернуть Zipkin
docker run -d -p 9411:9411 openzipkin/zipkin
Добавить плагин

Плагин zipkin может действовать на сервисе, маршруте, потребителе или глобально. Теперь применим его к сервису

curl -X POST http://localhost:8001/services/71b28160-15fc-4215-a68f-d0b607e9cb9f/plugins \
    --data "name=zipkin"  \
    --data "config.http_endpoint=http://172.17.23.14:9411/api/v2/spans" \
    --data "config.sample_ratio=1" \   # 全部采样
    --data "config.include_credential=true"

Добавить результат

{
    "created_at": 1582812902,
    "config": {
        "sample_ratio": 1,
        "http_endpoint": "http:\/\/172.17.23.14:9411\/api\/v2\/spans",
        "include_credential": true,
        "default_service_name": null
    },
    "id": "c58654d8-2fd5-43b6-854f-0fd65a353f7e",
    "service": {
        "id": "71b28160-15fc-4215-a68f-d0b607e9cb9f"
    },
    "enabled": true,
    "protocols": ["grpc", "grpcs", "http", "https"],
    "name": "zipkin",
    "consumer": null,
    "route": null,
    "tags": null
}

http_endpoint: адрес службы zipkin

sample_ratio: частота сбора При значении 1 собираются все образцы При значении 0 все образцы не собираются При десятичном значении от 0 до 1 собираются все образцы Используйте алгоритм случайного сбора по заданным параметрам

Проверьте эффект от использования плагина: После доступа по настроенному адресу частота сбора, установленная ранее, равна 1, что означает все коллекции.После доступа авторизуйтесь по адресу zipkin http://172.17.23.14:9411/zipkin

在这里插入图片描述

HMAC Authentication

Аутентификация подписи HMAC и проверка подписи шлюза Kong могут быть выполнены только в обратном направлении после прохождения проверки подписи.Существует множество практических сценариев применения.Конкретный процесс выглядит следующим образом:

  1. Создайте потребителя
  2. Создайте имя пользователя и секрет, соответствующие подключаемому модулю HMAC для потребителя, а клиент использует его подпись.
  3. Включить плагин HMAC в сервисе или маршруте
  4. Когда клиент запрашивает, в соответствии с ранее возвращенным именем пользователя и секретной подписью, шлюз Kong выполняет проверку подписи после сопоставления.
  • создать потребителя

создать команду

curl -i http://localhost:8001/consumers/ -d "username=test_hmac&custom_id=test_hmac_id"

Создать результаты

{
    "custom_id": "test_hmac_id",
    "created_at": 1583071044,
    "id": "c9a4ad0e-174f-4a7f-81b0-ce9e3261c177",
    "tags": null,
    "username": "test_hmac"
}
  • Создать информацию о подключаемом модуле HMAC, соответствующую потребителю.
curl -X POST http://localhost:8001/consumers/test_hmac/hmac-auth \
--data "username=test_hmac" \
--data "secret=test_hmac_secret123"

имя пользователя: имя пользователя, используемое при проверке подписи HMAC. секрет: секретный ключ, используемый при проверке подписи HMAC.

Создать результаты

{
    "created_at": 1583071212,
    "consumer": {
        "id": "c9a4ad0e-174f-4a7f-81b0-ce9e3261c177"
    },
    "id": "834a8f69-c63d-4183-8a50-b52ab6a6187e",
    "tags": null,
    "secret": "test_hmac_secret123",
    "username": "test_hmac"
}
  • Включить плагин HMAC

Сначала удалите плагин ограничения IP-адресов в предыдущей службе. В противном случае мои локальные и серверные тесты сообщат, что он не может быть обработан.

В соответствии с идентификатором, сгенерированным ранее созданным плагином, удалите его напрямую.

curl -i -X DELETE http://localhost:8001/plugins/c0364fe4-2d43-451e-9330-b45964cf1483

Вы можете добавить плагин к указанному маршруту или сервису.На этот раз добавьте этот плагин к маршруту и ​​протестируйте его снова.

добавить команду

curl -i -X POST http://localhost:8001/routes/c156de0e-4b08-43a3-bc2d-3f0cf5d5d00a/plugins \
      -d "name=hmac-auth" \
      -d "config.enforce_headers=date" \
      -d "config.algorithms=hmac-sha1" \
      -d "config.algorithms=hmac-sha256" \
      -d "config.validate_request_body=true"
enforce_headers: Header中必须要有的参数,后续用于签名验证

algorithms:用户想要支持的HMAC摘要算法列表。允许的值是hmac-sha1,hmac-sha256,
hmac-sha384,和hmac-sha512客户端请求时,从中选择一个即可

validate_request_body:启用验证请求体,设置为true之后,客户端请求头中若是有Digest,
Kong则会使用HMAC算法验证请求体body。

Добавить результат

{
    "created_at": 1583072768,
    "config": {
        "clock_skew": 300,
        "validate_request_body": true,
        "enforce_headers": ["date"],
        "algorithms": ["hmac-sha1", "hmac-sha256"],
        "anonymous": null,
        "hide_credentials": false
    },
    "id": "39188d02-5425-4f76-8795-5e028f793476",
    "service": null,
    "enabled": true,
    "protocols": ["grpc", "grpcs", "http", "https"],
    "name": "hmac-auth",
    "consumer": null,
    "route": {
        "id": "c156de0e-4b08-43a3-bc2d-3f0cf5d5d00a"
    },
    "tags": null
}
  • тест запроса клиента
重要请求头信息
1. Authorization 或者 Proxy-Authorization
    这个头的组成是
    credentials 签名算法  使用HMAC插件,固定值就是hmac
    params 具体的参数,参数用","分割。
        algorithm: 签名算法 
        headers: 签名计算包括的key 
        signature: 生成的签名,生成规则 
2. Digest:启用validate_request_body,需要生成
3. Date:必须是GMT时间格式

Тестовая функция Python

def test_hmac_authentication():
    # 创建消费者对应HMAC插件时的用户名和秘钥
    hmac_username = "test_hmac"
    hmac_secret = "test_hmac_secret123"

    url = "https://example.com/v1/test_kong"

    # 请求头
    # 注意,请求头的时间格式必须是GMT时间格式
    request_headers = {
        "Authorization": "",
        "Digest": "",
        "Date": datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
    }

    # 请求体
    request_body = {
        "data": {"test": "hmac"}
    }

    # 生成Digest
    #  body="A small body"
    #  digest=SHA-256(body)
    #  base64_digest=base64(digest)
    #  Digest: SHA-256=<base64_digest>
    base64_digest = base64.b64encode(hashlib.sha256(json.dumps(request_body).encode('utf-8')).digest()).decode('utf-8')
    request_headers['Digest'] = "SHA-256={}".format(base64_digest)

    # 生成签名
    # signing_string = "date: Thu, 22 Jun 2017 17:15:21 GMT\nGET /requests HTTP/1.1"
    # digest = HMAC - SHA256( < signing_string >, "secret")
    # base64_digest = base64( < digest >)
    # 签名字符串构造
    # 如果参数不是request-line,则名字用小写,然后跟":"和一个空格" ",
    # 如果参数是request-line,则追加http请求行【GET /requests HTTP/1.1】
    # 中间用换行符"\n"将所有的参数连接起来。

    # 按照上述规则拼接字符串
    sign_string = "date: {}\ndigest: {}".format(request_headers['Date'], request_headers['Digest'])

    # 开始签名
    sign_digest = hmac.new(hmac_secret.encode("utf-8"), sign_string.encode('utf-8'), digestmod='sha256').digest()
    sign_base64_digest = base64.b64encode(sign_digest).decode('utf-8')

    # 构建Authorization参数 具体信息 https://docs.konghq.com/hub/kong-inc/hmac-auth/#signature-authentication-scheme
    authorization = 'hmac username="{}", algorithm="hmac-sha256", headers="date digest", signature="{}"'.format(
        hmac_username, sign_base64_digest)

    request_headers['Authorization'] = authorization
    resp = requests.post(url, headers=request_headers, json=request_body)
    print(request_headers)
    print(resp.status_code)
    print(resp.json())

Результаты теста

# 失败
401
{'message': 'HMAC signature cannot be verified'}

# 成功
200
{'code': 200, 'message': 'test kong post success'}