微服務API網關-kong初探

一 概述

Kong是一個clould-native、快速的、可擴展的、分佈式的微服務抽象層(也稱爲API網關、API中間件或在某些情況下稱爲服務網格)框架。更確切地說,Kong是一個在Nginx中運行的Lua應用程序,並且可以通過lua-nginx模塊實現。Kong不是用這個模塊編譯Nginx,而是與OpenResty一起發佈,OpenResty已經包含了lua-nginx-module。OpenResty 不是 Nginx的分支,而是一組擴展其功能的模塊。

這爲可插拔架構奠定了基礎,可以在運行時啓用和執行Lua腳本(稱爲“插件”)。因此,我們認爲Kong是微服務架構的典範:它的核心是實現數據庫抽象,路由和插件管理。插件可以存在於單獨的代碼庫中,並且可以在幾行代碼中注入到請求生命週期的任何位置。Kong作爲開源項目在2015年推出,它的核心價值是高性能和可擴展性。

Kong被廣泛用於從初創企業到全球5000家公司以及政府組織的生產環境中。

如果構建Web、移動或IoT(物聯網)應用,可能最終需要使用通用的功能來實現這些應用。Kong充當微服務請求的網關(或側車),通過插件能夠提供負載平衡日誌記錄、身份驗證、速率限制、轉換等能力。

一個service可以創建多個routes,routes就相當於前端配置,可以隱藏業務真正的接口地址,service指定後端真實的轉發接口地址,在kong上進行認證/鑑權/日誌/分析/監控等控制。

二 特性

  • 雲原生(Cloud-Native):Kong可以在Kubernetes或物理環境上運行;
  • 動態負載平衡(Dynamic Load Balancing):跨多個上游服務的負載平衡業務。
  • 基於哈希的負載平衡(Hash-based Load Balancing):一致的散列/粘性會話的負載平衡。
  • 斷路器(Circuit-Breaker):智能跟蹤不健康的上游服務。
  • 健康檢查(Health Checks):主動和被動監控您的上游服務。
  • 服務發現(Service Discovery):解決如Consul等第三方DNS解析器的SRV記錄。
  • 無服務器(Serverless):從Kong中直接調用和保證AWS或OpenWhisk函數安全。
  • WebSockets:通過WebSockets與上游服務進行通信。
  • OAuth2.0:輕鬆的向API中添加OAuth2.0認證。
  • 日誌記錄(Logging):通過HTTP、TCP、UDP記錄請求或者相應的日誌,存儲在磁盤中。
  • 安全(Security):ACL,Bot檢測,IPs白名單/黑名單等。
  • 系統日誌(Syslog):記錄信息到系統日誌。
  • SSL:爲基礎服務或API設置特定的SSL證書。
  • 監視(Monitoring):能夠實時對關鍵負載和性能指標進行監控。
  • 轉發代理(Forward Proxy):使端口連接到中間透明的HTTP代理。
  • 認證(Authentications):支持HMAC,JWT和BASIC方式進行認證等等。
  • 速率限制(Rate-limiting):基於多個變量的阻塞和節流請求。
  • 轉換(Transformations):添加、刪除或操作HTTP請求和響應。
  • 緩存(Caching):在代理層進行緩存和服務響應。
  • 命令行工具(CLI):能夠通過命令行控制Kong的集羣。
  • REST API:可以通過REST API靈活的操作Kong。
  • GEO複製:在不同的區域,配置總是最新的。
  • 故障檢測與恢復(Failure Detection & Recovery):如果Cassandra節點失效,Kong並不會受影響。
  • 羣集(Clustering):所有的Kong節點會自動加入羣集,並更新各個節點上的配置。
  • 可擴展性(Scalability):通過添加節點,實現水平縮放。
  • 性能(Performance):通過縮放和使用Nigix,Kong能夠輕鬆處理負載。
  • 插件(Plugins):基於插件的可擴展體系結構,能夠方便的向Kong和API添加功能。

三 依賴組件

Kong部署在Nginx和Apache Cassandra或PostgreSQL等可靠技術之上,並提供了易於使用的RESTful API來操作和配置系統。下面是Kong的技術邏輯圖。基於這些技術,Kong提供相關的特性支持:

3.1 Nginx

  • 經過驗證的高性能基礎;
  • HTTP和反向代理服務器;
  • 處理低層級的操作。

3.2 OpenRestry

  • 支持Lua腳本;
  • 攔截請求/響應生命週期;
  • 基於Nginx進行擴展。

3.3 Clustering&Datastore

  • 支持Cassandra或PostgreSQL數據庫;
  • 內存級的緩存;
  • 支持水平擴展。

3.4 Plugins

  • 使用Lua創建插件;
  • 功能強大的定製能力;
  • 與第三方服務實現集成。

3.5 Restful Administration API

  • 通過Restful API管理Kong;
  • 支持CI/CD&DevOps;
  • 基於插件的可擴展。

四 架構圖

img

五 部署

5.1 物理服務器部署

5.1.1 配置yum源

sudo yum update -y
sudo yum install -y wget
wget https://bintray.com/kong/kong-rpm/rpm -O bintray-kong-kong-rpm.repo
export major_version=`grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release | cut -d "." -f1`
sed -i -e 's/baseurl.*/&\/centos\/'$major_version''/ bintray-kong-kong-rpm.repo
sudo mv bintray-kong-kong-rpm.repo /etc/yum.repos.d/
sudo yum update -y
sudo yum install -y kong

5.1.2 數據庫安裝

Kong支持PostgreSQL v9.5+和Cassandra 3.x.x作爲數據存儲。

按照文檔安裝PostgreSQL v11: https://www.postgresql.org/download/linux/redhat/

# 安裝PostgreSQL v11
yum install -y https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-centos11-11-2.noarch.rpm

yum install -y postgresql11 postgresql11-server

