Kong系列-05-使用入門

Kong是一個API網關,其核心能力是代理客戶端對上游服務的訪問,下面我們演示一下如何配置Kong來進行代理服務。

Kong傳統是通過Admin API進行管理的,對於Kong直接在操作系統如CentOS之上直接部署時,Kong的8001爲管理端口,8000爲Proxy端口;如果在Kubernetes集羣部署,gateway-kong-admin服務提供管理接口,gateway-kong-proxy服務提供了代理接口。

一般來說,在學習Kong Ingress Controller配置方式前,建議先學習一下Admin API的基本使用。本文先簡單介紹Admin API管理方式。

Kong的核心實體概念。

  • Client:指下游客戶端。
  • Service:指上游服務。
  • Route:定義匹配客戶端請求的規則,每個路由都與一個服務相關聯,而服務可能有多個與之相關聯的路由。
  • Plugin:它是在代理生命週期中運行的業務邏輯,插件可以生效於全局或者特定的路由和服務。
  • Consumer:消費者表示服務的消費者或者使用者,可能是一個用戶,也可能是一個應用。

本文中我們在Kong系列-04-Helm安裝Kong 1.3.0 with PostgreSQL and with Ingress Controller環境下演示。注意無數據DB-Less部署方式是不支持Admin API管理的。

kubectl get svc
NAME                                  TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
service/gateway-kong-admin            NodePort    10.1.6.70      <none>        8444:32444/TCP               4m24s
service/gateway-kong-proxy            NodePort    10.1.232.237   <none>        80:32080/TCP,443:32443/TCP   4m24s

我們先部署一個echo服務。該服務沒有對Kubernetes外暴露端口。如果想從Kubernetes集羣之外訪問該服務就需要通過Kong網關代理。

vi echo-server-service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: echo
  name: echo
spec:
  ports:
  - port: 8080
    name: high
    protocol: TCP
    targetPort: 8080
  - port: 80
    name: low
    protocol: TCP
    targetPort: 8080
  selector:
    app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: echo
  name: echo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: echo
    spec:
      containers:
      - image: e2eteam/echoserver:2.2
        name: echo
        ports:
        - containerPort: 8080
        env:
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        resources: {}

爲了讓Kong感知k8s的echo服務,需要在Kong中創建一個Kong的服務echo-service,該Kong服務指向k8s的echo服務。

curl -X POST \
  --url http://192.168.1.55:32444/services/ \
  --data 'name=echo-service' \
  --data 'url=http://echo:8080' \
  -s | python -m json.tool
{
    "client_certificate": null,
    "connect_timeout": 60000,
    "created_at": 1576504925,
    "host": "echo",
    "id": "f15edf62-cb68-4279-a41f-7f5273ccd001",
    "name": "echo-service",
    "path": null,
    "port": 8080,
    "protocol": "http",
    "read_timeout": 60000,
    "retries": 5,
    "tags": null,
    "updated_at": 1576504925,
    "write_timeout": 60000
}

查詢服務services列表,可以看出剛纔創建的服務echo-service。

curl -X GET \
  --url http://192.168.1.55:32444/services/ \
  -s | python -m json.tool
{
    "data": [
        {
            "client_certificate": null,
            "connect_timeout": 60000,
            "created_at": 1576504925,
            "host": "echo",
            "id": "f15edf62-cb68-4279-a41f-7f5273ccd001",
            "name": "echo-service",
            "path": null,
            "port": 8080,
            "protocol": "http",
            "read_timeout": 60000,
            "retries": 5,
            "tags": null,
            "updated_at": 1576504925,
            "write_timeout": 60000
        }
    ],
    "next": null
}

爲了讓Kong知道客戶端的哪些請求是訪問echo服務的,需要爲echo服務添加一條路由。每個服務是可以有多個路由與之對應。以下的路由規則爲路徑前綴爲/foo的請求,將被轉發到echo服務。

curl -X POST \
  --url http://192.168.1.55:32444/services/echo-service/routes \
  --data 'name=echo-service-route' \
  --data 'paths[]=/foo' \
  -s | python -m json.tool
{
    "created_at": 1576505187,
    "destinations": null,
    "headers": null,
    "hosts": null,
    "https_redirect_status_code": 426,
    "id": "d152f741-9ed1-47d2-98bc-f8c438075e2e",
    "methods": null,
    "name": "echo-service-route",
    "paths": [
        "/foo"
    ],
    "preserve_host": false,
    "protocols": [
        "http",
        "https"
    ],
    "regex_priority": 0,
    "service": {
        "id": "f15edf62-cb68-4279-a41f-7f5273ccd001"
    },
    "snis": null,
    "sources": null,
    "strip_path": true,
    "tags": null,
    "updated_at": 1576505187
}

測試一下,可以看出根據路由規則能夠訪問echo服務。

curl -iX GET --url http://192.168.1.55:32080/foo
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Date: Mon, 16 Dec 2019 14:09:21 GMT
Server: echoserver
X-Kong-Upstream-Latency: 5
X-Kong-Proxy-Latency: 65
Via: kong/1.3.0


