title | keywords | description | |||
---|---|---|---|---|---|
Deployment modes |
|
Documentation about the three deployment modes of Apache APISIX. |
APISIX has three different deployment modes for different production use cases. The table below summarises the deployment modes:
Deployment mode | Roles | Description |
---|---|---|
traditional | traditional | Data plane and control plane are deployed together. enable_admin attribute should be disabled manually. |
decoupled | data_plane / control_plane | Data plane and control plane are deployed independently. |
standalone | data_plane / traditional | The data_plane mode loads configuration from a local YAML file, while the traditional mode expects configuration through Admin API. |
Each of these deployment modes are explained in detail below.
In the traditional deployment mode, one instance of APISIX will be both the data_plane
and the control_plane
.
An example configuration of the traditional deployment mode is shown below:
apisix:
node_listen:
- port: 9080
deployment:
role: traditional
role_traditional:
config_provider: etcd
admin:
admin_listen:
port: 9180
etcd:
host:
- http://${etcd_IP}:${etcd_Port}
prefix: /apisix
timeout: 30
#END
The instance of APISIX deployed as the traditional role will:
- Listen on port
9080
to handle user requests, controlled bynode_listen
. - Listen on port
9180
to handle Admin API requests, controlled byadmin_listen
.
In the decoupled deployment mode the data_plane
and control_plane
instances of APISIX are deployed separately, i.e., one instance of APISIX is configured to be a data plane and the other to be a control plane.
The instance of APISIX deployed as the data plane will:
Once the service is started, it will handle the user requests.
The example below shows the configuration of an APISIX instance as data plane in the decoupled mode:
deployment:
role: data_plane
role_data_plane:
config_provider: etcd
#END
The instance of APISIX deployed as the control plane will:
- Listen on port
9180
and handle Admin API requests.
The example below shows the configuration of an APISIX instance as control plane in the decoupled mode:
deployment:
role: control_plane
role_control_plane:
config_provider: etcd
etcd:
host:
- https://${etcd_IP}:${etcd_Port}
prefix: /apisix
timeout: 30
#END
Turning on the APISIX node in Standalone mode will no longer use the default etcd as the configuration center.
This method is more suitable for two types of users:
- Kubernetes(k8s):Declarative API that dynamically updates the routing rules with a full yaml configuration.
- Different configuration centers: There are many implementations of the configuration center, such as Consul, etc., using the full yaml file for intermediate conversion.
Now, we have two standalone running modes, file-driven and API-driven.
-
The file-driven mode is the kind APISIX has always supported.
The routing rules in the
conf/apisix.yaml
file are loaded into memory immediately after the APISIX node service starts. At each interval (default: 1 second), APISIX checks for updates to the file. If changes are detected, it reloads the rules.Note: Reloading and updating routing rules are all hot memory updates. There is no replacement of working processes, since it's a hot update.
This requires us to set the APISIX role to data plane. That is, set
deployment.role
todata_plane
anddeployment.role_data_plane.config_provider
toyaml
.Refer to the example below:
deployment: role: data_plane role_data_plane: config_provider: yaml #END
This makes it possible to disable the Admin API and discover configuration changes and reloads based on the local file system.
-
The API-driven is an emerging paradigm for standalone.
The routing rules will be entirely in memory and not in a file, and it will need to be updated using the dedicated Standalone Admin API.
I.e. we need to send an HTTP PUT request to this API containing the configuration in JSON or YAML format, which will flush the configuration used by each worker in the current APISIX instance.
Changes will overwrite the entire configuration and take effect immediately without requiring a reboot, as it is hot updated.
This requires us to set the APISIX role to traditional (since we need to start both the API gateway and the Admin API endpoint) and use the yaml config provider. That is, set
deployment.role
totraditional
anddeployment.role_traditional.config_provider
toyaml
.Refer to the example below:
deployment: role: traditional role_traditional: config_provider: yaml #END
This disables the local file source of configuration in favor of the API. When APISIX starts, it uses the empty configuration until you update it via the API.
The following are API endpoints:
## Update configuration ## The conf_version is not required, if it is not entered by the client, the current 10-digit epoch time is used by default. curl -X PUT http://127.0.0.1:9180/apisix/admin/configs?conf_version=1234 \ -H "X-API-KEY: <apikey>" -H "Content-Type: application/json" ## or application/yaml --data-binary @config.json ## Get latest configuration curl -X GET http://127.0.0.1:9180/apisix/admin/configs -H "X-API-KEY: <apikey>" -H "Accept: application/json" ## or application/yaml
The update API validates the input and returns an error if it is invalid. If the configuration is accepted, it responds with a
202 Accepted
status and includes the latest configuration version in theX-APISIX-Conf-Version
header.The get API also returns the version number via the
X-APISIX-Conf-Version
header, and returns a response body containing the configuration in a specific format as requested by the clientAccept
header.These APIs apply the same security requirements as the Admin API — such as API key, TLS/mTLS, CORS, and IP allowlist — no changes or additions.
The API accepts input in the same format as the file-based mode described above, although it also allows the user to input JSON instead of just YAML. The following example still applies. However, the API does not rely on the
#END
suffix because HTTP will guarantee input integrity.Note: In this case, the Admin API based on etcd is not available. The configuration can only be flushed as a whole, rather than modified partially, and the client must send a request containing the complete new configuration to the API.
All of the rules are stored in one file which named conf/apisix.yaml
,
APISIX checks if this file has any change every second.
If the file is changed & it ends with #END
,
APISIX loads the rules from this file and updates its memory.
Here is a mini example:
routes:
-
uri: /hello
upstream:
nodes:
"127.0.0.1:1980": 1
type: roundrobin
#END
WARNING: APISIX will not load the rules into memory from file conf/apisix.yaml
if there is no #END
at the end.
Environment variables can also be used like so:
routes:
-
uri: /hello
upstream:
nodes:
"${{UPSTREAM_ADDR}}": 1
type: roundrobin
#END
WARNING: When using docker to deploy APISIX in standalone mode. New environment variables added to apisix.yaml
while APISIX has been initialized will only take effect after a reload.
More information about using environment variables can be found here.
Single Route:
routes:
-
uri: /hello
upstream:
nodes:
"127.0.0.1:1980": 1
type: roundrobin
#END
Multiple Routes:
routes:
-
uri: /hello
upstream:
nodes:
"127.0.0.1:1980": 1
type: roundrobin
-
uri: /hello2
upstream:
nodes:
"127.0.0.1:1981": 1
type: roundrobin
#END
routes:
-
uri: /hello
service_id: 1
services:
-
id: 1
upstream:
nodes:
"127.0.0.1:1980": 1
type: roundrobin
#END
routes:
-
uri: /hello
upstream_id: 1
upstreams:
-
id: 1
nodes:
"127.0.0.1:1980": 1
type: roundrobin
#END
routes:
-
uri: /hello
service_id: 1
services:
-
id: 1
upstream_id: 2
upstreams:
-
id: 2
nodes:
"127.0.0.1:1980": 1
type: roundrobin
#END
# plugins listed here will be hot reloaded and override the boot configuration
plugins:
- name: ip-restriction
- name: jwt-auth
- name: mqtt-proxy
stream: true # set 'stream' to true for stream plugins
#END
plugin_configs:
-
id: 1
plugins:
response-rewrite:
body: "hello\n"
routes:
- id: 1
uri: /hello
plugin_config_id: 1
upstream:
nodes:
"127.0.0.1:1980": 1
type: roundrobin
#END
ssls:
-
cert: |
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIJAI3Meu/gJVTLMA0GCSqGSIb3DQEBCwUAMG4xCzAJBgNV
BAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwISGFuZ3pob3UxDTAL
BgNVBAoMBHRlc3QxDTALBgNVBAsMBHRlc3QxGzAZBgNVBAMMEmV0Y2QuY2x1c3Rl
ci5sb2NhbDAeFw0yMDEwMjgwMzMzMDJaFw0yMTEwMjgwMzMzMDJaMG4xCzAJBgNV
BAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwISGFuZ3pob3UxDTAL
BgNVBAoMBHRlc3QxDTALBgNVBAsMBHRlc3QxGzAZBgNVBAMMEmV0Y2QuY2x1c3Rl
ci5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ/qwxCR7g5S
s9+VleopkLi5pAszEkHYOBpwF/hDeRdxU0I0e1zZTdTlwwPy2vf8m3kwoq6fmNCt
tdUUXh5Wvgi/2OA8HBBzaQFQL1Av9qWwyES5cx6p0ZBwIrcXQIsl1XfNSUpQNTSS
D44TGduXUIdeshukPvMvLWLezynf2/WlgVh/haWtDG99r/Gj3uBdjl0m/xGvKvIv
NFy6EdgG9fkwcIalutjrUnGl9moGjwKYu4eXW2Zt5el0d1AHXUsqK4voe0p+U2Nz
quDmvxteXWdlsz8o5kQT6a4DUtWhpPIfNj9oZfPRs3LhBFQ74N70kVxMOCdec1lU
bnFzLIMGlz0CAwEAAaNQME4wHQYDVR0OBBYEFFHeljijrr+SPxlH5fjHRPcC7bv2
MB8GA1UdIwQYMBaAFFHeljijrr+SPxlH5fjHRPcC7bv2MAwGA1UdEwQFMAMBAf8w
DQYJKoZIhvcNAQELBQADggEBAG6NNTK7sl9nJxeewVuogCdMtkcdnx9onGtCOeiQ
qvh5Xwn9akZtoLMVEdceU0ihO4wILlcom3OqHs9WOd6VbgW5a19Thh2toxKidHz5
rAaBMyZsQbFb6+vFshZwoCtOLZI/eIZfUUMFqMXlEPrKru1nSddNdai2+zi5rEnM
HCot43+3XYuqkvWlOjoi9cP+C4epFYrxpykVbcrtbd7TK+wZNiK3xtDPnVzjdNWL
geAEl9xrrk0ss4nO/EreTQgS46gVU+tLC+b23m2dU7dcKZ7RDoiA9bdVc4a2IsaS
2MvLL4NZ2nUh8hAEHiLtGMAV3C6xNbEyM07hEpDW6vk6tqk=
-----END CERTIFICATE-----
key: |
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCf6sMQke4OUrPf
lZXqKZC4uaQLMxJB2DgacBf4Q3kXcVNCNHtc2U3U5cMD8tr3/Jt5MKKun5jQrbXV
FF4eVr4Iv9jgPBwQc2kBUC9QL/alsMhEuXMeqdGQcCK3F0CLJdV3zUlKUDU0kg+O
Exnbl1CHXrIbpD7zLy1i3s8p39v1pYFYf4WlrQxvfa/xo97gXY5dJv8RryryLzRc
uhHYBvX5MHCGpbrY61JxpfZqBo8CmLuHl1tmbeXpdHdQB11LKiuL6HtKflNjc6rg
5r8bXl1nZbM/KOZEE+muA1LVoaTyHzY/aGXz0bNy4QRUO+De9JFcTDgnXnNZVG5x
cyyDBpc9AgMBAAECggEAatcEtehZPJaCeClPPF/Cwbe9YoIfe4BCk186lHI3z7K1
5nB7zt+bwVY0AUpagv3wvXoB5lrYVOsJpa9y5iAb3GqYMc/XDCKfD/KLea5hwfcn
BctEn0LjsPVKLDrLs2t2gBDWG2EU+udunwQh7XTdp2Nb6V3FdOGbGAg2LgrSwP1g
0r4z14F70oWGYyTQ5N8UGuyryVrzQH525OYl38Yt7R6zJ/44FVi/2TvdfHM5ss39
SXWi00Q30fzaBEf4AdHVwVCRKctwSbrIOyM53kiScFDmBGRblCWOxXbiFV+d3bjX
gf2zxs7QYZrFOzOO7kLtHGua4itEB02497v+1oKDwQKBgQDOBvCVGRe2WpItOLnj
SF8iz7Sm+jJGQz0D9FhWyGPvrN7IXGrsXavA1kKRz22dsU8xdKk0yciOB13Wb5y6
yLsr/fPBjAhPb4h543VHFjpAQcxpsH51DE0b2oYOWMmz+rXGB5Jy8EkP7Q4njIsc
2wLod1dps8OT8zFx1jX3Us6iUQKBgQDGtKkfsvWi3HkwjFTR+/Y0oMz7bSruE5Z8
g0VOHPkSr4XiYgLpQxjbNjq8fwsa/jTt1B57+By4xLpZYD0BTFuf5po+igSZhH8s
QS5XnUnbM7d6Xr/da7ZkhSmUbEaMeHONSIVpYNgtRo4bB9Mh0l1HWdoevw/w5Ryt
L/OQiPhfLQKBgQCh1iG1fPh7bbnVe/HI71iL58xoPbCwMLEFIjMiOFcINirqCG6V
LR91Ytj34JCihl1G4/TmWnsH1hGIGDRtJLCiZeHL70u32kzCMkI1jOhFAWqoutMa
7obDkmwraONIVW/kFp6bWtSJhhTQTD4adI9cPCKWDXdcCHSWj0Xk+U8HgQKBgBng
t1HYhaLzIZlP/U/nh3XtJyTrX7bnuCZ5FhKJNWrYjxAfgY+NXHRYCKg5x2F5j70V
be7pLhxmCnrPTMKZhik56AaTBOxVVBaYWoewhUjV4GRAaK5Wc8d9jB+3RizPFwVk
V3OU2DJ1SNZ+W2HBOsKrEfwFF/dgby6i2w6MuAP1AoGBAIxvxUygeT/6P0fHN22P
zAHFI4v2925wYdb7H//D8DIADyBwv18N6YH8uH7L+USZN7e4p2k8MGGyvTXeC6aX
IeVtU6fH57Ddn59VPbF20m8RCSkmBvSdcbyBmqlZSBE+fKwCliKl6u/GH0BNAWKz
r8yiEiskqRmy7P7MY9hDmEbG
-----END PRIVATE KEY-----
snis:
- "yourdomain.com"
#END
global_rules:
-
id: 1
plugins:
response-rewrite:
body: "hello\n"
#END
consumers:
- username: jwt
plugins:
jwt-auth:
key: user-key
secret: my-secret-key
#END
upstreams:
- id: 1
nodes:
"127.0.0.1:1980": 1
type: roundrobin
routes:
-
uri: /hello
upstream_id: 1
plugins:
http-logger:
batch_max_size: 1
uri: http://127.0.0.1:1980/log
plugin_metadata:
- id: http-logger # note the id is the plugin name
log_format:
host: "$host"
remote_addr: "$remote_addr"
#END
stream_routes:
- server_addr: 127.0.0.1
server_port: 1985
id: 1
upstream_id: 1
plugins:
mqtt-proxy:
protocol_name: "MQTT"
protocol_level: 4
upstreams:
- nodes:
"127.0.0.1:1995": 1
type: roundrobin
id: 1
#END
protos:
- id: helloworld
desc: hello world
content: >
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
#END