# 自啓
/usr/pgsql-11/bin/postgresql-11-setup initdb
systemctl enable postgresql-11
systemctl start postgresql-11
# 登錄psql
sudo su postgres
psql

# 創建數據庫,官方默認無密碼,此處我使用密碼
# CREATE USER kong; CREATE DATABASE kong OWNER kong;
CREATE USER kong with password 'kong';
CREATE DATABASE kong OWNER kong; 
grant all privileges on database kong to kong;

# 這裏可能會報連接錯誤
# psql: 致命錯誤:  對用戶"kong"的對等認證失敗
sudo find / -name pg_hba.conf
/var/lib/pgsql/11/data/pg_hba.conf

# 修改安全配置
vim /var/lib/pgsql/11/data/pg_hba.conf

# METHOD指定如何處理客戶端的認證。常用的有ident,md5,password,trust,reject
# ident是Linux下PostgreSQL默認的local認證方式,凡是能正確登錄服務器的操作系統用戶(注:不是數據庫用戶)就能使用本用戶映射的數據庫用戶不需密碼登錄數據庫。
# md5是常用的密碼認證方式,如果你不使用ident,最好使用md5。密碼是以md5形式傳送給數據庫,較安全,且不需建立同名的操作系統用戶。
# password是以明文密碼傳送給數據庫,建議不要在生產環境中使用。
# trust是隻要知道數據庫用戶名就不需要密碼或ident就能登錄,建議不要在生產環境中使用。
# reject是拒絕認證。

# "local" is for Unix domain socket connections only
local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5

# 將peer改爲md5()
# "local" is for Unix domain socket connections only
local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident

# 重啓psql
systemctl restart postgresql-11

# 登錄postgre
psql -U kong
# 輸入密碼

# 查看幫助
\h

# 退出
\q
# 這裏需要提前配置kong配置文件,默認/etc/kong/kong.conf.default
cp /etc/kong/kong.conf.default /etc/kong/kong.conf

# 修改裏面的數據庫配置,寫入用戶、密碼、數據庫、端口等信息
vim /etc/kong/kong.conf

[root@kong-server software]# egrep -v "^#|^$|^[[:space:]]+#" /etc/kong/kong.conf
database = postgres             # Determines which of PostgreSQL or Cassandra
pg_host = 127.0.0.1             # Host of the Postgres server.
pg_port = 5432                  # Port of the Postgres server.
pg_timeout = 5000               # Defines the timeout (in ms), for connecting,
pg_user = kong                  # Postgres user.
pg_password = kong                # Postgres user's password.
pg_database = kong              # The database name to connect to.  

# Kong migrations
kong migrations bootstrap [-c /path/to/kong.conf]

[root@kong-server software]# kong migrations bootstrap -c /etc/kong/kong.conf
Bootstrapping database...
migrating core on database 'kong'...
core migrated up to: 000_base (executed)
core migrated up to: 001_14_to_15 (executed)
core migrated up to: 002_15_to_1 (executed)
core migrated up to: 003_100_to_110 (executed)
core migrated up to: 004_110_to_120 (executed)
core migrated up to: 005_120_to_130 (executed)
migrating hmac-auth on database 'kong'...
hmac-auth migrated up to: 000_base_hmac_auth (executed)
hmac-auth migrated up to: 001_14_to_15 (executed)
migrating oauth2 on database 'kong'...
oauth2 migrated up to: 000_base_oauth2 (executed)
oauth2 migrated up to: 001_14_to_15 (executed)
oauth2 migrated up to: 002_15_to_10 (executed)
migrating jwt on database 'kong'...
jwt migrated up to: 000_base_jwt (executed)
jwt migrated up to: 001_14_to_15 (executed)
migrating basic-auth on database 'kong'...
basic-auth migrated up to: 000_base_basic_auth (executed)
basic-auth migrated up to: 001_14_to_15 (executed)
migrating key-auth on database 'kong'...
key-auth migrated up to: 000_base_key_auth (executed)
key-auth migrated up to: 001_14_to_15 (executed)
migrating rate-limiting on database 'kong'...
rate-limiting migrated up to: 000_base_rate_limiting (executed)
rate-limiting migrated up to: 001_14_to_15 (executed)
rate-limiting migrated up to: 002_15_to_10 (executed)
rate-limiting migrated up to: 003_10_to_112 (executed)
migrating acl on database 'kong'...
acl migrated up to: 000_base_acl (executed)
acl migrated up to: 001_14_to_15 (executed)
migrating response-ratelimiting on database 'kong'...
response-ratelimiting migrated up to: 000_base_response_rate_limiting (executed)
response-ratelimiting migrated up to: 001_14_to_15 (executed)
response-ratelimiting migrated up to: 002_15_to_10 (executed)
migrating session on database 'kong'...
session migrated up to: 000_base_session (executed)
27 migrations processed
27 executed
Database is up-to-date

5.1.2 啓動kong

在無數據庫模式配置Kong,一旦Kong啓動,訪問Admin API的/根端點已驗證它是否在沒有數據庫的情況下運行。


# Setting Up Kong in DB-less mode

要在無數據庫模式下使用Kong,有兩種方式:

修改配置文件kong.conf

vim /etc/kong/kong.conf

# database = postgres
database=off

# 或
export KONG_DATABASE=off

# 檢查配置,此命令將考慮您當前設置的環境變量,並在設置無效時報錯。此外,您還可以在調試模式下使用CLI,以便更深入地瞭解Kong的啓動屬性
kong start -c <kong.conf> --vv

# 啓動kong
kong start -c /etc/kong/kong.conf
kong start [-c /path/to/kong.conf]

[root@kong-server software]# kong start -c /etc/kong/kong.conf
Kong started
[root@kong-server software]# kong  health
nginx.......running

Kong is healthy at /usr/local/kong

