feat(apisix): add Cloudron package
- Implements Apache APISIX packaging for Cloudron platform. - Includes Dockerfile, CloudronManifest.json, and start.sh. - Configured to use Cloudron's etcd addon. 🤖 Generated with Gemini CLI Co-Authored-By: Gemini <noreply@google.com>
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
---
|
||||
title: consul
|
||||
---
|
||||
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
## Summary
|
||||
|
||||
APACHE APISIX supports Consul as a service discovery
|
||||
|
||||
## Configuration for discovery client
|
||||
|
||||
### Configuration for Consul
|
||||
|
||||
First of all, we need to add following configuration in `conf/config.yaml` :
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
consul:
|
||||
servers: # make sure service name is unique in these consul servers
|
||||
- "http://127.0.0.1:8500" # `http://127.0.0.1:8500` and `http://127.0.0.1:8600` are different clusters
|
||||
- "http://127.0.0.1:8600" # `consul` service is default skip service
|
||||
token: "..." # if your consul cluster has enabled acl access control, you need to specify the token
|
||||
skip_services: # if you need to skip special services
|
||||
- "service_a"
|
||||
timeout:
|
||||
connect: 1000 # default 2000 ms
|
||||
read: 1000 # default 2000 ms
|
||||
wait: 60 # default 60 sec
|
||||
weight: 1 # default 1
|
||||
fetch_interval: 5 # default 3 sec, only take effect for keepalive: false way
|
||||
keepalive: true # default true, use the long pull way to query consul servers
|
||||
sort_type: "origin" # default origin
|
||||
default_service: # you can define default service when missing hit
|
||||
host: "127.0.0.1"
|
||||
port: 20999
|
||||
metadata:
|
||||
fail_timeout: 1 # default 1 ms
|
||||
weight: 1 # default 1
|
||||
max_fails: 1 # default 1
|
||||
dump: # if you need, when registered nodes updated can dump into file
|
||||
path: "logs/consul.dump"
|
||||
expire: 2592000 # unit sec, here is 30 day
|
||||
```
|
||||
|
||||
And you can config it in short by default value:
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
consul:
|
||||
servers:
|
||||
- "http://127.0.0.1:8500"
|
||||
```
|
||||
|
||||
The `keepalive` has two optional values:
|
||||
|
||||
- `true`, default and recommend value, use the long pull way to query consul servers
|
||||
- `false`, not recommend, it would use the short pull way to query consul servers, then you can set the `fetch_interval` for fetch interval
|
||||
|
||||
The `sort_type` has four optional values:
|
||||
|
||||
- `origin`, not sorting
|
||||
- `host_sort`, sort by host
|
||||
- `port_sort`, sort by port
|
||||
- `combine_sort`, with the precondition that hosts are ordered, ports are also ordered.
|
||||
|
||||
#### Dump Data
|
||||
|
||||
When we need reload `apisix` online, as the `consul` module maybe loads data from CONSUL slower than load routes from ETCD, and would get the log at the moment before load successfully from consul:
|
||||
|
||||
```
|
||||
http_access_phase(): failed to set upstream: no valid upstream node
|
||||
```
|
||||
|
||||
So, we import the `dump` function for `consul` module. When reload, would load the dump file before from consul; when the registered nodes in consul been updated, would dump the upstream nodes into file automatically.
|
||||
|
||||
The `dump` has three optional values now:
|
||||
|
||||
- `path`, the dump file save path
|
||||
- support relative path, eg: `logs/consul.dump`
|
||||
- support absolute path, eg: `/tmp/consul.dump`
|
||||
- make sure the dump file's parent path exist
|
||||
- make sure the `apisix` has the dump file's read-write access permission,eg: add below config in `conf/config.yaml`
|
||||
|
||||
```yaml
|
||||
nginx_config: # config for render the template to generate nginx.conf
|
||||
user: root # specifies the execution user of the worker process.
|
||||
```
|
||||
|
||||
- `load_on_init`, default value is `true`
|
||||
- if `true`, just try to load the data from the dump file before loading data from consul when starting, does not care the dump file exists or not
|
||||
- if `false`, ignore loading data from the dump file
|
||||
- Whether `true` or `false`, we don't need to prepare a dump file for apisix at anytime
|
||||
- `expire`, unit sec, avoiding load expired dump data when load
|
||||
- default `0`, it is unexpired forever
|
||||
- recommend 2592000, which is 30 days(equals 3600 \* 24 \* 30)
|
||||
|
||||
### Register Http API Services
|
||||
|
||||
Now, register nodes into consul:
|
||||
|
||||
```shell
|
||||
curl -X PUT 'http://127.0.0.1:8500/v1/agent/service/register' \
|
||||
-d '{
|
||||
"ID": "service_a1",
|
||||
"Name": "service_a",
|
||||
"Tags": ["primary", "v1"],
|
||||
"Address": "127.0.0.1",
|
||||
"Port": 8000,
|
||||
"Meta": {
|
||||
"service_a_version": "4.0"
|
||||
},
|
||||
"EnableTagOverride": false,
|
||||
"Weights": {
|
||||
"Passing": 10,
|
||||
"Warning": 1
|
||||
}
|
||||
}'
|
||||
|
||||
curl -X PUT 'http://127.0.0.1:8500/v1/agent/service/register' \
|
||||
-d '{
|
||||
"ID": "service_a1",
|
||||
"Name": "service_a",
|
||||
"Tags": ["primary", "v1"],
|
||||
"Address": "127.0.0.1",
|
||||
"Port": 8002,
|
||||
"Meta": {
|
||||
"service_a_version": "4.0"
|
||||
},
|
||||
"EnableTagOverride": false,
|
||||
"Weights": {
|
||||
"Passing": 10,
|
||||
"Warning": 1
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
In some cases, same service name might exist in different consul servers.
|
||||
To avoid confusion, use the full consul key url path as service name in practice.
|
||||
|
||||
### Port Handling
|
||||
|
||||
When APISIX retrieves service information from Consul, it handles port values as follows:
|
||||
|
||||
- If the service registration includes a valid port number, that port will be used.
|
||||
- If the port is `nil` (not specified) or `0`, APISIX will default to port `80` for HTTP services.
|
||||
|
||||
### Upstream setting
|
||||
|
||||
#### L7
|
||||
|
||||
Here is an example of routing a request with a URL of "/*" to a service which named "service_a" and use consul discovery client in the registry :
|
||||
|
||||
:::note
|
||||
You can fetch the `admin_key` from `config.yaml` and save to an environment variable with the following command:
|
||||
|
||||
```bash
|
||||
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"uri": "/*",
|
||||
"upstream": {
|
||||
"service_name": "service_a",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "consul"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
The format response as below:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "/apisix/routes/1",
|
||||
"value": {
|
||||
"uri": "/*",
|
||||
"priority": 0,
|
||||
"id": "1",
|
||||
"upstream": {
|
||||
"scheme": "http",
|
||||
"type": "roundrobin",
|
||||
"hash_on": "vars",
|
||||
"discovery_type": "consul",
|
||||
"service_name": "service_a",
|
||||
"pass_host": "pass"
|
||||
},
|
||||
"create_time": 1669267329,
|
||||
"status": 1,
|
||||
"update_time": 1669267329
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You could find more usage in the `apisix/t/discovery/consul.t` file.
|
||||
|
||||
#### L4
|
||||
|
||||
Consul service discovery also supports use in L4, the configuration method is similar to L7.
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/stream_routes/1 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"remote_addr": "127.0.0.1",
|
||||
"upstream": {
|
||||
"scheme": "tcp",
|
||||
"service_name": "service_a",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "consul"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
You could find more usage in the `apisix/t/discovery/stream/consul.t` file.
|
||||
|
||||
## Debugging API
|
||||
|
||||
It also offers control api for debugging.
|
||||
|
||||
### Memory Dump API
|
||||
|
||||
```shell
|
||||
GET /v1/discovery/consul/dump
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```shell
|
||||
# curl http://127.0.0.1:9090/v1/discovery/consul/dump | jq
|
||||
{
|
||||
"config": {
|
||||
"fetch_interval": 3,
|
||||
"timeout": {
|
||||
"wait": 60,
|
||||
"connect": 6000,
|
||||
"read": 6000
|
||||
},
|
||||
"weight": 1,
|
||||
"servers": [
|
||||
"http://172.19.5.30:8500",
|
||||
"http://172.19.5.31:8500"
|
||||
],
|
||||
"keepalive": true,
|
||||
"default_service": {
|
||||
"host": "172.19.5.11",
|
||||
"port": 8899,
|
||||
"metadata": {
|
||||
"fail_timeout": 1,
|
||||
"weight": 1,
|
||||
"max_fails": 1
|
||||
}
|
||||
},
|
||||
"skip_services": [
|
||||
"service_d"
|
||||
]
|
||||
},
|
||||
"services": {
|
||||
"service_a": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 30513,
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 30514,
|
||||
"weight": 1
|
||||
}
|
||||
],
|
||||
"service_b": [
|
||||
{
|
||||
"host": "172.19.5.51",
|
||||
"port": 50051,
|
||||
"weight": 1
|
||||
}
|
||||
],
|
||||
"service_c": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 30511,
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 30512,
|
||||
"weight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Show Dump File API
|
||||
|
||||
It offers another control api for dump file view now. Maybe would add more api for debugging in future.
|
||||
|
||||
```shell
|
||||
GET /v1/discovery/consul/show_dump_file
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```shell
|
||||
curl http://127.0.0.1:9090/v1/discovery/consul/show_dump_file | jq
|
||||
{
|
||||
"services": {
|
||||
"service_a": [
|
||||
{
|
||||
"host": "172.19.5.12",
|
||||
"port": 8000,
|
||||
"weight": 120
|
||||
},
|
||||
{
|
||||
"host": "172.19.5.13",
|
||||
"port": 8000,
|
||||
"weight": 120
|
||||
}
|
||||
]
|
||||
},
|
||||
"expire": 0,
|
||||
"last_update": 1615877468
|
||||
}
|
||||
```
|
@@ -0,0 +1,314 @@
|
||||
---
|
||||
title: consul_kv
|
||||
---
|
||||
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
## Summary
|
||||
|
||||
For users that are using [nginx-upsync-module](https://github.com/weibocom/nginx-upsync-module) and Consul KV as a service discovery, like the Weibo Mobile Team, this may be needed.
|
||||
|
||||
Thanks to @fatman-x guy, who developed this module, called `consul_kv`, and its worker process data flow is below:
|
||||

|
||||
|
||||
## Configuration for discovery client
|
||||
|
||||
### Configuration for Consul KV
|
||||
|
||||
Add following configuration in `conf/config.yaml` :
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
consul_kv:
|
||||
servers:
|
||||
- "http://127.0.0.1:8500"
|
||||
- "http://127.0.0.1:8600"
|
||||
token: "..." # if your consul cluster has enabled acl access control, you need to specify the token
|
||||
prefix: "upstreams"
|
||||
skip_keys: # if you need to skip special keys
|
||||
- "upstreams/unused_api/"
|
||||
timeout:
|
||||
connect: 1000 # default 2000 ms
|
||||
read: 1000 # default 2000 ms
|
||||
wait: 60 # default 60 sec
|
||||
weight: 1 # default 1
|
||||
fetch_interval: 5 # default 3 sec, only take effect for keepalive: false way
|
||||
keepalive: true # default true, use the long pull way to query consul servers
|
||||
default_server: # you can define default server when missing hit
|
||||
host: "127.0.0.1"
|
||||
port: 20999
|
||||
metadata:
|
||||
fail_timeout: 1 # default 1 ms
|
||||
weight: 1 # default 1
|
||||
max_fails: 1 # default 1
|
||||
dump: # if you need, when registered nodes updated can dump into file
|
||||
path: "logs/consul_kv.dump"
|
||||
expire: 2592000 # unit sec, here is 30 day
|
||||
```
|
||||
|
||||
And you can config it in short by default value:
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
consul_kv:
|
||||
servers:
|
||||
- "http://127.0.0.1:8500"
|
||||
```
|
||||
|
||||
The `keepalive` has two optional values:
|
||||
|
||||
- `true`, default and recommend value, use the long pull way to query consul servers
|
||||
- `false`, not recommend, it would use the short pull way to query consul servers, then you can set the `fetch_interval` for fetch interval
|
||||
|
||||
#### Dump Data
|
||||
|
||||
When we need reload `apisix` online, as the `consul_kv` module maybe loads data from CONSUL slower than load routes from ETCD, and would get the log at the moment before load successfully from consul:
|
||||
|
||||
```
|
||||
http_access_phase(): failed to set upstream: no valid upstream node
|
||||
```
|
||||
|
||||
So, we import the `dump` function for `consul_kv` module. When reload, would load the dump file before from consul; when the registered nodes in consul been updated, would dump the upstream nodes into file automatically.
|
||||
|
||||
The `dump` has three optional values now:
|
||||
|
||||
- `path`, the dump file save path
|
||||
- support relative path, eg: `logs/consul_kv.dump`
|
||||
- support absolute path, eg: `/tmp/consul_kv.bin`
|
||||
- make sure the dump file's parent path exist
|
||||
- make sure the `apisix` has the dump file's read-write access permission,eg: `chown www:root conf/upstream.d/`
|
||||
- `load_on_init`, default value is `true`
|
||||
- if `true`, just try to load the data from the dump file before loading data from consul when starting, does not care the dump file exists or not
|
||||
- if `false`, ignore loading data from the dump file
|
||||
- Whether `true` or `false`, we don't need to prepare a dump file for apisix at anytime
|
||||
- `expire`, unit sec, avoiding load expired dump data when load
|
||||
- default `0`, it is unexpired forever
|
||||
- recommend 2592000, which is 30 days(equals 3600 \* 24 \* 30)
|
||||
|
||||
### Register Http API Services
|
||||
|
||||
Service register Key&Value template:
|
||||
|
||||
```
|
||||
Key: {Prefix}/{Service_Name}/{IP}:{Port}
|
||||
Value: {"weight": <Num>, "max_fails": <Num>, "fail_timeout": <Num>}
|
||||
```
|
||||
|
||||
The register consul key use `upstreams` as prefix by default. The http api service name called `webpages` for example, and you can also use `webpages/oneteam/hello` as service name. The api instance of node's ip and port make up new key: `<IP>:<Port>`.
|
||||
|
||||
Now, register nodes into consul:
|
||||
|
||||
```shell
|
||||
curl \
|
||||
-X PUT \
|
||||
-d ' {"weight": 1, "max_fails": 2, "fail_timeout": 1}' \
|
||||
http://127.0.0.1:8500/v1/kv/upstreams/webpages/172.19.5.12:8000
|
||||
|
||||
curl \
|
||||
-X PUT \
|
||||
-d ' {"weight": 1, "max_fails": 2, "fail_timeout": 1}' \
|
||||
http://127.0.0.1:8500/v1/kv/upstreams/webpages/172.19.5.13:8000
|
||||
```
|
||||
|
||||
In some case, same keys exist in different consul servers.
|
||||
To avoid confusion, use the full consul key url path as service name in practice.
|
||||
|
||||
### Upstream setting
|
||||
|
||||
#### L7
|
||||
|
||||
Here is an example of routing a request with a URL of "/*" to a service which named "http://127.0.0.1:8500/v1/kv/upstreams/webpages/" and use consul_kv discovery client in the registry :
|
||||
|
||||
:::note
|
||||
You can fetch the `admin_key` from `config.yaml` and save to an environment variable with the following command:
|
||||
|
||||
```bash
|
||||
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"uri": "/*",
|
||||
"upstream": {
|
||||
"service_name": "http://127.0.0.1:8500/v1/kv/upstreams/webpages/",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "consul_kv"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
The format response as below:
|
||||
|
||||
```json
|
||||
{
|
||||
"node": {
|
||||
"value": {
|
||||
"priority": 0,
|
||||
"update_time": 1612755230,
|
||||
"upstream": {
|
||||
"discovery_type": "consul_kv",
|
||||
"service_name": "http://127.0.0.1:8500/v1/kv/upstreams/webpages/",
|
||||
"hash_on": "vars",
|
||||
"type": "roundrobin",
|
||||
"pass_host": "pass"
|
||||
},
|
||||
"id": "1",
|
||||
"uri": "/*",
|
||||
"create_time": 1612755230,
|
||||
"status": 1
|
||||
},
|
||||
"key": "/apisix/routes/1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You could find more usage in the `apisix/t/discovery/consul_kv.t` file.
|
||||
|
||||
#### L4
|
||||
|
||||
Consul_kv service discovery also supports use in L4, the configuration method is similar to L7.
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/stream_routes/1 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"remote_addr": "127.0.0.1",
|
||||
"upstream": {
|
||||
"scheme": "tcp",
|
||||
"service_name": "http://127.0.0.1:8500/v1/kv/upstreams/webpages/",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "consul_kv"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
You could find more usage in the `apisix/t/discovery/stream/consul_kv.t` file.
|
||||
|
||||
## Debugging API
|
||||
|
||||
It also offers control api for debugging.
|
||||
|
||||
### Memory Dump API
|
||||
|
||||
```shell
|
||||
GET /v1/discovery/consul_kv/dump
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```shell
|
||||
# curl http://127.0.0.1:9090/v1/discovery/consul_kv/dump | jq
|
||||
{
|
||||
"config": {
|
||||
"fetch_interval": 3,
|
||||
"timeout": {
|
||||
"wait": 60,
|
||||
"connect": 6000,
|
||||
"read": 6000
|
||||
},
|
||||
"prefix": "upstreams",
|
||||
"weight": 1,
|
||||
"servers": [
|
||||
"http://172.19.5.30:8500",
|
||||
"http://172.19.5.31:8500"
|
||||
],
|
||||
"keepalive": true,
|
||||
"default_service": {
|
||||
"host": "172.19.5.11",
|
||||
"port": 8899,
|
||||
"metadata": {
|
||||
"fail_timeout": 1,
|
||||
"weight": 1,
|
||||
"max_fails": 1
|
||||
}
|
||||
},
|
||||
"skip_keys": [
|
||||
"upstreams/myapi/gateway/apisix/"
|
||||
]
|
||||
},
|
||||
"services": {
|
||||
"http://172.19.5.31:8500/v1/kv/upstreams/webpages/": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 30513,
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 30514,
|
||||
"weight": 1
|
||||
}
|
||||
],
|
||||
"http://172.19.5.30:8500/v1/kv/upstreams/1614480/grpc/": [
|
||||
{
|
||||
"host": "172.19.5.51",
|
||||
"port": 50051,
|
||||
"weight": 1
|
||||
}
|
||||
],
|
||||
"http://172.19.5.30:8500/v1/kv/upstreams/webpages/": [
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 30511,
|
||||
"weight": 1
|
||||
},
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 30512,
|
||||
"weight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Show Dump File API
|
||||
|
||||
It offers another control api for dump file view now. Maybe would add more api for debugging in future.
|
||||
|
||||
```shell
|
||||
GET /v1/discovery/consul_kv/show_dump_file
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```shell
|
||||
curl http://127.0.0.1:9090/v1/discovery/consul_kv/show_dump_file | jq
|
||||
{
|
||||
"services": {
|
||||
"http://172.19.5.31:8500/v1/kv/upstreams/1614480/webpages/": [
|
||||
{
|
||||
"host": "172.19.5.12",
|
||||
"port": 8000,
|
||||
"weight": 120
|
||||
},
|
||||
{
|
||||
"host": "172.19.5.13",
|
||||
"port": 8000,
|
||||
"weight": 120
|
||||
}
|
||||
]
|
||||
},
|
||||
"expire": 0,
|
||||
"last_update": 1615877468
|
||||
}
|
||||
```
|
@@ -0,0 +1,72 @@
|
||||
---
|
||||
title: Control Plane Service Discovery
|
||||
keywords:
|
||||
- API Gateway
|
||||
- Apache APISIX
|
||||
- ZooKeeper
|
||||
- Nacos
|
||||
- APISIX-Seed
|
||||
description: This documentation describes implementing service discovery through Nacos and ZooKeeper on the API Gateway APISIX Control Plane.
|
||||
---
|
||||
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
This document describes how to implement service discovery with Nacos and Zookeeper on the APISIX Control Plane.
|
||||
|
||||
## APISIX-Seed Architecture
|
||||
|
||||
Apache APISIX has supported Data Plane service discovery in the early days, and now APISIX also supports Control Plane service discovery through the [APISIX-Seed](https://github.com/api7/apisix-seed) project. The following figure shows the APISIX-Seed architecture diagram.
|
||||
|
||||

|
||||
|
||||
The specific information represented by the figures in the figure is as follows:
|
||||
|
||||
1. Register an upstream with APISIX and specify the service discovery type. APISIX-Seed will watch APISIX resource changes in etcd, filter discovery types, and obtain service names.
|
||||
2. APISIX-Seed subscribes the specified service name to the service registry to obtain changes to the corresponding service.
|
||||
3. After the client registers the service with the service registry, APISIX-Seed will obtain the new service information and write the updated service node into etcd;
|
||||
4. When the corresponding resources in etcd change, APISIX worker will refresh the latest service node information to memory.
|
||||
|
||||
:::note
|
||||
|
||||
It should be noted that after the introduction of APISIX-Seed, if the service of the registry changes frequently, the data in etcd will also change frequently. So, it is best to set the `--auto-compaction` option when starting etcd to compress the history periodically to avoid etcd eventually exhausting its storage space. Please refer to [revisions](https://etcd.io/docs/v3.5/learning/api/#revisions).
|
||||
|
||||
:::
|
||||
|
||||
## Why APISIX-Seed
|
||||
|
||||
- Network topology becomes simpler
|
||||
|
||||
APISIX does not need to maintain a network connection with each registry, and only needs to pay attention to the configuration information in etcd. This will greatly simplify the network topology.
|
||||
|
||||
- Total data volume about upstream service becomes smaller
|
||||
|
||||
Due to the characteristics of the registry, APISIX may store the full amount of registry service data in the worker, such as consul_kv. By introducing APISIX-Seed, each process of APISIX will not need to additionally cache upstream service-related information.
|
||||
|
||||
- Easier to manage
|
||||
|
||||
Service discovery configuration needs to be configured once per APISIX instance. By introducing APISIX-Seed, Apache APISIX will be in different to the configuration changes of the service registry.
|
||||
|
||||
## Supported service registry
|
||||
|
||||
ZooKeeper and Nacos are currently supported, and more service registries will be supported in the future. For more information, please refer to: [APISIX Seed](https://github.com/api7/apisix-seed#apisix-seed-for-apache-apisix).
|
||||
|
||||
- If you want to enable control plane ZooKeeper service discovery, please refer to: [ZooKeeper Deployment Tutorial](https://github.com/api7/apisix-seed/blob/main/docs/en/latest/zookeeper.md).
|
||||
|
||||
- If you want to enable control plane Nacos service discovery, please refer to: [Nacos Deployment Tutorial](https://github.com/api7/apisix-seed/blob/main/docs/en/latest/nacos.md).
|
@@ -0,0 +1,155 @@
|
||||
---
|
||||
title: DNS
|
||||
---
|
||||
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
## service discovery via DNS
|
||||
|
||||
Some service discovery system, like Consul, support exposing service information
|
||||
via DNS. Therefore we can use this way to discover service directly. Both L4 and L7 are supported.
|
||||
|
||||
First of all, we need to configure the address of DNS servers:
|
||||
|
||||
```yaml
|
||||
# add this to config.yaml
|
||||
discovery:
|
||||
dns:
|
||||
servers:
|
||||
- "127.0.0.1:8600" # use the real address of your dns server
|
||||
```
|
||||
|
||||
Unlike configuring the domain in the Upstream's `nodes` field, service discovery via
|
||||
DNS will return all records. For example, with upstream configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"discovery_type": "dns",
|
||||
"service_name": "test.consul.service",
|
||||
"type": "roundrobin"
|
||||
}
|
||||
```
|
||||
|
||||
and `test.consul.service` be resolved as `1.1.1.1` and `1.1.1.2`, this result will be the same as:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"type": "roundrobin",
|
||||
"nodes": [
|
||||
{"host": "1.1.1.1", "weight": 1},
|
||||
{"host": "1.1.1.2", "weight": 1}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Note that all the IPs from `test.consul.service` share the same weight.
|
||||
|
||||
The resolved records will be cached according to their TTL.
|
||||
For service whose record is not in the cache, we will query it in the order of `SRV -> A -> AAAA -> CNAME` by default.
|
||||
When we refresh the cache record, we will try from the last previously successful type.
|
||||
We can also customize the order by modifying the configuration file.
|
||||
|
||||
```yaml
|
||||
# add this to config.yaml
|
||||
discovery:
|
||||
dns:
|
||||
servers:
|
||||
- "127.0.0.1:8600" # use the real address of your dns server
|
||||
order: # order in which to try different dns record types when resolving
|
||||
- last # "last" will try the last previously successful type for a hostname.
|
||||
- SRV
|
||||
- A
|
||||
- AAAA
|
||||
- CNAME
|
||||
```
|
||||
|
||||
If you want to specify the port for the upstream server, you can add it to the `service_name`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"discovery_type": "dns",
|
||||
"service_name": "test.consul.service:1980",
|
||||
"type": "roundrobin"
|
||||
}
|
||||
```
|
||||
|
||||
Another way to do it is via the SRV record, see below.
|
||||
|
||||
### SRV record
|
||||
|
||||
By using SRV record you can specify the port and the weight of a service.
|
||||
|
||||
Assumed you have the SRV record like this:
|
||||
|
||||
```
|
||||
; under the section of blah.service
|
||||
A 300 IN A 1.1.1.1
|
||||
B 300 IN A 1.1.1.2
|
||||
B 300 IN A 1.1.1.3
|
||||
|
||||
; name TTL type priority weight port
|
||||
srv 86400 IN SRV 10 60 1980 A
|
||||
srv 86400 IN SRV 20 20 1981 B
|
||||
```
|
||||
|
||||
Upstream configuration like:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"discovery_type": "dns",
|
||||
"service_name": "srv.blah.service",
|
||||
"type": "roundrobin"
|
||||
}
|
||||
```
|
||||
|
||||
is the same as:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"type": "roundrobin",
|
||||
"nodes": [
|
||||
{"host": "1.1.1.1", "port": 1980, "weight": 60, "priority": -10},
|
||||
{"host": "1.1.1.2", "port": 1981, "weight": 10, "priority": -20},
|
||||
{"host": "1.1.1.3", "port": 1981, "weight": 10, "priority": -20}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Note that two records of domain B split the weight evenly.
|
||||
For SRV record, nodes with lower priority are chosen first, so the final priority is negative.
|
||||
|
||||
As for 0 weight SRV record, the [RFC 2782](https://www.ietf.org/rfc/rfc2782.txt) says:
|
||||
|
||||
> Domain administrators SHOULD use Weight 0 when there isn't any server
|
||||
selection to do, to make the RR easier to read for humans (less
|
||||
noisy). In the presence of records containing weights greater
|
||||
than 0, records with weight 0 should have a very small chance of
|
||||
being selected.
|
||||
|
||||
We treat weight 0 record has a weight of 1 so the node "have a very small chance of
|
||||
being selected", which is also the common way to treat this type of record.
|
||||
|
||||
For SRV record which has port 0, we will fallback to use the upstream protocol's default port.
|
||||
You can also specify the port in the "service_name" field directly, like "srv.blah.service:8848".
|
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: eureka
|
||||
---
|
||||
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
Apache APISIX supports service discovery via Eureka. For the details, please start your
|
||||
reading from [Supported discovery registries](../discovery.md#supported-discovery-registries).
|
@@ -0,0 +1,406 @@
|
||||
---
|
||||
title: Kubernetes
|
||||
keywords:
|
||||
- Kubernetes
|
||||
- Apache APISIX
|
||||
- Service discovery
|
||||
- Cluster
|
||||
- API Gateway
|
||||
description: This article introduce how to perform service discovery based on Kubernetes in Apache APISIX and summarize related issues.
|
||||
---
|
||||
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
## Summary
|
||||
|
||||
The [_Kubernetes_](https://kubernetes.io/) service discovery [_List-Watch_](https://kubernetes.io/docs/reference/using-api/api-concepts/) real-time changes of [_Endpoints_](https://kubernetes.io/docs/concepts/services-networking/service/) resources, then store theirs value into `ngx.shared.DICT`.
|
||||
|
||||
Discovery also provides a node query interface in accordance with the [_APISIX Discovery Specification_](../discovery.md).
|
||||
|
||||
## How To Use
|
||||
|
||||
Kubernetes service discovery both support single-cluster and multi-cluster modes, applicable to the case where the service is distributed in single or multiple Kubernetes clusters.
|
||||
|
||||
### Single-Cluster Mode Configuration
|
||||
|
||||
A detailed configuration for single-cluster mode Kubernetes service discovery is as follows:
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
kubernetes:
|
||||
service:
|
||||
# apiserver schema, options [http, https]
|
||||
schema: https #default https
|
||||
|
||||
# apiserver host, options [ipv4, ipv6, domain, environment variable]
|
||||
host: ${KUBERNETES_SERVICE_HOST} #default ${KUBERNETES_SERVICE_HOST}
|
||||
|
||||
# apiserver port, options [port number, environment variable]
|
||||
port: ${KUBERNETES_SERVICE_PORT} #default ${KUBERNETES_SERVICE_PORT}
|
||||
|
||||
client:
|
||||
# serviceaccount token or token_file
|
||||
token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
|
||||
#token: |-
|
||||
# eyJhbGciOiJSUzI1NiIsImtpZCI6Ikx5ME1DNWdnbmhQNkZCNlZYMXBsT3pYU3BBS2swYzBPSkN3ZnBESGpkUEEif
|
||||
# 6Ikx5ME1DNWdnbmhQNkZCNlZYMXBsT3pYU3BBS2swYzBPSkN3ZnBESGpkUEEifeyJhbGciOiJSUzI1NiIsImtpZCI
|
||||
|
||||
default_weight: 50 # weight assigned to each discovered endpoint. default 50, minimum 0
|
||||
|
||||
# kubernetes discovery support namespace_selector
|
||||
# you can use one of [equal, not_equal, match, not_match] filter namespace
|
||||
namespace_selector:
|
||||
# only save endpoints with namespace equal default
|
||||
equal: default
|
||||
|
||||
# only save endpoints with namespace not equal default
|
||||
#not_equal: default
|
||||
|
||||
# only save endpoints with namespace match one of [default, ^my-[a-z]+$]
|
||||
#match:
|
||||
#- default
|
||||
#- ^my-[a-z]+$
|
||||
|
||||
# only save endpoints with namespace not match one of [default, ^my-[a-z]+$ ]
|
||||
#not_match:
|
||||
#- default
|
||||
#- ^my-[a-z]+$
|
||||
|
||||
# kubernetes discovery support label_selector
|
||||
# for the expression of label_selector, please refer to https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
|
||||
label_selector: |-
|
||||
first="a",second="b"
|
||||
|
||||
# reserved lua shared memory size,1m memory can store about 1000 pieces of endpoint
|
||||
shared_size: 1m #default 1m
|
||||
|
||||
# if watch_endpoint_slices setting true, watch apiserver with endpointslices instead of endpoints
|
||||
watch_endpoint_slices: false #default false
|
||||
```
|
||||
|
||||
If the Kubernetes service discovery runs inside a pod, you can use minimal configuration:
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
kubernetes: { }
|
||||
```
|
||||
|
||||
If the Kubernetes service discovery runs outside a pod, you need to create or select a specified [_ServiceAccount_](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/), then get its token value, and use following configuration:
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
kubernetes:
|
||||
service:
|
||||
schema: https
|
||||
host: # enter apiserver host value here
|
||||
port: # enter apiserver port value here
|
||||
client:
|
||||
token: # enter serviceaccount token value here
|
||||
#token_file: # enter file path here
|
||||
```
|
||||
|
||||
### Single-Cluster Mode Query Interface
|
||||
|
||||
The Kubernetes service discovery provides a query interface in accordance with the [_APISIX Discovery Specification_](../discovery.md).
|
||||
|
||||
**function:**
|
||||
nodes(service_name)
|
||||
|
||||
**description:**
|
||||
nodes() function attempts to look up the ngx.shared.DICT for nodes corresponding to service_name, \
|
||||
service_name should match pattern: _[namespace]/[name]:[portName]_
|
||||
|
||||
+ namespace: The namespace where the Kubernetes endpoints is located
|
||||
|
||||
+ name: The name of the Kubernetes endpoints
|
||||
|
||||
+ portName: The `ports.name` value in the Kubernetes endpoints, if there is no `ports.name`, use `targetPort`, `port` instead. If `ports.name` exists, then port number cannot be used.
|
||||
|
||||
**return value:**
|
||||
if the Kubernetes endpoints value is as follows:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Endpoints
|
||||
metadata:
|
||||
name: plat-dev
|
||||
namespace: default
|
||||
subsets:
|
||||
- addresses:
|
||||
- ip: "10.5.10.109"
|
||||
- ip: "10.5.10.110"
|
||||
ports:
|
||||
- port: 3306
|
||||
name: port
|
||||
```
|
||||
|
||||
a nodes("default/plat-dev:port") call will get follow result:
|
||||
|
||||
```
|
||||
{
|
||||
{
|
||||
host="10.5.10.109",
|
||||
port= 3306,
|
||||
weight= 50,
|
||||
},
|
||||
{
|
||||
host="10.5.10.110",
|
||||
port= 3306,
|
||||
weight= 50,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Cluster Mode Configuration
|
||||
|
||||
A detailed configuration for multi-cluster mode Kubernetes service discovery is as follows:
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
kubernetes:
|
||||
- id: release # a custom name refer to the cluster, pattern ^[a-z0-9]{1,8}
|
||||
service:
|
||||
# apiserver schema, options [http, https]
|
||||
schema: https #default https
|
||||
|
||||
# apiserver host, options [ipv4, ipv6, domain, environment variable]
|
||||
host: "1.cluster.com"
|
||||
|
||||
# apiserver port, options [port number, environment variable]
|
||||
port: "6443"
|
||||
|
||||
client:
|
||||
# serviceaccount token or token_file
|
||||
token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
|
||||
#token: |-
|
||||
# eyJhbGciOiJSUzI1NiIsImtpZCI6Ikx5ME1DNWdnbmhQNkZCNlZYMXBsT3pYU3BBS2swYzBPSkN3ZnBESGpkUEEif
|
||||
# 6Ikx5ME1DNWdnbmhQNkZCNlZYMXBsT3pYU3BBS2swYzBPSkN3ZnBESGpkUEEifeyJhbGciOiJSUzI1NiIsImtpZCI
|
||||
|
||||
default_weight: 50 # weight assigned to each discovered endpoint. default 50, minimum 0
|
||||
|
||||
# kubernetes discovery support namespace_selector
|
||||
# you can use one of [equal, not_equal, match, not_match] filter namespace
|
||||
namespace_selector:
|
||||
# only save endpoints with namespace equal default
|
||||
equal: default
|
||||
|
||||
# only save endpoints with namespace not equal default
|
||||
#not_equal: default
|
||||
|
||||
# only save endpoints with namespace match one of [default, ^my-[a-z]+$]
|
||||
#match:
|
||||
#- default
|
||||
#- ^my-[a-z]+$
|
||||
|
||||
# only save endpoints with namespace not match one of [default, ^my-[a-z]+$]
|
||||
#not_match:
|
||||
#- default
|
||||
#- ^my-[a-z]+$
|
||||
|
||||
# kubernetes discovery support label_selector
|
||||
# for the expression of label_selector, please refer to https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
|
||||
label_selector: |-
|
||||
first="a",second="b"
|
||||
|
||||
# reserved lua shared memory size,1m memory can store about 1000 pieces of endpoint
|
||||
shared_size: 1m #default 1m
|
||||
|
||||
# if watch_endpoint_slices setting true, watch apiserver with endpointslices instead of endpoints
|
||||
watch_endpoint_slices: false #default false
|
||||
```
|
||||
|
||||
Multi-Kubernetes service discovery does not fill default values for service and client fields, you need to fill them according to the cluster configuration.
|
||||
|
||||
### Multi-Cluster Mode Query Interface
|
||||
|
||||
The Kubernetes service discovery provides a query interface in accordance with the [_APISIX Discovery Specification_](../discovery.md).
|
||||
|
||||
**function:**
|
||||
nodes(service_name)
|
||||
|
||||
**description:**
|
||||
nodes() function attempts to look up the ngx.shared.DICT for nodes corresponding to service_name, \
|
||||
service_name should match pattern: _[id]/[namespace]/[name]:[portName]_
|
||||
|
||||
+ id: value defined in service discovery configuration
|
||||
|
||||
+ namespace: The namespace where the Kubernetes endpoints is located
|
||||
|
||||
+ name: The name of the Kubernetes endpoints
|
||||
|
||||
+ portName: The `ports.name` value in the Kubernetes endpoints, if there is no `ports.name`, use `targetPort`, `port` instead. If `ports.name` exists, then port number cannot be used.
|
||||
|
||||
**return value:**
|
||||
if the Kubernetes endpoints value is as follows:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Endpoints
|
||||
metadata:
|
||||
name: plat-dev
|
||||
namespace: default
|
||||
subsets:
|
||||
- addresses:
|
||||
- ip: "10.5.10.109"
|
||||
- ip: "10.5.10.110"
|
||||
ports:
|
||||
- port: 3306
|
||||
name: port
|
||||
```
|
||||
|
||||
a nodes("release/default/plat-dev:port") call will get follow result:
|
||||
|
||||
```
|
||||
{
|
||||
{
|
||||
host="10.5.10.109",
|
||||
port= 3306,
|
||||
weight= 50,
|
||||
},
|
||||
{
|
||||
host="10.5.10.110",
|
||||
port= 3306,
|
||||
weight= 50,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Q&A
|
||||
|
||||
**Q: Why only support configuration token to access _Kubernetes APIServer_?**
|
||||
|
||||
A: Usually, we will use three ways to complete the authentication of _Kubernetes APIServer_:
|
||||
|
||||
+ mTLS
|
||||
+ Token
|
||||
+ Basic authentication
|
||||
|
||||
Because lua-resty-http does not currently support mTLS, and basic authentication is not recommended, so currently only the token authentication method is implemented.
|
||||
|
||||
**Q: APISIX inherits Nginx's multiple process model, does it mean that each nginx worker process will [_List-Watch_](https://kubernetes.io/docs/reference/using-api/api-concepts/) kubernetes endpoints resources?**
|
||||
|
||||
A: The Kubernetes service discovery only uses privileged processes to [_List-Watch_](https://kubernetes.io/docs/reference/using-api/api-concepts/) Kubernetes endpoints resources, then store theirs value into `ngx.shared.DICT`, worker processes get results by querying `ngx.shared.DICT`.
|
||||
|
||||
**Q: What permissions do [_ServiceAccount_](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) require?**
|
||||
|
||||
A: ServiceAccount requires the permissions of cluster-level [ get, list, watch ] endpoints resources, the declarative definition is as follows:
|
||||
|
||||
```yaml
|
||||
kind: ServiceAccount
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: apisix-test
|
||||
namespace: default
|
||||
---
|
||||
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: apisix-test
|
||||
rules:
|
||||
- apiGroups: [ "" ]
|
||||
resources: [ endpoints,endpointslices ]
|
||||
verbs: [ get,list,watch ]
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: apisix-test
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: apisix-test
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: apisix-test
|
||||
namespace: default
|
||||
```
|
||||
|
||||
**Q: How to get [_ServiceAccount_](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) token value?**
|
||||
|
||||
A: Assume your [_ServiceAccount_](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) located in namespace apisix and name is Kubernetes-discovery, you can use the following steps to get token value.
|
||||
|
||||
1. Get secret name. You can execute the following command, the output of the first column is the secret name we want:
|
||||
|
||||
```shell
|
||||
kubectl -n apisix get secrets | grep kubernetes-discovery
|
||||
```
|
||||
|
||||
2. Get token value. Assume secret resources name is kubernetes-discovery-token-c64cv, you can execute the following command, the output is the service account token value we want:
|
||||
|
||||
```shell
|
||||
kubectl -n apisix get secret kubernetes-discovery-token-c64cv -o jsonpath={.data.token} | base64 -d
|
||||
```
|
||||
|
||||
## Debugging API
|
||||
|
||||
It also offers control api for debugging.
|
||||
|
||||
### Memory Dump API
|
||||
|
||||
To query/list the nodes discoverd by kubernetes discovery, you can query the /v1/discovery/kubernetes/dump control API endpoint like so:
|
||||
|
||||
```shell
|
||||
GET /v1/discovery/kubernetes/dump
|
||||
```
|
||||
|
||||
Which will yield the following response:
|
||||
|
||||
```
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"endpoints": [
|
||||
{
|
||||
"value": "{\"https\":[{\"host\":\"172.18.164.170\",\"port\":6443,\"weight\":50},{\"host\":\"172.18.164.171\",\"port\":6443,\"weight\":50},{\"host\":\"172.18.164.172\",\"port\":6443,\"weight\":50}]}",
|
||||
"name": "default/kubernetes"
|
||||
},
|
||||
{
|
||||
"value": "{\"metrics\":[{\"host\":\"172.18.164.170\",\"port\":2379,\"weight\":50},{\"host\":\"172.18.164.171\",\"port\":2379,\"weight\":50},{\"host\":\"172.18.164.172\",\"port\":2379,\"weight\":50}]}",
|
||||
"name": "kube-system/etcd"
|
||||
},
|
||||
{
|
||||
"value": "{\"http-85\":[{\"host\":\"172.64.89.2\",\"port\":85,\"weight\":50}]}",
|
||||
"name": "test-ws/testing"
|
||||
}
|
||||
],
|
||||
"id": "first"
|
||||
}
|
||||
],
|
||||
"config": [
|
||||
{
|
||||
"default_weight": 50,
|
||||
"id": "first",
|
||||
"client": {
|
||||
"token": "xxx"
|
||||
},
|
||||
"service": {
|
||||
"host": "172.18.164.170",
|
||||
"port": "6443",
|
||||
"schema": "https"
|
||||
},
|
||||
"shared_size": "1m"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
@@ -0,0 +1,280 @@
|
||||
---
|
||||
title: nacos
|
||||
---
|
||||
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
## Service discovery via Nacos
|
||||
|
||||
The performance of this module needs to be improved:
|
||||
|
||||
1. send the request parallelly.
|
||||
|
||||
### Configuration for Nacos
|
||||
|
||||
Add following configuration in `conf/config.yaml` :
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
nacos:
|
||||
host:
|
||||
- "http://${username}:${password}@${host1}:${port1}"
|
||||
prefix: "/nacos/v1/"
|
||||
fetch_interval: 30 # default 30 sec
|
||||
# `weight` is the `default_weight` that will be attached to each discovered node that
|
||||
# doesn't have a weight explicitly provided in nacos results
|
||||
weight: 100 # default 100
|
||||
timeout:
|
||||
connect: 2000 # default 2000 ms
|
||||
send: 2000 # default 2000 ms
|
||||
read: 5000 # default 5000 ms
|
||||
```
|
||||
|
||||
And you can config it in short by default value:
|
||||
|
||||
```yaml
|
||||
discovery:
|
||||
nacos:
|
||||
host:
|
||||
- "http://192.168.33.1:8848"
|
||||
```
|
||||
|
||||
### Upstream setting
|
||||
|
||||
#### L7
|
||||
|
||||
Here is an example of routing a request with an URI of "/nacos/*" to a service which named "http://192.168.33.1:8848/nacos/v1/ns/instance/list?serviceName=APISIX-NACOS" and use nacos discovery client in the registry:
|
||||
|
||||
:::note
|
||||
You can fetch the `admin_key` from `config.yaml` and save to an environment variable with the following command:
|
||||
|
||||
```bash
|
||||
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"uri": "/nacos/*",
|
||||
"upstream": {
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "nacos"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
The formatted response as below:
|
||||
|
||||
```json
|
||||
{
|
||||
"node": {
|
||||
"key": "\/apisix\/routes\/1",
|
||||
"value": {
|
||||
"id": "1",
|
||||
"create_time": 1615796097,
|
||||
"status": 1,
|
||||
"update_time": 1615799165,
|
||||
"upstream": {
|
||||
"hash_on": "vars",
|
||||
"pass_host": "pass",
|
||||
"scheme": "http",
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "nacos"
|
||||
},
|
||||
"priority": 0,
|
||||
"uri": "\/nacos\/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### L4
|
||||
|
||||
Nacos service discovery also supports use in L4, the configuration method is similar to L7.
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/stream_routes/1 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"remote_addr": "127.0.0.1",
|
||||
"upstream": {
|
||||
"scheme": "tcp",
|
||||
"discovery_type": "nacos",
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### discovery_args
|
||||
|
||||
| Name | Type | Requirement | Default | Valid | Description |
|
||||
| ------------ | ------ | ----------- | ------- | ----- | ------------------------------------------------------------ |
|
||||
| namespace_id | string | optional | public | | This parameter is used to specify the namespace of the corresponding service |
|
||||
| group_name | string | optional | DEFAULT_GROUP | | This parameter is used to specify the group of the corresponding service |
|
||||
|
||||
#### Specify the namespace
|
||||
|
||||
Example of routing a request with an URI of "/nacosWithNamespaceId/*" to a service with name, namespaceId "http://192.168.33.1:8848/nacos/v1/ns/instance/list?serviceName=APISIX-NACOS&namespaceId=test_ns" and use nacos discovery client in the registry:
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/routes/2 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"uri": "/nacosWithNamespaceId/*",
|
||||
"upstream": {
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "nacos",
|
||||
"discovery_args": {
|
||||
"namespace_id": "test_ns"
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
The formatted response as below:
|
||||
|
||||
```json
|
||||
{
|
||||
"node": {
|
||||
"key": "\/apisix\/routes\/2",
|
||||
"value": {
|
||||
"id": "2",
|
||||
"create_time": 1615796097,
|
||||
"status": 1,
|
||||
"update_time": 1615799165,
|
||||
"upstream": {
|
||||
"hash_on": "vars",
|
||||
"pass_host": "pass",
|
||||
"scheme": "http",
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "nacos",
|
||||
"discovery_args": {
|
||||
"namespace_id": "test_ns"
|
||||
}
|
||||
},
|
||||
"priority": 0,
|
||||
"uri": "\/nacosWithNamespaceId\/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Specify the group
|
||||
|
||||
Example of routing a request with an URI of "/nacosWithGroupName/*" to a service with name, groupName "http://192.168.33.1:8848/nacos/v1/ns/instance/list?serviceName=APISIX-NACOS&groupName=test_group" and use nacos discovery client in the registry:
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/routes/3 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"uri": "/nacosWithGroupName/*",
|
||||
"upstream": {
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "nacos",
|
||||
"discovery_args": {
|
||||
"group_name": "test_group"
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
The formatted response as below:
|
||||
|
||||
```json
|
||||
{
|
||||
"node": {
|
||||
"key": "\/apisix\/routes\/3",
|
||||
"value": {
|
||||
"id": "3",
|
||||
"create_time": 1615796097,
|
||||
"status": 1,
|
||||
"update_time": 1615799165,
|
||||
"upstream": {
|
||||
"hash_on": "vars",
|
||||
"pass_host": "pass",
|
||||
"scheme": "http",
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "nacos",
|
||||
"discovery_args": {
|
||||
"group_name": "test_group"
|
||||
}
|
||||
},
|
||||
"priority": 0,
|
||||
"uri": "\/nacosWithGroupName\/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Specify the namespace and group
|
||||
|
||||
Example of routing a request with an URI of "/nacosWithNamespaceIdAndGroupName/*" to a service with name, namespaceId, groupName "http://192.168.33.1:8848/nacos/v1/ns/instance/list?serviceName=APISIX-NACOS&namespaceId=test_ns&groupName=test_group" and use nacos discovery client in the registry:
|
||||
|
||||
```shell
|
||||
$ curl http://127.0.0.1:9180/apisix/admin/routes/4 -H "X-API-KEY: $admin_key" -X PUT -i -d '
|
||||
{
|
||||
"uri": "/nacosWithNamespaceIdAndGroupName/*",
|
||||
"upstream": {
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "nacos",
|
||||
"discovery_args": {
|
||||
"namespace_id": "test_ns",
|
||||
"group_name": "test_group"
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
The formatted response as below:
|
||||
|
||||
```json
|
||||
{
|
||||
"node": {
|
||||
"key": "\/apisix\/routes\/4",
|
||||
"value": {
|
||||
"id": "4",
|
||||
"create_time": 1615796097,
|
||||
"status": 1,
|
||||
"update_time": 1615799165,
|
||||
"upstream": {
|
||||
"hash_on": "vars",
|
||||
"pass_host": "pass",
|
||||
"scheme": "http",
|
||||
"service_name": "APISIX-NACOS",
|
||||
"type": "roundrobin",
|
||||
"discovery_type": "nacos",
|
||||
"discovery_args": {
|
||||
"namespace_id": "test_ns",
|
||||
"group_name": "test_group"
|
||||
}
|
||||
},
|
||||
"priority": 0,
|
||||
"uri": "\/nacosWithNamespaceIdAndGroupName\/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user