Hostname: echo-75cf96d976-pwbg7

Pod Information:
        node name:      k8s-node2
        pod name:       echo-75cf96d976-pwbg7
        pod namespace:  default
        pod IP: 10.244.2.12

Server values:
        server_version=nginx: 1.14.2 - lua: 10015

Request Information:
        client_address=10.244.2.11
        method=GET
        real path=/
        query=
        request_version=1.1
        request_scheme=http
        request_uri=http://echo:8080/

Request Headers:
        accept=*/*
        connection=keep-alive
        host=echo:8080
        user-agent=curl/7.29.0
        x-forwarded-for=10.244.0.0
        x-forwarded-host=192.168.1.55
        x-forwarded-port=8000
        x-forwarded-proto=http
        x-real-ip=10.244.0.0

Request Body:
        -no body in request-

Kong通過插件擴展其網關能力,Kong的一個很大的優勢就是有功能豐富的開源插件,並且能方便地自定義插件。

key-auth插件是一個身份驗證插件,在添加此插件之前,對服務的所有請求都會被直接轉發到上游服務,如果添加並配置此插件後,只有正確密鑰的請求才會被轉發到上游服務,否則將被拒絕。以下API給echo-service應用了key-auth插件,意味所有對echo-service的請求都會被key-auth插件處理。

curl -X POST \
  --url http://192.168.1.55:32444/services/echo-service/plugins \
  --data 'name=key-auth' \
  -s | python -m json.tool
{
    "config": {
        "anonymous": null,
        "hide_credentials": false,
        "key_in_body": false,
        "key_names": [
            "apikey"
        ],
        "run_on_preflight": true
    },
    "consumer": null,
    "created_at": 1576674272,
    "enabled": true,
    "id": "0d8231dd-e820-45b4-bc78-f8b9758346fa",
    "name": "key-auth",
    "protocols": [
        "grpc",
        "grpcs",
        "http",
        "https"
    ],
    "route": null,
    "run_on": "first",
    "service": {
        "id": "f15edf62-cb68-4279-a41f-7f5273ccd001"
    },
    "tags": null
}

此時請求echo-service,由於沒有攜帶key,key-auth插件拒絕請求。

curl -iX GET --url http://192.168.1.55:32080/foo
HTTP/1.1 401 Unauthorized
Date: Wed, 18 Dec 2019 13:08:18 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
WWW-Authenticate: Key realm="kong"
Content-Length: 41
Server: kong/1.3.0

{"message":"No API key found in request"}

創建一個消費者consumer。

curl -X POST \
  --url http://192.168.1.55:32444/consumers \
  --data 'username=twingao' \
  -s | python -m json.tool
{
    "created_at": 1576674684,
    "custom_id": null,
    "id": "5b6be948-00bb-4479-a012-67d73824c2fe",
    "tags": null,
    "username": "twingao"
}

爲消費者twingao配置一個key。

curl -X POST \
  --url http://192.168.1.55:32444/consumers/twingao/key-auth \
  --data 'key=123456' \
  -s | python -m json.tool
{
    "consumer": {
        "id": "5b6be948-00bb-4479-a012-67d73824c2fe"
    },
    "created_at": 1576674825,
    "id": "0c815096-4cda-4056-824a-dff6eb799384",
    "key": "123456"
}

此時訪問echo-service,攜帶上請求頭apikey: 123456,key-auth身份驗證成功,會放行請求;如果攜帶的apikey不正確,則不會放行請求。

curl -iX GET --url http://192.168.1.55:32080/foo --header 'apikey: 123456'
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Date: Wed, 18 Dec 2019 13:19:22 GMT
Server: echoserver
X-Kong-Upstream-Latency: 7
X-Kong-Proxy-Latency: 66
Via: kong/1.3.0


Hostname: echo-75cf96d976-pwbg7

Pod Information:
        node name:      k8s-node2
        pod name:       echo-75cf96d976-pwbg7
        pod namespace:  default
        pod IP: 10.244.2.14

Server values:
        server_version=nginx: 1.14.2 - lua: 10015

Request Information:
        client_address=10.244.2.13
        method=GET
        real path=/
        query=
        request_version=1.1
        request_scheme=http
        request_uri=http://echo:8080/

Request Headers:
        accept=*/*
        apikey=123456
        connection=keep-alive
        host=echo:8080
        user-agent=curl/7.29.0
        x-consumer-id=5b6be948-00bb-4479-a012-67d73824c2fe
        x-consumer-username=twingao
        x-forwarded-for=10.244.0.0
        x-forwarded-host=192.168.1.55
        x-forwarded-port=8000
        x-forwarded-proto=http
        x-real-ip=10.244.0.0

Request Body:
        -no body in request-

curl -iX GET --url http://192.168.1.55:32080/foo --header 'apikey: 123'
HTTP/1.1 401 Unauthorized
Date: Wed, 18 Dec 2019 13:19:57 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Content-Length: 48
Server: kong/1.3.0

{"message":"Invalid authentication credentials"}
發佈了49 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章