Apache APISIX 是一個基於 OpenResty
和 Etcd 實現的動態、實時、高性能的 API 網關,目前已經進入 Apache 進行孵化。提供了豐富的流量管理功能,如負載均衡、動態路由、動態 upstream、A/B測試、金絲雀發布、限速、熔斷、防御惡意攻擊、認證、監控指標、服務可觀測性、服務治理等。可以使用 APISIX 來處理傳統的南北流量以及服務之間的東西向流量。
與傳統 API 網關相比,APISIX 具有動態路由和熱加載插件功能,避免了配置之后的 reload 操作,同時 APISIX 支持 HTTP(S)、HTTP2、Dubbo、QUIC、MQTT、TCP/UDP 等更多的協議。而且還內置了 Dashboard,提供強大而靈活的界面。同樣也提供了豐富的插件支持功能,而且還可以讓用戶自定義插件。
上圖是 APISIX 的架構圖,整體上分成數據面和控制面兩個部分,控制面用來管理路由,主要通過 etcd 來實現配置中心,數據面用來處理客戶端請求,通過 APISIX 自身來實現,會不斷去 watch etcd 中的 route、upstream 等數據。
APISIX Ingress
同樣作為一個 API 網關,APISIX 也支持作為 Kubernetes 的一個 Ingress 控制器進行使用。APISIX Ingress 在架構上分成了兩部分,一部分是 APISIX Ingress Controller,作為控制面它將完成配置管理與分發。另一部分 APISIX(代理) 負責承載業務流量。
當 Client 發起請求,到達 Apache APISIX 后,會直接把相應的業務流量傳輸到后端(如 Service Pod),從而完成轉發過程。此過程不需要經過 Ingress Controller,這樣做可以保證一旦有問題出現,或者是進行變更、擴縮容或者遷移處理等,都不會影響到用戶和業務流量。
同時在配置端,用戶通過 kubectl apply
創建資源,可將自定義 CRD 配置應用到 K8s 集群,Ingress Controller 會持續 watch 這些資源變更,來將相應配置應用到 Apache APISIX(通過 admin api)。
從上圖可以看出 APISIX Ingress 采用了數據面與控制面的分離架構,所以用戶可以選擇將數據面部署在 K8s 集群內部或外部。但 Ingress Nginx 是將控制面和數據面放在了同一個 Pod 中,如果 Pod 或控制面出現一點閃失,整個 Pod 就會掛掉,進而影響到業務流量。這種架構分離,給用戶提供了比較方便的部署選擇,同時在業務架構調整場景下,也方便進行相關數據的遷移與使用。
APISIX Ingress 控制器目前支持的核心特性包括:
- 全動態,支持高級路由匹配規則,可與 Apache APISIX 官方 50 多個插件 & 客戶自定義插件進行擴展使用
- 支持 CRD,更容易理解聲明式配置
- 兼容原生 Ingress 資源對象
- 支持流量切分
- 服務自動注冊發現,無懼擴縮容
- 更靈活的負載均衡策略,自帶健康檢查功能
- 支持 gRPC 與 TCP 4 層代理
安裝
我們這里在 Kubernetes 集群中來使用 APISIX,可以通過 Helm Chart 來進行安裝,首先添加官方提供的 Helm Chart 倉庫:
➜ helm repo add apisix https://charts.apiseven.com
➜ helm repo update
由於 APISIX 的 Chart 包中包含 dashboard 和 ingress 控制器的依賴,我們只需要在 values 中啟用即可安裝 ingress 控制器了:
➜ helm fetch apisix/apisix
➜ tar -xvf apisix-0.7.2.tgz
➜ mkdir -p apisix/ci
在 apisix/ci
目錄中新建一個用於安裝的 values 文件,內容如下所示:
# ci/prod.yaml
apisix:
enabled: true
nodeSelector: # 固定在node2節點上
kubernetes.io/hostname: node2
gateway:
type: NodePort
externalTrafficPolicy: Cluster
http:
enabled: true
servicePort: 80
containerPort: 9080
etcd:
enabled: true # 會自動創建3個節點的etcd集群
replicaCount: 1 # 多副本需要修改下模板,這里暫時運行一個etcd pod
dashboard:
enabled: true
ingress-controller:
enabled: true
config:
apisix:
serviceName: apisix-admin
serviceNamespace: apisix # 指定命名空間,如果不是 ingress-apisix 需要重新指定
經測試官方的 Helm Chart 包對 etcd 多節點集群支持不是很好,我測試跑3個節點會出問題,應該還需要重新修改模板去兼容,另外對外部的 etcd tls 集群兼容度也不好,比如 dashboard 的 Chart 需要自己修改模板去支持 tls,所以這里我們測試先改成 1 個副本的 etcd 集群。
APISIX 需要依賴 etcd,默認情況下 Helm Chart 會自動安裝一個3副本的 etcd 集群,需要提供一個默認的 StorageClass,如果你已經有默認的存儲類則可以忽略下面的步驟,這里我們安裝一個 nfs 的 provisioner,用下面的命令可以安裝一個默認的 StorageClass:
➜ helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
➜ helm upgrade --install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--set nfs.server=192.168.31.31 \ # 指定nfs地址
--set nfs.path=/var/lib/k8s/data \ # nfs路徑
--set image.repository=cnych/nfs-subdir-external-provisioner \
--set storageClass.defaultClass=true -n kube-system
安裝完成后會自動創建一個 StorageClass:
➜ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client (default) cluster.local/nfs-subdir-external-provisioner Delete Immediate true 35s
然后直接執行下面的命令進行一鍵安裝:
➜ helm upgrade --install apisix ./apisix -f ./apisix/ci/prod.yaml -n apisix
Release "apisix" does not exist. Installing it now.
NAME: apisix
LAST DEPLOYED: Thu Dec 30 16:28:38 2021
NAMESPACE: apisix
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export NODE_PORT=$(kubectl get --namespace apisix -o jsonpath="{.spec.ports[0].nodePort}" services apisix-gateway)
export NODE_IP=$(kubectl get nodes --namespace apisix -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
正常就可以成功部署 apisix 了:
➜ kubectl get pods -n apisix
NAME READY STATUS RESTARTS AGE
apisix-dashboard-b69d5c768-r6tqk 1/1 Running 0 85m
apisix-etcd-0 1/1 Running 0 90m
apisix-fb8cdb569-wz9gq 1/1 Running 0 87m
apisix-ingress-controller-7d5bbf5dd5-r6khq 1/1 Running 0 85m
➜ kubectl get svc -n apisix
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apisix-admin ClusterIP 10.97.108.252 <none> 9180/TCP 3h
apisix-dashboard NodePort 10.108.202.136 <none> 80:31756/TCP 3h
apisix-etcd ClusterIP 10.107.150.100 <none> 2379/TCP,2380/TCP 3h
apisix-etcd-headless ClusterIP None <none> 2379/TCP,2380/TCP 3h
apisix-gateway NodePort 10.97.214.188 <none> 80:32200/TCP 3h
apisix-ingress-controller ClusterIP 10.103.176.26 <none> 80/TCP 3h
測試
現在我們可以為 Dashboard 創建一個路由規則,新建一個如下所示的 ApisixRoute
資源對象即可:
apiVersion: apisix.apache.org/v2beta2
kind: ApisixRoute
metadata:
name: apisixdashboard
namespace: apisix
spec:
http:
- name: root
match:
hosts:
- apisix.yansongwei.com
paths:
- "/*"
backends:
- serviceName: apisix-dashboard
servicePort: 80
創建后 apisix-ingress-controller
會將上面的資源對象通過 admin api 映射成 APISIX 中的配置:
[root@yan-master1 ~]# kubectl get ar -n apisix
NAME HOSTS URIS AGE
apisixdashboard ["apisix.yansongwei.com"] ["/*"] 26s
[root@yan-master1 ~]# kubectl api-resources | grep apisi
apisixclusterconfigs acc apisix.apache.org/v2alpha1 false ApisixClusterConfig
apisixconsumers ac apisix.apache.org/v2alpha1 true ApisixConsumer
apisixroutes ar apisix.apache.org/v2beta2 true ApisixRoute
apisixtlses atls apisix.apache.org/v1 true ApisixTls
apisixupstreams au apisix.apache.org/v1 true ApisixUpstream
[root@yan-master1 ~]# kubectl get ar -n apisix
NAME HOSTS URIS AGE
apisixdashboard ["apisix.yansongwei.com"] ["/*"] 31s
所以其實我們的訪問入口是 APISIX,而 apisix-ingress-controller
只是一個用於監聽 crds,然后將 crds 翻譯成 APISIX 的配置的工具而已,現在就可以通過 apisix-gateway
的 NodePort 端口去訪問我們的 dashboard 了:

默認登錄用戶名和密碼都是 admin,登錄后在路由
菜單下正常可以看到上面我們創建的這個 dashboard 的路由信息:

點擊更多
下面的查看
就可以看到在 APISIX 下面真正的路由配置信息:

所以我們要使用 APISIX,也一定要理解其中的路由 Route 這個概念,路由(Route)是請求的入口點,它定義了客戶端請求與服務之間的匹配規則,路由可以與服務(Service)、上游(Upstream)關聯,一個服務可對應一組路由,一個路由可以對應一個上游對象(一組后端服務節點),因此,每個匹配到路由的請求將被網關代理到路由綁定的上游服務中。
理解了路由后自然就知道了我們還需要一個上游 Upstream 進行關聯,這個概念和 Nginx 中的 Upstream 基本是一致的,在上游
菜單下可以看到我們上面創建的 dashboard 對應的上游服務:

其實就是將 Kubernetes 中的 Endpoints 映射成 APISIX 中的 Upstream,然后我們可以自己在 APISIX 這邊進行負載。
APISIX 提供的 Dashboard 功能還是非常全面的,我們甚至都可以直接在頁面上進行所有的配置,包括插件這些,非常方便。

當然還有很多其他高級的功能,比如流量切分、請求認證等等,這些高級功能在 crds 中去使用則更加方便了,當然也是支持原生的 Ingress 資源對象的,關於 APISIX 的更多高級用法,后續再進行說明。