[root@kong-server software]# netstat -lntup
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:8444          0.0.0.0:*               LISTEN      31050/nginx: master
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      31050/nginx: master
tcp        0      0 127.0.0.1:8001          0.0.0.0:*               LISTEN      31050/nginx: master
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1453/sshd
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      30638/postmaster
tcp        0      0 0.0.0.0:8443            0.0.0.0:*               LISTEN      31050/nginx: master
tcp6       0      0 ::1:5432                :::*                    LISTEN      30638/postmaster
udp        0      0 0.0.0.0:68              0.0.0.0:*                           780/dhclient
udp        0      0 172.16.16.16:123        0.0.0.0:*                           3006/ntpd
udp        0      0 127.0.0.1:123           0.0.0.0:*                           3006/ntpd
udp6       0      0 fe80::5054:ff:fe94::123 :::*                                3006/ntpd
udp6       0      0 ::1:123                 :::*                                3006/ntpd
[root@kong-server software]# curl http://localhost:8001

停止:
kong stop
重新加載:
kong reload

5.1.3 安裝konga

konga爲目前最先版本的kong的dashboard,由於kong-dashboard目前爲更新適應新版本的kong,推薦使用konga

konga帶來的一個最大的便利就是可以很好地通過UI觀察到現在kong的所有的配置,並且可以對於管理kong節點情況進行查看、監控和預警,konga主要特性如下:

  • 多用戶管理
  • 管理多個Kong節點
  • 電子郵件異常信息通知
  • 管理所有Kong Admin API
  • 使用快照備份,還原和遷移Kong節點
  • 使用運行狀況檢查監控節點和API狀態
  • 輕鬆的數據庫集成(MySQL,postgresSQL,MongoDB)

  • node安裝
yum -y install git
cd /data/software && wget https://npm.taobao.org/mirrors/node/v10.16.2/node-v10.16.2-linux-x64.tar.xz
tar -xf node-v10.16.2-linux-x64.tar.xz 
mv node-v10.16.2-linux-x64 node
# 修改爲root的權限
chown root.root node -R
cat > /etc/profile.d/node.sh << EOF
export PATH=\$PATH:/data/software/node/bin
EOF
source /etc/profile.d/node.sh

node -v

# 安裝插件
npm install -g glup
npm install -g bower
npm install -g sails
npm install -g node-gyp
npm install -g grunt-sass
npm install -g node-sass
npm run bower-deps
npm install sails-postgresql
  • 安裝konga
git clone https://github.com/pantsel/konga.git
cd konga
npm install konga

#使用postgresql

CREATE USER konga with password 'konga';
CREATE DATABASE konga OWNER konga; 
grant all privileges on database konga to konga;
  • 配置
cp config/local_example.js config/local.js

# 配置默認數據庫
vi ./local.js
models: {
    connection: process.env.DB_ADAPTER || 'localDiskDb',
},
# 改成
models: {
    connection: process.env.DB_ADAPTER || 'postgres', // 這裏可以用‘mysql’,‘mongo’,‘sqlserver’,‘postgres’
},
# 保存

# 修改數據庫默認配置
vi connections.js
  postgres: {
    adapter: 'sails-postgresql',
    url: process.env.DB_URI,
    host: process.env.DB_HOST || 'localhost',
    user:  process.env.DB_USER || 'konga',
    password: process.env.DB_PASSWORD || 'konga',
    port: process.env.DB_PORT || 5432,
    database: process.env.DB_DATABASE ||'konga',
    // schema: process.env.DB_PG_SCHEMA ||'public',
    poolSize: process.env.DB_POOLSIZE || 10,
    ssl: process.env.DB_SSL ? true : false // If set, assume it's true
  },
# 保存

# 啓動
cd ../
npm start

# pm2 管理
npm install -g pm2 
cd konga
pm2 start app.js --name konga

pm2 logs

