使用NGINX Plus負載均衡Kubernetes服務

123tt 8年前發布 | 49K 次閱讀 Web服務器

來自: 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容器鏡像,創建的命令就在這篇博客文章

下面是我們怎么做的一個概括:
  1. 配置一個NGINX Plus pod用于暴露和負載均衡我們在步驟2中創建的服務。
  2. 創建一個提供靜態網頁的簡單服務,。
  3. 擴展或者縮減服務,查看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,我們可以看到新加的兩臺服務器。
    11.png

    我們還可以檢查NGINX Plus是否已經在pods的服務間負載均衡流量。如果是,當我們在瀏覽器中訪問http://10.245.1.3/nginx-service/時,我們可以看到默認NGINX的歡迎頁面。
    22.png

    如果我們刷新此頁面幾次,并查看儀表盤狀態,我們可以看到請求是如何分布在兩個上游服務器上的。

    擴展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 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!