This is an automated email from the ASF dual-hosted git repository.
chenjunxu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-apisix.git
The following commit(s) were added to refs/heads/master by this push:
new a53b470 feat: support saving k8s deployment info to upstream (#1502)
a53b470 is described below
commit a53b4707fb03efa40966a00f1525bdedad2334ce
Author: nic-chen <[email protected]>
AuthorDate: Mon Apr 27 10:47:17 2020 +0800
feat: support saving k8s deployment info to upstream (#1502)
* feat: support save k8s deployment info to upstream
---
apisix/admin/upstreams.lua | 12 ++++---
apisix/schema_def.lua | 28 ++++++++++++++--
doc/admin-api-cn.md | 10 +++++-
doc/admin-api.md | 10 +++++-
doc/architecture-design-cn.md | 13 +++++---
doc/architecture-design.md | 13 +++++---
t/admin/routes.t | 4 +--
t/admin/services.t | 6 ++--
t/admin/upstream.t | 4 +--
t/node/upstream.t | 76 +++++++++++++++++++++++++++++++++++++++----
10 files changed, 142 insertions(+), 34 deletions(-)
diff --git a/apisix/admin/upstreams.lua b/apisix/admin/upstreams.lua
index b49c33a..e989cd5 100644
--- a/apisix/admin/upstreams.lua
+++ b/apisix/admin/upstreams.lua
@@ -19,7 +19,6 @@ local get_routes = require("apisix.router").http_routes
local get_services = require("apisix.http.service").services
local tostring = tostring
local ipairs = ipairs
-local tonumber = tonumber
local type = type
@@ -99,17 +98,20 @@ local function check_conf(id, conf, need_id)
if need_id and conf.id and tostring(conf.id) ~= tostring(id) then
return nil, {error_msg = "wrong upstream id"}
end
+
+ -- let schema check id
+ if id and not conf.id then
+ conf.id = id
+ end
+
core.log.info("schema: ", core.json.delay_encode(core.schema.upstream))
core.log.info("conf : ", core.json.delay_encode(conf))
+
local ok, err = check_upstream_conf(conf)
if not ok then
return nil, {error_msg = err}
end
- if need_id and not tonumber(id) then
- return nil, {error_msg = "wrong type of service id"}
- end
-
return need_id and id or true
end
diff --git a/apisix/schema_def.lua b/apisix/schema_def.lua
index 50a783a..e261c98 100644
--- a/apisix/schema_def.lua
+++ b/apisix/schema_def.lua
@@ -29,8 +29,8 @@ local plugins_schema = {
local id_schema = {
anyOf = {
{
- type = "string", minLength = 1, maxLength = 32,
- pattern = [[^[0-9]+$]]
+ type = "string", minLength = 1, maxLength = 64,
+ pattern = [[^[a-zA-Z0-9-_]+$]]
},
{type = "integer", minimum = 1}
}
@@ -253,6 +253,25 @@ local upstream_schema = {
},
required = {"connect", "send", "read"},
},
+ k8s_deployment_info = {
+ type = "object",
+ properties = {
+ namespace = {type = "string", description = "k8s namespace"},
+ deploy_name = {type = "string", description = "k8s deployment
name"},
+ service_name = {type = "string", description = "k8s service
name"},
+ port = {type = "number", minimum = 0},
+ backend_type = {
+ type = "string",
+ default = "pod",
+ description = "k8s service name",
+ enum = {"svc", "pod"}
+ },
+ },
+ anyOf = {
+ {required = {"namespace", "deploy_name", "port"}},
+ {required = {"namespace", "service_name", "port"}},
+ },
+ },
type = {
description = "algorithms of load balancing",
type = "string",
@@ -280,7 +299,10 @@ local upstream_schema = {
desc = {type = "string", maxLength = 256},
id = id_schema
},
- required = {"nodes", "type"},
+ anyOf = {
+ {required = {"type", "nodes"}},
+ {required = {"type", "k8s_deployment_info"}},
+ },
additionalProperties = false,
}
diff --git a/doc/admin-api-cn.md b/doc/admin-api-cn.md
index d61bbe9..7a7d355 100644
--- a/doc/admin-api-cn.md
+++ b/doc/admin-api-cn.md
@@ -344,7 +344,8 @@ APISIX 的 Upstream 除了基本的复杂均衡算法选择外,还支持对上
|名字 |可选项 |类型 |说明 |示例|
|---------|---------|----|-----------|----|
-|nodes |必需|Node|哈希表,内部元素的 key 是上游机器地址列表,格式为`地址 + Port`,其中地址部分可以是 IP
也可以是域名,比如 `192.168.1.100:80`、`foo.com:80`等。value 则是节点的权重,特别的,当权重值为 `0`
有特殊含义,通常代表该上游节点失效,永远不希望被选中。|`192.168.1.100:80`|
+|nodes |与 `k8s_deployment_info` 二选一|Node|哈希表,内部元素的 key
是上游机器地址列表,格式为`地址 + Port`,其中地址部分可以是 IP 也可以是域名,比如
`192.168.1.100:80`、`foo.com:80`等。value 则是节点的权重,特别的,当权重值为 `0`
有特殊含义,通常代表该上游节点失效,永远不希望被选中。|`192.168.1.100:80`|
+|k8s_deployment_info|与 `nodes` 二选一|哈希表|字段包括
`namespace`、`deploy_name`、`service_name`、`port`、`backend_type`,其中 `port`
字段为数值,`backend_type` 为 `pod` 或 `service`,其他为字符串 | `{"namespace":
"test-namespace", "deploy_name": "test-deploy-name", "service_name":
"test-service-name", "backend_type": "pod", "port": 8080}` |
|type |必需|枚举|`roundrobin` 支持权重的负载,`chash`
一致性哈希,两者是二选一的|`roundrobin`||
|key |条件必需|匹配类型|该选项只有类型是 `chash` 才有效。根据 `key` 来查找对应的 node `id`,相同的
`key` 在同一个对象中,永远返回相同 id,目前支持的 Nginx 内置变量有 `uri, server_name, server_addr,
request_uri, remote_port, remote_addr, query_string, host, hostname,
arg_***`,其中 `arg_***` 是来自URL的请求参数,[Nginx
变量列表](http://nginx.org/en/docs/varindex.html)||
|checks
|可选|health_checker|配置健康检查的参数,详细可参考[health-check](health-check.md)||
@@ -367,6 +368,13 @@ upstream 对象 json 配置内容:
},
"enable_websocket": true,
"nodes": {"host:80": 100}, # 上游机器地址列表,格式为`地址 + Port`
+ "k8s_deployment_info": { # k8s deployment 信息
+ "namespace": "test-namespace",
+ "deploy_name": "test-deploy-name",
+ "service_name": "test-service-name",
+ "backend_type": "pod", # pod or service
+ "port": 8080
+ },
"type":"roundrobin", # chash or roundrobin
"checks": {}, # 配置健康检查的参数
"hash_on": "",
diff --git a/doc/admin-api.md b/doc/admin-api.md
index 9c40948..f60ccb6 100644
--- a/doc/admin-api.md
+++ b/doc/admin-api.md
@@ -337,7 +337,8 @@ In addition to the basic complex equalization algorithm
selection, APISIX's Upst
|Name |Optional|Description|
|------- |-----|------|
|type |required|`roundrobin` supports the weight of the load,
`chash` consistency hash, pick one of them.|
-|nodes |required|Hash table, the key of the internal element is the
upstream machine address list, the format is `Address + Port`, where the
address part can be IP or domain name, such as `192.168.1.100:80`,
`foo.com:80`, etc. Value is the weight of the node. In particular, when the
weight value is `0`, it has a special meaning, which usually means that the
upstream node is invalid and never wants to be selected.|
+|nodes |required if `k8s_deployment_info` not configured|Hash table,
the key of the internal element is the upstream machine address list, the
format is `Address + Port`, where the address part can be IP or domain name,
such as `192.168.1.100:80`, `foo.com:80`, etc. Value is the weight of the node.
In particular, when the weight value is `0`, it has a special meaning, which
usually means that the upstream node is invalid and never wants to be selected.|
+|k8s_deployment_info|required if `nodes` not configured|fields:
`namespace`、`deploy_name`、`service_name`、`port`、`backend_type`, `port` is
number, `backend_type` is `pod` or `service`, others is string. |
|hash_on |optional|This option is only valid if the `type` is `chash`.
Supported types `vars`(Nginx variables), `header`(custom header), `cookie`,
`consumer`, the default value is `vars`.|
|key |required|This option is only valid if the `type` is `chash`.
Find the corresponding node `id` according to `hash_on` and `key`. When
`hash_on` is set as `vars`, `key` is the required parameter, for now, it
support nginx built-in variables like `uri, server_name, server_addr,
request_uri, remote_port, remote_addr, query_string, host, hostname, arg_***`,
`arg_***` is arguments in the request line, [Nginx variables
list](http://nginx.org/en/docs/varindex.html). When `hash_ [...]
|checks |optional|Configure the parameters of the health check. For
details, refer to [health-check](health-check.md).|
@@ -359,6 +360,13 @@ Config Example:
},
"enable_websocket": true,
"nodes": {"host:80": 100}, # Upstream machine address list, the format is
`Address + Port`
+ "k8s_deployment_info": { # kubernetes deployment info
+ "namespace": "test-namespace",
+ "deploy_name": "test-deploy-name",
+ "service_name": "test-service-name",
+ "backend_type": "pod", # pod or service
+ "port": 8080
+ },
"type":"roundrobin", # chash or roundrobin
"checks": {}, # Health check parameters
"hash_on": "",
diff --git a/doc/architecture-design-cn.md b/doc/architecture-design-cn.md
index 251a0f3..3fa6884 100644
--- a/doc/architecture-design-cn.md
+++ b/doc/architecture-design-cn.md
@@ -238,7 +238,8 @@ APISIX 的 Upstream 除了基本的复杂均衡算法选择外,还支持对上
|名字 |可选|说明|
|------- |-----|------|
|type |必填|`roundrobin` 支持权重的负载,`chash` 一致性哈希,两者是二选一的|
-|nodes |必填|哈希表,内部元素的 key 是上游机器地址列表,格式为`地址 + Port`,其中地址部分可以是 IP
也可以是域名,比如 `192.168.1.100:80`、`foo.com:80` 等。value 则是节点的权重。当权重值为 `0`
代表该上游节点失效,不会被选中,可以用于暂时摘除节点的情况。|
+|nodes |与 `k8s_deployment_info` 二选一|哈希表,内部元素的 key 是上游机器地址列表,格式为`地址 +
Port`,其中地址部分可以是 IP 也可以是域名,比如 `192.168.1.100:80`、`foo.com:80` 等。value
则是节点的权重。当权重值为 `0` 代表该上游节点失效,不会被选中,可以用于暂时摘除节点的情况。|
+|k8s_deployment_info|与 `nodes` 二选一|哈希表|字段包括
`namespace`、`deploy_name`、`service_name`、`port`、`backend_type`,其中 `port`
字段为数值,`backend_type` 为 `pod` 或 `service`,其他为字符串 |
|key |可选|在 `type` 等于 `chash` 是必选项。 `key` 需要配合 `hash_on` 来使用,通过
`hash_on` 和 `key` 来查找对应的 node `id`|
|hash_on |可选|`hash_on` 支持的类型有
`vars`(Nginx内置变量),`header`(自定义header),`cookie`,`consumer`,默认值为 `vars`|
|checks |可选|配置健康检查的参数,详细可参考[health-check](health-check.md)|
@@ -259,10 +260,12 @@ APISIX 的 Upstream 除了基本的复杂均衡算法选择外,还支持对上
curl http://127.0.0.1:9080/apisix/admin/upstreams/1 -H 'X-API-KEY:
edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"type": "roundrobin",
- "nodes": {
- "127.0.0.1:80": 1,
- "127.0.0.2:80": 2,
- "foo.com:80": 3
+ "k8s_deployment_info": {
+ "namespace": "test-namespace",
+ "deploy_name": "test-deploy-name",
+ "service_name": "test-service-name",
+ "backend_type": "pod",
+ "port": 8080
}
}'
diff --git a/doc/architecture-design.md b/doc/architecture-design.md
index e580ab3..9edaadb 100644
--- a/doc/architecture-design.md
+++ b/doc/architecture-design.md
@@ -233,7 +233,8 @@ In addition to the basic complex equalization algorithm
selection, APISIX's Upst
|Name |Optional|Description|
|------- |-----|------|
|type |required|`roundrobin` supports the weight of the load,
`chash` consistency hash, pick one of them.|
-|nodes |required|Hash table, the key of the internal element is the
upstream machine address list, the format is `Address + Port`, where the
address part can be IP or domain name, such as `192.168.1.100:80`,
`foo.com:80`, etc. Value is the weight of the node. In particular, when the
weight value is `0`, it has a special meaning, which usually means that the
upstream node is invalid and never wants to be selected.|
+|nodes |required if `k8s_deployment_info` not configured|Hash table,
the key of the internal element is the upstream machine address list, the
format is `Address + Port`, where the address part can be IP or domain name,
such as `192.168.1.100:80`, `foo.com:80`, etc. Value is the weight of the node.
In particular, when the weight value is `0`, it has a special meaning, which
usually means that the upstream node is invalid and never wants to be selected.|
+|k8s_deployment_info |required if `nodes` not configured|fields:
`namespace`、`deploy_name`、`service_name`、`port`、`backend_type`, `port` is
number, `backend_type` is `pod` or `service`, others is string. |
|hash_on |optional|This option is only valid if the `type` is `chash`.
Supported types `vars`(Nginx variables), `header`(custom header), `cookie`,
`consumer`, the default value is `vars`.|
|key |required|This option is only valid if the `type` is `chash`.
Find the corresponding node `id` according to `hash_on` and `key`. When
`hash_on` is set as `vars`, `key` is the required parameter, for now, it
support nginx built-in variables like `uri, server_name, server_addr,
request_uri, remote_port, remote_addr, query_string, host, hostname, arg_***`,
`arg_***` is arguments in the request line, [Nginx variables
list](http://nginx.org/en/docs/varindex.html). When `hash_ [...]
|checks |optional|Configure the parameters of the health check. For
details, refer to [health-check](health-check.md).|
@@ -248,10 +249,12 @@ Create an upstream object use case:
curl http://127.0.0.1:9080/apisix/admin/upstreams/1 -H 'X-API-KEY:
edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"type": "roundrobin",
- "nodes": {
- "127.0.0.1:80": 1,
- "127.0.0.2:80": 2,
- "foo.com:80": 3
+ "k8s_deployment_info": {
+ "namespace": "test-namespace",
+ "deploy_name": "test-deploy-name",
+ "service_name": "test-service-name",
+ "backend_type": "pod",
+ "port": 8080
}
}'
diff --git a/t/admin/routes.t b/t/admin/routes.t
index 4c54c4f..78ab5c6 100644
--- a/t/admin/routes.t
+++ b/t/admin/routes.t
@@ -434,7 +434,7 @@ GET /t
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
- "service_id": "invalid_id",
+ "service_id": "invalid_id$",
"uri": "/index.html"
}]]
)
@@ -569,7 +569,7 @@ GET /t
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
- "upstream_id": "invalid",
+ "upstream_id": "invalid$",
"uri": "/index.html"
}]]
)
diff --git a/t/admin/services.t b/t/admin/services.t
index 97d0aea..6c6f503 100644
--- a/t/admin/services.t
+++ b/t/admin/services.t
@@ -353,7 +353,7 @@ GET /t
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/services/invalid_id',
+ local code, body = t('/apisix/admin/services/invalid_id$',
ngx.HTTP_PUT,
[[{
"plugins": {
@@ -475,7 +475,7 @@ GET /t
local code, body = t('/apisix/admin/services',
ngx.HTTP_PUT,
[[{
- "id": "invalid_id",
+ "id": "invalid_id$",
"plugins": {}
}]]
)
@@ -530,7 +530,7 @@ GET /t
ngx.HTTP_PUT,
[[{
"id": 1,
- "upstream_id": "invalid"
+ "upstream_id": "invalid$"
}]]
)
diff --git a/t/admin/upstream.t b/t/admin/upstream.t
index 6735914..da13134 100644
--- a/t/admin/upstream.t
+++ b/t/admin/upstream.t
@@ -244,7 +244,7 @@ GET /t
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
- local code, body = t('/apisix/admin/upstreams/invalid_id',
+ local code, body = t('/apisix/admin/upstreams/invalid_id$',
ngx.HTTP_PUT,
[[{
"nodes": {
@@ -374,7 +374,7 @@ GET /t
local code, body = t('/apisix/admin/upstreams',
ngx.HTTP_PUT,
[[{
- "id": "invalid_id",
+ "id": "invalid_id$",
"nodes": {
"127.0.0.1:8080": 1
},
diff --git a/t/node/upstream.t b/t/node/upstream.t
index bfdbba9..c6ae077 100644
--- a/t/node/upstream.t
+++ b/t/node/upstream.t
@@ -26,7 +26,69 @@ run_tests();
__DATA__
-=== TEST 1: set upstream(id: 1)
+=== TEST 1: set upstream(id: 1) invalid parameters
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/upstreams/1',
+ ngx.HTTP_PUT,
+ [[{
+ "type": "roundrobin",
+ "desc": "new upstream"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- error_code: 400
+--- no_error_log
+[error]
+
+
+
+=== TEST 2: set upstream(id: 1) k8s deployment info
+--- config
+ location /t {
+ content_by_lua_block {
+ local t = require("lib.test_admin").test
+ local code, body = t('/apisix/admin/upstreams/1',
+ ngx.HTTP_PUT,
+ [[{
+ "k8s_deployment_info": {
+ "namespace": "test-namespace",
+ "deploy_name": "test-deploy-name",
+ "service_name": "test-service-name",
+ "backend_type": "pod",
+ "port": 8080
+ },
+ "type": "roundrobin",
+ "desc": "new upstream"
+ }]]
+ )
+
+ if code >= 300 then
+ ngx.status = code
+ end
+ ngx.say(body)
+ }
+ }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 3: set upstream(id: 1) nodes
--- config
location /t {
content_by_lua_block {
@@ -57,7 +119,7 @@ passed
-=== TEST 2: set route(id: 1)
+=== TEST 4: set route(id: 1)
--- config
location /t {
content_by_lua_block {
@@ -85,7 +147,7 @@ passed
-=== TEST 3: /not_found
+=== TEST 5: /not_found
--- request
GET /not_found
--- error_code: 404
@@ -106,7 +168,7 @@ hello world
-=== TEST 5: delete upstream(id: 1)
+=== TEST 6: delete upstream(id: 1)
--- config
location /t {
content_by_lua_block {
@@ -131,7 +193,7 @@ GET /t
-=== TEST 6: delete route(id: 1)
+=== TEST 7: delete route(id: 1)
--- config
location /t {
content_by_lua_block {
@@ -155,7 +217,7 @@ GET /t
-=== TEST 7: delete upstream(id: 1)
+=== TEST 8: delete upstream(id: 1)
--- config
location /t {
content_by_lua_block {
@@ -179,7 +241,7 @@ GET /t
-=== TEST 8: delete upstream again(id: 1)
+=== TEST 9: delete upstream again(id: 1)
--- config
location /t {
content_by_lua_block {