使用NGINX Plus負載均衡Kubernetes服務
來自: http://dockone.io/article/957
【編者的話】此篇文章是Nginx的Michael Pleshakov發表在Nginx官方博客的一篇博文,通過這篇文章概括回顧了Kubernetes暴露服務相關的解決方案,并對最新的Ingreess API進行了說明,最后給出了Kubernetes通過集成NGINX Plus來暴露服務到互聯網的解決方案。這個方案解決了目前Kubernetes暴露服務的短板,整個實現過程也比較簡單,步驟清晰,具有很強的參考性。我們華三目前也在調研這方面的工作,希望此文能對大家有所幫助。
Kubernetes是由谷歌開發的一個開源系統,用于在集群內運行和管理以容器微服務為基礎的應用。使用Kubernetes的人經常需要確保可以從Kubernetes集群外部訪問在Kubernetes內創建的服務。
雖然Kubernetes提供了內置暴露服務解決方案,正像在下面Kubernetes內置暴露服務解決方案中所描述的,這些解決方案會局限你在4層負載均衡或循環HTTP負載平衡。
這篇文章會告訴你如何使用NGINX Plus作為高級7層負載均衡解決方案,用于暴露Kubernetes服務到互聯網上,無論你是在云服務還是在自有基礎設施上運行Kubernetes。
我們假定你對Kubernetes有所了解(pods, services, replication controllers, and labels)并且有一個運行的Kubernetes集群。要了解更多Kubernetes,請訪問官方Kubernetes用戶指南。
Kubernetes內置暴露服務解決方案
Kubernetes為暴露服務提供了多種選擇。其中兩種是NodePort和負載平衡器,分別對應不同類型的服務。Ingress API在Kubernetes1.1版本開始作為beta測試版供使用,已經成為第三種選擇。NodePort
指定服務類型為NodePort,會使得服務在每個Kubernetes節點上在相同的端口可用。為了暴露服務到互聯網,你在這個端口上暴露一個或多個節點。為了高可用性,你可以暴露多個節點并使用基于DNS的負載均衡在它們中分布流量,或者你把這些節點放在你選擇的負載均衡后。當傳入流量訪問端口的一個節點時,它會被在服務的pods之間負載平衡。負載平衡由每個節點上的Kubernetes代理完成,并且僅限于TCP/UDP負載均衡。
LoadBalancer
指定服務類型為負載平衡會分配用于在服務pods之間分布傳入流量的云負載平衡器。只有特定的云服務供應商和Google Container Engineand支持負載均衡器解決方案,如果你在你自己的基礎設施上運行Kubernetes,它是不可用的。此外,Kubernetes只允許你配置循環TCP負載均衡,即使云負載均衡器有高級功能,例如會話持久或請求映射。
Ingress API
創建Ingress資源使得你可以通過自定義URL(例如,服務A在URL /foo和服務B在URL /bar)和多個虛擬主機名(例如,一組服務是foo.example.com而另一組服務是bar.example.com)暴露服務到互聯網。Ingress控制器依賴Ingress資源并建立一個外部負載平衡器。Ingress控制器不是Kubernetes標準部署的一部分:你需要選擇最適合你的控制器或自己實現一個,并把它添加到你的Kubernetes集群。預計很快會出現各種各樣的控制器,但目前唯一可用的還是Google Compute Engine HTTP負載平衡控制器,而且是只有當你在Google Compute Engine或者Google Container Engine中運行Kubernetes時。Ingress API僅支持循環HTTP負載均衡,即使實際負載均衡器支持高級功能。
在撰寫本文時,無論是Ingress API還是Google Compute Engine HTTP Load Balancer控制器都還在測試階段。
盡管上面提到的解決方案配置簡單并且馬上就可以使用,他們沒有提供任何高級功能,特別是7層負載均衡相關的功能。
使用NGINX Plus暴露Kubernetes服務
為了集成NGINX Plus到Kubernetes上,我們需要確保NGINX Plus配置與Kubernetes保持同步,可以反映像pods添加或刪除這樣的Kubernetes服務變更。 使用開源的NGINX軟件,你需要手動修改NGINX配置文件并重新加載配置。使用NGINX Plus,有兩種方法動態更新配置:
With APIs – 此方法使用NGINX Plus的on-the-fly reconfiguration API 添加和刪除Kubernetes pods在NGINX Plus配置中的條目,并使用Kubernetes API來獲取pods的IP地址。這種方法需要我們寫一些代碼,這里我們也不進行深入討論。有關詳細信息,可以看Kelsey Hightower的網絡研討會,Bringing Kubernetes to the Edge with NGINX Plus,他在其中探討了API并新建了利用他們的應用。
通過重新解析DNS名稱 -這個方法像在以下章節描述的一樣僅僅需要對NGINX Plus的一次恰當配置。
Utilizing DNS-Based Reconfiguration
我們假設你已經有一個正在運行的Kubernetes集群并有一個可以使用kubectl工具的主機用于管理集群;有關說明,請參閱有關你群集類型的Kubernetes入門指南。你還需要編譯一個NGINX Plus容器鏡像,創建的命令就在這篇博客文章。下面是我們怎么做的一個概括:
- 配置一個NGINX Plus pod用于暴露和負載均衡我們在步驟2中創建的服務。
- 創建一個提供靜態網頁的簡單服務,。
- 擴展或者縮減服務,查看NGINX Plus如何自動重新配置。
> 注:我們使用運行在Google Compute Engine的Kubernetes 1.0.6版本測試了這個博客所描述的解決方案,而我們下面使用的是一個本地配置的Vagrant。
在命令的斜體字中,你Kubernetes設置中的值可能不同。
配置 NGINX Plus Pod
我們把NGINX Plus放在要暴露到互聯網節點的Kubernetes pod內。我們的pod通過復制控制器創建,我們同樣進行配置。我們Kubernetes相關的NGINX Plus配置文件放在NGINX Plus pod和節點的共享目錄內,這樣更加方便維護。選擇運行NGINX Plus Pod的節點
為了指定NGINX Plus pod運行的節點,我們添加一個標簽到該節點。運行下面命令,查詢運行的所有節點列表:$ kubectl get nodes
NAME LABELS STATUS
10.245.1.3 Kubernetes.io/hostname=10.245.1.3 Ready
10.245.1.4 Kubernetes.io/hostname=10.245.1.4 Ready
10.245.1.5 Kubernetes.io/hostname=10.245.1.5 Ready
我們選擇第一個節點,并通過下面命令添加一個標簽給它:
$ kubectl label node 10.245.1.3 role=nginxplus
為NGINX Plus Pod配置Replication Controller
我們不會直接創建NGINX Plus pod而是通過復制控制器。我們在Kubernetes的nginxplus-rc.yaml文件配置NGINX Plus pod 復制控制器。- 我們設置replicas的數量是1,就是說Kubernetes會確保始終有1個NGINX Plus pod在運行:如果pod出現故障,它會被新的pod替換。
- 在nodeSelector處我們指定NGINX Plus pod在標記角色: nginxplus的節點上創建。
- 我們的NGINX Plus容器暴露兩個端口,80和8080,并且我們配置他們與節點端口80和8080之間的映射。
- 我們的NGINX Plus容器共享節點的/etc/nginx/conf.d文件夾。作為下面配置NGINX Plus的進一步解釋,共享文件夾讓我們可以不用重建容器鏡像而重新配置NGINX Plus。
apiVersion: v1 kind: ReplicationController metadata: name: nginxplus-rc spec: replicas: 1 selector: app: nginxplus template: metadata: labels: app: nginxplus spec: nodeSelector: role: nginxplus containers: - name: nginxplus image: nginxplus ports: - name: http containerPort: 80 hostPort: 80 - name: http-alt containerPort: 8080 hostPort: 8080 volumeMounts: - mountPath: "/etc/nginx/conf.d" name: etc-nginx-confd volumes: - hostPath: path: "/etc/nginx/conf.d" name: etc-nginx-confd
使NGINX Plus Docker Image可用
正如我們上面所說,我們已經建立了一個NGINX Plus Docker鏡像。 現在我們讓它可用。為簡單起見,我們不使用私有Docker repository,我們只是手動加載鏡像。在我們編譯Docker鏡像的主機上,運行以下命令將鏡像保存成文件:
$ docker save -o nginxplus.tar nginxplus
我們把nginxplus.tar傳送到節點,運行以下命令從文件加載鏡像:
$ docker load -i nginxplus.tar
配置NGINX Plus
在NGINX Plus容器的/etc/nginx文件夾中,我們保留隨NGINX Plus包默認的主nginx.conf中的配置文件。 在默認文夾include指令讀取來自/etc/nginx/conf.d文件夾中的其他配置文件。正向在NGINX Plus復制控制器文件(nginxplus-rc.yaml)中表明的一樣,我們與NGINX Plus節點上的容器共享/etc/nginx/conf.d文件夾。 共享意味著我們可以修改存儲在文件夾(節點上)中的配置文件,而無需重建NGINX Plus容器鏡像,而如果我們直接在容器中創建的文件夾這是我們必須做的。我們把我們的Kubernetes特定配置文件(backend.conf)放在共享目錄。首先,讓我們創建/etc/nginx/conf.d文件夾。
$ mkdir /etc/nginx/conf.d
然后,我們創建backend.conf文件,其中包括以下指令:
- resolver -定義Kubernetes DNS解析的IP地址,使用默認的IP地址,10.0.0.10。valid參數告訴NGINX Plus每五秒鐘解析所有DNS名稱。 您的Kubernetes DNS服務IP地址可能會有所不同。運行此命令查看:
$ kubectl get svc kube-dns --namespace=kube-system
- upstream -創建一個名為后端的Kubernetes服務,我們揭露上游組。我們確定了服務器在上游組主機名,包括了resolve指令告訴NGINX重新解析主機名在運行時。
- server (兩次) -定義兩個虛擬服務器:
- 第一個服務器監聽端口80并且負載均衡在我們服務pods中的/nginx-service傳入請求。我們還配置積極的健康檢查 。
- 第二個服務器監聽端口8080。這里的我們成立了現場活動的監控NGINX Plus。稍后我們將用它來檢查 NGINX Plus 是否被正確地重新配置。
resolver 10.0.0.10 valid=5s;upstream backend { zone upstream-backend 64k; server nginx-service.default.svc.cluster.local resolve; }
server { listen 80;
status_zone backend-servers;
location /nginx-service/ { proxy_pass http://backend/; health_check; } }
server { listen 8080;
root /usr/share/nginx/html;
location = /status.html { }
location /status { status; } }</pre>
創建Replication Controller
現在,我們已經準備好在我們的節點上運行此命令創建復制器:
$ kubectl create -f nginxplus-rc.yaml
為了驗證創建NGINX Plus pod,運行:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginxplus-rc-0ts5t 1/1 Running 0 17s
我們在本地Vagrant 設定運行Kubernetes,所以我們知道,我們的節點的外部IP地址為10.245.1.3,在這個例子中的剩下部分我們將使用該地址。如果你在一個云服務提供商運行Kubernetes,您可以通過運行下面命令得到您節點的外部IP地址:
$ kubectl get nodes node-name -o json | grep -i externalIP -A 1 "type": "ExternalIP", "address": XXX.XXX.XXX.XXX
如果您在云服務中運行,別忘了設置防火墻規則允許NGINX Plus節點接收傳入的流量。請參閱您的云服務提供商文檔。
通過查看NGINX Plus實時活動監控儀表板可以檢查我們的NGINXPlus pod是否 起來并運行了,它節點的外部IP地址在端口8080上是否可用(在我們的例子中是http://10.245.1.3:8080/status.html)。 如果我們這時候訪問,不過我們是看不到我們服務的任何服務器,因為我們還沒有創建它。
創建一個簡單Kubernetes Service
現在是時候創建Kubernetes服務了。我們的服務包括兩個(開源)NGINX 服務器提供靜態web頁面。
為服務創建Replication Controller
首先,我們創建一個Replication Controller,這樣Kubernetes會確保指定數量的NGINX Web服務器副本(pods)始終在群集中運行。以下是聲明文件(nginx-rc.yaml):
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-rc
spec:
replicas: 2
selector:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:- containerPort: 80</code>
我們的控制器由兩個NGINX Web服務器組成。我們聲明一個控制器包含單個NGINX容器pods用于暴露端口80。Nginx的鏡像將從Docker Hub下載。
要創建復制控制器,我們運行以下命令:
$ kubectl create -f nginx-rc.yaml
要檢查是否已創建pods,我們可以運行下面的命令。我們使用標簽選擇app=nginx獲得僅在上一步的replication controller中創建的pods:
$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-rc-544f1 1/1 Running 0 2m
nginx-rc-uk6pm 1/1 Running 0 2m
創建Service
接下來,我們為replication controller創建的pods創建服務。我們使用下列文件(nginx-service.yaml)創建服務:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
ClusterIP: None
ports:- port: 80
targetPort: 80
protocol: TCP
selector:
app: nginx</code>
這里我們通過設置ClusterIP字段為None來聲明一個特殊的headless service。通過這類服務,不會分配集群的IP地址并且通過kube代理也無法使用服務。DNS查詢Kubernetes DNS會返回多個A記錄(我們pods的IP地址)。
通過設置selector field為app: nginx,我們聲明該pods屬于服務,即使用NGINX replication controller 創建的pods(在nginx-rc.yaml中定義)。
我們運行下面的命令創建服務:
$ kubectl create -f nginx-service.yaml
現在,如果我們刷新儀表盤頁面,并單擊右上角的Upstreams tab,我們可以看到新加的兩臺服務器。
我們還可以檢查NGINX Plus是否已經在pods的服務間負載均衡流量。如果是,當我們在瀏覽器中訪問http://10.245.1.3/nginx-service/時,我們可以看到默認NGINX的歡迎頁面。
如果我們刷新此頁面幾次,并查看儀表盤狀態,我們可以看到請求是如何分布在兩個上游服務器上的。
擴展Kubernetes服務
現在,讓我們再添加兩個pods到我們的服務并確保NGINX Plus配置會再次自動更新。我們運行此命令擴展replication controller 把pods數量更改為4:
$ kubectl scale rc nginx-rc --replicas=4
scaled
要檢查NGINX Plus是否重新配置,我們可以再查看儀表盤,但這次我們使用NGINX Plus狀態的API來替代。在我們的節點運行下面的命令,10.245.1.3是我們的NGINX Plus節點外部IP地址。為了格式化JSON輸出,我們管道輸出到jq。
$ curl -s 10.245.1.3:8080/status/upstreams/backend | jq . { "peers": [ { "id": 1, "server": "10.0.0.1:80", "backup": false, "weight": 1, "state": "unhealthy", "active": 0, "requests": 1, "responses": { "1xx": 0, "2xx": 0, "3xx": 0, "4xx": 0, "5xx": 0, "total": 0 }, "sent": 0, "received": 0, "fails": 0, "unavail": 0, "health_checks": { "checks": 1, "fails": 1, "unhealthy": 1, "last_passed": false }, "downtime": 33965, "downstart": 1445378182275, "selected": 1445378131000 }, { "id": 2, "server": "10.246.1.6:80", ... }, { "id": 3, "server": "10.246.3.2:80", ... { "id": 4, "server": "10.0.0.2:80", ... } ], "keepalive": 0 }
在peers中的JSON輸出數組正好有四個元素,對應每個NGINX Web服務器。
現在,讓我們減少pods的數量從4到1,再次檢查NGINX Plus狀態:
$ kubectl scale rc nginx-rc --replicas=1
scaled
$ curl -s 10.245.1.3:8080/status/upstreams/backend | jq .
現在peers中的JSON輸出數組只包含一個元素。
現在,我們已經把NGINX Plus運行起來,我們就可以開始利用其高級功能,如會話持久性,SSL終止,請求路由,高級監控和更多。
總結
NGINX Plus的on-the-fly reconfiguration讓你的Kubernetes集成更輕松:不管是通過API編程還是完全使用DNS的方式。使用NGINX Plus暴露Kubernetes服務到互聯網提供了許多當前Kubernetes內置負載均衡解決方案缺乏的功能。
原文鏈接:Load Balancing Kubernetes Services with NGINX Plus (翻譯:朱高校)
本文由用戶 123tt 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!