Kong提供了兩種負載均衡方案:
- 基於DNS的負載均衡
當使用基於DNS的負載均衡時,上游服務的註冊是在Kong之外完成,而Kong只接收來自DNS服務器的負載均衡域名解析。使用包含主機名(而不是IP地址)URL定義的每個API將自動使用基於DNS的負載均衡。
- Ring-Balancer環形均衡器
使用環形均衡器時,上游服務的添加和刪除將由Kong處理,不需要進行DNS域名解析(當然如果target配置爲域名也需要解析域名,但不需要DNS實現負載均衡)。Kong將扮演服務註冊中心的角色。使用upstream和target配置服務。
- 加權循環算法:默認情況下環形均衡器將使用加權循環的方案。
- 散列算法:以none、consumer、IP或者header爲輸入的散列算法。none就是加權循環算法。
負載均衡應用
- 藍綠部署Blue-Green Deployments
可以通過通過定義藍upstream和綠upstream。然後通過更新Kong Service,切換host對應的upstrean來達到藍綠的快速切換。
- 金絲雀發佈Canary Releases
直接使用環形均衡器,通過調整target的權重,允許一個平滑和可控的金絲雀環境。
下面驗證一下Ring-Balancer環形均衡器。先創建兩個echo服務,爲了驗證負載均衡,兩個echo服務的名稱定爲echo-v1和echo-v2,其port分別爲8080和8081。
vi echo-v1-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: echo-v1
name: echo-v1
spec:
ports:
- port: 8080
name: http
protocol: TCP
targetPort: 8080
selector:
app: echo-v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: echo-v1
name: echo-v1
spec:
replicas: 1
selector:
matchLabels:
app: echo-v1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: echo-v1
spec:
containers:
- image: e2eteam/echoserver:2.2
name: echo-v1
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: {}
vi echo-v2-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: echo-v2
name: echo-v2
spec:
ports:
- port: 8081
name: http
protocol: TCP
targetPort: 8080
selector:
app: echo-v2
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: echo-v2
name: echo-v2
spec:
replicas: 1
selector:
matchLabels:
app: echo-v2
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: echo-v2
spec:
containers:
- image: e2eteam/echoserver:2.2
name: echo-v2
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: {}
kubectl apply -f echo-v1-service.yaml
kubectl apply -f echo-v2-service.yaml
創建一個upstream,名稱爲echo-upstream。
curl -X POST \
--url http://192.168.1.55:32444/upstreams \
--data "name=echo-upstream" \
-s | python -m json.tool
{
"algorithm": "round-robin",
"created_at": 1577502909,
"hash_fallback": "none",
"hash_fallback_header": null,
"hash_on": "none",
"hash_on_cookie": null,
"hash_on_cookie_path": "/",
"hash_on_header": null,
"healthchecks": {
"active": {
"concurrency": 10,
"healthy": {
"http_statuses": [
200,
302
],
"interval": 0,
"successes": 0
},
"http_path": "/",
"https_sni": null,
"https_verify_certificate": true,
"timeout": 1,
"type": "http",
"unhealthy": {
"http_failures": 0,
"http_statuses": [
429,
404,
500,
501,
502,
503,
504,
505
],
"interval": 0,
"tcp_failures": 0,
"timeouts": 0
}
},
"passive": {
"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",
"unhealthy": {
"http_failures": 0,
"http_statuses": [
429,
500,
503
],
"tcp_failures": 0,
"timeouts": 0
}
}
},
"id": "d440cf4f-bf3a-4127-b610-4e811e5231c2",
"name": "echo-upstream",
"slots": 10000,
"tags": null
}
爲echo-upstream上游服務創建兩個負載均衡target,分別對應以上創建的兩個kubernetes的echo-v1和echo-v2服務。注意兩個target的權重,是150:50。
curl -X POST \
--url http://192.168.1.55:32444/upstreams/echo-upstream/targets \
--data "target=echo-v1:8080" \
--data "weight=150" \
-s | python -m json.tool
{
"created_at": 1577503409.365,
"id": "97f5c06a-a4a3-4734-ae3d-eac95a78f6f8",
"target": "echo-v1:8080",
"upstream": {
"id": "d440cf4f-bf3a-4127-b610-4e811e5231c2"
},
"weight": 150
}
curl -X POST \
--url http://192.168.1.55:32444/upstreams/echo-upstream/targets \
--data "target=echo-v2:8081" \
--data "weight=50" \
-s | python -m json.tool
{
"created_at": 1577503417.043,
"id": "e09063bf-634b-4dbb-a95d-71b5e9526cec",
"target": "echo-v2:8081",
"upstream": {
"id": "d440cf4f-bf3a-4127-b610-4e811e5231c2"
},
"weight": 50
}
創建service,其中host對應以上創建的echo-upstream。
curl -X POST \
--url http://192.168.1.55:32444/services/ \
--data "name=echo-service" \
--data "host=echo-upstream" \
-s | python -m json.tool
{
"client_certificate": null,
"connect_timeout": 60000,
"created_at": 1577503779,
"host": "echo-upstream",
"id": "1f47b93c-b677-4990-9cbc-4504cbd89f6d",
"name": "echo-service",
"path": null,
"port": 80,
"protocol": "http",
"read_timeout": 60000,
"retries": 5,
"tags": null,
"updated_at": 1577503779,
"write_timeout": 60000
}
創建路由。
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": 1577503971,
"destinations": null,
"headers": null,
"hosts": null,
"https_redirect_status_code": 426,
"id": "56861fa1-a605-4bb7-a7f9-3726ed41b762",
"methods": null,
"name": "echo-service-route",
"paths": [
"/foo"
],
"preserve_host": false,
"protocols": [
"http",
"https"
],
"regex_priority": 0,
"service": {
"id": "1f47b93c-b677-4990-9cbc-4504cbd89f6d"
},
"snis": null,
"sources": null,
"strip_path": true,
"tags": null,
"updated_at": 1577503971
}
測試一下效果。根據結果看echo-v1 : echo-v2基本上符合3 : 1。
curl -i 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: Sat, 28 Dec 2019 03:34:33 GMT
Server: echoserver
X-Kong-Upstream-Latency: 44
X-Kong-Proxy-Latency: 4
Via: kong/1.3.0
Hostname: echo-v1-7db89db86-5xvcw
Pod Information:
node name: k8s-node2
pod name: echo-v1-7db89db86-5xvcw
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.1.14
method=GET
real path=/
query=
request_version=1.1
request_scheme=http
request_uri=http://echo-v1:8080/
Request Headers:
accept=*/*
connection=keep-alive
host=echo-v1: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-
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v2-644b65df68-css5k
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v2-644b65df68-css5k
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v2-644b65df68-css5k
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v2-644b65df68-css5k
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v2-644b65df68-css5k
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v2-644b65df68-css5k
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw
curl -i http://192.168.1.55:32080/foo -s | grep "pod name:"
pod name: echo-v1-7db89db86-5xvcw