0|konga    | info:    Sails              <|    .-..-.
0|konga    | info:    v0.12.14            |\
0|konga    | info:                       /|.\
0|konga    | info:                      / || \
0|konga    | info:                    ,'  |'  \
0|konga    | info:                 .-'.-==|/_--'
0|konga    | info:                 `--'-------'
0|konga    | info:    __---___--___---___--___---___--___
0|konga    | info:  ____---___--___---___--___---___--___-__
0|konga    | info:
0|konga    | info: Server lifted in `/data/software/konga`
0|konga    | info: To see your app, visit http://localhost:1338
0|konga    | info: To shut down Sails, press <CTRL> + C at any time.
0|konga    |
0|konga    |
  • 訪問

IP:1338,默認用戶:admin,密碼:adminadminadmin

配置鏈接kong, http://localhost:8001

圖片描述
圖片描述

5.2 docker中運行

5.2.1 Docker中部署

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
3.準備數據庫
docker run --rm --network=kong-net -e "KONG_DATABASE=postgres" -e "KONG_PG_HOST=kong-database" -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" -e "KONG_PG_PASSWORD=kong" kong 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 8000:8000 -p 8443:8443 -p 8001:8001 -p 8444:8444 kong
5.運行konga
注意DB_HOST爲自己的ip地址
docker run -d -p 1337:1337 --network kong-net -e "TOKEN_SECRET=mark666" -e "DB_ADAPTER=postgres" -e "DB_HOST=10.234.2.204" -e "DB_PORT=5432:5432" -e "DB_USER=kong" -e "DB_PASSWORD=kong" -e "DB_DATABASE=kong_database" --name konga pantsel/konga

5.2.2 docker-compose部署

  • 創建虛擬網絡
docker network create kong-net

後續的應用及數據庫都使用這個虛擬網絡。

  • 編寫docker-compose.yaml
version: "3.7"
services: 
  kong:
    # 鏡像版本,目前最新
    image: kong:1.1.2
    environment:
    # 數據持久化方式,使用postgres數據庫
     - "KONG_DATABASE=postgres"
    # 數據庫容器名稱,Kong連接數據時使用些名稱
     - "KONG_PG_HOST=kong-database"
    # 數據庫名稱
     - "KONG_CASSANDRA_CONTACT_POINTS=kong-database"
    # 日誌記錄目錄
     - "KONG_PROXY_ACCESS_LOG=/dev/stdout"
     - "KONG_ADMIN_ACCESS_LOG=/dev/stdout"
     - "KONG_PROXY_ERROR_LOG=/dev/stderr"
     - "KONG_ADMIN_ERROR_LOG=/dev/stderr"
    # 暴露的端口
     - "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl"
    ports:
     - 8000:8000
     - 8443:8443
     - 8001:8001
     - 8444:8444
    # 使用docker網絡
    networks:
     - kong-net

    # 依賴數據庫服務
    depends_on:
      - kong-database
# kong 管理界面
  konga:
    image: pantsel/konga
    environment:
     - "TOKEN_SECRET=51liveup.cn"
     - "NODE_ENV=production"
    ports:
     - 8080:1337
    networks:
     - kong-net

    depends_on:
      - kong-database
      - 
# 數據庫服務
  kong-database:
    image: postgres:9.6
    ports:
      - "5432:5432"
    environment:
    # 訪問數據庫的用戶
      - POSTGRES_USER=kong
      - POSTGRES_DB=kong
    networks:
      - kong-net
    volumes:
    # 同步時間
      - /etc/localtime:/etc/localtime:ro
    # 數據庫持久化目錄
      - /data/data/postgresql:/var/lib/postgresql/data

networks:
  kong-net:
    external: true

使用docker-compose up 命令啓動服務。會發現啓動時報數據庫錯誤,這是因爲kong 使用的postgres 數據還需要進行初始化才能使用。

  • 初始化數據庫
docker run --rm \
     --network=kong-net \
     -e "KONG_DATABASE=postgres" \
     -e "KONG_PG_HOST=kong-database" \
     -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
     kong:latest kong migrations bootstrap

一定要在創建數據庫容器之後,並且保持數據庫的Docker容器在運行狀態,再執行初始化數據庫,數據庫初始化成功後,再次使用docker-compose up -d 啓動服務就可以了。

  • 驗證
curl -i http://localhost:8001/
  • dashboard

另外,也可以安裝一個Kong的客戶端來驗證。在安裝有Docker引擎的操作系統上執行如下的命令:

1.0之後的kong-dashboard就已經不兼容了,建議使用konga

5.2.3 安裝kong-dashboard

  • Kong Dashboard 3.3.0 is only partially compatible with Kong 0.13. It does not support the new Service and Route objects introduced in Kong 0.13.
# 下載鏡像pgbi/kong-dashboard
[root@master data]# docker run --rm -p 8080:8080 pgbi/kong-dashboard start --kong-url http://10.234.2.204:30493 --basic-auth [email protected]    
Connecting to Kong on http://10.234.2.204:30493 ...
What's on http://10.234.2.204:30493 isn't Kong
[root@master data]# kubectl get svc |grep kong
kong-kong-admin                     NodePort    10.104.75.151    <none>        8444:30493/TCP                                          52m
kong-kong-proxy                     NodePort    10.99.141.23     <none>        80:30877/TCP,443:31201/TCP                              52m
kong-postgresql                     ClusterIP   10.109.249.105   <none>        5432/TCP                                                52m
kong-postgresql-headless            ClusterIP   None             <none>        5432/TCP                                                52m

通過docker安裝一個Kong-Dashboard,安裝完成後,通過瀏覽器訪問:

5.3 kubernetes部署

5.3.1 前置條件

5.3.2 helm char配置

下表列示了Kong chart的配置參數和默認值:

參數 說明 默認值
image.repository Kong image kong
image.tag Kong image version 0.14.1
image.pullPolicy Image pull policy IfNotPresent
image.pullSecrets Image pull secrets null
replicaCount Kong instance count 1
admin.useTLS Secure Admin traffic true
admin.servicePort TCP port on which the Kong admin service is exposed 8444
admin.containerPort TCP port on which Kong app listens for admin traffic 8444
admin.nodePort Node port when service type is NodePort
admin.type k8s service type, Options: NodePort, ClusterIP, LoadBalancer NodePort
admin.loadBalancerIP Will reuse an existing ingress static IP for the admin service null
admin.loadBalancerSourceRanges Limit admin access to CIDRs if set and service type is LoadBalancer []
admin.ingress.enabled Enable ingress resource creation (works with proxy.type=ClusterIP) false
admin.ingress.tls Name of secret resource, containing TLS secret
admin.ingress.hosts List of ingress hosts. []
admin.ingress.path Ingress path. /
admin.ingress.annotations Ingress annotations. See documentation for your ingress controller for details {}
proxy.useTLS Secure Proxy traffic true
proxy.servicePort TCP port on which the Kong Proxy Service is exposed 8443
proxy.containerPort TCP port on which the Kong app listens for Proxy traffic 8443
proxy.nodePort Node port when service type is NodePort
proxy.type k8s service type. Options: NodePort, ClusterIP, LoadBalancer NodePort
proxy.loadBalancerSourceRanges Limit proxy access to CIDRs if set and service type is LoadBalancer []
proxy.loadBalancerIP To reuse an existing ingress static IP for the admin service
proxy.ingress.enabled Enable ingress resource creation (works with proxy.type=ClusterIP) false
proxy.ingress.tls Name of secret resource, containing TLS secret
proxy.ingress.hosts List of ingress hosts. []
proxy.ingress.path Ingress path. /
proxy.ingress.annotations Ingress annotations. See documentation for your ingress controller for details {}
env Additional Kong configurations
runMigrations Run Kong migrations job true
readinessProbe Kong readiness probe
livenessProbe Kong liveness probe
affinity Node/pod affinities
nodeSelector Node labels for pod assignment {}
podAnnotations Annotations to add to each pod {}
resources Pod resource requests & limits {}
tolerations List of node taints to tolerate []

5.3.3 安裝chart

啓用數據庫需要先安裝pvc

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: data-kong-postgresql-0 
spec:
  storageClassName: ceph-rdb
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

# 部署pvc
[root@master data]# kubectl get pvc |grep api-gateway
data-api-gateway-postgresql-0           Bound    pvc-d280166c-c03d-11e9-a45a-facf8ddba000   8Gi        RWO            ceph-rdb       11s
helm fetch stable/kong --version 0.13.0

[root@master kong-deploy]# helm install -n api-gateway kong/
NAME:   api-gateway
LAST DEPLOYED: Fri Aug 16 23:53:37 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Job
NAME                              COMPLETIONS  DURATION  AGE
api-gateway-kong-init-migrations  0/1          0s        0s

==> v1/Pod(related)
NAME                                    READY  STATUS    RESTARTS  AGE
api-gateway-kong-79f697ff7c-bcr7m       0/1    Init:0/1  0         0s
api-gateway-kong-init-migrations-hxgd6  0/1    Init:0/1  0         0s
api-gateway-postgresql-0                0/1    Init:0/1  0         0s

==> v1/Secret
NAME                    TYPE    DATA  AGE
api-gateway-postgresql  Opaque  1     0s

==> v1/Service
NAME                             TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)                     AGE
api-gateway-kong-admin           NodePort   10.100.226.67   <none>       8444:31466/TCP              0s
api-gateway-kong-proxy           NodePort   10.109.4.127    <none>       80:32287/TCP,443:32742/TCP  0s
api-gateway-postgresql           ClusterIP  10.102.197.253  <none>       5432/TCP                    0s
api-gateway-postgresql-headless  ClusterIP  None            <none>       5432/TCP                    0s

==> v1beta2/Deployment
NAME              READY  UP-TO-DATE  AVAILABLE  AGE
api-gateway-kong  0/1    1           0          0s

==> v1beta2/StatefulSet
NAME                    READY  AGE
api-gateway-postgresql  0/1    0s

NOTES:
1. Kong Admin can be accessed inside the cluster using:
     DNS=api-gateway-kong-admin.default.svc.cluster.local
     PORT=8444

To connect from outside the K8s cluster:
     HOST=$(kubectl get nodes --namespace default -o jsonpath='{.items[0].status.addresses[0].address}')
     PORT=$(kubectl get svc --namespace default api-gateway-kong-admin -o jsonpath='{.spec.ports[0].nodePort}')

2. Kong Proxy can be accessed inside the cluster using:
     DNS=api-gateway-kong-proxy.default.svc.cluster.localPORT=443To connect from outside the K8s cluster:
     HOST=$(kubectl get nodes --namespace default -o jsonpath='{.items[0].status.addresses[0].address}')
     PORT=$(kubectl get svc --namespace default api-gateway-kong-proxy -o jsonpath='{.spec.ports[0].nodePort}')

5.3.4 驗證Kong(命令行)

通過執行下面的命令,進入Kong的容器:

[root@master kong-deploy]# kubectl exec -it api-gateway-kong-79f697ff7c-bcr7m /bin/sh

/ # netstat -lntup
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:8443            0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:8444            0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      -
/ # curl -k https://localhost:8444

並在kong中執行如下的命令:

curl -k http://localhost:8444

如果kong正常運行的話,應該會返回一些內容。

[root@master ~]# kubectl get all |grep api-gateway

pod/api-gateway-kong-8cf4ddcbf-qb87c                          1/1     Running     0          15h
pod/api-gateway-kong-init-migrations-fsfqb                    0/1     Completed   0          15h
pod/api-gateway-postgresql-0                                  1/1     Running     0          15h
service/api-gateway-kong-admin              NodePort    10.103.90.21     <none>        8444:30840/TCP                                          15h
service/api-gateway-kong-proxy              NodePort    10.96.32.21      <none>        80:32582/TCP,443:31941/TCP                              15h
service/api-gateway-postgresql              ClusterIP   10.109.28.2      <none>        5432/TCP                                                15h
service/api-gateway-postgresql-headless     ClusterIP   None             <none>        5432/TCP                                                15h

deployment.apps/api-gateway-kong                         1/1     1            1           15h
replicaset.apps/api-gateway-kong-8cf4ddcbf                          1         1         1       15h
statefulset.apps/api-gateway-postgresql           1/1     15h

job.batch/api-gateway-kong-init-migrations     1/1           51s        15h

通過瀏覽器查看

圖片描述

{
    "plugins": {
        "enabled_in_cluster": [],
        "available_on_server": {
            "correlation-id": true,
            "pre-function": true,
            "cors": true,
            "ldap-auth": true,
            "loggly": true,
            "hmac-auth": true,
            "zipkin": true,
            "request-size-limiting": true,
            "azure-functions": true,
            "request-transformer": true,
            "oauth2": true,
            "response-transformer": true,
            "ip-restriction": true,
            "statsd": true,
            "jwt": true,
            "proxy-cache": true,
            "basic-auth": true,
            "key-auth": true,
            "http-log": true,
            "datadog": true,
            "tcp-log": true,
            "post-function": true,
            "prometheus": true,
            "acl": true,
            "kubernetes-sidecar-injector": true,
            "syslog": true,
            "file-log": true,
            "udp-log": true,
            "response-ratelimiting": true,
            "aws-lambda": true,
            "bot-detection": true,
            "rate-limiting": true,
            "request-termination": true
        }
    },
    "tagline": "Welcome to kong",
    "configuration": {
        "error_default_type": "text/plain",
        "admin_listen": [
            "0.0.0.0:8444 ssl"
        ],
        "proxy_access_log": "/dev/stdout",
        "trusted_ips": {},
        "prefix": "/usr/local/kong",
        "loaded_plugins": {
            "correlation-id": true,
            "pre-function": true,
            "cors": true,
            "rate-limiting": true,
            "loggly": true,
            "hmac-auth": true,
            "zipkin": true,
            "bot-detection": true,
            "azure-functions": true,
            "request-transformer": true,
            "oauth2": true,
            "response-transformer": true,
            "syslog": true,
            "statsd": true,
            "jwt": true,
            "proxy-cache": true,
            "basic-auth": true,
            "key-auth": true,
            "http-log": true,
            "datadog": true,
            "tcp-log": true,
            "post-function": true,
            "ldap-auth": true,
            "acl": true,
            "kubernetes-sidecar-injector": true,
            "ip-restriction": true,
            "file-log": true,
            "udp-log": true,
            "response-ratelimiting": true,
            "aws-lambda": true,
            "prometheus": true,
            "request-size-limiting": true,
            "request-termination": true
        },
        "cassandra_username": "kong",
        "ssl_cert_key": "/usr/local/kong/ssl/kong-default.key",
        "admin_ssl_cert_key": "/usr/local/kong/ssl/admin-kong-default.key",
        "dns_resolver": {},
        "pg_user": "kong",
        "pg_password": "******",
        "cassandra_data_centers": [
            "dc1:2",
            "dc2:3"
        ],
        "nginx_admin_directives": {},
        "nginx_http_directives": [
            {
                "value": "prometheus_metrics 5m",
                "name": "lua_shared_dict"
            }
        ],
        "pg_host": "api-gateway-postgresql",
        "nginx_acc_logs": "/usr/local/kong/logs/access.log",
        "pg_semaphore_timeout": 60000,
        "proxy_listen": [
            "0.0.0.0:8000",
            "0.0.0.0:8443 ssl"
        ],
        "client_ssl_cert_default": "/usr/local/kong/ssl/kong-default.crt",
        "cassandra_ssl": false,
        "db_update_frequency": 5,
        "db_update_propagation": 0,
        "stream_listen": [
            "off"
        ],
        "nginx_err_logs": "/usr/local/kong/logs/error.log",
        "cassandra_port": 9042,
        "dns_order": [
            "LAST",
            "SRV",
            "A",
            "CNAME"
        ],
        "dns_error_ttl": 1,
        "headers": [
            "server_tokens",
            "latency_tokens"
        ],
        "cassandra_lb_policy": "RequestRoundRobin",
        "nginx_optimizations": true,
        "pg_timeout": 5000,
        "database": "postgres",
        "pg_database": "kong",
        "nginx_worker_processes": "auto",
        "lua_package_cpath": "",
        "admin_ssl_cert": "/usr/local/kong/ssl/admin-kong-default.crt",
        "admin_acc_logs": "/usr/local/kong/logs/admin_access.log",
        "real_ip_header": "X-Real-IP",
        "ssl_cert_key_default": "/usr/local/kong/ssl/kong-default.key",
        "lua_package_path": "./?.lua;./?/init.lua;",
        "nginx_pid": "/usr/local/kong/pids/nginx.pid",
        "upstream_keepalive": 60,
        "nginx_conf": "/usr/local/kong/nginx.conf",
        "router_consistency": "strict",
        "dns_no_sync": false,
        "origins": {},
        "admin_access_log": "/dev/stdout",
        "admin_ssl_cert_default": "/usr/local/kong/ssl/admin-kong-default.crt",
        "client_ssl": false,
        "proxy_listeners": [
            {
                "transparent": false,
                "ssl": false,
                "ip": "0.0.0.0",
                "proxy_protocol": false,
                "port": 8000,
                "http2": false,
                "listener": "0.0.0.0:8000"
            },
            {
                "transparent": false,
                "ssl": true,
                "ip": "0.0.0.0",
                "proxy_protocol": false,
                "port": 8443,
                "http2": false,
                "listener": "0.0.0.0:8443 ssl"
            }
        ],
        "proxy_ssl_enabled": true,
        "stream_listeners": {},
        "db_cache_warmup_entities": [
            "services",
            "plugins"
        ],
        "enabled_headers": {
            "latency_tokens": true,
            "X-Kong-Proxy-Latency": true,
            "Via": true,
            "server_tokens": true,
            "Server": true,
            "X-Kong-Upstream-Latency": true,
            "X-Kong-Upstream-Status": false
        },
        "plugins": [
            "bundled"
        ],
        "ssl_ciphers": "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256",
        "db_resurrect_ttl": 30,
        "nginx_proxy_directives": {},
        "cassandra_consistency": "ONE",
        "client_max_body_size": "0",
        "admin_error_log": "/dev/stderr",
        "pg_ssl_verify": false,
        "dns_not_found_ttl": 30,
        "pg_ssl": false,
        "lua_ssl_verify_depth": 1,
        "ssl_cipher_suite": "modern",
        "cassandra_repl_strategy": "SimpleStrategy",
        "proxy_error_log": "/dev/stderr",
        "kong_env": "/usr/local/kong/.kong_env",
        "db_cache_ttl": 0,
        "pg_max_concurrent_queries": 0,
        "nginx_kong_conf": "/usr/local/kong/nginx-kong.conf",
        "cassandra_schema_consensus_timeout": 10000,
        "dns_hostsfile": "/etc/hosts",
        "admin_listeners": [
            {
                "transparent": false,
                "ssl": true,
                "ip": "0.0.0.0",
                "proxy_protocol": false,
                "port": 8444,
                "http2": false,
                "listener": "0.0.0.0:8444 ssl"
            }
        ],
        "dns_stale_ttl": 4,
        "ssl_cert": "/usr/local/kong/ssl/kong-default.crt",
        "cassandra_timeout": 5000,
        "admin_ssl_cert_key_default": "/usr/local/kong/ssl/admin-kong-default.key",
        "cassandra_ssl_verify": false,
        "mem_cache_size": "128m",
        "log_level": "notice",
        "real_ip_recursive": "off",
        "cassandra_repl_factor": 1,
        "client_ssl_cert_key_default": "/usr/local/kong/ssl/kong-default.key",
        "nginx_daemon": "off",
        "anonymous_reports": true,
        "nginx_sproxy_directives": {},
        "nginx_stream_directives": {},
        "pg_port": 5432,
        "nginx_kong_stream_conf": "/usr/local/kong/nginx-kong-stream.conf",
        "client_body_buffer_size": "8k",
        "ssl_preread_enabled": true,
        "ssl_cert_csr_default": "/usr/local/kong/ssl/kong-default.csr",
        "cassandra_contact_points": [
            "127.0.0.1"
        ],
        "cassandra_keyspace": "kong",
        "ssl_cert_default": "/usr/local/kong/ssl/kong-default.crt",
        "lua_socket_pool_size": 30,
        "admin_ssl_enabled": true
    },
    "version": "1.2.2",
    "node_id": "cc0f6fa7-3c2c-44f8-a523-8f9e53d7e41e",
    "lua_version": "LuaJIT 2.1.0-beta3",
    "prng_seeds": {
        "pid: 36": 195221171165,
        "pid: 35": 148625059221,
        "pid: 39": 191125165965,
        "pid: 1": 173981549072,
        "pid: 34": 137193103112,
        "pid: 38": 175366916141,
        "pid: 37": 192138146579,
        "pid: 32": 214162161921,
        "pid: 33": 152108231211
    },
    "timers": {
        "pending": 6,
        "running": 0
    },
    "hostname": "api-gateway-kong-79f697ff7c-bcr7m"
}
  • curl 創建一個service
curl -i -k -X POST \
--url https://10.234.2.204:30840/services/ \
--data 'name=baidu-service' \
--data 'url=https://www.baidu.com/'
  • 創建一個routes
curl -ik -X POST \
--url https://10.234.2.204:30840/services/baidu-service/routes \
--data 'hosts[]=baidu.com' \
--data 'paths[]=/api/baidu'
  • curl測試
#訪問proxy
curl -k http://10.234.2.204:32582/api/baidu --header 'Host: baidu.com'

圖片描述

六 使用

6.1 CLI使用

提供的CLI(命令行界面Command Line Interface)允許啓動,停止和管理Kong實例。CLI可以管理本地節點(如在當前計算機上)。

  • 通用參數
--help:打印此命令的幫助信息
--v:啓用詳細模式
--vv:啓用調試模式(很多輸出)
  • 命令
kong check <conf>       #檢查給定Kong配置文件的有效性。
kong health [OPTIONS]   #驗證Kong 的服務組件是否正常運行
kong migrations COMMAND [OPTIONS]
可用的命令如下:
  bootstrap                         引導數據庫並運行全部遷移(初始化)。
  up                                運行新遷移。
  finish                            完成正在等待中的遷移命令,在執行`up`後。
  list                              列出已執行的遷移。
  reset                             重置數據庫。
Options(可選):
 -y,--yes                           假設提示“yes”,並運行非交互模式
 -q,--quiet                         忽略所有輸出
 -f,--force                         依舊執行遷移,即使數據庫報告已經執行過了。
 --db-timeout     (default 60)      超時時間,以秒爲單位,所有數據庫操作通用(包括Cassandra的schema consensus)。
 --lock-timeout   (default 60)      超時時間,以秒爲單位, 節點等待領導節點遷移完成。
 -c,--conf        (optional string) 配置文件。
kong quit   [OPTIONS]   #優雅地退出一個正在運行的Kong節點(Nginx和其他節點)在給定的前綴目錄中配置的服務。
kong reload [OPTIONS]   #重新加載Kong節點(並啓動其他已配置的服務)在給定的前綴目錄中。
kong restart [OPTIONS]  #重新啓動Kong節點(以及其他配置的服務,如Serf)在給定的前綴目錄中。

更詳細的CLI參數可參考:CLI Reference

6.1 配置一個實例

配置一個訪問 www.baidu.com/ 的接口API,實際使用時會對接後端的業務數據接口地址。

路由定義了匹配客戶端請求的規則,每一個路由關聯一個 Service,每一個 Service 有可能被多個路由關聯,每一個匹配到指定的路由請求將被代理到它關聯的 Service 上,參見Kong Admin Api Route Object

kong admin接口

GET /routers/                                #列出所有路由
GET /services/                               #列出所有服務
GET /consumers/                              #列出所有用戶
GET /services/{service name or id}/routes    #列出服務關聯的路由
GET /plugins/                                #列出所有的插件配置
GET /plugins/enabled                         #列出所有可以使用的插件
GET /plugins/schema/{plugin name}            #獲得插件的配置模版
GET /certificates/                           #列出所有的證書
GET /snis/                                   #列出所有域名與證書的對應
GET /upstreams/                              #列出所有的upstream
GET /upstreams/{name or id}/health/          #查看upstream的健康狀態
GET /upstreams/{name or id}/targets/all      #列出upstream中所有的target

6.1.1 創建服務

服務是上游服務的抽象,可以是一個應用,或者具體某個接口。

  • 命令行方式創建服務:
curl -i -X POST \
--url http://134.175.74.48:8001/services/ \
--data 'name=baidu-service' \
--data 'url=https://www.baidu.com/'
  • postman創建

圖片描述
圖片描述
圖片描述

6.1.2 創建路由

在剛纔創建的baidu-service的服務上創建路由

  • Curl 創建
curl -i -X POST \
--url http://134.175.74.48:8001/services/baidu-service/routes \
--data 'hosts[]=baidu.com' \
--data 'paths[]=/api/baidu'
  • postman創建

圖片描述
圖片描述

6.1.3 測試

  • curl測試

這時候訪問kong的proxy地址時,如果host爲baidu.com,請求被轉發到http://baidu.com

curl  http://134.175.74.48:8000/api/baidu --header 'Host: baidu.com'
  • postman測試

圖片描述

測試post

圖片描述

利用konga web界面操作更爲方便。

6.2 插件使用

插件是用來擴展API的,例如爲API添加認證、設置ACL、限制速率等、集成oauth、ldap等。

6.2.1 認證-JWT

上面的配置,只要知道Router的地址,就可以訪問獲取數據,我們要把API加入身份認證。如果API面對不是具體用戶,而是其他的系統,可以使用JWT來進行系統間身份認證,使用Kong JWT插件就可能完成這功能。JWT 插件要在對應的Router上進行啓用。

curl -X POST http://134.175.74.48:8001/routes/8e6a1982-5dee-492c-8fe0-c046ebae573c/plugins \
    --data "name=jwt"

fee36521-e549-410f-8986-9fbba02219c1 是創建的service的ID。

這時再通過Postman 訪問上面的接口就會提示:

圖片描述

{
    "message": "Unauthorized"
}
  • 創建用戶
curl -i -X POST \
--url http://134.175.74.48:8001/consumers/  \
--data "username=kongauser1"
  • 用戶生成JWT憑證
curl -i -X POST \
--url http://134.175.74.48:8001/consumers/kongauser1/jwt \
--header "Content-Type: application/x-www-form-urlencoded"

返回憑證信息,也可以通過 get 方法查詢憑證信息

{
    "rsa_public_key": null,
    "created_at": 1560723665,
    "consumer": {
        "id": "8bb94f49-22a6-4d77-9a64-21f13adc0342"
    },
    "id": "a110d234-6dc1-4443-9da2-21acddc66e09",
    "algorithm": "HS256",
    "secret": "lCe8Lbb7F0KtLccaBcBnOvYg76V7wmQx",
    "key": "7yQoUdF0aFUC9N593uLQLbqL7RSPj2qM"
}

圖片描述

使用key和secret在 jwt.io/ 可以生成jwt 憑證信息.

圖片描述
圖片描述

再通過postman 訪問,就可以看到數據了。

6.2.2 安全-ACL

JWT插件可以保護API能夠被受信用戶訪問,但不能區別哪個用戶能夠訪問哪個API,即接口權限問題,我們使用ACL 插件解決這個問題.

在上面定義好的路由上啓用acl 插件,指定白名單,

curl -i -X POST \
--url http://134.175.74.48:8001/routes/afb8bfbd-977e-464f-8c94-05d6c5c98429/plugins \
--data "name=acl"  \
--data "config.whitelist=go2cloud-api-group"

此時再訪問api,會提示不能訪問這個服務。

{
    "message": "You cannot consume this service"
}

圖片描述

只需將kongauser1這個用戶關聯到白名單內的go2cloud-api-group組裏即可。

curl -i -X POST \
--url http://134.175.74.48:8001/consumers/tianqiuser/acls \
--data "group=tianqi"

圖片描述

再次訪問接口,能正常返回數據。

圖片描述

現在就可以對網關暴露的接口進行身份認證和權限控制了。

6.2.3 認證-key-auth

  • 爲服務或者路由創建key-auth,插件即可以應用在service上,也可以應用在route上
 curl -i -X POST \
  --url http://134.175.74.48:8001/services/go2cloud-api/plugins/ \
  --data 'name=key-auth'

圖片描述

獲取到的結果爲:

{
    "created_at": 1566027525,
    "config": {
        "key_names": [
            "apikey"
        ],
        "run_on_preflight": true,
        "anonymous": null,
        "hide_credentials": false,
        "key_in_body": false
    },
    "id": "9be2def2-df65-41a4-97b7-52e44b207427",
    "service": {
        "id": "ceb337a3-a6e0-4520-ba7a-f61403e36dcf"
    },
    "name": "key-auth",
    "protocols": [
        "grpc",
        "grpcs",
        "http",
        "https"
    ],
    "enabled": true,
    "run_on": "first",
    "consumer": null,
    "route": null,
    "tags": null
}
  • 創建用戶,在用戶中配置apk-key
curl -i -X POST \
  --url http://localhost:8001/consumers/ \
  --data "username=Jason"

curl -i -X POST \
  --url http://localhost:8001/consumers/Jason/key-auth/ \
  --data 'key=123456'

圖片描述

  • postman測試,認證方式爲apikey

圖片描述

https://docs.konghq.com/hub/)

6.2.4 認證-basic auth

  • 在service或route上創建basic auth
    圖片描述
  • 在consumers中創建basic credentials

圖片描述

  • 利用postman測試

圖片描述

6.2.5 安全-ip-restriction

顧名思義,用來設置接口IP的黑白名單

  • 在service或routes上創建basic auth,配置黑白名單

圖片描述

  • postman測試

圖片描述

將調用方的IP地址加入到白名單中,可以正常訪問。

6.2.6 安全-bot-detection

圖片描述
圖片描述

6.2.7 流控-rate-limiting

  • 在service或route配置流量控制

定義每秒/分鐘/小時/天/月/年可以發送的請求數量

限制可以根據服務或路由/ip地址/證書

策略可以利用本地,集羣或redis

例如配置限制每天只能調用10次

  • postman測試

圖片描述

6.2.8 流控-request/size-limiting/termination

request-size-limiting 請求payload size限制

request-termination 這允許(暫時)阻止API或消費者

圖片描述

此處只簡單列舉幾個插件,更詳細的插件請查看,

測試在k8s中目前還沒有將konga做成helm部署,後期可以自己將起做成charts方便在k8s中圖形化管理。

參考鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章