做者:榮濱,酷劃在線後端架構師,關注微服務治理,容器化技術,Service Mesh等技術領域html
Pepper Metrics是我與同事開發的一個開源工具(github.com/zrbcool/pep…),其經過收集jedis/mybatis/httpservlet/dubbo/motan的運行性能統計,並暴露成prometheus等主流時序數據庫兼容數據,經過grafana展現趨勢。其插件化的架構也很是方便使用者擴展並集成其餘開源組件。
請你們給個star,同時歡迎你們成爲開發者提交PR一塊兒完善項目。nginx
前面一篇文章主要是落地容器化以前對基礎網絡組件的調研及性能測試,感興趣的同窗請參考:阿里雲開源K8S CNI插件terway網絡性能測試git
目前公司的後端架構基本上是微服務的架構模式,以下圖,全部的入站流量均經過API網關進入到後端服務,API網關起到一個「保護神」的做用,監控着全部進入的請求,並具有防刷,監控接口性能,報警等重要功能,流量經過網關後服務間的調用均爲RPC調用。 github
在經歷完微服務改造後,雖然微服務架構給咱們帶來了很多紅利,可是也難免引入一些問題:數據庫
爲了解決上述問題,通過調查,咱們將目光鎖定容器服務Kubernetes,以解決咱們的問題,本篇文章主要關注nginx-ingress-controller(後面統一簡稱NGINX IC)部分,因此下面的架構主要突出API網關及IC。 下圖是咱們的過渡期方案: 經過引入一個內網的SLB來解決IC作爲咱們API網關upstream時,服務發現的問題。而且,能夠經過逐步切換接口到SLB上達到漸進式遷移的效果,粒度能夠作到接口+百分比級別。 過渡期間架構圖以下所示:json
所有遷移完成後,全部的機器回收,以下圖所示: 後端
查看IC的啓動命令參數,能夠找到: api
containers:
- args:
- /nginx-ingress-controller
- --ingress-class=xwz #看這裏
- --configmap=$(POD_NAMESPACE)/xwz-nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/xwz-tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/xwz-udp-services
- --annotations-prefix=nginx.ingress.kubernetes.io
- --publish-service=$(POD_NAMESPACE)/xwz-nginx-ingress-lb
- --v=2
複製代碼
以及網絡
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: "xwz" #看這裏
labels:
app: tap-revision-ing
wayne-app: tap-revision
wayne-ns: coohua
name: tap-revision-ing
namespace: coohua
spec:
rules:
- host: staging.coohua.com
http:
paths:
- backend:
serviceName: tap-revision-stable
servicePort: 80
path: /
複製代碼
接下來咱們來看下IC在Kubernetes內部署的資源結構,如圖所示: mybatis
咱們的場景是不須要特殊的權限配置的,因此咱們就簡單的把紅框裏面的幾個資源複製一份修改下其中的幾個配置(例如--ingress-class=xwz),而後直接引用默認IC的ServiceAccount,就完成了一組全新IC的部署,而且與Kubernetes自帶的IC是互相隔離的。 這裏我把我寫好的配置放到個人github上,讀者能夠參考:ingress resources
建立好新IC後,若是發現IC有以下錯誤
E0416 11:31:50.831279 6 leaderelection.go:304] Failed to update lock: configmaps "ingress-controller-leader-xwz" is forbidden: User "system:serviceaccount:kube-system:nginx-ingress-controller" cannot update resource "configmaps" in API group "" in the namespace "kube-system"
複製代碼
參考issue,須要修改clusterrole:nginx-ingress-controller,增長以下內容
...
- apiGroups:
- ""
resourceNames:
- ingress-controller-leader-nginx
- ingress-controller-leader-xwz #將新增長的configmap增長進來,否則會報上面提到的錯誤
resources:
- configmaps
...
複製代碼
Service的spec.externalTrafficPolicy當爲Cluster的時候: 集羣當中的每臺主機均可以充當三層路由器,起到負載均衡及轉發的做用,可是因爲其對請求包進行了SNAT操做,如圖所示:
Service的spec.externalTrafficPolicy當爲Local的時候: 節點只會把請求轉給節點內的IC的POD,因爲不通過SNAT操做,IC能夠獲取到客戶端的真實IP,若是節點沒有POD,就會報錯。這樣咱們就須要手工維護IC POD,節點,與SLB後端服務之間的關係。那麼有沒有一種方式能夠自動管理維護這個關係呢?實際上是有的,阿里雲容器服務爲咱們作好了這一切,只要在type爲LoadBalancer的Service上增長以下幾個annotation,它就能夠爲咱們將啓動了POD的worker節點的端口及IP自動添加到SLB後端服務當中,擴容縮容自動更新,以下所示(注意咱們使用的是內網SLB,type爲intranet,你們根據實際狀況修改):
metadata:
annotations:
service.beta.kubernetes.io/alicloud-loadbalancer-address-type: intranet
service.beta.kubernetes.io/alicloud-loadbalancer-force-override-listeners: "true"
service.beta.kubernetes.io/alicloud-loadbalancer-id: lb-2zec8x×××××××××965vt
複製代碼
對比 | Cluster | Local |
---|---|---|
優勢 | 簡單,K8S的默認方式 | 減小網絡轉發,性能好,能獲取客戶端真實IP |
缺點 | SNAT地址假裝網絡上增長一跳,性能降低,沒法獲取客戶端真實IP | 須要對節點的端口是否打開作檢查,須要自定義服務發現(阿里雲這塊已經作了與SLB的集成) |
咱們知道nginx的默認配置worker_processes爲auto的時候,會根據當前主機cpu信息自動計算,可是nginx並非一個cgroups aware的應用,因此其會盲目「自大」的認爲有「好多」cpu能夠用,這裏咱們就須要對其進行指定,能夠在configmap中設置參數:
apiVersion: v1
data:
worker-processes: "8"
kind: ConfigMap
metadata:
annotations:
labels:
app: ingress-nginx
name: xwz-nginx-configuration
namespace: kube-system
複製代碼
這塊咱們暫時使用默認的deployment當中給定的參數,後續調優的時候會根據狀況調整
initContainers:
- command:
- /bin/sh
- -c
- | sysctl -w net.core.somaxconn=65535 sysctl -w net.ipv4.ip_local_port_range="1024 65535" sysctl -w fs.file-max=1048576 sysctl -w fs.inotify.max_user_instances=16384 sysctl -w fs.inotify.max_user_watches=524288 sysctl -w fs.inotify.max_queued_events=16384 複製代碼
小流量灰度期間業務同窗反饋說第三方的反做弊發現咱們調用他們的接口異常,一輪分析下來發現,原來是發給第三方請求中攜帶的客戶端IP被寫爲了咱們API網關的主機IP 還記得前面的架構圖嗎?
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
...
spec:
template:
spec:
containers:
name: nginx-ingress-controller
...
volumeMounts:
- mountPath: /etc/nginx/template
name: nginx-template-volume
readOnly: true
....
volumes:
- name: nginx-template-volume
configMap:
name: xwz-nginx-template
items:
- key: nginx.tmpl
path: nginx.tmpl
複製代碼
至此問題解決
在現有的CooHua API網關上,已經有比較詳細的各類指標監控,因爲ingress-controller也暴露了prometheus的metrics,因此也很簡單的直接部署了社區版的dashboard,並對其進行了簡單的修改,以下圖所示:
請參考這篇文章 docs.nginx.com/nginx/admin…
yq.aliyun.com/articles/69… yq.aliyun.com/articles/64… bogdan-albei.blogspot.com/2017/09/ker… danielfm.me/posts/painl… www.asykim.com/blog/deep-d…