Tian Jiale's Blog

使用 Kong 搭建网关

为什么要自己搭建网关?

首先明确网关的用途,我使用网关完全是统一管理自己的各种后台接口。在搭建自己的网关前我的后台接口十分散乱,有的部署在云函数的 HTTP 事件触发器上,有的部署在云函数的 Web 云函数上,有的在腾讯云的 API 网关上,有的在 nginx 代理上,这次自己搭建网关主要是整理提供的接口,同时清理不必要的配置。

如果说单单上面的原因还不至于需要自己再折腾一次,但腾讯这几天取消了云函数的免费额度,而且下个月开始只要使用就会扣除基础服务费 12.8 元,这能忍吗?既然服务可以使用云函数跑,那照样可以在 docker 中跑,所以将云函数中的服务全部迁移到服务器的 docker 上。PS:由于云函数最开始不支持容器部署,所以一些旧的服务都是直接和云厂商的服务绑定的,这些旧服务就暂时停止吧。

启动 Kong Gateway(docker)

kong 作为一个开源的网关服务还是很稳定的,以下是 Kong 的部署方法,注意修改其中的 PASSWORD

  1. 启动数据库,这个数据库为 Kong 提供服务。

    docker run -d --name kong-database \
      --network=kong-net \
      -p 5432:5432 \
      -e "POSTGRES_USER=kong" \
      -e "POSTGRES_DB=kong" \
      -e "POSTGRES_PASSWORD=kongpass" \
      postgres:9.6
    
  2. 初始化配置,这里配置数据库。

    docker run --rm --network=kong-net \
      -e "KONG_DATABASE=postgres" \
      -e "KONG_PG_HOST=kong-database" \
      -e "KONG_PG_PASSWORD=kongpass" \
      kong/kong-gateway:2.8.1.0-alpine kong migrations bootstrap
    
  3. 启动 Kong 网关,因为后续将使用 nginx 代理,SSL 将放到 nginx 中配置,而且使用的是社区版,所以只是用 80018000 端口即可。

    docker run -d --name kong-gateway \
      --network=kong-net \
      -e "KONG_DATABASE=postgres" \
      -e "KONG_PG_HOST=kong-database" \
      -e "KONG_PG_USER=kong" \
      -e "KONG_PG_PASSWORD=kongpass" \
      -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
      -p 8000:8000 \
      -p 8001:8001 \
      kong/kong-gateway:2.8.1.0-alpine
    
    • :8000:用于提供网关服务;
    • :8001:用于配置 Kong 监听的管理 API

现在已经将 Kong 配置完成了,下面启动一个 UI 界面帮助我们管理。

启动 konga

konga 是一个第三方的 GUI 管理页面。

我们同样使用 docker 配置。

docker run -p 1337:1337 \
  --network kong-net \
  --name konga \
  -e "NODE_ENV=production" \
  -e "TOKEN_SECRET=fdasfeag34agft" \
  pantsel/konga

启动之后,只需要开启 1337 端口即可通过 UI 界面配置我们的 kong 网关。

首次进入需要填写 kong 配置接口,因为以上的服务都加入到了 kong-net 网络中,所以只需要填写 http://kong-gateway:8001 即可。

配置 nginx

因为需要使用 nginx 配置 SSL 服务,所以这里修改 nginx 配置。

server {
    listen 80;
    server_name hostname;

    return 301 https://hostname;
}

server {
    listen 443 ssl;
    server_name hostname;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header    Host            $http_host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect      off;
    }

    ssl_certificate /config/nginx/cert/fullchain.cer;
    ssl_certificate_key /config/nginx/cert/cert.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # intermediate configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000" always;
}

添加服务

Kong 中,需要区分 servicesroutesservices 是对后端服务的访问设置,routes 是网关对外提供的服务。一个 service 可以有多个 route,而一个 route 只能有一个 service。

因为我的服务都在一台服务器上,所以为了安全起见我将服务都加入到 kong 同一个网络中,所以在配置 service 时只需要在 HOST 字段填入容器名称即可,同时还可以不必添加端口映射,提高安全性。

Todo:这里应该填写一些如何添加服务更详细的说明,但不想写了,就这样吧,如果有问题再说。