ASP.NET Core on K8S學習之旅(13)Ocelot API網關接入
- 2020 年 5 月 15 日
- 筆記
- .NET Core, 【005】DevOps & 容器技術, 【022】.NET Core, Ingress, k8s, Ocelot
本篇已加入《.NET Core on K8S學習實踐系列文章索引》,可以點擊查看更多容器化技術相關係列文章。
上一篇介紹了Ingress的基本概念和Nginx Ingress的基本配置和使用,考慮到很多團隊都在使用Ocelot作為API網關(包括我司)做了很多限流和鑒權的工作,因此本篇介紹一下如何使用Ocelot接入替代Nginx Ingress作為統一入口。
一、準備工作
我們仍然以上一篇的兩個ASP.NET Core WebAPI示例作為K8s集群中的後端服務示例,這裡我們來快速地準備一個基於Ocelot的API網關服務。
至於怎麼創建Ocelot API網關,已經有很多文章介紹了,這裡就不再贅述。需要注意的步驟有以下幾點:
(1)根據Ocelot的版本引入匹配的K8s Provider:
可以看到,這個Provider包是張隊寫的,目前已經支持.NET Core 3.1,最新版本是15.0.6。這裡我選擇的是13.5.2,因為我的API網關服務還是.NET Core 2.2的版本。
KubeClient是kubernetes 的C#語言客戶端簡單易用,KubeClient是.NET Core(目標netstandard1.4)的可擴展Kubernetes API客戶端, github地址點擊這裡。這個Ocelot的kubernetes集成模塊就是使用KubeClient開發的,可以參考張隊的這篇文章。
(2)在StartUp類的ConfigureService方法中添加以下代碼:
services.AddOcelot()
.AddKubernetes();
(3)編寫ocelot.json配置文件:
{ "GlobalConfiguration": { "ServiceDiscoveryProvider": { "Token": "your token", "Namespace": "xdp-poc", "Type": "kube" } }, "ReRoutes": [ // API01: apple-api-svc { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "UpstreamPathTemplate": "/apple/{url}", "ServiceName": "apple-api-svc", "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ] }, // API02: banana-api-svc { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "UpstreamPathTemplate": "/banana/{url}", "ServiceName": "banana-api-svc", "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ] } ] }
由於我的是13.5.2的老版本,因此需要配置ServiceDiscoveryProvider下的信息(例如Token),這裡我直接使用的我要配置的命名空間xdp-poc下的default-token,你可以在這裡獲取到:
據張隊介紹,新版本的K8s Provider不再需要提供這些信息配置。
為了能夠讓這個serviceaccount能夠具有獲取endpoint的權限,我們還需要事先執行一下以下語句:
kubectl create clusterrolebinding k8s-api-admin\
--clusterrole=cluster-admin --user=admin --user=kubelet\
--group=system:serviceaccounts
如果不執行以上語句可能會出現KubeClient的權限不夠,無法獲取對應服務的註冊地址和端口,也就無法正確指向對應的服務接口。
默認情況下,如果在GlobalConfiguration中配置了ServiceNamespace,那麼在路由表中不再需要為每個路由設置ServiceNamespace,但是如果某一個或幾個是在不同的ServiceNamespace下,可以在其中為其單獨設置ServiceNamespace,如下所示:
{ "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "UpstreamPathTemplate": "/banana/{url}", "ServiceName": "banana-api-svc", "ServiceNamespace" : "kube-system", "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ] }
二、鏡像&部署
準備好了API網關的代碼,就可以生成鏡像並推送到鏡像倉庫了,這裡我仍然推到我的docker hub上,如下圖所示:
當然,實際中還是建議推到自己企業的私有鏡像倉庫(例如基於Harbor搭建一個)或者使用阿里雲或其他雲的私有鏡像倉庫服務。
然後,準備一個用於deploy的yaml文件如下:
apiVersion: apps/v1 kind: Deployment metadata: name: api-gateway-demo namespace: xdp-poc labels: name: api-gateway-demo spec: replicas: 2 selector: matchLabels: name: api-gateway-demo template: metadata: labels: name: api-gateway-demo spec: containers: - name: api-gateway-demo image: xilife/api-gateway-demo:1.0 ports: - containerPort: 80 imagePullPolicy: IfNotPresent --- kind: Service apiVersion: v1 metadata: name: api-gateway-svc namespace: xdp-poc spec: type: NodePort ports: - port: 80 targetPort: 80 nodePort: 30080 selector: name: api-gateway-demo
通過kubectl將其部署到K8s集群中:
kubectl apply -f deploy-api-gateway-svc.yaml
通過Dashboard也可以看到部署成功:
亦或通過查看容器日誌驗證:
三、快速驗證
這裡由於我剛剛設置的服務是NodePort方式,並且指定暴露的端口號是30080,那麼我直接通過IP+Port來直接訪問:
(1)AppleApi
(2)BananaApi
當然,你也可以為你的API網關入口配置SSL證書,通過https來訪問提高安全性(實際中也是強烈建議):
四、小結
本文介紹了如何在K8s集群中接入基於Ocelot的API網關服務來替代Ingress作為K8s集群API服務的統一入口,雖然示例很簡單,但是基本的介紹目的已經達到了。在此,也特別感謝Ocelot的貢獻者們,以及張隊貢獻的這個集成K8s的 Provider。
參考資料
Ocelot K8s部分Doc,//ocelot.readthedocs.io/en/latest/features/kubernetes.html
憂康,K8s-Endpoint訪問外部服務
楊波,《Sprint Boot與Kubernetes雲原生應用實踐》課程