Introduction
In this document, we will guide you on how to set up Apache APISIX/API7 with Declarative Configurations Tool (ADC, APISIX Declarative Configuration CLI) in a Kubernetes environment. To automate the process, we will use the apisix.yaml
file as the only source of truth, enabling us to leverage GitOps.
Keep in mind that certain actions have been highlighted in bold. This serves as a warning to exercise caution when working in the Production environment.
ADC Introduction
ADC takes the apisix.yaml
file as the only source and transforms configurations into API Gateways accordingly. In other words, API gateways have the same state as described in apisix.yaml
.
For more information, please refer to the https://github.com/api7/adc repository.
Scenarios
- Configure ADC and Connect ADC to Gateway Instances
- Publish Configurations
- Proxy Requests
- Key Authentication with Consumer & Plugin Enabled
- Modify Configurations and Apply Changes
Notes
- In this document, we are using API7 Enterprise Gateway v3.2.x, which is based on Apache APISIX 3.2 and does not yet provide Configuration Validation APIs. Therefore, we cannot utilize the adc validate command. This feature is available starting from Apache APISIX v3.5+.
- ADC supports loading your OpenAPI 3.0 spec file and converting it to
apisix.yaml
. However, you should update the converted file accordingly. For example, you need to add Authentication policies and bind a Service ID. We have plans to improve these functionalities for better user experience. - Enterprises may have different Git/SVN version control services and firewall policies. However, as long as the ADC tool can access Gateway’s Admin APIs, it will work. This document provides a demonstration of how to operate the ADC on a local computer.
Prerequisites
- Kubernetes: Kubernetes 1.28.2
- Note: API7 Enterprise doesn’t restrict Kubernetes version. This document runs Kubernetes on DigitalOcean.
- API7 Enterprise Gateway
- Note: API7.ai provides Docker image and Helm chart.
- ADC: 0.4.3
Deploy API7 Gateway on Kubernetes
$ helm repo add api7 https://charts.api7.ai
$ helm repo update api7
$ helm install api7 api7/api7 \
--create-namespace -n api7 \
# Note: To request for an IP and receive external traffic
--set gateway.type=LoadBalancer \
# Note: Define your random Admin API Key
--set admin.credentials.admin=**edd1c9f034335f136f87ad84b625c8f1** \
# Note: To allow ADC to connect to Admin APIs. **(Only for Testing)**
--set admin.type=**LoadBalancer** \
# Note: To allow ADC to access Admin APIs externally **(Only for Testing)**
--set admin.allow.ipList\[0\]=**0.0.0.0/0**
NAME: api7
LAST DEPLOYED: Wed Oct 18 16:06:17 2023
NAMESPACE: api7
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
export NODE_PORT=$(kubectl get --namespace api7 -o jsonpath="{.spec.ports[0].nodePort}" services api7-gateway)
export NODE_IP=$(kubectl get nodes --namespace api7 -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
$ kubectl get pods -n api7
NAME READY STATUS RESTARTS AGE
api7-5f7dd98c45-2k88s 1/1 Running 0 6m34s
api7-etcd-0 1/1 Running 0 6m34s
api7-etcd-1 1/1 Running 0 6m34s
api7-etcd-2 1/1 Running 0 6m34s
$ kubectl get svc -n api7
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
api7-admin LoadBalancer 10.245.61.242 **146.190.5.177** 9180:31517/TCP 6m53s
api7-etcd ClusterIP 10.245.88.194 <none> 2379/TCP,2380/TCP 6m53s
api7-etcd-headless ClusterIP None <none> 2379/TCP,2380/TCP 6m53s
api7-gateway LoadBalancer 10.245.162.181 **167.172.6.103** 80:31584/TCP 6m53s
Start Receiving Traffic
To receive traffic, we should set API7 Gateway as a LoadBalancer.
# Note: Because we have not configured any Routes yet, it should return Error 404 Not Found.
$curl -I http://167.172.6.103:80
HTTP/1.1 404 Not Found
Date: Wed, 18 Oct 2023 09:27:33 GMT
Content-Type: text/plain; charset=utf-8
Connection: keep-alive
Server: API7/3.2.2
Scenarios
Configure ADC
We need to verify Admin APIs are accessible.
$curl http://146.190.5.177:9180/apisix/admin/routes -H"X-API-Key: edd1c9f034335f136f87ad84b625c8f1"
{"list":[],"total":0}
Download ADC: Please visit https://github.com/api7/adc/releases to download the latest version.
# Note: I'm using Mac M1
$ ./adc -h
A command line interface for configuring APISIX declaratively.
It can be used to validate, dump, diff, and sync configurations with an APISIX instance.
Usage:
adc [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
configure Configure ADC with APISIX instance
diff Show the differences between the local and existing APISIX configuration
dump Dump the APISIX configuration
help Help about any command
openapi2apisix Convert OpenAPI configuration to ADC configuration
ping Verify connectivity with APISIX
sync Sync local configuration to APISIX
validate Validate the provided configuration file
version Print the version of ADC
Flags:
--config string config file (default is $HOME/.adc.yaml)
-h, --help help for adc
Use "adc [command] --help" for more information about a command.
Configure ADC:
# Note: We have plans to support passing values via --flag
$echo"**http://146.190.5.177:9180**\n**edd1c9f034335f136f87ad84b625c8f1**\n" | ./adc configure -f
Config file not found at /Users/username/.adc.yaml. Creating...
Please enter the APISIX server address:
Please enter the APISIX token:
ADC configured successfully!
Ping API Gateway Instances:
$./adc ping
Connected to backend successfully!
Publish Configurations
Create the apisix.yaml
file:
name: "Example configuration"
version: "1.0.0"
routes:
**- id: httpbin-route-anything**
methods:
- GET
name: httpbin-route-anything
service_id: httpbin-service
status: 1
uri: /anything
**- id: httpbin-route-ip**
methods:
- GET
name: httpbin-route-ip
service_id: httpbin-service
status: 1
uri: /ip
**- id: httpbin-route-protected-uuid**
methods:
- GET
name: httpbin-route-protected-uuid
service_id: httpbin-service
plugins:
key-auth:
_meta:
disable: false
status: 1
uri: /uuid
services:
- hosts:
**- api7.ai**
id: httpbin-service
name: httpbin-service
upstream:
hash_on: vars
id: httpbin
name: httpbin
nodes:
- host: httpbin.org
port: 80
weight: 1
pass_host: pass
scheme: http
type: roundrobin
consumers:
- username: tom
plugins:
key-auth:
key: tomskey
Sync apisix.yaml
to gateway instances
$./adcsync -f ./apisix.yaml
creating consumer: "tom"
creating service: "httpbin-service"
creating route: "httpbin-route-anything"
creating route: "httpbin-route-ip"
creating route: "httpbin-route-protected-uuid"
Summary: created 5, updated 0, deleted 0
Proxy Validation:
$curl 167.172.6.103/anything -H"Host: api7.ai" -v
* Trying 167.172.6.103:80...
* Connected to 167.172.6.103 (167.172.6.103) port 80 (#0)
> GET /anything HTTP/1.1
> Host: api7.ai
> User-Agent: curl/8.1.2
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 382
< Connection: keep-alive
< Date: Thu, 19 Oct 2023 03:38:58 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Server: API7/3.2.2
<
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "api7.ai",
"User-Agent": "curl/8.1.2",
"X-Amzn-Trace-Id": "Root=1-6530a4d2-0b74b9701a0367d758805510",
**"X-Forwarded-Host": "api7.ai"**
},
"json": null,
"method": "GET",
"origin": "10.104.0.2, 143.198.94.230",
"url": "http://api7.ai/anything"
}
Plugins Validation: Key Authentication
$curl 167.172.6.103/uuid -H"Host: api7.ai"
{"message":"Missing API key found in request"}
$curl 167.172.6.103/uuid -H"Host: api7.ai" -H"apikey: tomskey"
{
"uuid": "16abc3ad-dd3d-415e-a22c-e768753fd04c"
}
Modify Configurations and Apply Changes
Update the apisix.yaml
to the following configurations:
name: "Example configuration"
version: "1.0.0"
routes:
- id: httpbin-route-anything
methods:
- GET
name: httpbin-route-anything
service_id: httpbin-service
status: 1
uri: /anything
- id: httpbin-route-ip
methods:
- GET
name: httpbin-route-ip
service_id: httpbin-service
status: 1
uri: /ip
- id: httpbin-route-protected-uuid
methods:
- GET
name: httpbin-route-protected-uuid
service_id: httpbin-service
plugins:
key-auth:
_meta:
disable: false
status: 1
uri: /uuid
services:
- hosts:
**- httpbin**
id: httpbin-service
name: httpbin-service
upstream:
hash_on: vars
id: httpbin
name: httpbin
nodes:
- host: httpbin.org
port: 80
weight: 1
pass_host: pass
scheme: http
type: roundrobin
consumers:
- username: tom
plugins:
key-auth:
key: tomskey
Determine the differences between local configurations and remote configurations:
$ ./adc diff -f ./apisix.yaml
update service: "httpbin-service"
--- remote
+++ local
@@ -2,7 +2,7 @@
"id": "httpbin-service",
"name": "httpbin-service",
"hosts": [
- "api7.ai"
+ "httpbin"
],
"upstream": {
"id": "httpbin",
Summary: create 0, update 1, delete 0
Apply Changes:
$ ./adc sync -f ./apisix.yaml
updating service: "httpbin-service"
--- remote
+++ local
@@ -2,7 +2,7 @@
"id": "httpbin-service",
"name": "httpbin-service",
"hosts": [
- "api7.ai"
+ "httpbin"
],
"upstream": {
"id": "httpbin",
Summary: created 0, updated 1, deleted 0
Validation:
# Note: Because we have changed the Host attribute, it should return 404.
$curl 167.172.6.103/anything -H"Host: api7.ai"
{"error_msg":"404 Route Not Found"}
$curl 167.172.6.103/anything -H"Host: httpbin" -v
* Trying 167.172.6.103:80...
* Connected to 167.172.6.103 (167.172.6.103) port 80 (#0)
> GET /anything HTTP/1.1
> Host: httpbin
> User-Agent: curl/8.1.2
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 382
< Connection: keep-alive
< Date: Thu, 19 Oct 2023 03:39:55 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Server: API7/3.2.2
<
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "httpbin",
"User-Agent": "curl/8.1.2",
"X-Amzn-Trace-Id": "Root=1-6530a50b-4bff905e6dd3bb95674698d9",
**"X-Forwarded-Host": "httpbin"**
},
"json": null,
"method": "GET",
"origin": "10.104.0.3, 143.198.94.230",
"url": "http://httpbin/anything"
}
Q&A
How to upgrade chart?
$ helm install api7 api7/api7 --create-namespace -n api7 --set apisix.image.pullPolicy="Always"