使用NGINX Plus負載均衡Kubernetes服務

jopen 8年前發布 | 24K 次閱讀 Nginx 負載均衡 Web服務器 Kubernetes

【編者的話】

此篇文章是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</pre>

      在節點上使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
&quot;type&quot;: &quot;ExternalIP&quot;,
&quot;address&quot;: 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

    我們的控制器由兩個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

    這里我們通過設置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 .
    {
    &quot;peers&quot;: [
    {
    &quot;id&quot;: 1,
    &quot;server&quot;: &quot;10.0.0.1:80&quot;,
    &quot;backup&quot;: false,
    &quot;weight&quot;: 1,
    &quot;state&quot;: &quot;unhealthy&quot;,
    &quot;active&quot;: 0,
    &quot;requests&quot;: 1,
    &quot;responses&quot;: {
    &quot;1xx&quot;: 0,
    &quot;2xx&quot;: 0,
    &quot;3xx&quot;: 0,
    &quot;4xx&quot;: 0,
    &quot;5xx&quot;: 0,
    &quot;total&quot;: 0
    },
    &quot;sent&quot;: 0,
    &quot;received&quot;: 0,
    &quot;fails&quot;: 0,
    &quot;unavail&quot;: 0,
    &quot;health_checks&quot;: {
    &quot;checks&quot;: 1,
    &quot;fails&quot;: 1,
    &quot;unhealthy&quot;: 1,
    &quot;last_passed&quot;: false
    },
    &quot;downtime&quot;: 33965,
    &quot;downstart&quot;: 1445378182275,
    &quot;selected&quot;: 1445378131000
    },
    {
    &quot;id&quot;: 2,
    &quot;server&quot;: &quot;10.246.1.6:80&quot;,
    ...
    },
    {
    &quot;id&quot;: 3,
    &quot;server&quot;: &quot;10.246.3.2:80&quot;,
    ...
    {
    &quot;id&quot;: 4,
    &quot;server&quot;: &quot;10.0.0.2:80&quot;,
    ...
    }
    ],
    &quot;keepalive&quot;: 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 (翻譯:朱高校)

來自: http://dockone.io/article/957

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